From d2213b44d835747843fc8723ce46bddf738250db Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 27 May 2010 13:41:02 -0500 Subject: [PATCH] leds: CPCAP LED driver initial submission Initial submission of the Home key LED code. Code was ported from Sholes and updated with a work queue Change-Id: Ib25313471cd21fb941b8fa4ecab3811b6ef35d74 Signed-off-by: Dan Murphy --- drivers/leds/Kconfig | 6 + drivers/leds/Makefile | 1 + drivers/leds/leds-ld-cpcap-disp.c | 186 ++++++++++++++++++++++++++++++ include/linux/leds-ld-cpcap.h | 55 +++++++++ 4 files changed, 248 insertions(+) create mode 100755 drivers/leds/leds-ld-cpcap-disp.c create mode 100644 include/linux/leds-ld-cpcap.h diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 8e37852364f8..79a73be5e836 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -144,6 +144,12 @@ config LEDS_AUO_PANEL help This option enables support for AUO display backlight driver +config LEDS_CPCAP_DISP + tristate "LED Support for Display LEDS connected to CPCAP" + depends on LEDS_CLASS && MFD_CPCAP + help + This option enables support for display LEDs connected to CPCAP + config LEDS_GPIO tristate "LED Support for GPIO connected LEDs" depends on GENERIC_GPIO diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 19b63453d0d7..ac8203b3f07f 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o obj-$(CONFIG_LEDS_NS2) += leds-ns2.o obj-$(CONFIG_LEDS_AUO_PANEL) += leds-auo-panel-backlight.o +obj-$(CONFIG_LEDS_CPCAP_DISP) += leds-ld-cpcap-disp.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-ld-cpcap-disp.c b/drivers/leds/leds-ld-cpcap-disp.c new file mode 100755 index 000000000000..564e927b92cb --- /dev/null +++ b/drivers/leds/leds-ld-cpcap-disp.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009 Motorola, Inc. + * + * This program is free dispware; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free dispware Foundation. + * + * 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 dispware + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct disp_button_led_data { + struct led_classdev disp_button_class_dev; + struct cpcap_device *cpcap; + struct regulator *regulator; + struct work_struct brightness_work; + enum led_brightness brightness; + int regulator_state; +}; + +static void disp_button_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct disp_button_led_data *disp_button_led_data = + container_of(led_cdev, struct disp_button_led_data, + disp_button_class_dev); + + if (brightness > 255) + brightness = 255; + + disp_button_led_data->brightness = brightness; + schedule_work(&disp_button_led_data->brightness_work); +} +EXPORT_SYMBOL(disp_button_set); + +static void disp_button_brightness_work(struct work_struct *work) +{ + int cpcap_status = 0; + unsigned short brightness = 0; + + struct disp_button_led_data *disp_button_led_data = + container_of(work, struct disp_button_led_data, brightness_work); + + brightness = disp_button_led_data->brightness; + + if (brightness > 0) { + brightness = (LD_DISP_BUTTON_DUTY_CYCLE | + LD_DISP_BUTTON_CURRENT | LD_DISP_BUTTON_ON); + + if ((disp_button_led_data->regulator) && + (disp_button_led_data->regulator_state == 0)) { + regulator_enable(disp_button_led_data->regulator); + disp_button_led_data->regulator_state = 1; + } + + cpcap_status = cpcap_regacc_write(disp_button_led_data->cpcap, + CPCAP_REG_KLC, + brightness, + LD_DISP_BUTTON_CPCAP_MASK); + + if (cpcap_status < 0) + pr_err("%s: Writing to the register failed for %i\n", + __func__, cpcap_status); + + } else { + if ((disp_button_led_data->regulator) && + (disp_button_led_data->regulator_state == 1)) { + regulator_disable(disp_button_led_data->regulator); + disp_button_led_data->regulator_state = 0; + } + /* Due to a HW issue turn off the current then + turn off the duty cycle */ + brightness = 0x01; + cpcap_status = cpcap_regacc_write(disp_button_led_data->cpcap, + CPCAP_REG_KLC, brightness, + LD_DISP_BUTTON_CPCAP_MASK); + + brightness = 0x00; + cpcap_status = cpcap_regacc_write(disp_button_led_data->cpcap, + CPCAP_REG_KLC, brightness, + LD_DISP_BUTTON_CPCAP_MASK); + + if (cpcap_status < 0) + pr_err("%s: Writing to the register failed for %i\n", + __func__, cpcap_status); + } +} + +static int disp_button_probe(struct platform_device *pdev) +{ + int ret = 0; + struct disp_button_led_data *info; + + if (pdev == NULL) { + pr_err("%s: platform data required\n", __func__); + return -ENODEV; + + } + info = kzalloc(sizeof(struct disp_button_led_data), GFP_KERNEL); + if (info == NULL) { + ret = -ENOMEM; + return ret; + } + + info->cpcap = pdev->dev.platform_data; + platform_set_drvdata(pdev, info); + + info->regulator = regulator_get(&pdev->dev, LD_SUPPLY); + if (IS_ERR(info->regulator)) { + pr_err("%s: Cannot get %s regulator\n", __func__, LD_SUPPLY); + ret = PTR_ERR(info->regulator); + goto exit_request_reg_failed; + + } + info->regulator_state = 0; + + info->disp_button_class_dev.name = "button-backlight"; + info->disp_button_class_dev.brightness_set = disp_button_set; + ret = led_classdev_register(&pdev->dev, &info->disp_button_class_dev); + if (ret < 0) { + pr_err("%s:Register button backlight class failed\n", __func__); + goto err_reg_button_class_failed; + } + INIT_WORK(&info->brightness_work, disp_button_brightness_work); + return ret; + +err_reg_button_class_failed: + if (info->regulator) + regulator_put(info->regulator); +exit_request_reg_failed: + kfree(info); + return ret; +} + +static int disp_button_remove(struct platform_device *pdev) +{ + struct disp_button_led_data *info = platform_get_drvdata(pdev); + + if (info->regulator) + regulator_put(info->regulator); + + led_classdev_unregister(&info->disp_button_class_dev); + return 0; +} + +static struct platform_driver ld_disp_button_driver = { + .probe = disp_button_probe, + .remove = disp_button_remove, + .driver = { + .name = LD_DISP_BUTTON_DEV, + }, +}; + +static int __init led_disp_button_init(void) +{ + return platform_driver_register(&ld_disp_button_driver); +} + +static void __exit led_disp_button_exit(void) +{ + platform_driver_unregister(&ld_disp_button_driver); +} + +module_init(led_disp_button_init); +module_exit(led_disp_button_exit); + +MODULE_DESCRIPTION("Display Button Lighting driver"); +MODULE_AUTHOR("Motorola"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds-ld-cpcap.h b/include/linux/leds-ld-cpcap.h new file mode 100644 index 000000000000..4881fb4fe8f0 --- /dev/null +++ b/include/linux/leds-ld-cpcap.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Motorola, Inc. + * + * This program is free dispware; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free dispware Foundation. + * + * 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 dispware + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#ifndef __LED_LD_CPCAP_H__ +#define __LED_LD_CPCAP_H__ + +#define LD_MSG_IND_DEV "notification-led" +#define LD_DISP_BUTTON_DEV "button-backlight" +#define LD_KPAD_DEV "keyboard-backlight" +#define LD_AF_LED_DEV "af-led" +#define LD_SUPPLY "sw5" + +#define LD_MSG_IND_ON 0x1 +#define LD_MSG_IND_CURRENT 0x2 +#define LD_MSG_IND_LO_CURRENT 0x0 + +#define LD_MSG_IND_CPCAP_MASK 0x3FF + +#define LD_MSG_IND_LOW 0x20 +#define LD_MSG_IND_LOW_MED 0x20 +#define LD_MSG_IND_MEDIUM 0x30 +#define LD_MSG_IND_MED_HIGH 0x40 +#define LD_MSG_IND_HIGH 0x50 + +#define LD_LED_RED 0x01 +#define LD_LED_GREEN 0x02 +#define LD_LED_BLUE 0x04 + +#define LD_DISP_BUTTON_ON 0x1 +#define LD_DISP_BUTTON_CURRENT 0x0 +#define LD_DISP_BUTTON_DUTY_CYCLE 0x2A0 +#define LD_DISP_BUTTON_CPCAP_MASK 0x3FF + +#define LD_BLED_CPCAP_DUTY_CYCLE 0x41 +#define LD_BLED_CPCAP_MASK 0x3FF +#define LD_BLED_CPCAP_CURRENT 0x6 + +#define LD_ALT_ADBL_CURRENT 0x4 + +#endif /* __LED_LD_CPCAP_H__ */ -- 2.34.1