Commit 607e11ab authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds_for_4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds

Pull LED updates from Jacek Anaszewski:
 "New LED class driver:
   - LED driver for TI LP3952 6-Channel Color LED

  LED core improvements:
   - Only descend into leds directory when CONFIG_NEW_LEDS is set
   - Add no-op gpio_led_register_device when LED subsystem is disabled
   - MAINTAINERS: Add file patterns for led device tree bindings

  LED Trigger core improvements:
   - return error if invalid trigger name is provided via sysfs

  LED class drivers improvements
   - is31fl32xx: define complete i2c_device_id table
   - is31fl32xx: fix typo in id and match table names
   - leds-gpio: Set of_node for created LED devices
   - pca9532: Add device tree support

  Conversion of IDE trigger to common disk trigger:
   - leds: convert IDE trigger to common disk trigger
   - leds: documentation: 'ide-disk' to 'disk-activity'
   - unicore32: use the new LED disk activity trigger
   - parisc: use the new LED disk activity trigger
   - mips: use the new LED disk activity trigger
   - arm: use the new LED disk activity trigger
   - powerpc: use the new LED disk activity trigger"

* tag 'leds_for_4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  leds: is31fl32xx: define complete i2c_device_id table
  leds: is31fl32xx: fix typo in id and match table names
  leds: LED driver for TI LP3952 6-Channel Color LED
  leds: leds-gpio: Set of_node for created LED devices
  leds: triggers: return error if invalid trigger name is provided via sysfs
  leds: Only descend into leds directory when CONFIG_NEW_LEDS is set
  leds: Add no-op gpio_led_register_device when LED subsystem is disabled
  unicore32: use the new LED disk activity trigger
  parisc: use the new LED disk activity trigger
  mips: use the new LED disk activity trigger
  arm: use the new LED disk activity trigger
  powerpc: use the new LED disk activity trigger
  leds: documentation: 'ide-disk' to 'disk-activity'
  leds: convert IDE trigger to common disk trigger
  leds: pca9532: Add device tree support
  MAINTAINERS: Add file patterns for led device tree bindings
parents 78d51aee 5706c01f
......@@ -26,7 +26,9 @@ Optional properties for child nodes:
"default-on" - LED will turn on (but for leds-gpio see "default-state"
property in Documentation/devicetree/bindings/gpio/led.txt)
"heartbeat" - LED "double" flashes at a load average based rate
"ide-disk" - LED indicates disk activity
"disk-activity" - LED indicates disk activity
"ide-disk" - LED indicates IDE disk activity (deprecated),
in new implementations use "disk-activity"
"timer" - LED flashes at a fixed, configurable rate
- led-max-microamp : Maximum LED supply current in microamperes. This property
......
......@@ -33,9 +33,9 @@ Examples:
leds {
compatible = "gpio-leds";
hdd {
label = "IDE Activity";
label = "Disk Activity";
gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
fault {
......
*NXP - pca9532 PWM LED Driver
The PCA9532 family is SMBus I/O expander optimized for dimming LEDs.
The PWM support 256 steps.
Required properties:
- compatible:
"nxp,pca9530"
"nxp,pca9531"
"nxp,pca9532"
"nxp,pca9533"
- reg - I2C slave address
Each led is represented as a sub-node of the nxp,pca9530.
Optional sub-node properties:
- label: see Documentation/devicetree/bindings/leds/common.txt
- type: Output configuration, see dt-bindings/leds/leds-pca9532.h (default NONE)
- linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt
Example:
#include <dt-bindings/leds/leds-pca9532.h>
leds: pca9530@60 {
compatible = "nxp,pca9530";
reg = <0x60>;
red-power {
label = "pca:red:power";
type = <PCA9532_TYPE_LED>;
};
green-power {
label = "pca:green:power";
type = <PCA9532_TYPE_LED>;
};
};
For more product information please see the link below:
http://nxp.com/documents/data_sheet/PCA9532.pdf
......@@ -72,7 +72,7 @@ LEDs
echo 1 > /sys/class/leds/asus::mail/brightness
will switch the mail LED on.
You can also know if they are on/off by reading their content and use
kernel triggers like ide-disk or heartbeat.
kernel triggers like disk-activity or heartbeat.
Backlight
---------
......
......@@ -11,7 +11,7 @@ brightness support so will just be turned on for non-zero brightness settings.
The class also introduces the optional concept of an LED trigger. A trigger
is a kernel based source of led events. Triggers can either be simple or
complex. A simple trigger isn't configurable and is designed to slot into
existing subsystems with minimal additional code. Examples are the ide-disk,
existing subsystems with minimal additional code. Examples are the disk-activity,
nand-disk and sharpsl-charge triggers. With led triggers disabled, the code
optimises away.
......
......@@ -6783,6 +6783,7 @@ M: Jacek Anaszewski <j.anaszewski@samsung.com>
L: linux-leds@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git
S: Maintained
F: Documentation/devicetree/bindings/leds/
F: drivers/leds/
F: include/linux/leds.h
......
......@@ -86,7 +86,7 @@ led@2 {
led@3 {
label = "beagle-x15:usr3";
gpios = <&gpio7 15 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
default-state = "off";
};
};
......
......@@ -26,7 +26,7 @@ gpio-leds {
blue-sata {
label = "ns2:blue:sata";
gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
};
};
......
......@@ -129,7 +129,7 @@ &pmx_led_sys_blue &pmx_led_wifi_green
disk {
label = "topkick:yellow:disk";
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
system2 {
label = "topkick:red:system";
......
......@@ -76,7 +76,7 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_LOCOMO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
# CONFIG_DNOTIFY is not set
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
......
......@@ -180,7 +180,7 @@ CONFIG_LEDS_FSG=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_ISL1208=y
......
......@@ -288,7 +288,7 @@ static struct gpio_led evm_leds[] = {
{ .name = "DS2", .active_low = 1,
.default_trigger = "mmc0", },
{ .name = "DS1", .active_low = 1,
.default_trigger = "ide-disk", },
.default_trigger = "disk-activity", },
};
static const struct gpio_led_platform_data evm_led_data = {
......
......@@ -172,7 +172,7 @@ static struct gpio_led tps_leds[] = {
* Also, D9 requires non-battery power.
*/
{ .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9",
.default_trigger = "ide-disk", },
.default_trigger = "disk-activity", },
{ .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
{ .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
.default_trigger = "heartbeat", },
......
......@@ -464,7 +464,7 @@ static struct gpio_led spitz_gpio_leds[] = {
},
{
.name = "spitz:green:hddactivity",
.default_trigger = "ide-disk",
.default_trigger = "disk-activity",
.gpio = SPITZ_GPIO_LED_GREEN,
},
};
......
......@@ -146,7 +146,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
......
......@@ -147,7 +147,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
......
......@@ -152,7 +152,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
......
......@@ -146,7 +146,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
......
......@@ -90,7 +90,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
......
......@@ -727,7 +727,7 @@ void __init txx9_iocled_init(unsigned long baseaddr,
int i;
static char *default_triggers[] __initdata = {
"heartbeat",
"ide-disk",
"disk-activity",
"nand-disk",
NULL,
};
......
......@@ -215,7 +215,7 @@ static int __init rbtx4939_led_probe(struct platform_device *pdev)
int i;
static char *default_triggers[] __initdata = {
"heartbeat",
"ide-disk",
"disk-activity",
"nand-disk",
};
......
......@@ -214,7 +214,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_DMADEVICES=y
......
......@@ -231,7 +231,7 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_LEDS_TRIGGER_BACKLIGHT=m
CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
......
......@@ -472,7 +472,7 @@ pwr {
hdd {
gpios = <&mcu_pio 1 0>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
};
};
......@@ -496,7 +496,7 @@ pwr {
hdd {
gpios = <&mcu_pio 1 0>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
};
};
......@@ -480,7 +480,7 @@ pwr {
hdd {
gpios = <&mcu_pio 1 0>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
};
};
......@@ -446,7 +446,7 @@ pwr {
hdd {
gpios = <&mcu_pio 1 0>;
linux,default-trigger = "ide-disk";
linux,default-trigger = "disk-activity";
};
};
};
......@@ -158,7 +158,7 @@ CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_PMU=y
CONFIG_ADB_PMU_LED=y
CONFIG_ADB_PMU_LED_IDE=y
CONFIG_ADB_PMU_LED_DISK=y
CONFIG_PMAC_APM_EMU=m
CONFIG_PMAC_MEDIABAY=y
CONFIG_PMAC_BACKLIGHT=y
......
......@@ -442,7 +442,7 @@ CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_PMU=y
CONFIG_ADB_PMU_LED=y
CONFIG_ADB_PMU_LED_IDE=y
CONFIG_ADB_PMU_LED_DISK=y
CONFIG_PMAC_APM_EMU=y
CONFIG_PMAC_MEDIABAY=y
CONFIG_PMAC_BACKLIGHT=y
......
......@@ -161,7 +161,7 @@ CONFIG_LEDS_GPIO=y
# LED Triggers
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
# Real Time Clock
......
......@@ -27,7 +27,7 @@ static const struct gpio_led puv3_gpio_leds[] = {
{ .name = "cpuhealth", .gpio = GPO_CPU_HEALTH, .active_low = 0,
.default_trigger = "heartbeat", },
{ .name = "hdd_led", .gpio = GPO_HDD_LED, .active_low = 1,
.default_trigger = "ide-disk", },
.default_trigger = "disk-activity", },
};
static const struct gpio_led_platform_data puv3_gpio_led_data = {
......
......@@ -122,7 +122,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
......
......@@ -69,6 +69,7 @@
#include <asm/unaligned.h>
#include <linux/cdrom.h>
#include <linux/ratelimit.h>
#include <linux/leds.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
......@@ -5078,6 +5079,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
/* Trigger the LED (if available) */
ledtrig_disk_activity();
/* XXX: New EH and old EH use different mechanisms to
* synchronize EH with regular execution path.
*
......
......@@ -186,7 +186,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
BUG_ON(rq->cmd_type != REQ_TYPE_FS);
ledtrig_ide_activity();
ledtrig_disk_activity();
pr_debug("%s: %sing: block=%llu, sectors=%u\n",
drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
......
......@@ -228,6 +228,20 @@ config LEDS_LP3944
To compile this driver as a module, choose M here: the
module will be called leds-lp3944.
config LEDS_LP3952
tristate "LED Support for TI LP3952 2 channel LED driver"
depends on LEDS_CLASS
depends on I2C
depends on ACPI
depends on GPIOLIB
select REGMAP_I2C
help
This option enables support for LEDs connected to the Texas
Instruments LP3952 LED driver.
To compile this driver as a module, choose M here: the
module will be called leds-lp3952.
config LEDS_LP55XX_COMMON
tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
......
......@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o
obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o
obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
......
......@@ -60,6 +60,8 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
goto unlock;
}
}
/* we come here only if buf matches no trigger */
ret = -EINVAL;
up_read(&triggers_list_lock);
unlock:
......
......@@ -165,6 +165,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
return ERR_PTR(-ENOMEM);
device_for_each_child_node(dev, child) {
struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];
struct gpio_led led = {};
const char *state = NULL;
......@@ -205,12 +206,12 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
ret = create_gpio_led(&led, &priv->leds[priv->num_leds],
dev, NULL);
ret = create_gpio_led(&led, led_dat, dev, NULL);
if (ret < 0) {
fwnode_handle_put(child);
goto err;
}
led_dat->cdev.dev->of_node = np;
priv->num_leds++;
}
......
......@@ -50,7 +50,7 @@ static struct led_classdev hp6xx_red_led = {
static struct led_classdev hp6xx_green_led = {
.name = "hp6xx:green",
.default_trigger = "ide-disk",
.default_trigger = "disk-activity",
.brightness_set = hp6xxled_green_set,
.flags = LED_CORE_SUSPENDRESUME,
};
......
......@@ -422,7 +422,7 @@ static int is31fl32xx_parse_dt(struct device *dev,
return ret;
}
static const struct of_device_id of_is31fl31xx_match[] = {
static const struct of_device_id of_is31fl32xx_match[] = {
{ .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, },
{ .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, },
{ .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, },
......@@ -432,7 +432,7 @@ static const struct of_device_id of_is31fl31xx_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, of_is31fl31xx_match);
MODULE_DEVICE_TABLE(of, of_is31fl32xx_match);
static int is31fl32xx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
......@@ -444,7 +444,7 @@ static int is31fl32xx_probe(struct i2c_client *client,
int count;
int ret = 0;
of_dev_id = of_match_device(of_is31fl31xx_match, dev);
of_dev_id = of_match_device(of_is31fl32xx_match, dev);
if (!of_dev_id)
return -EINVAL;
......@@ -482,23 +482,29 @@ static int is31fl32xx_remove(struct i2c_client *client)
}
/*
* i2c-core requires that id_table be non-NULL, even though
* it is not used for DeviceTree based instantiation.
* i2c-core (and modalias) requires that id_table be properly filled,
* even though it is not used for DeviceTree based instantiation.
*/
static const struct i2c_device_id is31fl31xx_id[] = {
static const struct i2c_device_id is31fl32xx_id[] = {
{ "is31fl3236" },
{ "is31fl3235" },
{ "is31fl3218" },
{ "sn3218" },
{ "is31fl3216" },
{ "sn3216" },
{},
};
MODULE_DEVICE_TABLE(i2c, is31fl31xx_id);
MODULE_DEVICE_TABLE(i2c, is31fl32xx_id);
static struct i2c_driver is31fl32xx_driver = {
.driver = {
.name = "is31fl32xx",
.of_match_table = of_is31fl31xx_match,
.of_match_table = of_is31fl32xx_match,
},
.probe = is31fl32xx_probe,
.remove = is31fl32xx_remove,
.id_table = is31fl31xx_id,
.id_table = is31fl32xx_id,
};
module_i2c_driver(is31fl32xx_driver);
......
/*
* LED driver for TI lp3952 controller
*
* Copyright (C) 2016, DAQRI, LLC.
* Author: Tony Makkiel <tony.makkiel@daqri.com>
*
* 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/acpi.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/leds-lp3952.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
static int lp3952_register_write(struct i2c_client *client, u8 reg, u8 val)
{
int ret;
struct lp3952_led_array *priv = i2c_get_clientdata(client);
ret = regmap_write(priv->regmap, reg, val);
if (ret)
dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n",
__func__, reg, val, ret);
return ret;
}
static void lp3952_on_off(struct lp3952_led_array *priv,
enum lp3952_leds led_id, bool on)
{
int ret, val;
dev_dbg(&priv->client->dev, "%s LED %d to %d\n", __func__, led_id, on);
val = 1 << led_id;
if (led_id == LP3952_LED_ALL)
val = LP3952_LED_MASK_ALL;
ret = regmap_update_bits(priv->regmap, LP3952_REG_LED_CTRL, val,
on ? val : 0);
if (ret)
dev_err(&priv->client->dev, "%s, Error %d\n", __func__, ret);
}
/*
* Using Imax to control brightness. There are 4 possible
* setting 25, 50, 75 and 100 % of Imax. Possible values are
* values 0-4. 0 meaning turn off.
*/
static int lp3952_set_brightness(struct led_classdev *cdev,
enum led_brightness value)
{
unsigned int reg, shift_val;
struct lp3952_ctrl_hdl *led = container_of(cdev,
struct lp3952_ctrl_hdl,
cdev);
struct lp3952_led_array *priv = (struct lp3952_led_array *)led->priv;
dev_dbg(cdev->dev, "Brightness request: %d on %d\n", value,
led->channel);
if (value == LED_OFF) {
lp3952_on_off(priv, led->channel, false);
return 0;
}
if (led->channel > LP3952_RED_1) {
dev_err(cdev->dev, " %s Invalid LED requested", __func__);
return -EINVAL;
}
if (led->channel >= LP3952_BLUE_1) {
reg = LP3952_REG_RGB1_MAX_I_CTRL;
shift_val = (led->channel - LP3952_BLUE_1) * 2;
} else {
reg = LP3952_REG_RGB2_MAX_I_CTRL;
shift_val = led->channel * 2;
}
/* Enable the LED in case it is not enabled already */
lp3952_on_off(priv, led->channel, true);
return regmap_update_bits(priv->regmap, reg, 3 << shift_val,
--value << shift_val);
}
static int lp3952_get_label(struct device *dev, const char *label, char *dest)
{
int ret;
const char *str;
ret = device_property_read_string(dev, label, &str);
if (!ret)
strncpy(dest, str, LP3952_LABEL_MAX_LEN);
return ret;
}
static int lp3952_register_led_classdev(struct lp3952_led_array *priv)
{
int i, acpi_ret, ret = -ENODEV;
static const char *led_name_hdl[LP3952_LED_ALL] = {
"blue2",
"green2",
"red2",
"blue1",
"green1",
"red1"
};
for (i = 0; i < LP3952_LED_ALL; i++) {
acpi_ret = lp3952_get_label(&priv->client->dev, led_name_hdl[i],
priv->leds[i].name);
if (acpi_ret)
continue;
priv->leds[i].cdev.name = priv->leds[i].name;
priv->leds[i].cdev.brightness = LED_OFF;
priv->leds[i].cdev.max_brightness = LP3952_BRIGHT_MAX;
priv->leds[i].cdev.brightness_set_blocking =
lp3952_set_brightness;
priv->leds[i].channel = i;
priv->leds[i].priv = priv;
ret = devm_led_classdev_register(&priv->client->dev,
&priv->leds[i].cdev);
if (ret < 0) {
dev_err(&priv->client->dev,
"couldn't register LED %s\n",
priv->leds[i].cdev.name);
break;
}
}
return ret;
}
static int lp3952_set_pattern_gen_cmd(struct lp3952_led_array *priv,
u8 cmd_index, u8 r, u8 g, u8 b,
enum lp3952_tt tt, enum lp3952_cet cet)
{
int ret;
struct ptrn_gen_cmd line = {
{
{
.r = r,
.g = g,
.b = b,
.cet = cet,
.tt = tt
}
}
};
if (cmd_index >= LP3952_CMD_REG_COUNT)
return -EINVAL;
ret = lp3952_register_write(priv->client,
LP3952_REG_CMD_0 + cmd_index * 2,
line.bytes.msb);
if (ret)
return ret;
return lp3952_register_write(priv->client,
LP3952_REG_CMD_0 + cmd_index * 2 + 1,
line.bytes.lsb);
}
static int lp3952_configure(struct lp3952_led_array *priv)
{
int ret;
/* Disable any LEDs on from any previous conf. */
ret = lp3952_register_write(priv->client, LP3952_REG_LED_CTRL, 0);
if (ret)
return ret;
/* enable rgb patter, loop */
ret = lp3952_register_write(priv->client, LP3952_REG_PAT_GEN_CTRL,
LP3952_PATRN_LOOP | LP3952_PATRN_GEN_EN);
if (ret)
return ret;
/* Update Bit 6 (Active mode), Select both Led sets, Bit [1:0] */
ret = lp3952_register_write(priv->client, LP3952_REG_ENABLES,
LP3952_ACTIVE_MODE | LP3952_INT_B00ST_LDR);
if (ret)
return ret;
/* Set Cmd1 for RGB intensity,cmd and transition time */
return lp3952_set_pattern_gen_cmd(priv, 0, I46, I71, I100, TT0,
CET197);
}
static const struct regmap_config lp3952_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = REG_MAX,
.cache_type = REGCACHE_RBTREE,
};
static int lp3952_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
struct lp3952_led_array *priv;
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->client = client;
priv->enable_gpio = devm_gpiod_get(&client->dev, "nrst",
GPIOD_OUT_HIGH);
if (IS_ERR(priv->enable_gpio)) {
status = PTR_ERR(priv->enable_gpio);
dev_err(&client->dev, "Failed to enable gpio: %d\n", status);
return status;
}
priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap);
if (IS_ERR(priv->regmap)) {
int err = PTR_ERR(priv->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
err);
return err;
}
i2c_set_clientdata(client, priv);
status = lp3952_configure(priv);
if (status) {
dev_err(&client->dev, "Probe failed. Device not found (%d)\n",
status);
return status;
}
status = lp3952_register_led_classdev(priv);
if (status) {
dev_err(&client->dev, "Unable to register led_classdev: %d\n",
status);
return status;
}
return 0;
}
static int lp3952_remove(struct i2c_client *client)
{
struct lp3952_led_array *priv;
priv = i2c_get_clientdata(client);
lp3952_on_off(priv, LP3952_LED_ALL, false);
gpiod_set_value(priv->enable_gpio, 0);
return 0;
}
static const struct i2c_device_id lp3952_id[] = {
{LP3952_NAME, 0},
{}
};
#ifdef CONFIG_ACPI
static const struct acpi_device_id lp3952_acpi_match[] = {
{"TXNW3952", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, lp3952_acpi_match);
#endif
static struct i2c_driver lp3952_i2c_driver = {
.driver = {
.name = LP3952_NAME,
.acpi_match_table = ACPI_PTR(lp3952_acpi_match),
},
.probe = lp3952_probe,
.remove = lp3952_remove,
.id_table = lp3952_id,
};
module_i2c_driver(lp3952_i2c_driver);
MODULE_AUTHOR("Tony Makkiel <tony.makkiel@daqri.com>");
MODULE_DESCRIPTION("lp3952 I2C LED controller driver");
MODULE_LICENSE("GPL v2");
......@@ -21,6 +21,8 @@
#include <linux/workqueue.h>
#include <linux/leds-pca9532.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_device.h>
/* m = num_leds*/
#define PCA9532_REG_INPUT(i) ((i) >> 3)
......@@ -86,9 +88,22 @@ static const struct pca9532_chip_info pca9532_chip_info_tbl[] = {
},
};
#ifdef CONFIG_OF
static const struct of_device_id of_pca9532_leds_match[] = {
{ .compatible = "nxp,pca9530", .data = (void *)pca9530 },
{ .compatible = "nxp,pca9531", .data = (void *)pca9531 },
{ .compatible = "nxp,pca9532", .data = (void *)pca9532 },
{ .compatible = "nxp,pca9533", .data = (void *)pca9533 },
{},
};
MODULE_DEVICE_TABLE(of, of_pca9532_leds_match);
#endif
static struct i2c_driver pca9532_driver = {
.driver = {
.name = "leds-pca953x",
.of_match_table = of_match_ptr(of_pca9532_leds_match),
},
.probe = pca9532_probe,
.remove = pca9532_remove,
......@@ -354,6 +369,7 @@ static int pca9532_configure(struct i2c_client *client,
led->state = pled->state;
led->name = pled->name;
led->ldev.name = led->name;
led->ldev.default_trigger = led->default_trigger;
led->ldev.brightness = LED_OFF;
led->ldev.brightness_set_blocking =
pca9532_set_brightness;
......@@ -432,15 +448,66 @@ static int pca9532_configure(struct i2c_client *client,
return err;
}
static struct pca9532_platform_data *
pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
{
struct pca9532_platform_data *pdata;
struct device_node *child;
const struct of_device_id *match;
int devid, maxleds;
int i = 0;
match = of_match_device(of_pca9532_leds_match, dev);
if (!match)
return ERR_PTR(-ENODEV);
devid = (int)(uintptr_t)match->data;
maxleds = pca9532_chip_info_tbl[devid].num_leds;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
for_each_child_of_node(np, child) {
if (of_property_read_string(child, "label",
&pdata->leds[i].name))
pdata->leds[i].name = child->name;
of_property_read_u32(child, "type", &pdata->leds[i].type);
of_property_read_string(child, "linux,default-trigger",
&pdata->leds[i].default_trigger);
if (++i >= maxleds) {
of_node_put(child);
break;
}
}
return pdata;
}
static int pca9532_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int devid;
struct pca9532_data *data = i2c_get_clientdata(client);
struct pca9532_platform_data *pca9532_pdata =
dev_get_platdata(&client->dev);
if (!pca9532_pdata)
return -EIO;
struct device_node *np = client->dev.of_node;
if (!pca9532_pdata) {
if (np) {
pca9532_pdata =
pca9532_of_populate_pdata(&client->dev, np);
if (IS_ERR(pca9532_pdata))
return PTR_ERR(pca9532_pdata);
} else {
dev_err(&client->dev, "no platform data\n");
return -EINVAL;
}
devid = (int)(uintptr_t)of_match_device(
of_pca9532_leds_match, &client->dev)->data;
} else {
devid = id->driver_data;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
......@@ -450,7 +517,7 @@ static int pca9532_probe(struct i2c_client *client,
if (!data)
return -ENOMEM;
data->chip_info = &pca9532_chip_info_tbl[id->driver_data];
data->chip_info = &pca9532_chip_info_tbl[devid];
dev_info(&client->dev, "setting platform data\n");
i2c_set_clientdata(client, data);
......
......@@ -33,12 +33,12 @@ config LEDS_TRIGGER_ONESHOT
If unsure, say Y.
config LEDS_TRIGGER_IDE_DISK
bool "LED IDE Disk Trigger"
depends on IDE_GD_ATA
config LEDS_TRIGGER_DISK
bool "LED Disk Trigger"
depends on IDE_GD_ATA || ATA
depends on LEDS_TRIGGERS
help
This allows LEDs to be controlled by IDE disk activity.
This allows LEDs to be controlled by disk activity.
If unsure, say Y.
config LEDS_TRIGGER_MTD
......
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
obj-$(CONFIG_LEDS_TRIGGER_DISK) += ledtrig-disk.o
obj-$(CONFIG_LEDS_TRIGGER_MTD) += ledtrig-mtd.o
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
......
/*
* LED IDE-Disk Activity Trigger
* LED Disk Activity Trigger
*
* Copyright 2006 Openedhand Ltd.
*
......@@ -17,20 +17,25 @@
#define BLINK_DELAY 30
DEFINE_LED_TRIGGER(ledtrig_disk);
DEFINE_LED_TRIGGER(ledtrig_ide);
void ledtrig_ide_activity(void)
void ledtrig_disk_activity(void)
{
unsigned long ide_blink_delay = BLINK_DELAY;
unsigned long blink_delay = BLINK_DELAY;
led_trigger_blink_oneshot(ledtrig_disk,
&blink_delay, &blink_delay, 0);
led_trigger_blink_oneshot(ledtrig_ide,
&ide_blink_delay, &ide_blink_delay, 0);
&blink_delay, &blink_delay, 0);
}
EXPORT_SYMBOL(ledtrig_ide_activity);
EXPORT_SYMBOL(ledtrig_disk_activity);
static int __init ledtrig_ide_init(void)
static int __init ledtrig_disk_init(void)
{
led_trigger_register_simple("disk-activity", &ledtrig_disk);
led_trigger_register_simple("ide-disk", &ledtrig_ide);
return 0;
}
device_initcall(ledtrig_ide_init);
device_initcall(ledtrig_disk_init);
......@@ -96,19 +96,18 @@ config ADB_PMU_LED
Support the front LED on Power/iBooks as a generic LED that can
be triggered by any of the supported triggers. To get the
behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this
and the ide-disk LED trigger and configure appropriately through
sysfs.
and the disk LED trigger and configure appropriately through sysfs.
config ADB_PMU_LED_IDE
bool "Use front LED as IDE LED by default"
config ADB_PMU_LED_DISK
bool "Use front LED as DISK LED by default"
depends on ADB_PMU_LED
depends on LEDS_CLASS
depends on IDE_GD_ATA
select LEDS_TRIGGERS
select LEDS_TRIGGER_IDE_DISK
select LEDS_TRIGGER_DISK
help
This option makes the front LED default to the IDE trigger
so that it blinks on IDE activity.
This option makes the front LED default to the disk trigger
so that it blinks on disk activity.
config PMAC_SMU
bool "Support for SMU based PowerMacs"
......
......@@ -73,8 +73,8 @@ static void pmu_led_set(struct led_classdev *led_cdev,
static struct led_classdev pmu_led = {
.name = "pmu-led::front",
#ifdef CONFIG_ADB_PMU_LED_IDE
.default_trigger = "ide-disk",
#ifdef CONFIG_ADB_PMU_LED_DISK
.default_trigger = "disk-activity",
#endif
.brightness_set = pmu_led_set,
};
......
/*
* This header provides constants for pca9532 LED bindings.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef _DT_BINDINGS_LEDS_PCA9532_H
#define _DT_BINDINGS_LEDS_PCA9532_H
#define PCA9532_TYPE_NONE 0
#define PCA9532_TYPE_LED 1
#define PCA9532_TYPE_N2100_BEEP 2
#define PCA9532_TYPE_GPIO 3
#define PCA9532_LED_TIMER2 4
#endif /* _DT_BINDINGS_LEDS_PCA9532_H */
/*
* LED driver for TI lp3952 controller
*
* Copyright (C) 2016, DAQRI, LLC.
* Author: Tony Makkiel <tony.makkiel@daqri.com>
*
* 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.
*
*/
#ifndef LEDS_LP3952_H_
#define LEDS_LP3952_H_
#define LP3952_NAME "lp3952"
#define LP3952_CMD_REG_COUNT 8
#define LP3952_BRIGHT_MAX 4
#define LP3952_LABEL_MAX_LEN 15
#define LP3952_REG_LED_CTRL 0x00
#define LP3952_REG_R1_BLNK_TIME_CTRL 0x01
#define LP3952_REG_R1_BLNK_CYCLE_CTRL 0x02
#define LP3952_REG_G1_BLNK_TIME_CTRL 0x03
#define LP3952_REG_G1_BLNK_CYCLE_CTRL 0x04
#define LP3952_REG_B1_BLNK_TIME_CTRL 0x05
#define LP3952_REG_B1_BLNK_CYCLE_CTRL 0x06
#define LP3952_REG_ENABLES 0x0B
#define LP3952_REG_PAT_GEN_CTRL 0x11
#define LP3952_REG_RGB1_MAX_I_CTRL 0x12
#define LP3952_REG_RGB2_MAX_I_CTRL 0x13
#define LP3952_REG_CMD_0 0x50
#define LP3952_REG_RESET 0x60
#define REG_MAX LP3952_REG_RESET
#define LP3952_PATRN_LOOP BIT(1)
#define LP3952_PATRN_GEN_EN BIT(2)
#define LP3952_INT_B00ST_LDR BIT(2)
#define LP3952_ACTIVE_MODE BIT(6)
#define LP3952_LED_MASK_ALL 0x3f
/* Transition Time in ms */
enum lp3952_tt {
TT0,
TT55,
TT110,
TT221,
TT422,
TT885,
TT1770,
TT3539
};
/* Command Execution Time in ms */
enum lp3952_cet {
CET197,
CET393,
CET590,
CET786,
CET1180,
CET1376,
CET1573,
CET1769,
CET1966,
CET2163,
CET2359,
CET2556,
CET2763,
CET2949,
CET3146
};
/* Max Current in % */
enum lp3952_colour_I_log_0 {
I0,
I7,
I14,
I21,
I32,
I46,
I71,
I100
};
enum lp3952_leds {
LP3952_BLUE_2,
LP3952_GREEN_2,
LP3952_RED_2,
LP3952_BLUE_1,
LP3952_GREEN_1,
LP3952_RED_1,
LP3952_LED_ALL
};
struct lp3952_ctrl_hdl {
struct led_classdev cdev;
char name[LP3952_LABEL_MAX_LEN];
enum lp3952_leds channel;
void *priv;
};
struct ptrn_gen_cmd {
union {
struct {
u16 tt:3;
u16 b:3;
u16 cet:4;
u16 g:3;
u16 r:3;
};
struct {
u8 lsb;
u8 msb;
} bytes;
};
} __packed;
struct lp3952_led_array {
struct regmap *regmap;
struct i2c_client *client;
struct gpio_desc *enable_gpio;
struct lp3952_ctrl_hdl leds[LP3952_LED_ALL];
};
#endif /* LEDS_LP3952_H_ */
......@@ -16,6 +16,7 @@
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <dt-bindings/leds/leds-pca9532.h>
enum pca9532_state {
PCA9532_OFF = 0x0,
......@@ -24,16 +25,14 @@ enum pca9532_state {
PCA9532_PWM1 = 0x3
};
enum pca9532_type { PCA9532_TYPE_NONE, PCA9532_TYPE_LED,
PCA9532_TYPE_N2100_BEEP, PCA9532_TYPE_GPIO };
struct pca9532_led {
u8 id;
struct i2c_client *client;
char *name;
const char *name;
const char *default_trigger;
struct led_classdev ldev;
struct work_struct work;
enum pca9532_type type;
u32 type;
enum pca9532_state state;
};
......
......@@ -325,10 +325,10 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
#endif /* CONFIG_LEDS_TRIGGERS */
/* Trigger specific functions */
#ifdef CONFIG_LEDS_TRIGGER_IDE_DISK
extern void ledtrig_ide_activity(void);
#ifdef CONFIG_LEDS_TRIGGER_DISK
extern void ledtrig_disk_activity(void);
#else
static inline void ledtrig_ide_activity(void) {}
static inline void ledtrig_disk_activity(void) {}
#endif
#ifdef CONFIG_LEDS_TRIGGER_MTD
......@@ -387,8 +387,16 @@ struct gpio_led_platform_data {
unsigned long *delay_off);
};
#ifdef CONFIG_NEW_LEDS
struct platform_device *gpio_led_register_device(
int id, const struct gpio_led_platform_data *pdata);
#else
static inline struct platform_device *gpio_led_register_device(
int id, const struct gpio_led_platform_data *pdata)
{
return 0;
}
#endif
enum cpu_led_event {
CPU_LED_IDLE_START, /* CPU enters idle */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment