From 8432c343221372d937b8030cca9efbd3aa506d54 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 2 Jun 2010 07:40:55 -0500 Subject: [PATCH] leds: Create generic CPCAP led driver Commonized the CPCAP LED driver into a single driver for all LEDs connected to the CPCAP. Change-Id: Ic62356010f3e1b355f7da757c3f08608765a71da Signed-off-by: Dan Murphy --- drivers/leds/Kconfig | 2 +- drivers/leds/Makefile | 2 +- drivers/leds/leds-ld-cpcap-disp.c | 186 ---------------------------- drivers/leds/leds-ld-cpcap.c | 197 ++++++++++++++++++++++++++++++ include/linux/leds-ld-cpcap.h | 62 +++++----- include/linux/spi/cpcap.h | 44 ------- 6 files changed, 230 insertions(+), 263 deletions(-) delete mode 100755 drivers/leds/leds-ld-cpcap-disp.c create mode 100755 drivers/leds/leds-ld-cpcap.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 79a73be5e836..8012334ab14b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -144,7 +144,7 @@ config LEDS_AUO_PANEL help This option enables support for AUO display backlight driver -config LEDS_CPCAP_DISP +config LEDS_CPCAP tristate "LED Support for Display LEDS connected to CPCAP" depends on LEDS_CLASS && MFD_CPCAP help diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index ac8203b3f07f..975a65694254 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -39,7 +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 +obj-$(CONFIG_LEDS_CPCAP) += leds-ld-cpcap.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 deleted file mode 100755 index 564e927b92cb..000000000000 --- a/drivers/leds/leds-ld-cpcap-disp.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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/drivers/leds/leds-ld-cpcap.c b/drivers/leds/leds-ld-cpcap.c new file mode 100755 index 000000000000..b0cebda0285f --- /dev/null +++ b/drivers/leds/leds-ld-cpcap.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2010 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 cpcap_led_data { + struct led_classdev cpcap_class_dev; + struct cpcap_device *cpcap; + struct cpcap_led *pdata; + struct regulator *regulator; + struct work_struct brightness_work; + enum led_brightness brightness; + int regulator_state; +}; + +static void cpcap_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct cpcap_led_data *cpcap_led_data = + container_of(led_cdev, struct cpcap_led_data, + cpcap_class_dev); + + if (brightness > 255) + brightness = 255; + + cpcap_led_data->brightness = brightness; + schedule_work(&cpcap_led_data->brightness_work); +} +EXPORT_SYMBOL(cpcap_set); + +static void cpcap_brightness_work(struct work_struct *work) +{ + int cpcap_status = 0; + unsigned short brightness = 0; + + struct cpcap_led_data *cpcap_led_data = + container_of(work, struct cpcap_led_data, brightness_work); + + brightness = cpcap_led_data->brightness; + + if (brightness > 0) { + brightness = (cpcap_led_data->pdata->cpcap_duty_cycle | + cpcap_led_data->pdata->cpcap_current | 0x01); + + if ((cpcap_led_data->regulator) && + (cpcap_led_data->regulator_state == 0)) { + regulator_enable(cpcap_led_data->regulator); + cpcap_led_data->regulator_state = 1; + } + + cpcap_status = cpcap_regacc_write(cpcap_led_data->cpcap, + cpcap_led_data->pdata->cpcap_register, + brightness, + cpcap_led_data->pdata->cpcap_mask); + + if (cpcap_status < 0) + pr_err("%s: Writing to the register failed for %i\n", + __func__, cpcap_status); + + } else { + if ((cpcap_led_data->regulator) && + (cpcap_led_data->regulator_state == 1)) { + regulator_disable(cpcap_led_data->regulator); + cpcap_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(cpcap_led_data->cpcap, + cpcap_led_data->pdata->cpcap_register, + brightness, + cpcap_led_data->pdata->cpcap_mask); + + + brightness = 0x00; + cpcap_status = cpcap_regacc_write(cpcap_led_data->cpcap, + cpcap_led_data->pdata->cpcap_register, + brightness, + cpcap_led_data->pdata->cpcap_mask); + + + if (cpcap_status < 0) + pr_err("%s: Writing to the register failed for %i\n", + __func__, cpcap_status); + } +} + +static int cpcap_probe(struct platform_device *pdev) +{ + int ret = 0; + struct cpcap_led_data *info; + + if (pdev == NULL) { + pr_err("%s: platform data required\n", __func__); + return -ENODEV; + + } + info = kzalloc(sizeof(struct cpcap_led_data), GFP_KERNEL); + if (info == NULL) { + ret = -ENOMEM; + return ret; + } + + info->pdata = pdev->dev.platform_data; + info->cpcap = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, info); + + if (info->pdata->led_regulator != NULL) { + info->regulator = regulator_get(&pdev->dev, + info->pdata->led_regulator); + if (IS_ERR(info->regulator)) { + pr_err("%s: Cannot get %s regulator\n", + __func__, info->pdata->led_regulator); + ret = PTR_ERR(info->regulator); + goto exit_request_reg_failed; + + } + } + info->regulator_state = 0; + + info->cpcap_class_dev.name = info->pdata->class_name; + info->cpcap_class_dev.brightness_set = cpcap_set; + ret = led_classdev_register(&pdev->dev, &info->cpcap_class_dev); + if (ret < 0) { + pr_err("%s:Register %s class failed\n", + __func__, info->cpcap_class_dev.name); + goto err_reg_button_class_failed; + } + INIT_WORK(&info->brightness_work, cpcap_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 cpcap_remove(struct platform_device *pdev) +{ + struct cpcap_led_data *info = platform_get_drvdata(pdev); + + if (info->regulator) + regulator_put(info->regulator); + + led_classdev_unregister(&info->cpcap_class_dev); + return 0; +} + +static struct platform_driver ld_cpcap_driver = { + .probe = cpcap_probe, + .remove = cpcap_remove, + .driver = { + .name = LD_CPCAP_LED_DRV, + }, +}; + +static int __init led_cpcap_init(void) +{ + return platform_driver_register(&ld_cpcap_driver); +} + +static void __exit led_cpcap_exit(void) +{ + platform_driver_unregister(&ld_cpcap_driver); +} + +module_init(led_cpcap_init); +module_exit(led_cpcap_exit); + +MODULE_DESCRIPTION("CPCAP Lighting driver"); +MODULE_AUTHOR("Dan Murphy "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds-ld-cpcap.h b/include/linux/leds-ld-cpcap.h index 4881fb4fe8f0..208551be2106 100644 --- a/include/linux/leds-ld-cpcap.h +++ b/include/linux/leds-ld-cpcap.h @@ -19,37 +19,37 @@ #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 +#ifdef __KERNEL__ -#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 +#define LD_CPCAP_LED_DRV "cpcap_led_driver" +#define LD_DISP_BUTTON_DEV "button-backlight" +#define LD_PRIVACY_LED_DEV "privacy-led" + +struct cpcap_display_led { + unsigned int display_reg; + unsigned int display_mask; + unsigned int display_on; + unsigned int display_off; + unsigned int display_init; + unsigned int poll_intvl; + unsigned int zone0; + unsigned int zone1; + unsigned int zone2; + unsigned int zone3; + unsigned int zone4; +}; + +struct cpcap_led { + unsigned int cpcap_register; + unsigned int cpcap_mask; + unsigned int on_val; + unsigned int off_val; + unsigned int cpcap_duty_cycle; + unsigned int cpcap_current; + char *class_name; + char *led_regulator; +}; + +#endif /* __KERNEL__ */ #endif /* __LED_LD_CPCAP_H__ */ diff --git a/include/linux/spi/cpcap.h b/include/linux/spi/cpcap.h index a89396ff0ad4..13df90046c35 100644 --- a/include/linux/spi/cpcap.h +++ b/include/linux/spi/cpcap.h @@ -65,7 +65,6 @@ enum cpcap_regulator_id { CPCAP_VVIB, CPCAP_VUSB, CPCAP_VAUDIO, - CPCAP_NUM_REGULATORS }; @@ -504,48 +503,6 @@ struct cpcap_adc_ato { unsigned short atox_ps_factor_out; }; -struct cpcap_display_led { - unsigned int display_reg; - unsigned int display_mask; - unsigned int display_on; - unsigned int display_off; - unsigned int display_init; - unsigned int poll_intvl; - unsigned int zone0; - unsigned int zone1; - unsigned int zone2; - unsigned int zone3; - unsigned int zone4; -}; - -struct cpcap_button_led { - unsigned int button_reg; - unsigned int button_mask; - unsigned int button_on; - unsigned int button_off; -}; - -struct cpcap_kpad_led { - unsigned int kpad_reg; - unsigned int kpad_mask; - unsigned int kpad_on; - unsigned int kpad_off; -}; - -struct cpcap_rgb_led { - unsigned int rgb_reg; - unsigned int rgb_mask; - unsigned int rgb_on; - unsigned int rgb_off; -}; - -struct cpcap_leds { - struct cpcap_display_led display_led; - struct cpcap_button_led button_led; - struct cpcap_kpad_led kpad_led; - struct cpcap_rgb_led rgb_led; -}; - struct cpcap_batt_data { int status; int health; @@ -581,7 +538,6 @@ struct cpcap_platform_data { unsigned short *regulator_off_mode_values; struct regulator_init_data *regulator_init; struct cpcap_adc_ato *adc_ato; - struct cpcap_leds *leds; void (*ac_changed)(struct power_supply *, struct cpcap_batt_ac_data *); void (*batt_changed)(struct power_supply *, -- 2.34.1