diff options
author | Chaitanya Bandi <bandik@nvidia.com> | 2012-09-05 13:36:08 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:34:15 -0700 |
commit | 4f4cc3907e28470f3b6a65482a95a9b4730af272 (patch) | |
tree | 661632a592001cde9d821d6ffe20812c38546b55 /drivers/leds | |
parent | ff237d9405c0bff826db99e1cf121f1476b7da20 (diff) |
leds: max8831: Add led support for MAX8831
Added led driver support for MAX8831
Bug 1034472
Change-Id: I15e24f312ce4da725b5cddb916f74920c3c602b1
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/131319
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: Gerrit_Virtual_Submit
Rebase-Id: R879a212b8570f44fddeede2e1d3ebc776aa377b1
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 7 | ||||
-rw-r--r-- | drivers/leds/Makefile | 3 | ||||
-rw-r--r-- | drivers/leds/leds-max8831.c | 206 |
3 files changed, 216 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index ef992293598a..f6c6a5875d67 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -24,6 +24,13 @@ config LEDS_CLASS comment "LED drivers" +config LEDS_MAX8831 + tristate "LED Support for Maxim MAX8831" + depends on LEDS_CLASS + help + This option enables the led support for Maxim LED + controller MAX8831. + config LEDS_88PM860X tristate "LED Support for Marvell 88PM860x PMIC" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index ac2897732b02..7c12d1b70f4a 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o + # LED Platform Drivers obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o @@ -54,6 +55,8 @@ obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o +obj-$(CONFIG_LEDS_MAX8831) += leds-max8831.o + # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-max8831.c b/drivers/leds/leds-max8831.c new file mode 100644 index 000000000000..0ae7fe7bd2a8 --- /dev/null +++ b/drivers/leds/leds-max8831.c @@ -0,0 +1,206 @@ +/* + * LEDs driver for MAX8831 + * + * Copyright (c) 2008-2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <linux/workqueue.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/leds.h> +#include <linux/ctype.h> +#include <linux/mfd/max8831.h> +#include <linux/delay.h> + +struct max8831_led { + struct led_classdev cdev; + struct work_struct work; + enum led_brightness new_brightness; + struct device *master; + int id; +}; + +static void max8831_led_work(struct work_struct *work) +{ + struct max8831_led *led = container_of(work, struct max8831_led, work); + unsigned int on_off_addr = MAX8831_CTRL; + unsigned int blink_reg = 0; + unsigned int curr_ctrl_reg = 0; + unsigned int led_enb_mask = 0; + + on_off_addr = MAX8831_CTRL; + + switch (led->id) { + case MAX8831_ID_LED1: + curr_ctrl_reg = MAX8831_CURRENT_CTRL_LED1; + led_enb_mask = MAX8831_CTRL_LED1_ENB; + break; + case MAX8831_ID_LED2: + curr_ctrl_reg = MAX8831_CURRENT_CTRL_LED2; + led_enb_mask = MAX8831_CTRL_LED2_ENB; + break; + case MAX8831_ID_LED3: + curr_ctrl_reg = MAX8831_CURRENT_CTRL_LED3; + led_enb_mask = MAX8831_CTRL_LED3_ENB; + blink_reg = MAX8831_BLINK_CTRL_LED3; + break; + case MAX8831_ID_LED4: + curr_ctrl_reg = MAX8831_CURRENT_CTRL_LED4; + led_enb_mask = MAX8831_CTRL_LED4_ENB; + blink_reg = MAX8831_BLINK_CTRL_LED4; + break; + case MAX8831_ID_LED5: + curr_ctrl_reg = MAX8831_CURRENT_CTRL_LED5; + led_enb_mask = MAX8831_CTRL_LED5_ENB; + blink_reg = MAX8831_BLINK_CTRL_LED5; + break; + } + + /* disable blinking */ + if (blink_reg) + max8831_update_bits(led->master, blink_reg, + MAX8831_BLINK_ENB, 0); + + if (led->new_brightness == 0) { + max8831_update_bits(led->master, on_off_addr, led_enb_mask, 0); + } else { + max8831_update_bits(led->master, on_off_addr, led_enb_mask, + led_enb_mask); + max8831_write(led->master, curr_ctrl_reg, led->new_brightness); + } +} + +static void max8831_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct max8831_led *led; + + led = container_of(led_cdev, struct max8831_led, cdev); + + led->new_brightness = value; + /* + * Must use workqueue for the actual I/O since I2C operations + * can sleep. + */ + schedule_work(&led->work); +} + +static int max8831_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct max8831_led *led; + unsigned int reg_val = 0; + unsigned int reg = 0; + led = container_of(led_cdev, struct max8831_led, cdev); + + if (*delay_on == 256) + reg_val |= 0; + if (*delay_on == 512) + reg_val |= 1; + if (*delay_on == 1024) + reg_val |= 2; + if (*delay_on == 2048) + reg_val |= 3; + + if (*delay_off == 1024) + reg_val |= 0 << MAX8831_BLINK_OFF_TIMER_SHIFT; + if (*delay_off == 2048) + reg_val |= 1 << MAX8831_BLINK_OFF_TIMER_SHIFT; + if (*delay_off == 4096) + reg_val |= 2 << MAX8831_BLINK_OFF_TIMER_SHIFT; + if (*delay_off == 8192) + reg_val |= 3 << MAX8831_BLINK_OFF_TIMER_SHIFT; + + reg_val = reg_val | MAX8831_BLINK_ENB; + + if (led->id == MAX8831_ID_LED3) + reg = 0x17; + else if (led->id == MAX8831_ID_LED4) + reg = 0x18; + else if (led->id == MAX8831_ID_LED5) + reg = 0x19; + + max8831_led_set(&led->cdev, MAX8831_KEY_LEDS_MAX_CURR); + max8831_write(led->master, reg, reg_val); + return 0; +} + +static int __devinit max8831_led_probe(struct platform_device *pdev) +{ + struct led_info *pdata = pdev->dev.platform_data; + struct max8831_led *led; + int err; + + if (!pdata) + return -ENODEV; + + led = devm_kzalloc(&pdev->dev, + sizeof(struct max8831_led), GFP_KERNEL); + + led->cdev.name = pdata->name; + led->cdev.brightness_set = max8831_led_set; + + led->id = pdev->id; + led->new_brightness = LED_OFF; + led->master = pdev->dev.parent; + + if (led->id > 1) { + led->cdev.blink_set = max8831_led_set_blink; + led->cdev.max_brightness = MAX8831_KEY_LEDS_MAX_CURR; + } else { + led->cdev.max_brightness = MAX8831_BL_LEDS_MAX_CURR; + } + + err = led_classdev_register(led->master, &led->cdev); + if (err < 0) + return err; + + + INIT_WORK(&led->work, max8831_led_work); + platform_set_drvdata(pdev, led); + return 0; +} + +static int __devexit max8831_led_remove(struct platform_device *pdev) +{ + struct max8831_led *led = platform_get_drvdata(pdev); + led_classdev_unregister(&led->cdev); + cancel_work_sync(&led->work); + return 0; +} + +static struct platform_driver max8831_led_driver = { + .driver = { + .name = "max8831_led_bl", + .owner = THIS_MODULE, + }, + .probe = max8831_led_probe, + .remove = __devexit_p(max8831_led_remove), +}; +module_platform_driver(max8831_led_driver); + +MODULE_AUTHOR("Chaitanya Bandi<bandik@nvidia.com>"); +MODULE_DESCRIPTION("MAX8831 LED driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max8831-led"); |