diff options
Diffstat (limited to 'drivers/mxc/pmic/mc13892/pmic_light.c')
-rw-r--r-- | drivers/mxc/pmic/mc13892/pmic_light.c | 685 |
1 files changed, 685 insertions, 0 deletions
diff --git a/drivers/mxc/pmic/mc13892/pmic_light.c b/drivers/mxc/pmic/mc13892/pmic_light.c new file mode 100644 index 000000000000..caaa98d7d7d9 --- /dev/null +++ b/drivers/mxc/pmic/mc13892/pmic_light.c @@ -0,0 +1,685 @@ +/* + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @file mc13892/pmic_light.c + * @brief This is the main file of PMIC(mc13783) Light and Backlight driver. + * + * @ingroup PMIC_LIGHT + */ + +/* + * Includes + */ +#define DEBUG +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/fs.h> +#include <linux/pmic_light.h> +#include <linux/pmic_status.h> + +#define BIT_CL_MAIN_LSH 9 +#define BIT_CL_AUX_LSH 21 +#define BIT_CL_KEY_LSH 9 +#define BIT_CL_RED_LSH 9 +#define BIT_CL_GREEN_LSH 21 +#define BIT_CL_BLUE_LSH 9 + +#define BIT_CL_MAIN_WID 3 +#define BIT_CL_AUX_WID 3 +#define BIT_CL_KEY_WID 3 +#define BIT_CL_RED_WID 3 +#define BIT_CL_GREEN_WID 3 +#define BIT_CL_BLUE_WID 3 + +#define BIT_DC_MAIN_LSH 3 +#define BIT_DC_AUX_LSH 15 +#define BIT_DC_KEY_LSH 3 +#define BIT_DC_RED_LSH 3 +#define BIT_DC_GREEN_LSH 15 +#define BIT_DC_BLUE_LSH 3 + +#define BIT_DC_MAIN_WID 6 +#define BIT_DC_AUX_WID 6 +#define BIT_DC_KEY_WID 6 +#define BIT_DC_RED_WID 6 +#define BIT_DC_GREEN_WID 6 +#define BIT_DC_BLUE_WID 6 + +#define BIT_RP_MAIN_LSH 2 +#define BIT_RP_AUX_LSH 14 +#define BIT_RP_KEY_LSH 2 +#define BIT_RP_RED_LSH 2 +#define BIT_RP_GREEN_LSH 14 +#define BIT_RP_BLUE_LSH 2 + +#define BIT_RP_MAIN_WID 1 +#define BIT_RP_AUX_WID 1 +#define BIT_RP_KEY_WID 1 +#define BIT_RP_RED_WID 1 +#define BIT_RP_GREEN_WID 1 +#define BIT_RP_BLUE_WID 1 + +#define BIT_HC_MAIN_LSH 1 +#define BIT_HC_AUX_LSH 13 +#define BIT_HC_KEY_LSH 1 + +#define BIT_HC_MAIN_WID 1 +#define BIT_HC_AUX_WID 1 +#define BIT_HC_KEY_WID 1 + +#define BIT_BP_RED_LSH 0 +#define BIT_BP_GREEN_LSH 12 +#define BIT_BP_BLUE_LSH 0 + +#define BIT_BP_RED_WID 2 +#define BIT_BP_GREEN_WID 2 +#define BIT_BP_BLUE_WID 2 + +int pmic_light_init_reg(void) +{ + CHECK_ERROR(pmic_write_reg(REG_LED_CTL0, 0, PMIC_ALL_BITS)); + CHECK_ERROR(pmic_write_reg(REG_LED_CTL1, 0, PMIC_ALL_BITS)); + CHECK_ERROR(pmic_write_reg(REG_LED_CTL2, 0, PMIC_ALL_BITS)); + CHECK_ERROR(pmic_write_reg(REG_LED_CTL3, 0, PMIC_ALL_BITS)); + + return 0; +} + +static int pmic_light_suspend(struct platform_device *dev, pm_message_t state) +{ + return 0; +}; + +static int pmic_light_resume(struct platform_device *pdev) +{ + return 0; +}; + +PMIC_STATUS mc13892_bklit_set_hi_current(enum lit_channel channel, int mode) +{ + unsigned int mask; + unsigned int value; + int reg; + + switch (channel) { + case LIT_MAIN: + value = BITFVAL(BIT_HC_MAIN, mode); + mask = BITFMASK(BIT_HC_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + value = BITFVAL(BIT_HC_AUX, mode); + mask = BITFMASK(BIT_HC_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + value = BITFVAL(BIT_HC_KEY, mode); + mask = BITFMASK(BIT_HC_KEY); + reg = REG_LED_CTL1; + break; + default: + return PMIC_PARAMETER_ERROR; + } + CHECK_ERROR(pmic_write_reg(reg, value, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_get_hi_current(enum lit_channel channel, int *mode) +{ + unsigned int mask; + int reg; + + switch (channel) { + case LIT_MAIN: + mask = BITFMASK(BIT_HC_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + mask = BITFMASK(BIT_HC_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + mask = BITFMASK(BIT_HC_KEY); + reg = REG_LED_CTL1; + break; + default: + return PMIC_PARAMETER_ERROR; + } + + CHECK_ERROR(pmic_read_reg(reg, mode, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_set_current(enum lit_channel channel, + unsigned char level) +{ + unsigned int mask; + unsigned int value; + int reg; + + if (level > LIT_CURR_HI_42) + return PMIC_PARAMETER_ERROR; + else if (level >= LIT_CURR_HI_0) { + CHECK_ERROR(mc13892_bklit_set_hi_current(channel, 1)); + level -= LIT_CURR_HI_0; + } + + switch (channel) { + case LIT_MAIN: + value = BITFVAL(BIT_CL_MAIN, level); + mask = BITFMASK(BIT_CL_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + value = BITFVAL(BIT_CL_AUX, level); + mask = BITFMASK(BIT_CL_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + value = BITFVAL(BIT_CL_KEY, level); + mask = BITFMASK(BIT_CL_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + value = BITFVAL(BIT_CL_RED, level); + mask = BITFMASK(BIT_CL_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + value = BITFVAL(BIT_CL_GREEN, level); + mask = BITFMASK(BIT_CL_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + value = BITFVAL(BIT_CL_BLUE, level); + mask = BITFMASK(BIT_CL_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + CHECK_ERROR(pmic_write_reg(reg, value, mask)); + + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_get_current(enum lit_channel channel, + unsigned char *level) +{ + unsigned int reg_value = 0; + unsigned int mask = 0; + int reg, mode; + + CHECK_ERROR(mc13892_bklit_get_hi_current(channel, &mode)); + + switch (channel) { + case LIT_MAIN: + mask = BITFMASK(BIT_CL_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + mask = BITFMASK(BIT_CL_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + mask = BITFMASK(BIT_CL_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + mask = BITFMASK(BIT_CL_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + mask = BITFMASK(BIT_CL_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + mask = BITFMASK(BIT_CL_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + + CHECK_ERROR(pmic_read_reg(reg, ®_value, mask)); + + switch (channel) { + case LIT_MAIN: + *level = BITFEXT(reg_value, BIT_CL_MAIN); + break; + case LIT_AUX: + *level = BITFEXT(reg_value, BIT_CL_AUX); + break; + case LIT_KEY: + *level = BITFEXT(reg_value, BIT_CL_KEY); + break; + case LIT_RED: + *level = BITFEXT(reg_value, BIT_CL_RED); + break; + case LIT_GREEN: + *level = BITFEXT(reg_value, BIT_CL_GREEN); + break; + case LIT_BLUE: + *level = BITFEXT(reg_value, BIT_CL_BLUE); + break; + default: + return PMIC_PARAMETER_ERROR; + } + + if (mode == 1) + *level += LIT_CURR_HI_0; + + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_set_dutycycle(enum lit_channel channel, + unsigned char dc) +{ + unsigned int mask; + unsigned int value; + int reg; + + switch (channel) { + case LIT_MAIN: + value = BITFVAL(BIT_DC_MAIN, dc); + mask = BITFMASK(BIT_DC_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + value = BITFVAL(BIT_DC_AUX, dc); + mask = BITFMASK(BIT_DC_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + value = BITFVAL(BIT_DC_KEY, dc); + mask = BITFMASK(BIT_DC_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + value = BITFVAL(BIT_DC_RED, dc); + mask = BITFMASK(BIT_DC_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + value = BITFVAL(BIT_DC_GREEN, dc); + mask = BITFMASK(BIT_DC_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + value = BITFVAL(BIT_DC_BLUE, dc); + mask = BITFMASK(BIT_DC_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + CHECK_ERROR(pmic_write_reg(reg, value, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_get_dutycycle(enum lit_channel channel, + unsigned char *dc) +{ + unsigned int mask; + int reg; + unsigned int reg_value = 0; + + switch (channel) { + case LIT_MAIN: + mask = BITFMASK(BIT_DC_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + mask = BITFMASK(BIT_DC_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + mask = BITFMASK(BIT_DC_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + mask = BITFMASK(BIT_DC_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + mask = BITFMASK(BIT_DC_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + mask = BITFMASK(BIT_DC_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + + CHECK_ERROR(pmic_read_reg(reg, ®_value, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_set_ramp(enum lit_channel channel, int flag) +{ + unsigned int mask; + unsigned int value; + int reg; + + switch (channel) { + case LIT_MAIN: + value = BITFVAL(BIT_RP_MAIN, flag); + mask = BITFMASK(BIT_RP_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + value = BITFVAL(BIT_RP_AUX, flag); + mask = BITFMASK(BIT_RP_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + value = BITFVAL(BIT_RP_KEY, flag); + mask = BITFMASK(BIT_RP_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + value = BITFVAL(BIT_RP_RED, flag); + mask = BITFMASK(BIT_RP_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + value = BITFVAL(BIT_RP_GREEN, flag); + mask = BITFMASK(BIT_RP_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + value = BITFVAL(BIT_RP_BLUE, flag); + mask = BITFMASK(BIT_RP_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + CHECK_ERROR(pmic_write_reg(reg, value, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_get_ramp(enum lit_channel channel, int *flag) +{ + unsigned int mask; + int reg; + + switch (channel) { + case LIT_MAIN: + mask = BITFMASK(BIT_RP_MAIN); + reg = REG_LED_CTL0; + break; + case LIT_AUX: + mask = BITFMASK(BIT_RP_AUX); + reg = REG_LED_CTL0; + break; + case LIT_KEY: + mask = BITFMASK(BIT_RP_KEY); + reg = REG_LED_CTL1; + break; + case LIT_RED: + mask = BITFMASK(BIT_RP_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + mask = BITFMASK(BIT_RP_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + mask = BITFMASK(BIT_RP_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + + CHECK_ERROR(pmic_read_reg(reg, flag, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_set_blink_p(enum lit_channel channel, int period) +{ + unsigned int mask; + unsigned int value; + int reg; + + switch (channel) { + case LIT_RED: + value = BITFVAL(BIT_BP_RED, period); + mask = BITFMASK(BIT_BP_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + value = BITFVAL(BIT_BP_GREEN, period); + mask = BITFMASK(BIT_BP_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + value = BITFVAL(BIT_BP_BLUE, period); + mask = BITFMASK(BIT_BP_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + CHECK_ERROR(pmic_write_reg(reg, value, mask)); + return PMIC_SUCCESS; +} + +PMIC_STATUS mc13892_bklit_get_blink_p(enum lit_channel channel, int *period) +{ + unsigned int mask; + int reg; + + switch (channel) { + case LIT_RED: + mask = BITFMASK(BIT_BP_RED); + reg = REG_LED_CTL2; + break; + case LIT_GREEN: + mask = BITFMASK(BIT_BP_GREEN); + reg = REG_LED_CTL2; + break; + case LIT_BLUE: + mask = BITFMASK(BIT_BP_BLUE); + reg = REG_LED_CTL3; + break; + default: + return PMIC_PARAMETER_ERROR; + } + + CHECK_ERROR(pmic_read_reg(reg, period, mask)); + return PMIC_SUCCESS; +} + +EXPORT_SYMBOL(mc13892_bklit_set_current); +EXPORT_SYMBOL(mc13892_bklit_get_current); +EXPORT_SYMBOL(mc13892_bklit_set_dutycycle); +EXPORT_SYMBOL(mc13892_bklit_get_dutycycle); +EXPORT_SYMBOL(mc13892_bklit_set_ramp); +EXPORT_SYMBOL(mc13892_bklit_get_ramp); +EXPORT_SYMBOL(mc13892_bklit_set_blink_p); +EXPORT_SYMBOL(mc13892_bklit_get_blink_p); + +static int pmic_light_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef DEBUG +static ssize_t lit_info(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return 0; +} + +enum { + SET_CURR = 0, + SET_DC, + SET_RAMP, + SET_BP, + SET_CH, + LIT_CMD_MAX +}; + +static const char *const lit_cmd[LIT_CMD_MAX] = { + [SET_CURR] = "cur", + [SET_DC] = "dc", + [SET_RAMP] = "ra", + [SET_BP] = "bp", + [SET_CH] = "ch" +}; + +static int cmd(unsigned int index, int value) +{ + static int ch = LIT_MAIN; + int ret = 0; + + switch (index) { + case SET_CH: + ch = value; + break; + case SET_CURR: + pr_debug("set %d cur %d\n", ch, value); + ret = mc13892_bklit_set_current(ch, value); + break; + case SET_DC: + pr_debug("set %d dc %d\n", ch, value); + ret = mc13892_bklit_set_dutycycle(ch, value); + break; + case SET_RAMP: + pr_debug("set %d ramp %d\n", ch, value); + ret = mc13892_bklit_set_ramp(ch, value); + break; + case SET_BP: + pr_debug("set %d bp %d\n", ch, value); + ret = mc13892_bklit_set_blink_p(ch, value); + break; + default: + pr_debug("error command\n"); + break; + } + + if (ret == PMIC_SUCCESS) + pr_debug("command exec successfully!\n"); + + return 0; +} + +static ssize_t lit_ctl(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int state = 0; + const char *const *s; + char *p, *q; + int error; + int len, value = 0; + + pr_debug("lit_ctl\n"); + + q = NULL; + q = memchr(buf, ' ', count); + + if (q != NULL) { + len = q - buf; + q += 1; + value = simple_strtoul(q, NULL, 10); + } else { + p = memchr(buf, '\n', count); + len = p ? p - buf : count; + } + + for (s = &lit_cmd[state]; state < LIT_CMD_MAX; s++, state++) { + if (*s && !strncmp(buf, *s, len)) + break; + } + if (state < LIT_CMD_MAX && *s) + error = cmd(state, value); + else + error = -EINVAL; + + return count; +} + +#else +static ssize_t lit_info(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static ssize_t lit_ctl(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + +#endif + +static DEVICE_ATTR(lit, 0644, lit_info, lit_ctl); + +static int pmic_light_probe(struct platform_device *pdev) +{ + int ret = 0; + + pr_debug("PMIC ADC start probe\n"); + ret = device_create_file(&(pdev->dev), &dev_attr_lit); + if (ret) { + pr_debug("Can't create device file!\n"); + return -ENODEV; + } + + pmic_light_init_reg(); + + pr_debug("PMIC Light successfully loaded\n"); + return 0; +} + +static struct platform_driver pmic_light_driver_ldm = { + .driver = { + .name = "pmic_light", + }, + .suspend = pmic_light_suspend, + .resume = pmic_light_resume, + .probe = pmic_light_probe, + .remove = pmic_light_remove, +}; + +/* + * Initialization and Exit + */ + +static int __init pmic_light_init(void) +{ + pr_debug("PMIC Light driver loading...\n"); + return platform_driver_register(&pmic_light_driver_ldm); +} +static void __exit pmic_light_exit(void) +{ + platform_driver_unregister(&pmic_light_driver_ldm); + pr_debug("PMIC Light driver successfully unloaded\n"); +} + +/* + * Module entry points + */ + +subsys_initcall(pmic_light_init); +module_exit(pmic_light_exit); + +MODULE_DESCRIPTION("PMIC_LIGHT"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); |