backlight: optimize pwm level step calculation

PD#168569: backlight: optimize pwm level step calculation

Change-Id: I570c12cc44af399a861ca54ad98180314924c180
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2018-06-15 17:23:24 +08:00
committed by Jianxin Pan
parent 7ff9741701
commit 31c9040d47
9 changed files with 288 additions and 226 deletions

View 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:

View 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));

View 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;
}

View 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;
temp = bl_pwm->pwm_cnt;
temp = (((temp * bl_pwm->pwm_duty) + 50) / 100);
bl_pwm->pwm_level = (unsigned int)temp;
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);
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);
}
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);
}
bl_pwm_ctrl(bl_pwm, 1);
}
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;
}
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);

View File

@@ -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);

View 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;

View File

@@ -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;

View 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));

View 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;