backlight: optimize pwm level step calculation
authorEvoke Zhang <evoke.zhang@amlogic.com>
Fri, 15 Jun 2018 09:23:24 +0000 (17:23 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 1 Aug 2018 11:07:52 +0000 (04:07 -0700)
PD#168569: backlight: optimize pwm level step calculation

Change-Id: I570c12cc44af399a861ca54ad98180314924c180
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
drivers/amlogic/media/vout/backlight/aml_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.h
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h
drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c
include/linux/amlogic/media/vout/lcd/aml_ldim.h

index b966ade..f9d8a2b 100644 (file)
@@ -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:
index 4835aed..ad81ac4 100644 (file)
@@ -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));
index d3317fb..d9cbc5f 100644 (file)
@@ -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;
 }
index 3e06167..d7fe8dd 100644 (file)
@@ -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);
index 690969c..6d5a111 100644 (file)
 #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);
 
index 409848b..440f364 100644 (file)
@@ -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;
index 56fb088..1e08047 100644 (file)
 #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;
 
index 5b64f47..7f5e91c 100644 (file)
@@ -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));
index c672e41..dac5acc 100644 (file)
@@ -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;