From 31c9040d47ccda0f69dc260c6ae8ba8a9edd6893 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 15 Jun 2018 17:23:24 +0800 Subject: [PATCH] backlight: optimize pwm level step calculation PD#168569: backlight: optimize pwm level step calculation Change-Id: I570c12cc44af399a861ca54ad98180314924c180 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/backlight/aml_bl.c | 174 ++++++++------ .../media/vout/backlight/aml_ldim/global_bl.c | 25 +- .../media/vout/backlight/aml_ldim/iw7027_bl.c | 2 +- .../media/vout/backlight/aml_ldim/ldim_dev_drv.c | 257 ++++++++++++--------- .../media/vout/backlight/aml_ldim/ldim_dev_drv.h | 7 +- .../media/vout/backlight/aml_ldim/ldim_drv.c | 10 +- .../media/vout/backlight/aml_ldim/ldim_drv.h | 6 +- .../media/vout/backlight/aml_ldim/ob3350_bl.c | 28 +-- include/linux/amlogic/media/vout/lcd/aml_ldim.h | 7 +- 9 files changed, 289 insertions(+), 227 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index b966ade..f9d8a2b 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -329,6 +329,14 @@ static void bl_gpio_set(int index, int value) } } +static inline unsigned int bl_do_div(unsigned long num, unsigned int den) +{ + unsigned long ret = num; + + do_div(ret, den); + return (unsigned int)ret; +} + /* ****************************************************** */ #define BL_PINMUX_MAX 6 static char *bl_pinmux_str[BL_PINMUX_MAX] = { @@ -441,8 +449,6 @@ static void bl_set_pwm_vs(struct bl_pwm_config_s *bl_pwm, ve[i] = 0x1fff; } } else { - bl_pwm->pwm_level = - (((bl_pwm->pwm_cnt * bl_pwm->pwm_duty / 10) + 5) / 10); pwm_hi = bl_pwm->pwm_level; n = bl_pwm->pwm_freq; sw = (bl_pwm->pwm_cnt * 10 / n + 5) / 10; @@ -486,15 +492,13 @@ static void bl_set_pwm_vs(struct bl_pwm_config_s *bl_pwm, static void bl_set_pwm_normal(struct bl_pwm_config_s *bl_pwm, unsigned int pol, unsigned int out_level) { - unsigned int pwm_period, pwm_duty, port_index; + unsigned int port_index; if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { BLERR("%s: invalid bl_pwm_ch\n", __func__); return; } - pwm_period = 1000000000 / bl_pwm->pwm_freq; - pwm_duty = (pwm_period * bl_pwm->pwm_duty) / 100; port_index = bl_pwm->pwm_data.port_index; if (bl_debug_print_flag) { pr_info("pwm: pwm=0x%p, port_index=%d, meson_index=%d\n", @@ -503,8 +507,8 @@ static void bl_set_pwm_normal(struct bl_pwm_config_s *bl_pwm, if (((port_index % 2) == bl_pwm->pwm_data.meson_index) && (port_index == bl_pwm->pwm_port)) { bl_pwm->pwm_data.state.polarity = pol; - bl_pwm->pwm_data.state.duty_cycle = pwm_duty; - bl_pwm->pwm_data.state.period = pwm_period; + bl_pwm->pwm_data.state.duty_cycle = bl_pwm->pwm_level; + bl_pwm->pwm_data.state.period = bl_pwm->pwm_cnt; bl_pwm->pwm_data.state.enabled = true; if (bl_debug_print_flag) { BLPR( @@ -934,6 +938,8 @@ static unsigned int bl_level_mapping(unsigned int level) static void bl_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { + unsigned long temp; + if (bl_pwm_bypass) return; @@ -958,10 +964,16 @@ static void bl_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) } } + temp = bl_pwm->pwm_cnt; + bl_pwm->pwm_level = bl_do_div(((temp * bl_pwm->pwm_duty) + 50), 100); + if (bl_debug_print_flag) { BLPR("pwm port %d: duty=%d%%, duty_max=%d%%, duty_min=%d%%\n", bl_pwm->pwm_port, bl_pwm->pwm_duty, bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + BLPR("pwm port %d: pwm_max=%d, pwm_min=%d, pwm_level=%d\n", + bl_pwm->pwm_port, + bl_pwm->pwm_max, bl_pwm->pwm_min, bl_pwm->pwm_level); } bl_set_pwm(bl_pwm); } @@ -970,8 +982,9 @@ static void bl_set_level_pwm(struct bl_pwm_config_s *bl_pwm, unsigned int level) { unsigned int min = bl_pwm->level_min; unsigned int max = bl_pwm->level_max; - unsigned int pwm_max = bl_pwm->pwm_duty_max; - unsigned int pwm_min = bl_pwm->pwm_duty_min; + unsigned int pwm_max = bl_pwm->pwm_max; + unsigned int pwm_min = bl_pwm->pwm_min; + unsigned long temp; if (bl_pwm_bypass) return; @@ -980,17 +993,23 @@ static void bl_set_level_pwm(struct bl_pwm_config_s *bl_pwm, unsigned int level) max = bl_level_mapping(max); min = bl_level_mapping(min); if ((max <= min) || (level < min)) { - bl_pwm->pwm_duty = pwm_min; + bl_pwm->pwm_level = pwm_min; } else { - bl_pwm->pwm_duty = ((pwm_max - pwm_min) * (level - min) * - 10 / (max - min) + 5) / 10 + pwm_min; + temp = pwm_max - pwm_min; + bl_pwm->pwm_level = + bl_do_div((temp * (level - min)), (max - min)) + + pwm_min; } + temp = bl_pwm->pwm_level; + bl_pwm->pwm_duty = (bl_do_div((temp * 1000), bl_pwm->pwm_cnt) + 5) / 10; if (bl_debug_print_flag) { - BLPR("port %d mapping: level=%d, level_max=%d, level_min=%d\n", + BLPR("pwm port %d: level=%d, level_max=%d, level_min=%d\n", bl_pwm->pwm_port, level, max, min); - BLPR("port %d: duty=%d%%, duty_max=%d%%, duty_min=%d%%\n", - bl_pwm->pwm_port, bl_pwm->pwm_duty, pwm_max, pwm_min); + BLPR( + "pwm port %d: duty=%d%%, pwm_max=%d, pwm_min=%d, pwm_level=%d\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty, + bl_pwm->pwm_max, bl_pwm->pwm_min, bl_pwm->pwm_level); } bl_set_pwm(bl_pwm); @@ -1196,6 +1215,7 @@ enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str) void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) { unsigned int cnt; + unsigned long temp; if (bl_debug_print_flag) { BLPR("%s pwm_port %d: freq = %u\n", @@ -1206,19 +1226,21 @@ void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) case BL_PWM_VS: cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; bl_pwm->pwm_cnt = cnt; - bl_pwm->pwm_max = (bl_pwm->pwm_cnt * - bl_pwm->pwm_duty_max / 100); - bl_pwm->pwm_min = (bl_pwm->pwm_cnt * - bl_pwm->pwm_duty_min / 100); - if (bl_debug_print_flag) - BLPR("pwm_cnt = %u, pwm_max = %u, pwm_min = %u\n", - bl_pwm->pwm_cnt, - bl_pwm->pwm_max, - bl_pwm->pwm_min); break; default: + /* for pwm api: pwm_period */ + bl_pwm->pwm_cnt = 1000000000 / bl_pwm->pwm_freq; break; } + + temp = bl_pwm->pwm_cnt; + bl_pwm->pwm_max = bl_do_div((temp * bl_pwm->pwm_duty_max), 100); + bl_pwm->pwm_min = bl_do_div((temp * bl_pwm->pwm_duty_min), 100); + + if (bl_debug_print_flag) { + BLPR("pwm_cnt = %u, pwm_max = %u, pwm_min = %u\n", + bl_pwm->pwm_cnt, bl_pwm->pwm_max, bl_pwm->pwm_min); + } } static void aml_bl_config_print(struct bl_config_s *bconf) @@ -1258,23 +1280,20 @@ static void aml_bl_config_print(struct bl_config_s *bconf) if (bconf->bl_pwm) { bl_pwm = bconf->bl_pwm; BLPR("pwm_index = %d\n", bl_pwm->index); - BLPR("pwm_method = %d\n", bl_pwm->pwm_method); BLPR("pwm_port = %d\n", bl_pwm->pwm_port); + BLPR("pwm_method = %d\n", bl_pwm->pwm_method); if (bl_pwm->pwm_port == BL_PWM_VS) { BLPR("pwm_freq = %d x vfreq\n", bl_pwm->pwm_freq); - BLPR("pwm_cnt = %u\n", bl_pwm->pwm_cnt); } else { BLPR("pwm_freq = %uHz\n", bl_pwm->pwm_freq); - BLPR("pwm_cnt = %u\n", bl_pwm->pwm_cnt); - BLPR("pwm_pre_div = %u\n", - bl_pwm->pwm_pre_div); } BLPR("pwm_level_max = %u\n", bl_pwm->level_max); BLPR("pwm_level_min = %u\n", bl_pwm->level_min); BLPR("pwm_duty_max = %d%%\n", bl_pwm->pwm_duty_max); BLPR("pwm_duty_min = %d%%\n", bl_pwm->pwm_duty_min); + BLPR("pwm_cnt = %u\n", bl_pwm->pwm_cnt); BLPR("pwm_max = %u\n", bl_pwm->pwm_max); BLPR("pwm_min = %u\n", bl_pwm->pwm_min); } @@ -1288,20 +1307,14 @@ static void aml_bl_config_print(struct bl_config_s *bconf) if (bconf->bl_pwm_combo0) { bl_pwm = bconf->bl_pwm_combo0; BLPR("pwm_combo0_index = %d\n", bl_pwm->index); - BLPR("pwm_combo0_method = %d\n", bl_pwm->pwm_method); BLPR("pwm_combo0_port = %d\n", bl_pwm->pwm_port); + BLPR("pwm_combo0_method = %d\n", bl_pwm->pwm_method); if (bl_pwm->pwm_port == BL_PWM_VS) { BLPR("pwm_combo0_freq = %d x vfreq\n", bl_pwm->pwm_freq); - BLPR("pwm_combo0_cnt = %u\n", - bl_pwm->pwm_cnt); } else { BLPR("pwm_combo0_freq = %uHz\n", bl_pwm->pwm_freq); - BLPR("pwm_combo0_cnt = %u\n", - bl_pwm->pwm_cnt); - BLPR("pwm_combo0_pre_div = %u\n", - bl_pwm->pwm_pre_div); } BLPR("pwm_combo0_level_max = %u\n", bl_pwm->level_max); BLPR("pwm_combo0_level_min = %u\n", bl_pwm->level_min); @@ -1309,27 +1322,22 @@ static void aml_bl_config_print(struct bl_config_s *bconf) bl_pwm->pwm_duty_max); BLPR("pwm_combo0_duty_min = %d\n", bl_pwm->pwm_duty_min); - BLPR("pwm_combo0_max = %u\n", bl_pwm->pwm_max); - BLPR("pwm_combo0_min = %u\n", bl_pwm->pwm_min); + BLPR("pwm_combo0_pwm_cnt = %u\n", bl_pwm->pwm_cnt); + BLPR("pwm_combo0_pwm_max = %u\n", bl_pwm->pwm_max); + BLPR("pwm_combo0_pwm_min = %u\n", bl_pwm->pwm_min); } /* pwm_combo_1 */ if (bconf->bl_pwm_combo1) { bl_pwm = bconf->bl_pwm_combo1; BLPR("pwm_combo1_index = %d\n", bl_pwm->index); - BLPR("pwm_combo1_method = %d\n", bl_pwm->pwm_method); BLPR("pwm_combo1_port = %d\n", bl_pwm->pwm_port); + BLPR("pwm_combo1_method = %d\n", bl_pwm->pwm_method); if (bl_pwm->pwm_port == BL_PWM_VS) { BLPR("pwm_combo1_freq = %d x vfreq\n", bl_pwm->pwm_freq); - BLPR("pwm_combo1_cnt = %u\n", - bl_pwm->pwm_cnt); } else { BLPR("pwm_combo1_freq = %uHz\n", bl_pwm->pwm_freq); - BLPR("pwm_combo1_cnt = %u\n", - bl_pwm->pwm_cnt); - BLPR("pwm_combo1_pre_div = %u\n", - bl_pwm->pwm_pre_div); } BLPR("pwm_combo1_level_max = %u\n", bl_pwm->level_max); BLPR("pwm_combo1_level_min = %u\n", bl_pwm->level_min); @@ -1337,8 +1345,9 @@ static void aml_bl_config_print(struct bl_config_s *bconf) bl_pwm->pwm_duty_max); BLPR("pwm_combo1_duty_min = %d\n", bl_pwm->pwm_duty_min); - BLPR("pwm_combo1_max = %u\n", bl_pwm->pwm_max); - BLPR("pwm_combo1_min = %u\n", bl_pwm->pwm_min); + BLPR("pwm_combo1_pwm_cnt = %u\n", bl_pwm->pwm_cnt); + BLPR("pwm_combo1_pwm_max = %u\n", bl_pwm->pwm_max); + BLPR("pwm_combo1_pwm_min = %u\n", bl_pwm->pwm_min); } break; default: @@ -1946,13 +1955,12 @@ static int aml_bl_config_load_from_unifykey(struct bl_config_s *bconf) } static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, - struct platform_device *pdev) + struct device_node *blnode) { int ret = 0; int index0 = BL_PWM_MAX; int index1 = BL_PWM_MAX; phandle pwm_phandle; - struct device_node *blnode = pdev->dev.of_node; struct device_node *pnode = NULL; struct device_node *child; struct bl_pwm_config_s *bl_pwm = NULL; @@ -1960,43 +1968,42 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, ret = of_property_read_u32(blnode, "bl_pwm_config", &pwm_phandle); if (ret) { BLERR("not match bl_pwm_config node\n"); - } else { - pnode = of_find_node_by_phandle(pwm_phandle); - if (!pnode) { - BLERR("can't find bl_pwm_config node\n"); - return -1; - } + return -1; + } + pnode = of_find_node_by_phandle(pwm_phandle); + if (!pnode) { + BLERR("can't find bl_pwm_config node\n"); + return -1; } /*request for pwm device */ for_each_child_of_node(pnode, child) { ret = of_property_read_u32(child, "pwm_port_index", &index0); if (ret) { - BLERR("invalid %d pwm_port_index parameters\n", index0); + BLERR("failed to get pwm_port_index\n"); return ret; } ret = of_property_read_u32_index(child, "pwms", 1, &index1); if (ret) { - BLERR("invalid %d meson_pwm_index\n", index1); + BLERR("failed to get meson_pwm_index\n"); return ret; } if (index0 >= BL_PWM_VS) continue; + if ((index0 % 2) != index1) + continue; bl_pwm = NULL; switch (bconf->method) { case BL_CTRL_PWM: - if ((index0 == bconf->bl_pwm->pwm_port) && - ((index0 % 2) == index1)) + if (index0 == bconf->bl_pwm->pwm_port) bl_pwm = bconf->bl_pwm; break; case BL_CTRL_PWM_COMBO: - if ((index0 == bconf->bl_pwm_combo0->pwm_port) && - ((index0 % 2) == index1)) + if (index0 == bconf->bl_pwm_combo0->pwm_port) bl_pwm = bconf->bl_pwm_combo0; - if ((index0 == bconf->bl_pwm_combo1->pwm_port) && - ((index0 % 2) == index1)) + if (index0 == bconf->bl_pwm_combo1->pwm_port) bl_pwm = bconf->bl_pwm_combo1; break; default: @@ -2078,7 +2085,7 @@ static int aml_bl_config_load(struct bl_config_s *bconf, switch (bconf->method) { case BL_CTRL_PWM: case BL_CTRL_PWM_COMBO: - ret = aml_bl_pwm_channel_register(bconf, pdev); + ret = aml_bl_pwm_channel_register(bconf, pdev->dev.of_node); bl_pwm_pinmux_set(bconf); break; #ifdef CONFIG_AMLOGIC_BL_EXTERN @@ -2440,17 +2447,22 @@ static ssize_t bl_debug_pwm_show(struct class *class, bl_pwm = bconf->bl_pwm; len += sprintf(buf+len, "pwm_index: %d\n" - "pwm_method: %d\n" "pwm_port: %d\n" + "pwm_method: %d\n" "pwm_freq: %d\n" "pwm_duty_max: %d\n" "pwm_duty_min: %d\n" "pwm_cnt: %d\n" + "pwm_max: %d\n" + "pwm_min: %d\n" + "pwm_level: %d\n" "pwm_duty: %d%%\n", - bl_pwm->index, bl_pwm->pwm_method, - bl_pwm->pwm_port, bl_pwm->pwm_freq, + bl_pwm->index, bl_pwm->pwm_port, + bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, - bl_pwm->pwm_cnt, bl_pwm->pwm_duty); + bl_pwm->pwm_cnt, + bl_pwm->pwm_max, bl_pwm->pwm_min, + bl_pwm->pwm_level, bl_pwm->pwm_duty); switch (bl_pwm->pwm_port) { case BL_PWM_A: case BL_PWM_B: @@ -2503,17 +2515,22 @@ static ssize_t bl_debug_pwm_show(struct class *class, bl_pwm = bconf->bl_pwm_combo0; len += sprintf(buf+len, "pwm_0_index: %d\n" - "pwm_0_method: %d\n" "pwm_0_port: %d\n" + "pwm_0_method: %d\n" "pwm_0_freq: %d\n" "pwm_0_duty_max: %d\n" "pwm_0_duty_min: %d\n" "pwm_0_cnt: %d\n" + "pwm_0_max: %d\n" + "pwm_0_min: %d\n" + "pwm_0_level: %d\n" "pwm_0_duty: %d%%\n", - bl_pwm->index, bl_pwm->pwm_method, - bl_pwm->pwm_port, bl_pwm->pwm_freq, + bl_pwm->index, bl_pwm->pwm_port, + bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, - bl_pwm->pwm_cnt, bl_pwm->pwm_duty); + bl_pwm->pwm_cnt, + bl_pwm->pwm_max, bl_pwm->pwm_min, + bl_pwm->pwm_level, bl_pwm->pwm_duty); switch (bl_pwm->pwm_port) { case BL_PWM_A: case BL_PWM_B: @@ -2561,17 +2578,22 @@ static ssize_t bl_debug_pwm_show(struct class *class, len += sprintf(buf+len, "\n" "pwm_1_index: %d\n" - "pwm_1_method: %d\n" "pwm_1_port: %d\n" + "pwm_1_method: %d\n" "pwm_1_freq: %d\n" "pwm_1_duty_max: %d\n" "pwm_1_duty_min: %d\n" "pwm_1_cnt: %d\n" + "pwm_1_max: %d\n" + "pwm_1_min: %d\n" + "pwm_1_level: %d\n" "pwm_1_duty: %d%%\n", - bl_pwm->index, bl_pwm->pwm_method, - bl_pwm->pwm_port, bl_pwm->pwm_freq, + bl_pwm->index, bl_pwm->pwm_port, + bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, - bl_pwm->pwm_cnt, bl_pwm->pwm_duty); + bl_pwm->pwm_cnt, + bl_pwm->pwm_max, bl_pwm->pwm_min, + bl_pwm->pwm_level, bl_pwm->pwm_duty); switch (bl_pwm->pwm_port) { case BL_PWM_A: case BL_PWM_B: diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c index 4835aed..ad81ac4 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c @@ -44,7 +44,6 @@ static int global_hw_init_on(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); ldim_drv->pinmux_ctrl(ldim_drv->ldev_conf->pinmux_name); mdelay(2); ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, @@ -60,29 +59,16 @@ static int global_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); + ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); return 0; } -static unsigned int global_get_value(unsigned int level) -{ - struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - - unsigned int val; - unsigned int dim_max, dim_min; - - dim_max = ldim_drv->ldev_conf->dim_max; - dim_min = ldim_drv->ldev_conf->dim_min; - - val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - - return val; -} - static int global_smr(unsigned short *buf, unsigned char len) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - unsigned short val; + unsigned int dim_max, dim_min; + unsigned int level, val; if (global_on_flag == 0) { if (ldim_debug_print) @@ -95,7 +81,10 @@ static int global_smr(unsigned short *buf, unsigned char len) return -1; } - val = global_get_value(buf[0]); + dim_max = ldim_drv->ldev_conf->dim_max; + dim_min = ldim_drv->ldev_conf->dim_min; + level = buf[0]; + val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); ldim_drv->ldev_conf->pwm_config.pwm_duty = val; ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index d3317fb..d9cbc5f 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -204,7 +204,6 @@ static int iw7027_hw_init_on(void) /* step 1: system power_on */ ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); /* step 2: delay for internal logic stable */ mdelay(10); @@ -266,6 +265,7 @@ static int iw7027_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); + ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); return 0; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index 3e06167..d7fe8dd 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -273,101 +273,33 @@ unsigned int ldim_gpio_get(int index) return gpiod_get_value(ld_gpio->gpio); } -static unsigned int pwm_reg[6] = { - PWM_PWM_A, - PWM_PWM_B, - PWM_PWM_C, - PWM_PWM_D, - PWM_PWM_E, - PWM_PWM_F, -}; - -static unsigned int pwm_reg_txlx[6] = { - PWM_PWM_A_TXLX, - PWM_PWM_B_TXLX, - PWM_PWM_C_TXLX, - PWM_PWM_D_TXLX, - PWM_PWM_E_TXLX, - PWM_PWM_F_TXLX, -}; - -void ldim_set_duty_pwm(struct bl_pwm_config_s *ld_pwm) +void ldim_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned int pwm_hi = 0, pwm_lo = 0; - unsigned int port = ld_pwm->pwm_port; - unsigned int vs[4], ve[4], sw, n, i; - struct aml_bl_drv_s *bl_drv = aml_bl_get_driver(); + unsigned long temp; - if (ld_pwm->pwm_port >= BL_PWM_MAX) + if (bl_pwm->pwm_port >= BL_PWM_MAX) return; - ld_pwm->pwm_level = ld_pwm->pwm_cnt * ld_pwm->pwm_duty / 100; - if (ldim_debug_print) { - LDIMPR("pwm port %d: duty=%d%%, duty_max=%d, duty_min=%d\n", - ld_pwm->pwm_port, ld_pwm->pwm_duty, - ld_pwm->pwm_duty_max, ld_pwm->pwm_duty_min); - } + temp = bl_pwm->pwm_cnt; + temp = (((temp * bl_pwm->pwm_duty) + 50) / 100); + bl_pwm->pwm_level = (unsigned int)temp; - switch (ld_pwm->pwm_method) { - case BL_PWM_POSITIVE: - pwm_hi = ld_pwm->pwm_level; - pwm_lo = ld_pwm->pwm_cnt - ld_pwm->pwm_level; - break; - case BL_PWM_NEGATIVE: - pwm_lo = ld_pwm->pwm_level; - pwm_hi = ld_pwm->pwm_cnt - ld_pwm->pwm_level; - break; - default: - LDIMERR("port %d: invalid pwm_method %d\n", - port, ld_pwm->pwm_method); - break; - } if (ldim_debug_print) { - LDIMPR("port %d: pwm_cnt=%d, pwm_hi=%d, pwm_lo=%d\n", - port, ld_pwm->pwm_cnt, pwm_hi, pwm_lo); - } - - switch (port) { - case BL_PWM_A: - case BL_PWM_B: - case BL_PWM_C: - case BL_PWM_D: - case BL_PWM_E: - case BL_PWM_F: - if (bl_drv->data->chip_type == BL_CHIP_TXLX) - bl_cbus_write(pwm_reg_txlx[port], - (pwm_hi << 16) | pwm_lo); - else - bl_cbus_write(pwm_reg[port], (pwm_hi << 16) | pwm_lo); - break; - case BL_PWM_VS: - n = ld_pwm->pwm_freq; - sw = (ld_pwm->pwm_cnt * 10 / n + 5) / 10; - pwm_hi = (pwm_hi * 10 / n + 5) / 10; - pwm_hi = (pwm_hi > 1) ? pwm_hi : 1; - if (ldim_debug_print) - LDIMPR("n=%d, sw=%d, pwm_high=%d\n", n, sw, pwm_hi); - for (i = 0; i < n; i++) { - vs[i] = 1 + (sw * i); - ve[i] = vs[i] + pwm_hi - 1; - if (ldim_debug_print) { - LDIMPR("vs[%d]=%d, ve[%d]=%d\n", - i, vs[i], i, ve[i]); - } - } - for (i = n; i < 4; i++) { - vs[i] = 0xffff; - ve[i] = 0xffff; - } - bl_vcbus_write(VPU_VPU_PWM_V0, (2 << 14) | /* vsync latch */ - (ve[0] << 16) | (vs[0])); - bl_vcbus_write(VPU_VPU_PWM_V1, (ve[1] << 16) | (vs[1])); - bl_vcbus_write(VPU_VPU_PWM_V2, (ve[2] << 16) | (vs[2])); - bl_vcbus_write(VPU_VPU_PWM_V3, (ve[3] << 16) | (vs[3])); - break; - default: - break; + LDIMPR( + "pwm port %d: duty=%d%%, pwm_max=%d, pwm_min=%d, pwm_level=%d\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty, + bl_pwm->pwm_max, bl_pwm->pwm_min, bl_pwm->pwm_level); } + + bl_pwm_ctrl(bl_pwm, 1); +} + +void ldim_pwm_off(struct bl_pwm_config_s *bl_pwm) +{ + if (bl_pwm->pwm_port >= BL_PWM_MAX) + return; + + bl_pwm_ctrl(bl_pwm, 0); } /* ****************************************************** */ @@ -381,19 +313,23 @@ static char *ldim_pinmux_str[] = { static int ldim_pwm_pinmux_ctrl(char *pin_str) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - struct bl_pwm_config_s *ld_pwm; + struct bl_pwm_config_s *bl_pwm; int ret = 0; if (strcmp(pin_str, "invalid") == 0) return 0; - ld_pwm = &ldim_drv->ldev_conf->pwm_config; - if (ld_pwm->pwm_port >= BL_PWM_MAX) + bl_pwm = &ldim_drv->ldev_conf->pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_MAX) + return 0; + + ldim_set_duty_pwm(bl_pwm); + + if (ldim_drv->pinmux_flag) return 0; - bl_pwm_ctrl(ld_pwm, 1); /* request pwm pinmux */ - if (ld_pwm->pwm_port == BL_PWM_VS) { + if (bl_pwm->pwm_port == BL_PWM_VS) { ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, ldim_pinmux_str[1]); if (IS_ERR(ldim_drv->pin)) { @@ -414,6 +350,7 @@ static int ldim_pwm_pinmux_ctrl(char *pin_str) ldim_pinmux_str[0], ldim_drv->pin); } } + ldim_drv->pinmux_flag = 1; return ret; } @@ -433,7 +370,10 @@ static int ldim_pwm_vs_update(void) static void ldim_config_print(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - struct bl_pwm_config_s *ld_pwm; + struct aml_bl_drv_s *bl_drv = aml_bl_get_driver(); + struct bl_pwm_config_s *bl_pwm; + struct pwm_state pstate; + unsigned int value; int i, n, len = 0; char *str = NULL; @@ -444,7 +384,7 @@ static void ldim_config_print(void) ldim_drv->valid_flag, ldim_drv->dev_index); if (ldim_drv->ldev_conf) { - ld_pwm = &ldim_drv->ldev_conf->pwm_config; + bl_pwm = &ldim_drv->ldev_conf->pwm_config; pr_info("dev_name = %s\n" "type = %d\n" "en_gpio = %d\n" @@ -508,21 +448,125 @@ static void ldim_config_print(void) default: break; } - if (ld_pwm->pwm_port < BL_PWM_MAX) { - pr_info("pwm_port = %d\n" - "pwm_pol = %d\n" - "pwm_freq = %d\n" - "pwm_duty = %d%%\n" - "pwm_pointer = %p\n", - ld_pwm->pwm_port, ld_pwm->pwm_method, - ld_pwm->pwm_freq, ld_pwm->pwm_duty, - ld_pwm->pwm_data.pwm); + if (bl_pwm->pwm_port < BL_PWM_MAX) { + pr_info("pwm_port: %d\n" + "pwm_pol: %d\n" + "pwm_freq: %d\n" + "pwm_cnt: %d\n" + "pwm_level: %d\n" + "pwm_duty: %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_method, + bl_pwm->pwm_freq, bl_pwm->pwm_cnt, + bl_pwm->pwm_level, bl_pwm->pwm_duty); + switch (bl_pwm->pwm_port) { + case BL_PWM_A: + case BL_PWM_B: + case BL_PWM_C: + case BL_PWM_D: + case BL_PWM_E: + case BL_PWM_F: + if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { + pr_info("pwm invalid\n"); + break; + } + pr_info("pwm_pointer: %p\n", + bl_pwm->pwm_data.pwm); + pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); + pr_info("pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", + pstate.period, pstate.duty_cycle, + pstate.polarity, pstate.enabled); + value = bl_cbus_read(bl_drv->data->pwm_reg[ + bl_pwm->pwm_port]); + pr_info("pwm_reg: 0x%08x\n", + value); + break; + case BL_PWM_VS: + pr_info("pwm_reg0: 0x%08x\n" + "pwm_reg1: 0x%08x\n" + "pwm_reg2: 0x%08x\n" + "pwm_reg3: 0x%08x\n", + bl_vcbus_read(VPU_VPU_PWM_V0), + bl_vcbus_read(VPU_VPU_PWM_V1), + bl_vcbus_read(VPU_VPU_PWM_V2), + bl_vcbus_read(VPU_VPU_PWM_V3)); + break; + default: + break; + } } } else { pr_info("device config is null\n"); } } +static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, + struct device_node *blnode) +{ + int ret = 0; + int index0 = BL_PWM_MAX; + int index1 = BL_PWM_MAX; + phandle pwm_phandle; + struct device_node *pnode = NULL; + struct device_node *child; + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + + ret = of_property_read_u32(blnode, "bl_pwm_config", &pwm_phandle); + if (ret) { + LDIMERR("not match bl_pwm_config node\n"); + return -1; + } + pnode = of_find_node_by_phandle(pwm_phandle); + if (!pnode) { + LDIMERR("can't find bl_pwm_config node\n"); + return -1; + } + + /*request for pwm device */ + for_each_child_of_node(pnode, child) { + ret = of_property_read_u32(child, "pwm_port_index", &index0); + if (ret) { + LDIMERR("failed to get pwm_port_index\n"); + return ret; + } + ret = of_property_read_u32_index(child, "pwms", 1, &index1); + if (ret) { + LDIMERR("failed to get meson_pwm_index\n"); + return ret; + } + + if (index0 >= BL_PWM_VS) + continue; + if ((index0 % 2) != index1) + continue; + if (index0 != bl_pwm->pwm_port) + continue; + + bl_pwm->pwm_data.port_index = index0; + bl_pwm->pwm_data.meson_index = index1; + bl_pwm->pwm_data.pwm = devm_of_pwm_get( + ldim_drv->dev, child, NULL); + if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { + ret = PTR_ERR(bl_pwm->pwm_data.pwm); + LDIMERR("unable to request bl_pwm\n"); + return ret; + } + bl_pwm->pwm_data.meson = to_meson_pwm( + bl_pwm->pwm_data.pwm->chip); + pwm_init_state(bl_pwm->pwm_data.pwm, &(bl_pwm->pwm_data.state)); + LDIMPR("register pwm_ch(%d) 0x%p\n", + bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); + } + + LDIMPR("%s ok\n", __func__); + + return ret; + +} + static int ldim_dev_get_config_from_dts(struct device_node *np, int index) { char ld_propname[20]; @@ -598,6 +642,11 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) ldim_dev_config.pwm_config.pwm_duty); bl_pwm_config_init(&ldim_dev_config.pwm_config); + + if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_VS) { + ldim_dev_pwm_channel_register( + &ldim_dev_config.pwm_config, np); + } } ret = of_property_read_u32_array(child, "en_gpio_on_off", temp, 3); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.h index 690969c..6d5a111 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.h @@ -18,14 +18,19 @@ #ifndef __LDIM_DEV_DRV_H #define __LDIM_DEV_DRV_H +/* ldim global api */ extern void ldim_gpio_set(int index, int value); extern unsigned int ldim_gpio_get(int index); +extern void ldim_set_duty_pwm(struct bl_pwm_config_s *ld_pwm); +extern void ldim_pwm_off(struct bl_pwm_config_s *ld_pwm); +/* ldim dev api */ extern int ldim_dev_iw7027_probe(void); extern int ldim_dev_iw7027_remove(void); + extern int ldim_dev_ob3350_probe(void); extern int ldim_dev_ob3350_remove(void); -extern void ldim_set_duty_pwm(struct bl_pwm_config_s *ld_pwm); + extern int ldim_dev_global_probe(void); extern int ldim_dev_global_remove(void); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index 409848b..440f364 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -3172,6 +3172,7 @@ static struct aml_ldim_driver_s ldim_driver = { .valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */ .dev_index = 0xff, .static_pic_flag = 0, + .pinmux_flag = 0, .ldim_conf = &ldim_config, .ldev_conf = NULL, .ldim_matrix_buf = NULL, @@ -3999,8 +4000,7 @@ static ssize_t ldim_attr_store(struct class *cla, fw_print_frequent, Dbprint_lv); } else if (!strcmp(parm[0], "info")) { - pr_info("ldim_drv_ver = %s\n", - LDIM_DRV_VER); + pr_info("ldim_drv_ver: %s\n", LDIM_DRV_VER); ldim_driver.config_print(); pr_info("\nldim_blk_row = %d\n" "ldim_blk_col = %d\n" @@ -4134,7 +4134,7 @@ int aml_ldim_get_config_dts(struct device_node *child) if (ret) LDIMERR("failed to get ldim_dev_index\n"); else - ldim_driver.dev_index = para[0]; + ldim_driver.dev_index = (unsigned char)para[0]; LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); return 0; @@ -4269,6 +4269,10 @@ int aml_ldim_probe(struct platform_device *pdev) struct ldim_dev_s *devp = &ldim_dev; struct aml_bl_drv_s *bl_drv = aml_bl_get_driver(); +#ifdef LDIM_DEBUG_INFO + ldim_debug_print = 1; +#endif + /* function flag */ ldim_on_flag = 0; ldim_func_en = 0; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index 56fb088..1e08047 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -28,11 +28,13 @@ #define Wr(reg, val) aml_write_vcbus(reg, val) #define Rd(adr) aml_read_vcbus(adr) -/*#define LDIM_EXT_DEBUG_INFO*/ +/*#define LDIM_DEBUG_INFO*/ #define LDIMPR(fmt, args...) pr_info("ldim: "fmt"", ## args) #define LDIMERR(fmt, args...) pr_err("ldim: error: "fmt"", ## args) -#define LDIM_DRV_VER "20180629" +/*20180629: initial version */ +/*20180725: new pwm control flow support */ +#define LDIM_DRV_VER "20180725" extern unsigned char ldim_debug_print; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c index 5b64f47..7f5e91c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c @@ -47,7 +47,7 @@ static int ob3350_hw_init_on(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); mdelay(2); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->pinmux_ctrl(ldim_drv->ldev_conf->pinmux_name); mdelay(20); @@ -60,42 +60,32 @@ static int ob3350_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); + ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); return 0; } -static unsigned int ob3350_get_value(unsigned int level) -{ - struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - - unsigned int val; - unsigned int dim_max, dim_min; - - dim_max = ldim_drv->ldev_conf->dim_max; - dim_min = ldim_drv->ldev_conf->dim_min; - - val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - - return val; -} - static int ob3350_smr(unsigned short *buf, unsigned char len) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - unsigned short val; + unsigned int dim_max, dim_min; + unsigned int level, val; if (ob3350_on_flag == 0) { if (ldim_debug_print) LDIMPR("%s: on_flag=%d\n", __func__, ob3350_on_flag); return 0; - } + } if (len != 1) { LDIMERR("%s: data len %d invalid\n", __func__, len); return -1; } - val = ob3350_get_value(buf[0]); + dim_max = ldim_drv->ldev_conf->dim_max; + dim_min = ldim_drv->ldev_conf->dim_min; + level = buf[0]; + val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); ldim_drv->ldev_conf->pwm_config.pwm_duty = val; ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); diff --git a/include/linux/amlogic/media/vout/lcd/aml_ldim.h b/include/linux/amlogic/media/vout/lcd/aml_ldim.h index c672e41..dac5acc 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_ldim.h +++ b/include/linux/amlogic/media/vout/lcd/aml_ldim.h @@ -80,9 +80,10 @@ struct ldim_dev_config_s { /*******global API******/ struct aml_ldim_driver_s { - int valid_flag; - int dev_index; - int static_pic_flag; + unsigned char valid_flag; + unsigned char dev_index; + unsigned char static_pic_flag; + unsigned char pinmux_flag; struct ldim_config_s *ldim_conf; struct ldim_dev_config_s *ldev_conf; -- 2.7.4