| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029 |
- /*
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * mt65xx leds driver
- *
- */
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/string.h>
- #include <linux/ctype.h>
- #include <linux/leds.h>
- #include <linux/of.h>
- /* #include <linux/leds-mt65xx.h> */
- #include <linux/workqueue.h>
- #include <linux/wakelock.h>
- #include <linux/slab.h>
- #include <linux/delay.h>
- /* #include <mach/mt_pwm.h>
- #include <mach/upmu_common_sw.h>
- #include <mach/upmu_common.h>
- #include <mach/upmu_sw.h>
- #include <mach/upmu_hw.h>*/
- #ifdef CONFIG_MTK_AAL_SUPPORT
- #include <ddp_aal.h>
- /* #include <linux/aee.h> */
- #endif
- #include <mt-plat/mt_pwm.h>
- #include <mt-plat/upmu_common.h>
- #include "leds_sw.h"
- #include "leds_hal.h"
- #include "ddp_pwm.h"
- #include "mtkfb.h"
- /* for LED&Backlight bringup, define the dummy API */
- #ifndef CONFIG_MTK_PMIC
- u16 pmic_set_register_value(u32 flagname, u32 val)
- {
- return 0;
- }
- #endif
- #ifndef CONFIG_MTK_PWM
- s32 pwm_set_spec_config(struct pwm_spec_config *conf)
- {
- return 0;
- }
- void mt_pwm_disable(u32 pwm_no, u8 pmic_pad)
- {
- }
- #endif
- static DEFINE_MUTEX(leds_mutex);
- static DEFINE_MUTEX(leds_pmic_mutex);
- /****************************************************************************
- * variables
- ***************************************************************************/
- /* struct cust_mt65xx_led* bl_setting_hal = NULL; */
- static unsigned int bl_brightness_hal = 102;
- static unsigned int bl_duty_hal = 21;
- static unsigned int bl_div_hal = CLK_DIV1;
- static unsigned int bl_frequency_hal = 32000;
- /* for button led don't do ISINK disable first time */
- static int button_flag_isink0;
- static int button_flag_isink1;
- static int button_flag_isink2;
- static int button_flag_isink3;
- struct wake_lock leds_suspend_lock;
- char *leds_name[MT65XX_LED_TYPE_TOTAL] = {
- "red",
- "green",
- "blue",
- "jogball-backlight",
- "keyboard-backlight",
- "button-backlight",
- "lcd-backlight",
- };
- struct cust_mt65xx_led *pled_dtsi = NULL;
- /****************************************************************************
- * DEBUG MACROS
- ***************************************************************************/
- static int debug_enable_led_hal = 1;
- #define LEDS_DEBUG(format, args...) do { \
- if (debug_enable_led_hal) { \
- pr_debug("[LED]"format, ##args);\
- } \
- } while (0)
- /*****************PWM *************************************************/
- #define PWM_DIV_NUM 8
- static int time_array_hal[PWM_DIV_NUM] = {
- 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
- static unsigned int div_array_hal[PWM_DIV_NUM] = {
- 1, 2, 4, 8, 16, 32, 64, 128 };
- static unsigned int backlight_PWM_div_hal = CLK_DIV1; /* this para come from cust_leds. */
- /****************************************************************************
- * func:return global variables
- ***************************************************************************/
- void mt_leds_wake_lock_init(void)
- {
- wake_lock_init(&leds_suspend_lock, WAKE_LOCK_SUSPEND, "leds wakelock");
- }
- unsigned int mt_get_bl_brightness(void)
- {
- return bl_brightness_hal;
- }
- unsigned int mt_get_bl_duty(void)
- {
- return bl_duty_hal;
- }
- unsigned int mt_get_bl_div(void)
- {
- return bl_div_hal;
- }
- unsigned int mt_get_bl_frequency(void)
- {
- return bl_frequency_hal;
- }
- unsigned int *mt_get_div_array(void)
- {
- return &div_array_hal[0];
- }
- void mt_set_bl_duty(unsigned int level)
- {
- bl_duty_hal = level;
- }
- void mt_set_bl_div(unsigned int div)
- {
- bl_div_hal = div;
- }
- void mt_set_bl_frequency(unsigned int freq)
- {
- bl_frequency_hal = freq;
- }
- struct cust_mt65xx_led *get_cust_led_dtsi(void)
- {
- struct device_node *led_node = NULL;
- bool isSupportDTS = false;
- int i, ret;
- int mode, data;
- int pwm_config[5] = { 0 };
- /*LEDS_DEBUG("get_cust_led_dtsi: get the leds info from device tree\n");*/
- if (pled_dtsi == NULL) {
- /* this can allocat an new struct array */
- pled_dtsi = kmalloc(MT65XX_LED_TYPE_TOTAL *
- sizeof(struct
- cust_mt65xx_led),
- GFP_KERNEL);
- if (pled_dtsi == NULL) {
- LEDS_DEBUG("get_cust_led_dtsi kmalloc fail\n");
- goto out;
- }
- for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {
- char node_name[32] = "mediatek,";
- pled_dtsi[i].name = leds_name[i];
- led_node =
- of_find_compatible_node(NULL, NULL,
- strcat(node_name,
- leds_name[i]));
- if (!led_node) {
- LEDS_DEBUG("Cannot find LED node from dts\n");
- pled_dtsi[i].mode = 0;
- pled_dtsi[i].data = -1;
- } else {
- isSupportDTS = true;
- ret =
- of_property_read_u32(led_node, "led_mode",
- &mode);
- if (!ret) {
- pled_dtsi[i].mode = mode;
- LEDS_DEBUG
- ("The %s's led mode is : %d\n",
- pled_dtsi[i].name,
- pled_dtsi[i].mode);
- } else {
- LEDS_DEBUG
- ("led dts can not get led mode");
- pled_dtsi[i].mode = 0;
- }
- ret =
- of_property_read_u32(led_node, "data",
- &data);
- if (!ret) {
- pled_dtsi[i].data = data;
- LEDS_DEBUG
- ("The %s's led data is : %ld\n",
- pled_dtsi[i].name,
- pled_dtsi[i].data);
- } else {
- LEDS_DEBUG
- ("led dts can not get led data");
- pled_dtsi[i].data = -1;
- }
- ret =
- of_property_read_u32_array(led_node,
- "pwm_config",
- pwm_config,
- ARRAY_SIZE
- (pwm_config));
- if (!ret) {
- LEDS_DEBUG
- ("The %s's pwm config data is %d %d %d %d %d\n",
- pled_dtsi[i].name, pwm_config[0],
- pwm_config[1], pwm_config[2],
- pwm_config[3], pwm_config[4]);
- pled_dtsi[i].config_data.clock_source =
- pwm_config[0];
- pled_dtsi[i].config_data.div =
- pwm_config[1];
- pled_dtsi[i].config_data.low_duration =
- pwm_config[2];
- pled_dtsi[i].config_data.High_duration =
- pwm_config[3];
- pled_dtsi[i].config_data.pmic_pad =
- pwm_config[4];
- } else
- LEDS_DEBUG
- ("led dts can not get pwm config data.\n");
- switch (pled_dtsi[i].mode) {
- case MT65XX_LED_MODE_CUST_LCM:
- pled_dtsi[i].data =
- (long)mtkfb_set_backlight_level;
- LEDS_DEBUG
- ("kernel:the backlight hw mode is LCM.\n");
- break;
- case MT65XX_LED_MODE_CUST_BLS_PWM:
- pled_dtsi[i].data =
- (long)disp_bls_set_backlight;
- LEDS_DEBUG
- ("kernel:the backlight hw mode is BLS.\n");
- break;
- default:
- break;
- }
- }
- }
- if (!isSupportDTS) {
- kfree(pled_dtsi);
- pled_dtsi = NULL;
- }
- }
- out:
- return pled_dtsi;
- }
- struct cust_mt65xx_led *mt_get_cust_led_list(void)
- {
- struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi();
- return cust_led_list;
- }
- /****************************************************************************
- * internal functions
- ***************************************************************************/
- static int brightness_mapto64(int level)
- {
- if (level < 30)
- return (level >> 1) + 7;
- else if (level <= 120)
- return (level >> 2) + 14;
- else if (level <= 160)
- return level / 5 + 20;
- else
- return (level >> 3) + 33;
- }
- static int find_time_index(int time)
- {
- int index = 0;
- while (index < 8) {
- if (time < time_array_hal[index])
- return index;
- index++;
- }
- return PWM_DIV_NUM - 1;
- }
- int mt_led_set_pwm(int pwm_num, struct nled_setting *led)
- {
- struct pwm_spec_config pwm_setting;
- int time_index = 0;
- pwm_setting.pwm_no = pwm_num;
- pwm_setting.mode = PWM_MODE_OLD;
- LEDS_DEBUG("led_set_pwm: mode=%d,pwm_no=%d\n", led->nled_mode,
- pwm_num);
- /* We won't choose 32K to be the clock src of old mode because of system performance. */
- /* The setting here will be clock src = 26MHz, CLKSEL = 26M/1625 (i.e. 16K) */
- pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K;
- switch (led->nled_mode) {
- /* Actually, the setting still can not to turn off NLED. We should disable PWM to turn off NLED. */
- case NLED_OFF:
- pwm_setting.PWM_MODE_OLD_REGS.THRESH = 0;
- pwm_setting.clk_div = CLK_DIV1;
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2;
- break;
- case NLED_ON:
- pwm_setting.PWM_MODE_OLD_REGS.THRESH = 30 / 2;
- pwm_setting.clk_div = CLK_DIV1;
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2;
- break;
- case NLED_BLINK:
- LEDS_DEBUG("LED blink on time = %d offtime = %d\n",
- led->blink_on_time, led->blink_off_time);
- time_index =
- find_time_index(led->blink_on_time + led->blink_off_time);
- LEDS_DEBUG("LED div is %d\n", time_index);
- pwm_setting.clk_div = time_index;
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH =
- (led->blink_on_time +
- led->blink_off_time) * MIN_FRE_OLD_PWM /
- div_array_hal[time_index];
- pwm_setting.PWM_MODE_OLD_REGS.THRESH =
- (led->blink_on_time * 100) / (led->blink_on_time +
- led->blink_off_time);
- }
- pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.GDURATION = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
- pwm_set_spec_config(&pwm_setting);
- return 0;
- }
- /************************ led breath function*****************************/
- /*************************************************************************
- //func is to swtich to breath mode from PWM mode of ISINK
- //para: enable: 1 : breath mode; 0: PWM mode;
- *************************************************************************/
- #if 0
- static int led_switch_breath_pmic(enum mt65xx_led_pmic pmic_type,
- struct nled_setting *led, int enable)
- {
- /* int time_index = 0; */
- /* int duty = 0; */
- LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type);
- if ((pmic_type != MT65XX_LED_PMIC_NLED_ISINK0
- && pmic_type != MT65XX_LED_PMIC_NLED_ISINK1
- && pmic_type != MT65XX_LED_PMIC_NLED_ISINK2
- && pmic_type != MT65XX_LED_PMIC_NLED_ISINK3)
- || led->nled_mode != NLED_BLINK) {
- return -1;
- }
- if (1 == enable) {
- switch (pmic_type) {
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_ISINK_CH0_MODE,
- ISINK_BREATH_MODE);
- pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TR1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TR2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TF1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TF2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TON_SEL,
- 0x02);
- pmic_set_register_value(PMIC_ISINK_BREATH0_TOFF_SEL,
- 0x03);
- pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, 11);
- /* pmic_set_register_value(PMIC_ISINK_CH0_EN,NLED_ON); */
- break;
- case MT65XX_LED_PMIC_NLED_ISINK1:
- pmic_set_register_value(PMIC_ISINK_CH1_MODE,
- ISINK_BREATH_MODE);
- pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TR1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TR2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TF1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TF2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TON_SEL,
- 0x02);
- pmic_set_register_value(PMIC_ISINK_BREATH1_TOFF_SEL,
- 0x03);
- pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, 11);
- /* pmic_set_register_value(PMIC_ISINK_CH1_EN,NLED_ON); */
- break;
- case MT65XX_LED_PMIC_NLED_ISINK2:
- pmic_set_register_value(PMIC_ISINK_CH2_MODE,
- ISINK_BREATH_MODE);
- pmic_set_register_value(PMIC_ISINK_CH2_STEP, ISINK_3);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TR1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TR2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TF1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TF2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TON_SEL,
- 0x02);
- pmic_set_register_value(PMIC_ISINK_BREATH2_TOFF_SEL,
- 0x03);
- pmic_set_register_value(PMIC_ISINK_DIM2_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM2_FSEL, 11);
- /* pmic_set_register_value(PMIC_ISINK_CH2_EN,NLED_ON); */
- break;
- case MT65XX_LED_PMIC_NLED_ISINK3:
- pmic_set_register_value(PMIC_ISINK_CH3_MODE,
- ISINK_BREATH_MODE);
- pmic_set_register_value(PMIC_ISINK_CH3_STEP, ISINK_3);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TR1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TR2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TF1_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TF2_SEL,
- 0x04);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TON_SEL,
- 0x02);
- pmic_set_register_value(PMIC_ISINK_BREATH3_TOFF_SEL,
- 0x03);
- pmic_set_register_value(PMIC_ISINK_DIM3_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM3_FSEL, 11);
- /* pmic_set_register_value(PMIC_ISINK_CH3_EN,NLED_ON); */
- break;
- default:
- break;
- }
- } else {
- switch (pmic_type) {
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_ISINK_CH3_MODE,
- ISINK_PWM_MODE);
- break;
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_ISINK_CH3_MODE,
- ISINK_PWM_MODE);
- break;
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_ISINK_CH3_MODE,
- ISINK_PWM_MODE);
- break;
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_ISINK_CH3_MODE,
- ISINK_PWM_MODE);
- break;
- default:
- break;
- }
- }
- return 0;
- }
- #endif
- #define PMIC_PERIOD_NUM 8
- /* 100 * period, ex: 0.01 Hz -> 0.01 * 100 = 1 */
- int pmic_period_array[] = { 250, 500, 1000, 1250, 1666, 2000, 2500, 10000 };
- /* int pmic_freqsel_array[] = {99999, 9999, 4999, 1999, 999, 499, 199, 4, 0}; */
- int pmic_freqsel_array[] = { 0, 4, 199, 499, 999, 1999, 1999, 1999 };
- static int find_time_index_pmic(int time_ms)
- {
- int i;
- for (i = 0; i < PMIC_PERIOD_NUM; i++) {
- if (time_ms <= pmic_period_array[i])
- return i;
- }
- return PMIC_PERIOD_NUM - 1;
- }
- int mt_led_blink_pmic(enum mt65xx_led_pmic pmic_type, struct nled_setting *led)
- {
- int time_index = 0;
- int duty = 0;
- LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type);
- if ((pmic_type != MT65XX_LED_PMIC_NLED_ISINK0
- && pmic_type != MT65XX_LED_PMIC_NLED_ISINK1)
- || led->nled_mode != NLED_BLINK) {
- return -1;
- }
- LEDS_DEBUG("LED blink on time = %d offtime = %d\n",
- led->blink_on_time, led->blink_off_time);
- time_index =
- find_time_index_pmic(led->blink_on_time + led->blink_off_time);
- LEDS_DEBUG("LED index is %d freqsel=%d\n", time_index,
- pmic_freqsel_array[time_index]);
- duty =
- 32 * led->blink_on_time / (led->blink_on_time +
- led->blink_off_time);
- /* pmic_set_register_value(PMIC_RG_G_DRV_2M_CK_PDN(0X0); // DISABLE POWER DOWN ,Indicator no need) */
- pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
- switch (pmic_type) {
- case MT65XX_LED_PMIC_NLED_ISINK0:
- pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0);
- pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_CKSEL, 0);
- pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE);
- pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */
- pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, duty);
- pmic_set_register_value(PMIC_ISINK_DIM0_FSEL,
- pmic_freqsel_array[time_index]);
- pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON);
- break;
- case MT65XX_LED_PMIC_NLED_ISINK1:
- pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0);
- pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_CKSEL, 0);
- pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE);
- pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */
- pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, duty);
- pmic_set_register_value(PMIC_ISINK_DIM1_FSEL,
- pmic_freqsel_array[time_index]);
- pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON);
- break;
- default:
- break;
- }
- return 0;
- }
- int mt_backlight_set_pwm(int pwm_num, u32 level, u32 div,
- struct PWM_config *config_data)
- {
- struct pwm_spec_config pwm_setting;
- unsigned int BacklightLevelSupport =
- Cust_GetBacklightLevelSupport_byPWM();
- pwm_setting.pwm_no = pwm_num;
- if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT)
- pwm_setting.mode = PWM_MODE_OLD;
- else
- pwm_setting.mode = PWM_MODE_FIFO; /* New mode fifo and periodical mode */
- pwm_setting.pmic_pad = config_data->pmic_pad;
- if (config_data->div) {
- pwm_setting.clk_div = config_data->div;
- backlight_PWM_div_hal = config_data->div;
- } else
- pwm_setting.clk_div = div;
- if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT) {
- if (config_data->clock_source)
- pwm_setting.clk_src = PWM_CLK_OLD_MODE_BLOCK;
- else
- pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K; /* actually.
- it's block/1625 = 26M/1625 = 16KHz @ MT6571 */
- pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0;
- pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0;
- pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 0;
- pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0;
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 255; /* 256 level */
- pwm_setting.PWM_MODE_OLD_REGS.THRESH = level;
- LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:duty is %d/%d\n",
- BacklightLevelSupport, level,
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH);
- LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:clk_src/div is %d%d\n",
- BacklightLevelSupport, pwm_setting.clk_src,
- pwm_setting.clk_div);
- if (level > 0 && level < 256) {
- pwm_set_spec_config(&pwm_setting);
- LEDS_DEBUG
- ("[LEDS][%d]backlight_set_pwm: old mode: thres/data_width is %d/%d\n",
- BacklightLevelSupport,
- pwm_setting.PWM_MODE_OLD_REGS.THRESH,
- pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH);
- } else {
- LEDS_DEBUG("[LEDS][%d]Error level in backlight\n",
- BacklightLevelSupport);
- mt_pwm_disable(pwm_setting.pwm_no,
- config_data->pmic_pad);
- }
- return 0;
- } else {
- if (config_data->clock_source) {
- pwm_setting.clk_src = PWM_CLK_NEW_MODE_BLOCK;
- } else {
- pwm_setting.clk_src =
- PWM_CLK_NEW_MODE_BLOCK_DIV_BY_1625;
- }
- if (config_data->High_duration && config_data->low_duration) {
- pwm_setting.PWM_MODE_FIFO_REGS.HDURATION =
- config_data->High_duration;
- pwm_setting.PWM_MODE_FIFO_REGS.LDURATION =
- pwm_setting.PWM_MODE_FIFO_REGS.HDURATION;
- } else {
- pwm_setting.PWM_MODE_FIFO_REGS.HDURATION = 4;
- pwm_setting.PWM_MODE_FIFO_REGS.LDURATION = 4;
- }
- pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.STOP_BITPOS_VALUE = 31;
- pwm_setting.PWM_MODE_FIFO_REGS.GDURATION =
- (pwm_setting.PWM_MODE_FIFO_REGS.HDURATION + 1) * 32 - 1;
- pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
- LEDS_DEBUG("[LEDS]backlight_set_pwm:duty is %d\n", level);
- LEDS_DEBUG
- ("[LEDS]backlight_set_pwm:clk_src/div/high/low is %d%d%d%d\n",
- pwm_setting.clk_src, pwm_setting.clk_div,
- pwm_setting.PWM_MODE_FIFO_REGS.HDURATION,
- pwm_setting.PWM_MODE_FIFO_REGS.LDURATION);
- if (level > 0 && level <= 32) {
- pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
- pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 =
- (1 << level) - 1;
- pwm_set_spec_config(&pwm_setting);
- } else if (level > 32 && level <= 64) {
- pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 1;
- level -= 32;
- pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 =
- (1 << level) - 1;
- pwm_set_spec_config(&pwm_setting);
- } else {
- LEDS_DEBUG("[LEDS]Error level in backlight\n");
- mt_pwm_disable(pwm_setting.pwm_no,
- config_data->pmic_pad);
- }
- return 0;
- }
- }
- void mt_led_pwm_disable(int pwm_num)
- {
- struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi();
- mt_pwm_disable(pwm_num, cust_led_list->config_data.pmic_pad);
- }
- void mt_backlight_set_pwm_duty(int pwm_num, u32 level, u32 div,
- struct PWM_config *config_data)
- {
- mt_backlight_set_pwm(pwm_num, level, div, config_data);
- }
- void mt_backlight_set_pwm_div(int pwm_num, u32 level, u32 div,
- struct PWM_config *config_data)
- {
- mt_backlight_set_pwm(pwm_num, level, div, config_data);
- }
- void mt_backlight_get_pwm_fsel(unsigned int bl_div, unsigned int *bl_frequency)
- {
- }
- void mt_store_pwm_register(unsigned int addr, unsigned int value)
- {
- }
- unsigned int mt_show_pwm_register(unsigned int addr)
- {
- return 0;
- }
- int mt_brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, u32 div)
- {
- static bool first_time = true;
- LEDS_DEBUG("PMIC#%d:%d\n", pmic_type, level);
- mutex_lock(&leds_pmic_mutex);
- if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK0) {
- if ((button_flag_isink0 == 0) && (first_time == true)) { /* button
- flag ==0, means this ISINK is not for button backlight */
- if (button_flag_isink1 == 0)
- pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF); /* sw
- workround for sync leds status */
- if (button_flag_isink2 == 0)
- pmic_set_register_value(PMIC_ISINK_CH2_EN,
- NLED_OFF);
- if (button_flag_isink3 == 0)
- pmic_set_register_value(PMIC_ISINK_CH3_EN,
- NLED_OFF);
- first_time = false;
- }
- pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
- pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0);
- pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_CKSEL, 0);
- pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE);
- pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */
- pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, ISINK_1KHZ); /* 1KHz */
- if (level)
- pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON);
- else
- pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF);
- mutex_unlock(&leds_pmic_mutex);
- return 0;
- } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK1) {
- if ((button_flag_isink1 == 0) && (first_time == true)) { /* button
- flag ==0, means this ISINK is not for button backlight */
- if (button_flag_isink0 == 0)
- pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF); /* sw
- workround for sync leds status */
- if (button_flag_isink2 == 0)
- pmic_set_register_value(PMIC_ISINK_CH2_EN,
- NLED_OFF);
- if (button_flag_isink3 == 0)
- pmic_set_register_value(PMIC_ISINK_CH3_EN,
- NLED_OFF);
- first_time = false;
- }
- pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
- pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0);
- pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_CKSEL, 0);
- pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE);
- pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */
- pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15);
- pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, ISINK_1KHZ); /* 1KHz */
- if (level)
- pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON);
- else
- pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF);
- mutex_unlock(&leds_pmic_mutex);
- return 0;
- }
- mutex_unlock(&leds_pmic_mutex);
- return -1;
- }
- int mt_brightness_set_pmic_duty_store(u32 level, u32 div)
- {
- return -1;
- }
- int mt_mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level)
- {
- struct nled_setting led_tmp_setting = { 0, 0, 0 };
- int tmp_level = level;
- static bool button_flag;
- unsigned int BacklightLevelSupport =
- Cust_GetBacklightLevelSupport_byPWM();
- switch (cust->mode) {
- case MT65XX_LED_MODE_PWM:
- if (strcmp(cust->name, "lcd-backlight") == 0) {
- bl_brightness_hal = level;
- if (level == 0) {
- mt_pwm_disable(cust->data,
- cust->config_data.pmic_pad);
- } else {
- if (BacklightLevelSupport ==
- BACKLIGHT_LEVEL_PWM_256_SUPPORT)
- level = brightness_mapping(tmp_level);
- else
- level = brightness_mapto64(tmp_level);
- mt_backlight_set_pwm(cust->data, level,
- bl_div_hal,
- &cust->config_data);
- }
- bl_duty_hal = level;
- } else {
- if (level == 0) {
- led_tmp_setting.nled_mode = NLED_OFF;
- mt_led_set_pwm(cust->data, &led_tmp_setting);
- mt_pwm_disable(cust->data,
- cust->config_data.pmic_pad);
- } else {
- led_tmp_setting.nled_mode = NLED_ON;
- mt_led_set_pwm(cust->data, &led_tmp_setting);
- }
- }
- return 1;
- case MT65XX_LED_MODE_GPIO:
- LEDS_DEBUG("brightness_set_cust:go GPIO mode!!!!!\n");
- return ((cust_set_brightness) (cust->data)) (level);
- case MT65XX_LED_MODE_PMIC:
- /* for button baclight used SINK channel, when set button ISINK,
- don't do disable other ISINK channel */
- if ((strcmp(cust->name, "button-backlight") == 0)) {
- if (button_flag == false) {
- switch (cust->data) {
- case MT65XX_LED_PMIC_NLED_ISINK0:
- button_flag_isink0 = 1;
- break;
- case MT65XX_LED_PMIC_NLED_ISINK1:
- button_flag_isink1 = 1;
- break;
- case MT65XX_LED_PMIC_NLED_ISINK2:
- button_flag_isink2 = 1;
- break;
- case MT65XX_LED_PMIC_NLED_ISINK3:
- button_flag_isink3 = 1;
- break;
- default:
- break;
- }
- button_flag = true;
- }
- }
- return mt_brightness_set_pmic(cust->data, level, bl_div_hal);
- case MT65XX_LED_MODE_CUST_LCM:
- if (strcmp(cust->name, "lcd-backlight") == 0)
- bl_brightness_hal = level;
- LEDS_DEBUG("brightness_set_cust:backlight control by LCM\n");
- /* warning for this API revork */
- return ((cust_brightness_set) (cust->data)) (level, bl_div_hal);
- case MT65XX_LED_MODE_CUST_BLS_PWM:
- if (strcmp(cust->name, "lcd-backlight") == 0)
- bl_brightness_hal = level;
- return ((cust_set_brightness) (cust->data)) (level);
- case MT65XX_LED_MODE_NONE:
- default:
- break;
- }
- return -1;
- }
- void mt_mt65xx_led_work(struct work_struct *work)
- {
- struct mt65xx_led_data *led_data =
- container_of(work, struct mt65xx_led_data, work);
- LEDS_DEBUG("%s:%d\n", led_data->cust.name, led_data->level);
- mutex_lock(&leds_mutex);
- mt_mt65xx_led_set_cust(&led_data->cust, led_data->level);
- mutex_unlock(&leds_mutex);
- }
- void mt_mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
- {
- struct mt65xx_led_data *led_data =
- container_of(led_cdev, struct mt65xx_led_data, cdev);
- /* unsigned long flags; */
- /* spin_lock_irqsave(&leds_lock, flags); */
- #ifdef CONFIG_MTK_AAL_SUPPORT
- if (led_data->level != level) {
- led_data->level = level;
- if (strcmp(led_data->cust.name, "lcd-backlight") != 0) {
- LEDS_DEBUG("Set NLED directly %d at time %lu\n",
- led_data->level, jiffies);
- schedule_work(&led_data->work);
- } else {
- if (level != 0
- && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) {
- level = 1;
- } else {
- level =
- (level * CONFIG_LIGHTNESS_MAPPING_VALUE) /
- 255;
- }
- LEDS_DEBUG
- ("Set Backlight directly %d at time %lu, mapping level is %d\n",
- led_data->level, jiffies, level);
- /* mt_mt65xx_led_set_cust(&led_data->cust, led_data->level); */
- disp_aal_notify_backlight_changed((((1 <<
- MT_LED_INTERNAL_LEVEL_BIT_CNT)
- - 1) * level +
- 127) / 255);
- }
- }
- #else
- /* do something only when level is changed */
- if (led_data->level != level) {
- led_data->level = level;
- if (strcmp(led_data->cust.name, "lcd-backlight") != 0) {
- LEDS_DEBUG("Set NLED directly %d at time %lu\n",
- led_data->level, jiffies);
- schedule_work(&led_data->work);
- } else {
- if (level != 0
- && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) {
- level = 1;
- } else {
- level =
- (level * CONFIG_LIGHTNESS_MAPPING_VALUE) /
- 255;
- }
- LEDS_DEBUG
- ("Set Backlight directly %d at time %lu, mapping level is %d\n",
- led_data->level, jiffies, level);
- if (MT65XX_LED_MODE_CUST_BLS_PWM == led_data->cust.mode) {
- mt_mt65xx_led_set_cust(&led_data->cust,
- ((((1 <<
- MT_LED_INTERNAL_LEVEL_BIT_CNT)
- - 1) * level +
- 127) / 255));
- } else {
- mt_mt65xx_led_set_cust(&led_data->cust, level);
- }
- }
- }
- /* spin_unlock_irqrestore(&leds_lock, flags); */
- #endif
- /* if(0!=aee_kernel_Powerkey_is_press()) */
- /* aee_kernel_wdt_kick_Powkey_api("mt_mt65xx_led_set",WDT_SETBY_Backlight); */
- }
- int mt_mt65xx_blink_set(struct led_classdev *led_cdev,
- unsigned long *delay_on, unsigned long *delay_off)
- {
- struct mt65xx_led_data *led_data =
- container_of(led_cdev, struct mt65xx_led_data, cdev);
- static int got_wake_lock;
- struct nled_setting nled_tmp_setting = { 0, 0, 0 };
- /* only allow software blink when delay_on or delay_off changed */
- if (*delay_on != led_data->delay_on
- || *delay_off != led_data->delay_off) {
- led_data->delay_on = *delay_on;
- led_data->delay_off = *delay_off;
- if (led_data->delay_on && led_data->delay_off) { /* enable blink */
- led_data->level = 255; /* when enable blink then to set the level (255) */
- /* AP PWM all support OLD mode */
- if (led_data->cust.mode == MT65XX_LED_MODE_PWM) {
- nled_tmp_setting.nled_mode = NLED_BLINK;
- nled_tmp_setting.blink_off_time =
- led_data->delay_off;
- nled_tmp_setting.blink_on_time =
- led_data->delay_on;
- mt_led_set_pwm(led_data->cust.data,
- &nled_tmp_setting);
- return 0;
- } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC)
- && (led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK0
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK1
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK2
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK3)) {
- nled_tmp_setting.nled_mode = NLED_BLINK;
- nled_tmp_setting.blink_off_time =
- led_data->delay_off;
- nled_tmp_setting.blink_on_time =
- led_data->delay_on;
- mt_led_blink_pmic(led_data->cust.data,
- &nled_tmp_setting);
- return 0;
- } else if (!got_wake_lock) {
- wake_lock(&leds_suspend_lock);
- got_wake_lock = 1;
- }
- } else if (!led_data->delay_on && !led_data->delay_off) { /* disable blink */
- /* AP PWM all support OLD mode */
- if (led_data->cust.mode == MT65XX_LED_MODE_PWM) {
- nled_tmp_setting.nled_mode = NLED_OFF;
- mt_led_set_pwm(led_data->cust.data,
- &nled_tmp_setting);
- return 0;
- } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC)
- && (led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK0
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK1
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK2
- || led_data->cust.data ==
- MT65XX_LED_PMIC_NLED_ISINK3)) {
- mt_brightness_set_pmic(led_data->cust.data, 0,
- 0);
- return 0;
- } else if (got_wake_lock) {
- wake_unlock(&leds_suspend_lock);
- got_wake_lock = 0;
- }
- }
- return -1;
- }
- /* delay_on and delay_off are not changed */
- return 0;
- }
|