Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 7 Feb 2008 17:45:14 +0000 (09:45 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 7 Feb 2008 17:45:14 +0000 (09:45 -0800)
* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
  leds: Add HP Jornada 6xx driver
  leds: Remove the now uneeded ixp4xx driver
  leds: Add power LED to the wrap driver
  leds: Fix led-gpio active_low default brightness
  leds: hw acceleration for Clevo mail LED driver
  leds: Add support for hardware accelerated LED flashing
  leds: Standardise LED naming scheme
  leds: Add clevo notebook LED driver

23 files changed:
Documentation/leds-class.txt
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
drivers/hwmon/applesmc.c
drivers/input/misc/wistron_btns.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-ams-delta.c
drivers/leds/leds-clevo-mail.c [new file with mode: 0644]
drivers/leds/leds-corgi.c
drivers/leds/leds-gpio.c
drivers/leds/leds-hp6xx.c [new file with mode: 0644]
drivers/leds/leds-ixp4xx-gpio.c [deleted file]
drivers/leds/leds-locomo.c
drivers/leds/leds-net48xx.c
drivers/leds/leds-spitz.c
drivers/leds/leds-tosa.c
drivers/leds/leds-wrap.c
drivers/leds/ledtrig-timer.c
drivers/misc/asus-laptop.c
drivers/net/wireless/b43/leds.c
include/linux/leds.h

index 8c35c0426110f149100be9cb2c17921e8e25ae39..56757c751d6fc5611b181f6d79302a195b3fe8c7 100644 (file)
@@ -39,12 +39,33 @@ LED Device Naming
 
 Is currently of the form:
 
-"devicename:colour"
+"devicename:colour:function"
 
 There have been calls for LED properties such as colour to be exported as
 individual led class attributes. As a solution which doesn't incur as much
 overhead, I suggest these become part of the device name. The naming scheme
-above leaves scope for further attributes should they be needed.
+above leaves scope for further attributes should they be needed. If sections
+of the name don't apply, just leave that section blank.
+
+
+Hardware accelerated blink of LEDs
+==================================
+
+Some LEDs can be programmed to blink without any CPU interaction. To
+support this feature, a LED driver can optionally implement the
+blink_set() function (see <linux/leds.h>). If implemeted, triggers can
+attempt to use it before falling back to software timers. The blink_set()
+function should return 0 if the blink setting is supported, or -EINVAL
+otherwise, which means that LED blinking will be handled by software.
+
+The blink_set() function should choose a user friendly blinking
+value if it is called with *delay_on==0 && *delay_off==0 parameters. In
+this case the driver should give back the chosen value through delay_on
+and delay_off parameters to the leds subsystem.
+
+Any call to the brightness_set() callback function should cancel the
+previously programmed hardware blinking function so setting the brightness
+to 0 can also cancel the blinking of the LED.
 
 
 Known Issues
@@ -55,10 +76,6 @@ would cause nightmare dependency issues. I see this as a minor issue
 compared to the benefits the simple trigger functionality brings. The
 rest of the LED subsystem can be modular.
 
-Some leds can be programmed to flash in hardware. As this isn't a generic
-LED device property, this should be exported as a device specific sysfs
-attribute rather than part of the class if this functionality is required.
-
 
 Future Development
 ==================
index 688659668bdf12156627f7780057ae76c6e9b5fb..8cb07437a807f81d92eed0bbd1a7d82b5118ab5d 100644 (file)
@@ -71,11 +71,11 @@ static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
 
 static struct gpio_led dsmg600_led_pins[] = {
        {
-               .name           = "power",
+               .name           = "dsmg600:green:power",
                .gpio           = DSMG600_LED_PWR_GPIO,
        },
        {
-               .name           = "wlan",
+               .name           = "dsmg600:green:wlan",
                .gpio           = DSMG600_LED_WLAN_GPIO,
                .active_low     = true,
        },
index 4cecae84837b37309039280122ed726356d6ab5c..159e1c4f1edaa789deb76336aa1616fd38c02c1c 100644 (file)
@@ -60,17 +60,17 @@ static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
 
 static struct gpio_led nas100d_led_pins[] = {
        {
-               .name           = "wlan",   /* green led */
+               .name           = "nas100d:green:wlan",
                .gpio           = NAS100D_LED_WLAN_GPIO,
                .active_low     = true,
        },
        {
-               .name           = "power",  /* blue power led (off=flashing) */
+               .name           = "nas100d:blue:power",  /* (off=flashing) */
                .gpio           = NAS100D_LED_PWR_GPIO,
                .active_low     = true,
        },
        {
-               .name           = "disk",   /* yellow led */
+               .name           = "nas100d:yellow:disk",
                .gpio           = NAS100D_LED_DISK_GPIO,
                .active_low     = true,
        },
index acaebcbce53a07319cade57fb80f5bdbb8543ea1..d9a182895a0f998bee850213b0c607dbc13eceb4 100644 (file)
@@ -63,20 +63,20 @@ static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
 
 static struct gpio_led nslu2_led_pins[] = {
        {
-               .name           = "ready",  /* green led */
+               .name           = "nslu2:green:ready",
                .gpio           = NSLU2_LED_GRN_GPIO,
        },
        {
-               .name           = "status", /* red led */
+               .name           = "nslu2:red:status",
                .gpio           = NSLU2_LED_RED_GPIO,
        },
        {
-               .name           = "disk-1",
+               .name           = "nslu2:green:disk-1",
                .gpio           = NSLU2_LED_DISK1_GPIO,
                .active_low     = true,
        },
        {
-               .name           = "disk-2",
+               .name           = "nslu2:green:disk-2",
                .gpio           = NSLU2_LED_DISK2_GPIO,
                .active_low     = true,
        },
index 86c66c345f8b76f8274272796917c740ba312e26..0c94770b7f83cd5fca272ba22877a9f045121904 100644 (file)
@@ -905,7 +905,7 @@ static ssize_t applesmc_key_at_index_store(struct device *dev,
 }
 
 static struct led_classdev applesmc_backlight = {
-       .name                   = "smc:kbd_backlight",
+       .name                   = "smc::kbd_backlight",
        .default_trigger        = "nand-disk",
        .brightness_set         = applesmc_brightness_set,
 };
index b438d998625c695f3d7f031ecf851f8c2683be18..72176f3d49cb3ad5e0c091c35fdcebff9047a984 100644 (file)
@@ -998,12 +998,12 @@ static void wistron_wifi_led_set(struct led_classdev *led_cdev,
 }
 
 static struct led_classdev wistron_mail_led = {
-       .name                   = "mail:green",
+       .name                   = "wistron:green:mail",
        .brightness_set         = wistron_mail_led_set,
 };
 
 static struct led_classdev wistron_wifi_led = {
-       .name                   = "wifi:red",
+       .name                   = "wistron:red:wifi",
        .brightness_set         = wistron_wifi_led_set,
 };
 
index ec568fa1c6cc3b2ec92e6314de868416bb1e2ded..851a3b01781e71e05a1bb1fa7d5cdc1e05cc7187 100644 (file)
@@ -39,15 +39,6 @@ config LEDS_SPITZ
          This option enables support for the LEDs on Sharp Zaurus
          SL-Cxx00 series (C1000, C3000, C3100).
 
-config LEDS_IXP4XX
-       tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
-       depends on LEDS_CLASS && ARCH_IXP4XX
-       help
-         This option enables support for the LEDs connected to GPIO
-         outputs of the Intel IXP4XX processors.  To be useful the
-         particular board must have LEDs and they must be connected
-         to the GPIO lines.  If unsure, say Y.
-
 config LEDS_TOSA
        tristate "LED Support for the Sharp SL-6000 series"
        depends on LEDS_CLASS && PXA_SHARPSL
@@ -100,6 +91,13 @@ config LEDS_COBALT_RAQ
        help
          This option enables support for the Cobalt Raq series LEDs.
 
+config LEDS_HP6XX
+       tristate "LED Support for the HP Jornada 6xx"
+       depends on LEDS_CLASS && SH_HP6XX
+       help
+         This option enables led support for the handheld
+         HP Jornada 620/660/680/690.
+
 config LEDS_GPIO
        tristate "LED Support for GPIO connected LEDs"
        depends on LEDS_CLASS && GENERIC_GPIO
@@ -114,6 +112,32 @@ config LEDS_CM_X270
        help
          This option enables support for the CM-X270 LEDs.
 
+config LEDS_CLEVO_MAIL
+       tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
+       depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
+       help
+         This driver makes the mail LED accessible from userspace
+         programs through the leds subsystem. This LED have three
+         known mode: off, blink at 0.5Hz and blink at 1Hz.
+
+         The driver supports two kinds of interface: using ledtrig-timer
+         or through /sys/class/leds/clevo::mail/brightness. As this LED
+         cannot change it's brightness it blinks instead. The brightness
+         value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
+         blink at 1Hz.
+
+         This module can drive the mail LED for the following notebooks:
+
+               Clevo D410J
+               Clevo D410V
+               Clevo D400V/D470V (not tested, but might work)
+               Clevo M540N
+               Clevo M5x0N (not tested, but might work)
+               Positivo Mobile (Clevo M5x0V)
+
+         To compile this driver as a module, choose M here: the
+         module will be called leds-clevo-mail.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
@@ -128,7 +152,11 @@ config LEDS_TRIGGER_TIMER
        depends on LEDS_TRIGGERS
        help
          This allows LEDs to be controlled by a programmable timer
-         via sysfs. If unsure, say Y.
+         via sysfs. Some LED hardware can be programmed to start
+         blinking the LED without any further software interaction.
+         For more details read Documentation/leds-class.txt.
+
+         If unsure, say Y.
 
 config LEDS_TRIGGER_IDE_DISK
        bool "LED IDE Disk Trigger"
index a60de1b46c2cd28ec7c3a88471949877f1006aa8..bc6afc8dcb278d8be7e3b71cfe65412649da6c32 100644 (file)
@@ -8,7 +8,6 @@ obj-$(CONFIG_LEDS_TRIGGERS)             += led-triggers.o
 obj-$(CONFIG_LEDS_CORGI)               += leds-corgi.o
 obj-$(CONFIG_LEDS_LOCOMO)              += leds-locomo.o
 obj-$(CONFIG_LEDS_SPITZ)               += leds-spitz.o
-obj-$(CONFIG_LEDS_IXP4XX)              += leds-ixp4xx-gpio.o
 obj-$(CONFIG_LEDS_TOSA)                        += leds-tosa.o
 obj-$(CONFIG_LEDS_S3C24XX)             += leds-s3c24xx.o
 obj-$(CONFIG_LEDS_AMS_DELTA)           += leds-ams-delta.o
@@ -19,6 +18,8 @@ obj-$(CONFIG_LEDS_COBALT_QUBE)                += leds-cobalt-qube.o
 obj-$(CONFIG_LEDS_COBALT_RAQ)          += leds-cobalt-raq.o
 obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o
 obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
+obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
+obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
index 599878c8e7146fb65f2799ca6cfba1a13dc652c0..9e3077463d8481944e351b466e3d4e6749751cb9 100644 (file)
@@ -37,42 +37,42 @@ static void ams_delta_led_set(struct led_classdev *led_cdev,
 static struct ams_delta_led ams_delta_leds[] = {
        {
                .cdev           = {
-                       .name           = "ams-delta:camera",
+                       .name           = "ams-delta::camera",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_CAMERA,
        },
        {
                .cdev           = {
-                       .name           = "ams-delta:advert",
+                       .name           = "ams-delta::advert",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_ADVERT,
        },
        {
                .cdev           = {
-                       .name           = "ams-delta:email",
+                       .name           = "ams-delta::email",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_EMAIL,
        },
        {
                .cdev           = {
-                       .name           = "ams-delta:handsfree",
+                       .name           = "ams-delta::handsfree",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_HANDSFREE,
        },
        {
                .cdev           = {
-                       .name           = "ams-delta:voicemail",
+                       .name           = "ams-delta::voicemail",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_VOICEMAIL,
        },
        {
                .cdev           = {
-                       .name           = "ams-delta:voice",
+                       .name           = "ams-delta::voice",
                        .brightness_set = ams_delta_led_set,
                },
                .bitmask        = AMS_DELTA_LATCH1_LED_VOICE,
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
new file mode 100644 (file)
index 0000000..6c3d33b
--- /dev/null
@@ -0,0 +1,219 @@
+
+#include <linux/module.h>
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/leds.h>
+
+#include <linux/io.h>
+#include <linux/dmi.h>
+
+#include <linux/i8042.h>
+
+#define CLEVO_MAIL_LED_OFF             0x0084
+#define CLEVO_MAIL_LED_BLINK_1HZ       0x008A
+#define CLEVO_MAIL_LED_BLINK_0_5HZ     0x0083
+
+MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
+MODULE_DESCRIPTION("Clevo mail LED driver");
+MODULE_LICENSE("GPL");
+
+static unsigned int __initdata nodetect;
+module_param_named(nodetect, nodetect, bool, 0);
+MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
+
+static struct platform_device *pdev;
+
+static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
+{
+       printk(KERN_INFO KBUILD_MODNAME ": '%s' found\n", id->ident);
+       return 1;
+}
+
+/*
+ * struct mail_led_whitelist - List of known good models
+ *
+ * Contains the known good models this driver is compatible with.
+ * When adding a new model try to be as strict as possible. This
+ * makes it possible to keep the false positives (the model is
+ * detected as working, but in reality it is not) as low as
+ * possible.
+ */
+static struct dmi_system_id __initdata mail_led_whitelist[] = {
+       {
+               .callback = clevo_mail_led_dmi_callback,
+               .ident = "Clevo D410J",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
+               }
+       },
+       {
+               .callback = clevo_mail_led_dmi_callback,
+               .ident = "Clevo M5x0N",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
+               }
+       },
+       {
+               .callback = clevo_mail_led_dmi_callback,
+               .ident = "Positivo Mobile",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
+                       DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
+               }
+       },
+       {
+               .callback = clevo_mail_led_dmi_callback,
+               .ident = "Clevo D410V",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
+                       DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
+               }
+       },
+       { }
+};
+
+static void clevo_mail_led_set(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       if (value == LED_OFF)
+               i8042_command(NULL, CLEVO_MAIL_LED_OFF);
+       else if (value <= LED_HALF)
+               i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+       else
+               i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+
+}
+
+static int clevo_mail_led_blink(struct led_classdev *led_cdev,
+                               unsigned long* delay_on,
+                               unsigned long* delay_off)
+{
+       int status = -EINVAL;
+
+       if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) {
+               /* Special case: the leds subsystem requested us to
+                * chose one user friendly blinking of the LED, and
+                * start it. Let's blink the led slowly (0.5Hz).
+                */
+               *delay_on = 1000; /* ms */
+               *delay_off = 1000; /* ms */
+               i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+               status = 0;
+
+       } else if (*delay_on == 500 /* ms */ && *delay_off == 500 /* ms */) {
+               /* blink the led with 1Hz */
+               i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+               status = 0;
+
+       } else if (*delay_on == 1000 /* ms */ && *delay_off == 1000 /* ms */) {
+               /* blink the led with 0.5Hz */
+               i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+               status = 0;
+
+       } else {
+               printk(KERN_DEBUG KBUILD_MODNAME
+                      ": clevo_mail_led_blink(..., %lu, %lu),"
+                      " returning -EINVAL (unsupported)\n",
+                      *delay_on, *delay_off);
+       }
+
+       return status;
+}
+
+static struct led_classdev clevo_mail_led = {
+       .name                   = "clevo::mail",
+       .brightness_set         = clevo_mail_led_set,
+       .blink_set              = clevo_mail_led_blink,
+};
+
+static int __init clevo_mail_led_probe(struct platform_device *pdev)
+{
+       return led_classdev_register(&pdev->dev, &clevo_mail_led);
+}
+
+static int clevo_mail_led_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&clevo_mail_led);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int clevo_mail_led_suspend(struct platform_device *dev,
+                                 pm_message_t state)
+{
+       led_classdev_suspend(&clevo_mail_led);
+       return 0;
+}
+
+static int clevo_mail_led_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&clevo_mail_led);
+       return 0;
+}
+#else
+#define clevo_mail_led_suspend    NULL
+#define clevo_mail_led_resume     NULL
+#endif
+
+static struct platform_driver clevo_mail_led_driver = {
+       .probe          = clevo_mail_led_probe,
+       .remove         = clevo_mail_led_remove,
+       .suspend        = clevo_mail_led_suspend,
+       .resume         = clevo_mail_led_resume,
+       .driver         = {
+               .name           = KBUILD_MODNAME,
+       },
+};
+
+static int __init clevo_mail_led_init(void)
+{
+       int error = 0;
+       int count = 0;
+
+       /* Check with the help of DMI if we are running on supported hardware */
+       if (!nodetect) {
+               count = dmi_check_system(mail_led_whitelist);
+       } else {
+               count = 1;
+               printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
+                      "If the driver works on your hardware please "
+                      "report model and the output of dmidecode in tracker "
+                      "at http://sourceforge.net/projects/clevo-mailled/\n");
+       }
+
+       if (!count)
+               return -ENODEV;
+
+       pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
+       if (!IS_ERR(pdev)) {
+               error = platform_driver_probe(&clevo_mail_led_driver,
+                                             clevo_mail_led_probe);
+               if (error) {
+                       printk(KERN_ERR KBUILD_MODNAME
+                              ": Can't probe platform driver\n");
+                       platform_device_unregister(pdev);
+               }
+       } else
+               error = PTR_ERR(pdev);
+
+       return error;
+}
+
+static void __exit clevo_mail_led_exit(void)
+{
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&clevo_mail_led_driver);
+
+       clevo_mail_led_set(NULL, LED_OFF);
+}
+
+module_init(clevo_mail_led_init);
+module_exit(clevo_mail_led_exit);
index cf1dcd719a282eae18e596e7673807b48ef524c5..e45f6c4b59ba4fd6c57293ba60dd55e49013aada 100644 (file)
@@ -38,13 +38,13 @@ static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightnes
 }
 
 static struct led_classdev corgi_amber_led = {
-       .name                   = "corgi:amber",
+       .name                   = "corgi:amber:charge",
        .default_trigger        = "sharpsl-charge",
        .brightness_set         = corgiled_amber_set,
 };
 
 static struct led_classdev corgi_green_led = {
-       .name                   = "corgi:green",
+       .name                   = "corgi:green:mail",
        .default_trigger        = "nand-disk",
        .brightness_set         = corgiled_green_set,
 };
index 99bc50059d3531499fa78ca369129a5f7d8c0e39..6c0a9c4761ee13ffd2333db779c7b8f42091ea21 100644 (file)
@@ -85,7 +85,7 @@ static int gpio_led_probe(struct platform_device *pdev)
                led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
                led_dat->active_low = cur_led->active_low;
                led_dat->cdev.brightness_set = gpio_led_set;
-               led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
+               led_dat->cdev.brightness = LED_OFF;
 
                ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
                if (ret < 0)
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
new file mode 100644 (file)
index 0000000..82d4ec3
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * LED Triggers Core
+ * For the HP Jornada 620/660/680/690 handhelds
+ *
+ * Copyright 2008 Kristoffer Ericson <kristoffer.ericson@gmail.com>
+ *     this driver is based on leds-spitz.c by Richard Purdie.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hd64461.h>
+#include <asm/hp6xx.h>
+
+static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       u8 v8;
+
+       v8 = inb(PKDR);
+       if (value)
+               outb(v8 & (~PKDR_LED_GREEN), PKDR);
+       else
+               outb(v8 | PKDR_LED_GREEN, PKDR);
+}
+
+static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       u16 v16;
+
+       v16 = inw(HD64461_GPBDR);
+       if (value)
+               outw(v16 & (~HD64461_GPBDR_LED_RED), HD64461_GPBDR);
+       else
+               outw(v16 | HD64461_GPBDR_LED_RED, HD64461_GPBDR);
+}
+
+static struct led_classdev hp6xx_red_led = {
+       .name                   = "hp6xx:red",
+       .default_trigger        = "hp6xx-charge",
+       .brightness_set         = hp6xxled_red_set,
+};
+
+static struct led_classdev hp6xx_green_led = {
+       .name                   = "hp6xx:green",
+       .default_trigger        = "ide-disk",
+       .brightness_set         = hp6xxled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int hp6xxled_suspend(struct platform_device *dev, pm_message_t state)
+{
+       led_classdev_suspend(&hp6xx_red_led);
+       led_classdev_suspend(&hp6xx_green_led);
+       return 0;
+}
+
+static int hp6xxled_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&hp6xx_red_led);
+       led_classdev_resume(&hp6xx_green_led);
+       return 0;
+}
+#endif
+
+static int hp6xxled_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &hp6xx_red_led);
+       if (ret < 0)
+               return ret;
+
+       ret = led_classdev_register(&pdev->dev, &hp6xx_green_led);
+       if (ret < 0)
+               led_classdev_unregister(&hp6xx_red_led);
+
+       return ret;
+}
+
+static int hp6xxled_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&hp6xx_red_led);
+       led_classdev_unregister(&hp6xx_green_led);
+
+       return 0;
+}
+
+static struct platform_driver hp6xxled_driver = {
+       .probe          = hp6xxled_probe,
+       .remove         = hp6xxled_remove,
+#ifdef CONFIG_PM
+       .suspend        = hp6xxled_suspend,
+       .resume         = hp6xxled_resume,
+#endif
+       .driver         = {
+               .name           = "hp6xx-led",
+       },
+};
+
+static int __init hp6xxled_init(void)
+{
+       return platform_driver_register(&hp6xxled_driver);
+}
+
+static void __exit hp6xxled_exit(void)
+{
+       platform_driver_unregister(&hp6xxled_driver);
+}
+
+module_init(hp6xxled_init);
+module_exit(hp6xxled_exit);
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c
deleted file mode 100644 (file)
index 7dcf0b9..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * IXP4XX GPIO driver LED driver
- *
- * Author: John Bowler <jbowler@acm.org>
- *
- * Copyright (c) 2006 John Bowler
- *
- * Permission is hereby granted, free of charge, to any
- * person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the
- * Software without restriction, including without
- * limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the
- * following conditions:
- *
- * The above copyright notice and this permission notice
- * shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
- * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
- * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/leds.h>
-#include <asm/arch/hardware.h>
-
-extern spinlock_t gpio_lock;
-
-/* Up to 16 gpio lines are possible. */
-#define GPIO_MAX 16
-static struct ixp4xxgpioled_device {
-       struct led_classdev ancestor;
-       int               flags;
-} ixp4xxgpioled_devices[GPIO_MAX];
-
-void ixp4xxgpioled_brightness_set(struct led_classdev *pled,
-                               enum led_brightness value)
-{
-       const struct ixp4xxgpioled_device *const ixp4xx_dev =
-               container_of(pled, struct ixp4xxgpioled_device, ancestor);
-       const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices;
-
-       if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) {
-               /* Set or clear the 'gpio_pin' bit according to the style
-                * and the required setting (value > 0 == on)
-                */
-               const int gpio_value =
-                       (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ?
-                               IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW;
-
-               {
-                       unsigned long flags;
-                       spin_lock_irqsave(&gpio_lock, flags);
-                       gpio_line_set(gpio_pin, gpio_value);
-                       spin_unlock_irqrestore(&gpio_lock, flags);
-               }
-       }
-}
-
-/* LEDs are described in resources, the following iterates over the valid
- * LED resources.
- */
-#define for_all_leds(i, pdev) \
-       for (i=0; i<pdev->num_resources; ++i) \
-               if (pdev->resource[i].start < GPIO_MAX && \
-                       pdev->resource[i].name != 0)
-
-/* The following applies 'operation' to each LED from the given platform,
- * the function always returns 0 to allow tail call elimination.
- */
-static int apply_to_all_leds(struct platform_device *pdev,
-       void (*operation)(struct led_classdev *pled))
-{
-       int i;
-
-       for_all_leds(i, pdev)
-               operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int ixp4xxgpioled_suspend(struct platform_device *pdev,
-                               pm_message_t state)
-{
-       return apply_to_all_leds(pdev, led_classdev_suspend);
-}
-
-static int ixp4xxgpioled_resume(struct platform_device *pdev)
-{
-       return apply_to_all_leds(pdev, led_classdev_resume);
-}
-#endif
-
-static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled)
-{
-       led_classdev_unregister(pled);
-       pled->name = 0;
-}
-
-static int ixp4xxgpioled_remove(struct platform_device *pdev)
-{
-       return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led);
-}
-
-static int ixp4xxgpioled_probe(struct platform_device *pdev)
-{
-       /* The board level has to tell the driver where the
-        * LEDs are connected - there is no way to find out
-        * electrically.  It must also say whether the GPIO
-        * lines are active high or active low.
-        *
-        * To do this read the num_resources (the number of
-        * LEDs) and the struct resource (the data for each
-        * LED).  The name comes from the resource, and it
-        * isn't copied.
-        */
-       int i;
-
-       for_all_leds(i, pdev) {
-               const u8 gpio_pin = pdev->resource[i].start;
-               int      rc;
-
-               if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&gpio_lock, flags);
-                       gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT);
-                       /* The config can, apparently, reset the state,
-                        * I suspect the gpio line may be an input and
-                        * the config may cause the line to be latched,
-                        * so the setting depends on how the LED is
-                        * connected to the line (which affects how it
-                        * floats if not driven).
-                        */
-                       gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH);
-                       spin_unlock_irqrestore(&gpio_lock, flags);
-
-                       ixp4xxgpioled_devices[gpio_pin].flags =
-                               pdev->resource[i].flags & IORESOURCE_BITS;
-
-                       ixp4xxgpioled_devices[gpio_pin].ancestor.name =
-                               pdev->resource[i].name;
-
-                       /* This is how a board manufacturer makes the LED
-                        * come on on reset - the GPIO line will be high, so
-                        * make the LED light when the line is low...
-                        */
-                       if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW)
-                               ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100;
-                       else
-                               ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0;
-
-                       ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0;
-
-                       ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set =
-                               ixp4xxgpioled_brightness_set;
-
-                       ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0;
-               }
-
-               rc = led_classdev_register(&pdev->dev,
-                               &ixp4xxgpioled_devices[gpio_pin].ancestor);
-               if (rc < 0) {
-                       ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0;
-                       ixp4xxgpioled_remove(pdev);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-static struct platform_driver ixp4xxgpioled_driver = {
-       .probe   = ixp4xxgpioled_probe,
-       .remove  = ixp4xxgpioled_remove,
-#ifdef CONFIG_PM
-       .suspend = ixp4xxgpioled_suspend,
-       .resume  = ixp4xxgpioled_resume,
-#endif
-       .driver  = {
-               .name = "IXP4XX-GPIO-LED",
-       },
-};
-
-static int __init ixp4xxgpioled_init(void)
-{
-       return platform_driver_register(&ixp4xxgpioled_driver);
-}
-
-static void __exit ixp4xxgpioled_exit(void)
-{
-       platform_driver_unregister(&ixp4xxgpioled_driver);
-}
-
-module_init(ixp4xxgpioled_init);
-module_exit(ixp4xxgpioled_exit);
-
-MODULE_AUTHOR("John Bowler <jbowler@acm.org>");
-MODULE_DESCRIPTION("IXP4XX GPIO LED driver");
-MODULE_LICENSE("Dual MIT/GPL");
index 2207335e9212e97b64a05bdd290819ceee83a89d..7295f7f52185162d68b98f72dc5dc66ee565c9a0 100644 (file)
@@ -43,13 +43,13 @@ static void locomoled_brightness_set1(struct led_classdev *led_cdev,
 }
 
 static struct led_classdev locomo_led0 = {
-       .name                   = "locomo:amber",
+       .name                   = "locomo:amber:charge",
        .default_trigger        = "sharpsl-charge",
        .brightness_set         = locomoled_brightness_set0,
 };
 
 static struct led_classdev locomo_led1 = {
-       .name                   = "locomo:green",
+       .name                   = "locomo:green:mail",
        .default_trigger        = "nand-disk",
        .brightness_set         = locomoled_brightness_set1,
 };
index 45ba3d45bcb8a8387461883ae050aa308213a812..054360473c9490ea6e4251188dcbf4cad92fa310 100644 (file)
@@ -31,7 +31,7 @@ static void net48xx_error_led_set(struct led_classdev *led_cdev,
 }
 
 static struct led_classdev net48xx_error_led = {
-       .name           = "net48xx:error",
+       .name           = "net48xx::error",
        .brightness_set = net48xx_error_led_set,
 };
 
index 126d09cc96ecf97cad158fe47315e73c13e96779..93e1012b17e620c1c85e8ad037180142676d11b4 100644 (file)
@@ -38,13 +38,13 @@ static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightnes
 }
 
 static struct led_classdev spitz_amber_led = {
-       .name                   = "spitz:amber",
+       .name                   = "spitz:amber:charge",
        .default_trigger        = "sharpsl-charge",
        .brightness_set         = spitzled_amber_set,
 };
 
 static struct led_classdev spitz_green_led = {
-       .name                   = "spitz:green",
+       .name                   = "spitz:green:hddactivity",
        .default_trigger        = "ide-disk",
        .brightness_set         = spitzled_green_set,
 };
@@ -72,8 +72,10 @@ static int spitzled_probe(struct platform_device *pdev)
 {
        int ret;
 
-       if (machine_is_akita())
+       if (machine_is_akita()) {
+               spitz_green_led.name = "spitz:green:mail";
                spitz_green_led.default_trigger = "nand-disk";
+       }
 
        ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
        if (ret < 0)
index fb2416a38303ce87aab0766dac1c9997ecca506a..9e0a188fbb0a224ceb66fc7fe3b22a0bc4668437 100644 (file)
@@ -45,13 +45,13 @@ static void tosaled_green_set(struct led_classdev *led_cdev,
 }
 
 static struct led_classdev tosa_amber_led = {
-       .name                   = "tosa:amber",
+       .name                   = "tosa:amber:charge",
        .default_trigger        = "sharpsl-charge",
        .brightness_set         = tosaled_amber_set,
 };
 
 static struct led_classdev tosa_green_led = {
-       .name                   = "tosa:green",
+       .name                   = "tosa:green:mail",
        .default_trigger        = "nand-disk",
        .brightness_set         = tosaled_green_set,
 };
index 27fb2d8e991fd55343f51021df26887ddffa3f29..7ac61a7b56ad9b5d62a035f05f530a567c5deacb 100644 (file)
 #include <linux/scx200_gpio.h>
 
 #define DRVNAME "wrap-led"
+#define WRAP_POWER_LED_GPIO    2
 #define WRAP_ERROR_LED_GPIO    3
-#define        WRAP_EXTRA_LED_GPIO     18
+#define WRAP_EXTRA_LED_GPIO    18
 
 static struct platform_device *pdev;
 
+static void wrap_power_led_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       if (value)
+               scx200_gpio_set_low(WRAP_POWER_LED_GPIO);
+       else
+               scx200_gpio_set_high(WRAP_POWER_LED_GPIO);
+}
+
 static void wrap_error_led_set(struct led_classdev *led_cdev,
                enum led_brightness value)
 {
@@ -42,13 +52,18 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev,
                scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO);
 }
 
+static struct led_classdev wrap_power_led = {
+       .name           = "wrap::power",
+       .brightness_set = wrap_power_led_set,
+};
+
 static struct led_classdev wrap_error_led = {
-       .name           = "wrap:error",
+       .name           = "wrap::error",
        .brightness_set = wrap_error_led_set,
 };
 
 static struct led_classdev wrap_extra_led = {
-       .name           = "wrap:extra",
+       .name           = "wrap::extra",
        .brightness_set = wrap_extra_led_set,
 };
 
@@ -56,6 +71,7 @@ static struct led_classdev wrap_extra_led = {
 static int wrap_led_suspend(struct platform_device *dev,
                pm_message_t state)
 {
+       led_classdev_suspend(&wrap_power_led);
        led_classdev_suspend(&wrap_error_led);
        led_classdev_suspend(&wrap_extra_led);
        return 0;
@@ -63,6 +79,7 @@ static int wrap_led_suspend(struct platform_device *dev,
 
 static int wrap_led_resume(struct platform_device *dev)
 {
+       led_classdev_resume(&wrap_power_led);
        led_classdev_resume(&wrap_error_led);
        led_classdev_resume(&wrap_extra_led);
        return 0;
@@ -76,17 +93,31 @@ static int wrap_led_probe(struct platform_device *pdev)
 {
        int ret;
 
+       ret = led_classdev_register(&pdev->dev, &wrap_power_led);
+       if (ret < 0)
+               return ret;
+
        ret = led_classdev_register(&pdev->dev, &wrap_error_led);
-       if (ret == 0) {
-               ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
-               if (ret < 0)
-                       led_classdev_unregister(&wrap_error_led);
-       }
+       if (ret < 0)
+               goto err1;
+
+       ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
+       if (ret < 0)
+               goto err2;
+
+       return ret;
+
+err2:
+       led_classdev_unregister(&wrap_error_led);
+err1:
+       led_classdev_unregister(&wrap_power_led);
+
        return ret;
 }
 
 static int wrap_led_remove(struct platform_device *pdev)
 {
+       led_classdev_unregister(&wrap_power_led);
        led_classdev_unregister(&wrap_error_led);
        led_classdev_unregister(&wrap_extra_led);
        return 0;
index ed9ff02c77ea742c23c616a0f340c400770c33ec..82c55d6e49023ff9fe2866a819a1c5ec7bad7949 100644 (file)
@@ -77,8 +77,21 @@ static ssize_t led_delay_on_store(struct device *dev,
                count++;
 
        if (count == size) {
-               timer_data->delay_on = state;
-               mod_timer(&timer_data->timer, jiffies + 1);
+               if (timer_data->delay_on != state) {
+                       /* the new value differs from the previous */
+                       timer_data->delay_on = state;
+
+                       /* deactivate previous settings */
+                       del_timer_sync(&timer_data->timer);
+
+                       /* try to activate hardware acceleration, if any */
+                       if (!led_cdev->blink_set ||
+                           led_cdev->blink_set(led_cdev,
+                               &timer_data->delay_on, &timer_data->delay_off)) {
+                               /* no hardware acceleration, blink via timer */
+                               mod_timer(&timer_data->timer, jiffies + 1);
+                       }
+               }
                ret = count;
        }
 
@@ -110,8 +123,21 @@ static ssize_t led_delay_off_store(struct device *dev,
                count++;
 
        if (count == size) {
-               timer_data->delay_off = state;
-               mod_timer(&timer_data->timer, jiffies + 1);
+               if (timer_data->delay_off != state) {
+                       /* the new value differs from the previous */
+                       timer_data->delay_off = state;
+
+                       /* deactivate previous settings */
+                       del_timer_sync(&timer_data->timer);
+
+                       /* try to activate hardware acceleration, if any */
+                       if (!led_cdev->blink_set ||
+                           led_cdev->blink_set(led_cdev,
+                               &timer_data->delay_on, &timer_data->delay_off)) {
+                               /* no hardware acceleration, blink via timer */
+                               mod_timer(&timer_data->timer, jiffies + 1);
+                       }
+               }
                ret = count;
        }
 
@@ -143,6 +169,13 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
        if (rc)
                goto err_out_delayon;
 
+       /* If there is hardware support for blinking, start one
+        * user friendly blink rate chosen by the driver.
+        */
+       if (led_cdev->blink_set)
+               led_cdev->blink_set(led_cdev,
+                       &timer_data->delay_on, &timer_data->delay_off);
+
        return;
 
 err_out_delayon:
index 0846c33296bc7e1a0da8aabf21a7023667613edb..3a36a294e91b2ce731586950edb4ac5d4e9da8b2 100644 (file)
@@ -239,7 +239,7 @@ static struct workqueue_struct *led_workqueue;
        static int object##_led_wk;                                     \
        static DECLARE_WORK(object##_led_work, object##_led_update);    \
        static struct led_classdev object##_led = {                     \
-               .name           = "asus:" ledname,                      \
+               .name           = "asus::" ledname,                     \
                .brightness_set = object##_led_set,                     \
        }
 
index 0908335892dbba7214fc1d995d7a9af2da7f54e5..0aac1ff511df768a6ea38175e22a270a00ebaf20 100644 (file)
@@ -147,12 +147,12 @@ static void b43_map_led(struct b43_wldev *dev,
        case B43_LED_TRANSFER:
        case B43_LED_APTRANSFER:
                snprintf(name, sizeof(name),
-                        "b43-%s:tx", wiphy_name(hw->wiphy));
+                        "b43-%s::tx", wiphy_name(hw->wiphy));
                b43_register_led(dev, &dev->led_tx, name,
                                 ieee80211_get_tx_led_name(hw),
                                 led_index, activelow);
                snprintf(name, sizeof(name),
-                        "b43-%s:rx", wiphy_name(hw->wiphy));
+                        "b43-%s::rx", wiphy_name(hw->wiphy));
                b43_register_led(dev, &dev->led_rx, name,
                                 ieee80211_get_rx_led_name(hw),
                                 led_index, activelow);
@@ -162,7 +162,7 @@ static void b43_map_led(struct b43_wldev *dev,
        case B43_LED_RADIO_B:
        case B43_LED_MODE_BG:
                snprintf(name, sizeof(name),
-                        "b43-%s:radio", wiphy_name(hw->wiphy));
+                        "b43-%s::radio", wiphy_name(hw->wiphy));
                b43_register_led(dev, &dev->led_radio, name,
                                 b43_rfkill_led_name(dev),
                                 led_index, activelow);
@@ -173,7 +173,7 @@ static void b43_map_led(struct b43_wldev *dev,
        case B43_LED_WEIRD:
        case B43_LED_ASSOC:
                snprintf(name, sizeof(name),
-                        "b43-%s:assoc", wiphy_name(hw->wiphy));
+                        "b43-%s::assoc", wiphy_name(hw->wiphy));
                b43_register_led(dev, &dev->led_assoc, name,
                                 ieee80211_get_assoc_led_name(hw),
                                 led_index, activelow);
index 00f89fd6c52a21f83d26a7b94e351e3c782854bf..0201f6f51ceab72892ce6b2c167d8dceaa2a23d5 100644 (file)
@@ -38,6 +38,11 @@ struct led_classdev {
        void            (*brightness_set)(struct led_classdev *led_cdev,
                                          enum led_brightness brightness);
 
+       /* Activate hardware accelerated blink */
+       int             (*blink_set)(struct led_classdev *led_cdev,
+                                    unsigned long *delay_on,
+                                    unsigned long *delay_off);
+
        struct device           *dev;
        struct list_head         node;                  /* LED Device list */
        char                    *default_trigger;       /* Trigger to use */