| /* |
| * drivers/amlogic/media/vout/lcd/lcd_bl.c |
| * |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| #include <common.h> |
| #include <malloc.h> |
| #include <dm.h> |
| #include <asm/gpio.h> |
| #include <fdtdec.h> |
| #include <amlogic/media/vout/lcd/aml_lcd.h> |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| #include <amlogic/media/vout/lcd/bl_ldim.h> |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| #include <amlogic/media/vout/lcd/bl_extern.h> |
| #endif |
| #include "lcd_reg.h" |
| #include "lcd_common.h" |
| |
| static unsigned int bl_off_policy; |
| static unsigned int bl_status; |
| |
| static struct bl_config_s *bl_check_valid(void) |
| { |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| struct bl_config_s *bconf; |
| #ifdef CONFIG_AML_BL_EXTERN |
| struct aml_bl_extern_driver_s *bl_ext; |
| #endif |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| struct aml_ldim_driver_s *ldim_drv; |
| #endif |
| |
| bconf = lcd_drv->bl_config; |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| if (bconf->bl_pwm == NULL) { |
| LCDERR("bl: no bl_pwm struct\n"); |
| bconf = NULL; |
| } |
| break; |
| case BL_CTRL_PWM_COMBO: |
| if (bconf->bl_pwm_combo0 == NULL) { |
| LCDERR("bl: no bl_pwm_combo_0 struct\n"); |
| bconf = NULL; |
| } |
| if (bconf->bl_pwm_combo1 == NULL) { |
| LCDERR("bl: no bl_pwm_combo_1 struct\n"); |
| bconf = NULL; |
| } |
| break; |
| case BL_CTRL_GPIO: |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_drv = aml_ldim_get_driver(); |
| if (ldim_drv == NULL) { |
| LCDERR("bl: no ldim driver\n"); |
| bconf = NULL; |
| } |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| bl_ext = aml_bl_extern_get_driver(); |
| if (bl_ext == NULL) { |
| LCDERR("bl: no bl_extern driver\n"); |
| bconf = NULL; |
| } |
| break; |
| #endif |
| default: |
| if (lcd_debug_print_flag) |
| LCDPR("bl: invalid control_method: %d\n", bconf->method); |
| bconf = NULL; |
| break; |
| } |
| return bconf; |
| } |
| |
| /* *************************************** |
| * bl gpio |
| * *************************************** */ |
| static struct lcd_cpu_gpio_s bl_gpio[BL_GPIO_NUM_MAX] = { |
| {.name = "invalid", .probe_flag = 0, .register_flag = 0,}, |
| {.name = "invalid", .probe_flag = 0, .register_flag = 0,}, |
| {.name = "invalid", .probe_flag = 0, .register_flag = 0,}, |
| {.name = "invalid", .probe_flag = 0, .register_flag = 0,}, |
| {.name = "invalid", .probe_flag = 0, .register_flag = 0,}, |
| }; |
| |
| static void bl_gpio_info_print(void) |
| { |
| int i; |
| |
| LCDPR("bl: gpio_info:\n"); |
| for (i = 0; i < BL_GPIO_NUM_MAX; i++) { |
| if (strcmp(bl_gpio[i].name, "invalid") == 0) |
| break; |
| if (bl_gpio[i].probe_flag == 1) { |
| printf("%d: %s, register=%d\n", |
| i, bl_gpio[i].name, bl_gpio[i].register_flag); |
| } |
| } |
| printf("\n"); |
| } |
| |
| static int bl_gpio_probe(const char *name, int index) |
| { |
| if (name == NULL) { |
| LCDERR("bl: %s: gpio name is null\n", __func__); |
| return -1; |
| } |
| if (index >= BL_GPIO_NUM_MAX) { |
| LCDERR("bl: %s: invalid gpio: %d\n", __func__, index); |
| return -1; |
| } |
| if (bl_gpio[index].probe_flag == 1) { |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: gpio %s(%d) is already probed\n", |
| bl_gpio[index].name, index); |
| } |
| return 0; |
| } |
| |
| if (lcd_debug_print_flag) |
| LCDPR("bl: probe gpio: %s(%d)\n", name, index); |
| strcpy(bl_gpio[index].name, name); |
| /* init gpio flag */ |
| bl_gpio[index].probe_flag = 1; |
| bl_gpio[index].register_flag = 0; |
| |
| return 0; |
| } |
| |
| static int bl_gpio_request(int index) |
| { |
| int ret = 0; |
| |
| if (index >= BL_GPIO_NUM_MAX) { |
| LCDERR("bl: %s: invalid gpio: %d\n", __func__, index); |
| return -1; |
| } |
| if (bl_gpio[index].probe_flag == 0) { |
| LCDERR("bl: gpio %d is not probed\n", index); |
| return -1; |
| } |
| if (bl_gpio[index].register_flag == 1) { |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: gpio %s(%d) is already registered\n", |
| bl_gpio[index].name, index); |
| } |
| return 0; |
| } |
| |
| ret = dm_gpio_lookup_name(bl_gpio[index].name, &bl_gpio[index].gpio); |
| if (ret) { |
| LCDERR("bl: lookup gpio: wrong name %s\n", bl_gpio[index].name); |
| return -1; |
| } |
| |
| ret = dm_gpio_request(&bl_gpio[index].gpio, "aml_lcd_bl"); |
| if (ret) { |
| LCDERR("bl: request gpio %s(%d) failed\n", bl_gpio[index].name, index); |
| return -1; |
| } |
| |
| if (lcd_debug_print_flag) |
| LCDPR("bl: request gpio: %s(%d)\n", bl_gpio[index].name, index); |
| bl_gpio[index].register_flag = 1; |
| |
| return 0; |
| } |
| |
| static int bl_gpio_set(int index, int value) |
| { |
| int ret = 0; |
| |
| if (index >= BL_GPIO_NUM_MAX) { |
| LCDERR("bl: %s: invalid gpio: %d\n", __func__, index); |
| return -1; |
| } |
| if (bl_gpio[index].register_flag == 0) { |
| ret = bl_gpio_request(index); |
| if (ret) |
| return -1; |
| } |
| |
| switch (value) { |
| case LCD_GPIO_OUTPUT_LOW: |
| ret = dm_gpio_set_dir_flags(&bl_gpio[index].gpio, GPIOD_IS_OUT); |
| if (ret) { |
| LCDERR("bl: set gpio %s(%d) direction failed\n", |
| bl_gpio[index].name, index); |
| return ret; |
| } |
| dm_gpio_set_value(&bl_gpio[index].gpio, 0); |
| break; |
| case LCD_GPIO_OUTPUT_HIGH: |
| ret = dm_gpio_set_dir_flags(&bl_gpio[index].gpio, GPIOD_IS_OUT); |
| if (ret) { |
| LCDERR("bl: set gpio %s(%d) direction failed\n", |
| bl_gpio[index].name, index); |
| return ret; |
| } |
| dm_gpio_set_value(&bl_gpio[index].gpio, 1); |
| break; |
| case LCD_GPIO_INPUT: |
| default: |
| ret = dm_gpio_set_dir_flags(&bl_gpio[index].gpio, GPIOD_IS_IN); |
| if (ret) { |
| LCDERR("bl: set gpio %s(%d) direction failed\n", |
| bl_gpio[index].name, index); |
| return ret; |
| } |
| break; |
| } |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: gpio: %s(%d), value: %d\n", |
| bl_gpio[index].name, index, value); |
| } |
| |
| return 0; |
| } |
| /* *************************************** */ |
| |
| static void bl_pwm_pinmux_clr_gpio_set(struct bl_pwm_config_s *bl_pwm, int gpio_level) |
| { |
| int i = 0; |
| |
| if (bl_pwm == NULL) |
| return; |
| |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm_port=%d, pinmux_flag=%d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pinmux_flag); |
| } |
| if (bl_pwm->pinmux_flag > 0) { |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| lcd_pinmux_clr_mask(bl_pwm->pinmux_set[i][0], |
| bl_pwm->pinmux_set[i][1]); |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: port=%d, pinmux_clr=%d,0x%08x\n", |
| __func__, bl_pwm->pwm_port, |
| bl_pwm->pinmux_set[i][0], bl_pwm->pinmux_set[i][1]); |
| } |
| i++; |
| } |
| bl_pwm->pinmux_flag = 0; |
| } |
| /* set gpio */ |
| if (bl_pwm->pwm_gpio < BL_GPIO_NUM_MAX) |
| bl_gpio_set(bl_pwm->pwm_gpio, gpio_level); |
| } |
| |
| static void bl_pwm_pinmux_set_gpio_clr(struct bl_pwm_config_s *bl_pwm) |
| { |
| int i = 0; |
| |
| if (bl_pwm == NULL) |
| return; |
| |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm_port=%d, pinmux_flag=%d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pinmux_flag); |
| } |
| if (bl_pwm->pinmux_flag > 0) |
| return; |
| |
| /* set pinmux */ |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| lcd_pinmux_set_mask(bl_pwm->pinmux_set[i][0], |
| bl_pwm->pinmux_set[i][1]); |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: port=%d, pinmux_set=%d,0x%08x\n", |
| __func__, bl_pwm->pwm_port, |
| bl_pwm->pinmux_set[i][0], bl_pwm->pinmux_set[i][1]); |
| } |
| i++; |
| } |
| bl_pwm->pinmux_flag = 1; |
| } |
| |
| static void bl_set_pwm_gpio_check(struct bl_pwm_config_s *bl_pwm) |
| { |
| unsigned int gpio_level; |
| |
| /* pwm duty 100% or 0% special control */ |
| if (bl_pwm->pwm_duty_max > 100) { |
| if ((bl_pwm->pwm_duty == 0) || (bl_pwm->pwm_duty == 255)) { |
| switch (bl_pwm->pwm_method) { |
| case BL_PWM_POSITIVE: |
| if (bl_pwm->pwm_duty == 0) |
| gpio_level = 0; |
| else |
| gpio_level = 1; |
| break; |
| case BL_PWM_NEGATIVE: |
| if (bl_pwm->pwm_duty == 0) |
| gpio_level = 1; |
| else |
| gpio_level = 0; |
| break; |
| default: |
| LCDERR("bl: %s: port=%d: invalid pwm_method %d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pwm_method); |
| gpio_level = 0; |
| break; |
| } |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm port=%d, duty=%d%%, switch to gpio %d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pwm_duty*100/255, gpio_level); |
| } |
| bl_pwm_pinmux_clr_gpio_set(bl_pwm, gpio_level); |
| } else { |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm_port=%d set as pwm\n", |
| __func__, bl_pwm->pwm_port); |
| } |
| bl_pwm_pinmux_set_gpio_clr(bl_pwm); |
| } |
| } else { |
| if ((bl_pwm->pwm_duty == 0) || (bl_pwm->pwm_duty == 100)) { |
| switch (bl_pwm->pwm_method) { |
| case BL_PWM_POSITIVE: |
| if (bl_pwm->pwm_duty == 0) |
| gpio_level = 0; |
| else |
| gpio_level = 1; |
| break; |
| case BL_PWM_NEGATIVE: |
| if (bl_pwm->pwm_duty == 0) |
| gpio_level = 1; |
| else |
| gpio_level = 0; |
| break; |
| default: |
| LCDERR("bl: %s: port=%d: invalid pwm_method %d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pwm_method); |
| gpio_level = 0; |
| break; |
| } |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm port=%d, duty=%d%%, switch to gpio %d\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pwm_duty, gpio_level); |
| } |
| bl_pwm_pinmux_clr_gpio_set(bl_pwm, gpio_level); |
| } else { |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: pwm_port=%d set as pwm\n", |
| __func__, bl_pwm->pwm_port); |
| } |
| bl_pwm_pinmux_set_gpio_clr(bl_pwm); |
| } |
| } |
| } |
| |
| static void bl_pwm_pinmux_ctrl(struct bl_config_s *bconf, int status) |
| { |
| int i; |
| |
| if (lcd_debug_print_flag) |
| LCDPR("bl: %s: %d\n", __func__, status); |
| if (status) { |
| /* set pinmux */ |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bl_set_pwm_gpio_check(bconf->bl_pwm); |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bl_set_pwm_gpio_check(bconf->bl_pwm_combo0); |
| bl_set_pwm_gpio_check(bconf->bl_pwm_combo1); |
| break; |
| default: |
| break; |
| } |
| } else { |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bconf->bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| lcd_pinmux_clr_mask(bconf->bl_pwm->pinmux_set[i][0], |
| bconf->bl_pwm->pinmux_set[i][1]); |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: port=%d, pinmux_clr=%d,0x%08x\n", |
| __func__, bconf->bl_pwm->pwm_port, |
| bconf->bl_pwm->pinmux_set[i][0], |
| bconf->bl_pwm->pinmux_set[i][1]); |
| } |
| i++; |
| } |
| bconf->bl_pwm->pinmux_flag = 0; |
| |
| if (bconf->bl_pwm->pwm_gpio < BL_GPIO_NUM_MAX) |
| bl_gpio_set(bconf->bl_pwm->pwm_gpio, bconf->bl_pwm->pwm_gpio_off); |
| break; |
| case BL_CTRL_PWM_COMBO: |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bconf->bl_pwm_combo0->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| lcd_pinmux_clr_mask(bconf->bl_pwm_combo0->pinmux_set[i][0], |
| bconf->bl_pwm_combo0->pinmux_set[i][1]); |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: port=%d, pinmux_clr=%d,0x%08x\n", |
| __func__, bconf->bl_pwm_combo0->pwm_port, |
| bconf->bl_pwm_combo0->pinmux_set[i][0], |
| bconf->bl_pwm_combo0->pinmux_set[i][1]); |
| } |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bconf->bl_pwm_combo1->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| lcd_pinmux_clr_mask(bconf->bl_pwm_combo1->pinmux_set[i][0], |
| bconf->bl_pwm_combo1->pinmux_set[i][1]); |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s: port=%d, pinmux_clr=%d,0x%08x\n", |
| __func__, bconf->bl_pwm_combo1->pwm_port, |
| bconf->bl_pwm_combo1->pinmux_set[i][0], |
| bconf->bl_pwm_combo1->pinmux_set[i][1]); |
| } |
| i++; |
| } |
| bconf->bl_pwm_combo0->pinmux_flag = 0; |
| bconf->bl_pwm_combo1->pinmux_flag = 0; |
| |
| if (bconf->bl_pwm_combo0->pwm_gpio < BL_GPIO_NUM_MAX) { |
| bl_gpio_set(bconf->bl_pwm_combo0->pwm_gpio, |
| bconf->bl_pwm_combo0->pwm_gpio_off); |
| } |
| if (bconf->bl_pwm_combo1->pwm_gpio < BL_GPIO_NUM_MAX) { |
| bl_gpio_set(bconf->bl_pwm_combo1->pwm_gpio, |
| bconf->bl_pwm_combo1->pwm_gpio_off); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| static unsigned int pwm_misc[6][5] = { |
| /* pwm_reg, pre_div, clk_sel, clk_en, pwm_en*/ |
| {PWM_MISC_REG_AB, 8, 4, 15, 0,}, |
| {PWM_MISC_REG_AB, 16, 6, 23, 0,}, |
| {PWM_MISC_REG_CD, 8, 4, 15, 0,}, |
| {PWM_MISC_REG_CD, 16, 6, 23, 0,}, |
| {PWM_MISC_REG_EF, 8, 4, 15, 0,}, |
| {PWM_MISC_REG_EF, 16, 6, 23, 0,}, |
| }; |
| |
| 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 void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) |
| { |
| unsigned int freq, pre_div, cnt; |
| int i; |
| |
| if (bl_pwm == NULL) { |
| LCDERR("bl: %s: bl_pwm is NULL\n", __func__); |
| return; |
| } |
| if (bl_pwm->pwm_port >= BL_PWM_MAX) |
| return; |
| |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: %s pwm_port %d: freq = %u\n", |
| __func__, bl_pwm->pwm_port, bl_pwm->pwm_freq); |
| } |
| freq = bl_pwm->pwm_freq; |
| switch (bl_pwm->pwm_port) { |
| case BL_PWM_VS: |
| cnt = lcd_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; |
| bl_pwm->pwm_cnt = cnt; |
| bl_pwm->pwm_pre_div = 0; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: pwm_cnt = %u\n", bl_pwm->pwm_cnt); |
| break; |
| default: |
| for (i = 0; i < 0x7f; i++) { |
| pre_div = i; |
| cnt = XTAL_FREQ_HZ / (freq * (pre_div + 1)) - 2; |
| if (cnt <= 0xffff) /* 16bit */ |
| break; |
| } |
| bl_pwm->pwm_cnt = cnt; |
| bl_pwm->pwm_pre_div = pre_div; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: pwm_cnt = %u, pwm_pre_div = %u\n", cnt, pre_div); |
| break; |
| } |
| |
| if (bl_pwm->pwm_duty_max > 100) { |
| bl_pwm->pwm_max = (bl_pwm->pwm_cnt * bl_pwm->pwm_duty_max / 255); |
| bl_pwm->pwm_min = (bl_pwm->pwm_cnt * bl_pwm->pwm_duty_min / 255); |
| } else { |
| 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 (lcd_debug_print_flag) |
| LCDPR("bl: pwm_max = %u, pwm_min = %u\n", bl_pwm->pwm_max, bl_pwm->pwm_min); |
| } |
| |
| void bl_pwm_config_update(struct bl_config_s *bconf) |
| { |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| struct aml_ldim_driver_s *ldim_drv; |
| #endif |
| |
| if (bconf == NULL) { |
| LCDERR("bl: bconf is null\n"); |
| return; |
| } |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bl_pwm_config_init(bconf->bl_pwm); |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bl_pwm_config_init(bconf->bl_pwm_combo0); |
| bl_pwm_config_init(bconf->bl_pwm_combo1); |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_drv = aml_ldim_get_driver(); |
| if (ldim_drv) { |
| if (ldim_drv->ldev_conf) |
| bl_pwm_config_init(&ldim_drv->ldev_conf->pwm_config); |
| else |
| LCDERR("bl: ldim_config is null\n"); |
| } else { |
| LCDERR("bl: ldim_drv is null\n"); |
| } |
| break; |
| #endif |
| default: |
| break; |
| } |
| } |
| |
| static unsigned int bl_level_mapping(unsigned int level) |
| { |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| unsigned int mid = lcd_drv->bl_config->level_mid; |
| unsigned int mid_map =lcd_drv->bl_config->level_mid_mapping; |
| unsigned int max = lcd_drv->bl_config->level_max; |
| unsigned int min = lcd_drv->bl_config->level_min; |
| |
| if (mid == mid_map) |
| return level; |
| |
| level = level > max ? max : level; |
| if ((level >= mid) && (level <= max)) |
| level = (((level - mid) * (max - mid_map)) / (max - mid)) + mid_map; |
| else if ((level >= min) && (level < mid)) |
| level = (((level - min) * (mid_map - min)) / (mid - min)) + min; |
| else |
| level = 0; |
| |
| return level; |
| } |
| |
| static void bl_set_pwm(struct bl_pwm_config_s *bl_pwm) |
| { |
| unsigned int pwm_hi = 0, pwm_lo = 0; |
| unsigned int port = bl_pwm->pwm_port; |
| unsigned int vs[4], ve[4], sw, n, i, pol = 0; |
| |
| if (bl_status > 0) |
| bl_set_pwm_gpio_check(bl_pwm); |
| |
| switch (bl_pwm->pwm_method) { |
| case BL_PWM_POSITIVE: |
| pwm_hi = bl_pwm->pwm_level; |
| pwm_lo = bl_pwm->pwm_cnt - bl_pwm->pwm_level; |
| pol = 0; |
| break; |
| case BL_PWM_NEGATIVE: |
| pwm_lo = bl_pwm->pwm_level; |
| pwm_hi = bl_pwm->pwm_cnt - bl_pwm->pwm_level; |
| pol = 1; |
| break; |
| default: |
| LCDERR("bl: port %d: invalid pwm_method %d\n", port, bl_pwm->pwm_method); |
| break; |
| } |
| |
| 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: |
| lcd_cbus_write(pwm_reg[port], (pwm_hi << 16) | pwm_lo); |
| if (lcd_debug_print_flag) |
| LCDPR("bl: pwm_reg=0x%08x\n", lcd_cbus_read(pwm_reg[port])); |
| break; |
| case BL_PWM_VS: |
| pwm_hi = bl_pwm->pwm_level; |
| memset(vs, 0xffff, sizeof(unsigned int) * 4); |
| memset(ve, 0xffff, sizeof(unsigned int) * 4); |
| n = bl_pwm->pwm_freq; |
| sw = (bl_pwm->pwm_cnt * 10 / n + 5) / 10; |
| pwm_hi = (pwm_hi * 10 / n + 5) / 10; |
| pwm_hi = (pwm_hi > 1) ? pwm_hi : 1; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: 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 (lcd_debug_print_flag) { |
| LCDPR("bl: vs[%d]=%d, ve[%d]=%d\n", |
| i, vs[i], i, ve[i]); |
| } |
| } |
| lcd_vcbus_write(VPU_VPU_PWM_V0, (pol << 31) | |
| (ve[0] << 16) | (vs[0])); |
| lcd_vcbus_write(VPU_VPU_PWM_V1, (ve[1] << 16) | (vs[1])); |
| lcd_vcbus_write(VPU_VPU_PWM_V2, (ve[2] << 16) | (vs[2])); |
| lcd_vcbus_write(VPU_VPU_PWM_V3, (ve[3] << 16) | (vs[3])); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| 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_max; |
| unsigned int pwm_min = bl_pwm->pwm_min; |
| |
| level = bl_level_mapping(level); |
| max = bl_level_mapping(max); |
| min = bl_level_mapping(min); |
| if ((max <= min) || (level < min)) |
| bl_pwm->pwm_level = pwm_min; |
| else |
| bl_pwm->pwm_level = (pwm_max - pwm_min) * (level - min) / (max - min) + pwm_min; |
| |
| if (bl_pwm->pwm_duty_max > 100) |
| bl_pwm->pwm_duty = bl_pwm->pwm_level * 255 / bl_pwm->pwm_cnt; |
| else |
| bl_pwm->pwm_duty = ((bl_pwm->pwm_level * 1000 / bl_pwm->pwm_cnt) + 5) / 10; |
| |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: port %d: level=%d, level_max=%d, level_min=%d\n", |
| bl_pwm->pwm_port, level, max, min); |
| LCDPR("bl: port %d: pwm_max=%d, pwm_min=%d, pwm_level=%d, duty=%d%%\n", |
| bl_pwm->pwm_port, pwm_max, pwm_min, bl_pwm->pwm_level, bl_pwm->pwm_duty); |
| } |
| |
| bl_set_pwm(bl_pwm); |
| } |
| |
| void bl_set_level(unsigned int level) |
| { |
| unsigned int temp = 0; |
| struct bl_config_s *bconf; |
| struct bl_pwm_config_s *pwm0, *pwm1; |
| #ifdef CONFIG_AML_BL_EXTERN |
| struct aml_bl_extern_driver_s *bl_ext; |
| #endif |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| struct aml_ldim_driver_s *ldim_drv; |
| #endif |
| |
| bconf = bl_check_valid(); |
| if (bconf == NULL) |
| return; |
| |
| LCDPR("bl: set level: %u, last level: %u\n", level, bconf->level); |
| /* level range check */ |
| level = (level > bconf->level_max ? bconf->level_max : |
| (level < bconf->level_min ? bconf->level_min : level)); |
| bconf->level = level; |
| |
| switch (bconf->method) { |
| case BL_CTRL_GPIO: |
| break; |
| case BL_CTRL_PWM: |
| bl_set_level_pwm(bconf->bl_pwm, level); |
| break; |
| case BL_CTRL_PWM_COMBO: |
| pwm0 = bconf->bl_pwm_combo0; |
| pwm1 = bconf->bl_pwm_combo1; |
| if ((level >= pwm0->level_min) && (level <= pwm0->level_max)) { |
| temp = (pwm0->level_min > pwm1->level_min) ? pwm1->level_max : pwm1->level_min; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: pwm0 region, level=%u, pwm1_level=%u\n", level, temp); |
| bl_set_level_pwm(pwm0, level); |
| bl_set_level_pwm(pwm1, temp); |
| } else if ((level >= pwm1->level_min) && (level <= pwm1->level_max)) { |
| temp = (pwm1->level_min > pwm0->level_min) ? pwm0->level_max : pwm0->level_min; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: pwm1 region, level=%u, pwm0_level=%u\n", level, temp); |
| bl_set_level_pwm(pwm0, temp); |
| bl_set_level_pwm(pwm1, level); |
| } |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_drv = aml_ldim_get_driver(); |
| if (ldim_drv->set_level) |
| ldim_drv->set_level(level); |
| else |
| LCDERR("bl: ldim set_level is null\n"); |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| bl_ext = aml_bl_extern_get_driver(); |
| if (bl_ext->set_level) |
| bl_ext->set_level(level); |
| else |
| LCDERR("bl: bl_extern set_level is null\n"); |
| break; |
| #endif |
| default: |
| if (lcd_debug_print_flag) |
| LCDERR("bl: wrong backlight control method\n"); |
| break; |
| } |
| } |
| |
| unsigned int bl_get_level(void) |
| { |
| struct bl_config_s *bconf; |
| |
| bconf = bl_check_valid(); |
| if (bconf == NULL) |
| return 0; |
| |
| return bconf->level; |
| } |
| |
| void bl_pwm_ctrl(struct bl_pwm_config_s *bl_pwm, int status) |
| { |
| int port, pre_div; |
| |
| port = bl_pwm->pwm_port; |
| pre_div = bl_pwm->pwm_pre_div; |
| if (status) { |
| /* enable pwm */ |
| 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: |
| /* pwm clk_div */ |
| lcd_cbus_setb(pwm_misc[port][0], pre_div, pwm_misc[port][1], 7); |
| /* pwm clk_sel */ |
| lcd_cbus_setb(pwm_misc[port][0], 0, pwm_misc[port][2], 2); |
| /* pwm clk_en */ |
| lcd_cbus_setb(pwm_misc[port][0], 1, pwm_misc[port][3], 1); |
| /* pwm enable */ |
| lcd_cbus_setb(pwm_misc[port][0], 0x3, pwm_misc[port][4], 2); |
| break; |
| default: |
| break; |
| } |
| } else { |
| /* disable pwm */ |
| 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: |
| /* pwm clk_disable */ |
| lcd_cbus_setb(pwm_misc[port][0], 0, pwm_misc[port][3], 1); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| static void bl_power_en_ctrl(struct bl_config_s *bconf, int status) |
| { |
| int val; |
| |
| if (status) |
| val = bconf->en_gpio_on; |
| else |
| val = bconf->en_gpio_off; |
| if (bconf->en_gpio < BL_GPIO_NUM_MAX) |
| bl_gpio_set(bconf->en_gpio, val); |
| } |
| |
| void bl_power_ctrl(int status) |
| { |
| __attribute__((__unused__)) int gpio, value; |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| struct bl_config_s *bconf; |
| #ifdef CONFIG_AML_BL_EXTERN |
| struct aml_bl_extern_driver_s *bl_ext; |
| #endif |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| struct aml_ldim_driver_s *ldim_drv; |
| #endif |
| |
| bconf = bl_check_valid(); |
| if (bconf == NULL) |
| return; |
| |
| gpio = bconf->en_gpio; |
| value = status ? bconf->en_gpio_on : bconf->en_gpio_off; |
| if (lcd_debug_print_flag) |
| LCDPR("bl: status=%d gpio=%d value=%d\n", status, gpio, value); |
| |
| if (status) { |
| /* bl_off_policy */ |
| if (bl_off_policy != BL_OFF_POLICY_NONE) { |
| LCDPR("bl_off_policy=%d for bl_off\n", bl_off_policy); |
| return; |
| } |
| |
| bl_status = 1; |
| /* check if factory test */ |
| if (lcd_drv->factory_bl_power_on_delay >= 0) { |
| LCDPR("bl: %s: factory test power_on_delay!\n", __func__); |
| if (lcd_drv->factory_bl_power_on_delay > 0) |
| mdelay(lcd_drv->factory_bl_power_on_delay); |
| } else { |
| if (bconf->power_on_delay > 0) |
| mdelay(bconf->power_on_delay); |
| } |
| |
| switch (bconf->method) { |
| case BL_CTRL_GPIO: |
| bl_power_en_ctrl(bconf, 1); |
| break; |
| case BL_CTRL_PWM: |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| if (bconf->pwm_on_delay > 0) |
| mdelay(bconf->pwm_on_delay); |
| /* step 2: power on pwm */ |
| bl_pwm_ctrl(bconf->bl_pwm, 1); |
| bl_pwm_pinmux_ctrl(bconf, 1); |
| } else { |
| /* step 1: power on pwm */ |
| bl_pwm_ctrl(bconf->bl_pwm, 1); |
| bl_pwm_pinmux_ctrl(bconf, 1); |
| if (bconf->pwm_on_delay > 0) |
| mdelay(bconf->pwm_on_delay); |
| /* step 2: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| } |
| break; |
| case BL_CTRL_PWM_COMBO: |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| if (bconf->pwm_on_delay > 0) |
| mdelay(bconf->pwm_on_delay); |
| /* step 2: power on pwm_combo */ |
| bl_pwm_ctrl(bconf->bl_pwm_combo0, 1); |
| bl_pwm_ctrl(bconf->bl_pwm_combo1, 1); |
| bl_pwm_pinmux_ctrl(bconf, 1); |
| } else { |
| /* step 1: power on pwm_combo */ |
| bl_pwm_ctrl(bconf->bl_pwm_combo0, 1); |
| bl_pwm_ctrl(bconf->bl_pwm_combo1, 1); |
| bl_pwm_pinmux_ctrl(bconf, 1); |
| if (bconf->pwm_on_delay > 0) |
| mdelay(bconf->pwm_on_delay); |
| /* step 2: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| } |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_drv = aml_ldim_get_driver(); |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| /* step 2: power on ldim */ |
| if (ldim_drv->power_on) |
| ldim_drv->power_on(); |
| else |
| LCDERR("bl: ldim power on is null\n"); |
| } else { |
| /* step 1: power on ldim */ |
| if (ldim_drv->power_on) |
| ldim_drv->power_on(); |
| else |
| LCDERR("bl: ldim power on is null\n"); |
| /* step 2: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| } |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| bl_ext = aml_bl_extern_get_driver(); |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| /* step 2: power on bl_extern */ |
| if (bl_ext->power_on) |
| bl_ext->power_on(); |
| else |
| LCDERR("bl: bl_extern power on is null\n"); |
| } else { |
| /* step 1: power on bl_extern */ |
| if (bl_ext->power_on) |
| bl_ext->power_on(); |
| else |
| LCDERR("bl: bl_extern power on is null\n"); |
| /* step 2: power on enable */ |
| bl_power_en_ctrl(bconf, 1); |
| } |
| break; |
| #endif |
| default: |
| if (lcd_debug_print_flag) |
| LCDERR("bl: wrong backlight control method\n"); |
| break; |
| } |
| } else { |
| bl_status = 0; |
| switch (bconf->method) { |
| case BL_CTRL_GPIO: |
| bl_power_en_ctrl(bconf, 0); |
| break; |
| case BL_CTRL_PWM: |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power off pwm */ |
| bl_pwm_ctrl(bconf->bl_pwm, 0); |
| bl_pwm_pinmux_ctrl(bconf, 0); |
| if (bconf->pwm_off_delay > 0) |
| mdelay(bconf->pwm_off_delay); |
| /* step 2: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| } else { |
| /* step 1: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| /* step 2: power off pwm */ |
| if (bconf->pwm_off_delay > 0) |
| mdelay(bconf->pwm_off_delay); |
| bl_pwm_ctrl(bconf->bl_pwm, 0); |
| bl_pwm_pinmux_ctrl(bconf, 0); |
| } |
| break; |
| case BL_CTRL_PWM_COMBO: |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power off pwm_combo */ |
| bl_pwm_ctrl(bconf->bl_pwm_combo0, 0); |
| bl_pwm_ctrl(bconf->bl_pwm_combo1, 0); |
| bl_pwm_pinmux_ctrl(bconf, 0); |
| if (bconf->pwm_off_delay > 0) |
| mdelay(bconf->pwm_off_delay); |
| /* step 2: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| } else { |
| /* step 1: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| /* step 2: power off pwm_combo */ |
| if (bconf->pwm_off_delay > 0) |
| mdelay(bconf->pwm_off_delay); |
| bl_pwm_ctrl(bconf->bl_pwm_combo0, 0); |
| bl_pwm_ctrl(bconf->bl_pwm_combo1, 0); |
| bl_pwm_pinmux_ctrl(bconf, 0); |
| } |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_drv = aml_ldim_get_driver(); |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power off ldim */ |
| if (ldim_drv->power_off) |
| ldim_drv->power_off(); |
| else |
| LCDERR("bl: ldim power off is null\n"); |
| /* step 2: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| } else { |
| /* step 1: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| /* step 2: power off ldim */ |
| if (ldim_drv->power_off) |
| ldim_drv->power_off(); |
| else |
| LCDERR("bl: ldim power off is null\n"); |
| } |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| bl_ext = aml_bl_extern_get_driver(); |
| if (bconf->en_sequence_reverse) { |
| /* step 1: power off bl_extern */ |
| if (bl_ext->power_off) |
| bl_ext->power_off(); |
| else |
| LCDERR("bl: bl_extern: power off is null\n"); |
| /* step 2: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| } else { |
| /* step 1: power off enable */ |
| bl_power_en_ctrl(bconf, 0); |
| /* step 2: power off bl_extern */ |
| if (bl_ext->power_off) |
| bl_ext->power_off(); |
| else |
| LCDERR("bl: bl_extern: power off is null\n"); |
| } |
| break; |
| #endif |
| default: |
| if (lcd_debug_print_flag) |
| LCDERR("bl: wrong backlight control method\n"); |
| break; |
| } |
| if (bconf->power_off_delay > 0) |
| mdelay(bconf->power_off_delay); |
| } |
| LCDPR("bl: %s: %d\n", __func__, status); |
| } |
| |
| static char *bl_pwm_name[] = { |
| "PWM_A", |
| "PWM_B", |
| "PWM_C", |
| "PWM_D", |
| "PWM_E", |
| "PWM_F", |
| "PWM_VS", |
| }; |
| |
| enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str) |
| { |
| enum bl_pwm_port_e pwm_port = BL_PWM_MAX; |
| int i; |
| |
| for (i = 0; i < ARRAY_SIZE(bl_pwm_name); i++) { |
| if (strcmp(str, bl_pwm_name[i]) == 0) { |
| pwm_port = i; |
| break; |
| } |
| } |
| |
| return pwm_port; |
| } |
| |
| static void bl_pinmux_print(struct bl_config_s *bconf) |
| { |
| struct bl_pwm_config_s *bl_pwm; |
| int i; |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bl_pwm = bconf->bl_pwm; |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: bl_pinmux set: %d, 0x%08x\n", |
| bl_pwm->pinmux_set[i][0], bl_pwm->pinmux_set[i][1]); |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_clr[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: bl_pinmux clr: %d, 0x%08x\n", |
| bl_pwm->pinmux_clr[i][0], bl_pwm->pinmux_clr[i][1]); |
| i++; |
| } |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bl_pwm = bconf->bl_pwm_combo0; |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: pwm_combo0 pinmux_set: %d, 0x%08x\n", |
| bl_pwm->pinmux_set[i][0], bl_pwm->pinmux_set[i][1]); |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_clr[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: pwm_combo0 pinmux_clr: %d, 0x%08x\n", |
| bl_pwm->pinmux_clr[i][0], bl_pwm->pinmux_clr[i][1]); |
| i++; |
| } |
| |
| bl_pwm = bconf->bl_pwm_combo1; |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: pwm_combo1 pinmux_set: %d, 0x%08x\n", |
| bl_pwm->pinmux_set[i][0], bl_pwm->pinmux_set[i][1]); |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (bl_pwm->pinmux_clr[i][0] == LCD_PINMUX_END) |
| break; |
| LCDPR("bl: pwm_combo1 pinmux_clr: %d, 0x%08x\n", |
| bl_pwm->pinmux_clr[i][0], bl_pwm->pinmux_clr[i][1]); |
| i++; |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void bl_config_print(void) |
| { |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| struct bl_config_s *bconf; |
| struct bl_pwm_config_s *bl_pwm; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver(); |
| #endif |
| |
| bconf = lcd_drv->bl_config; |
| LCDPR("bl: name: %s\n", bconf->name); |
| LCDPR("bl: method: %d\n", bconf->method); |
| |
| LCDPR("bl: level_default = %d\n", bconf->level_default); |
| LCDPR("bl: level_min = %d\n", bconf->level_min); |
| LCDPR("bl: level_max = %d\n", bconf->level_max); |
| LCDPR("bl: level_mid = %d\n", bconf->level_mid); |
| LCDPR("bl: level_mid_mapping = %d\n", bconf->level_mid_mapping); |
| |
| LCDPR("bl: en_gpio = %d\n", bconf->en_gpio); |
| LCDPR("bl: en_gpio_on = %d\n", bconf->en_gpio_on); |
| LCDPR("bl: en_gpio_off = %d\n", bconf->en_gpio_off); |
| /* check if factory test */ |
| if (lcd_drv->factory_bl_power_on_delay >= 0) |
| LCDPR("bl: factory test power_on_delay = %d\n", bconf->power_on_delay); |
| else |
| LCDPR("bl: power_on_delay = %d\n", bconf->power_on_delay); |
| LCDPR("bl: power_off_delay = %d\n", bconf->power_off_delay); |
| bl_gpio_info_print(); |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| if (bconf->bl_pwm) { |
| bl_pwm = bconf->bl_pwm; |
| LCDPR("bl: pwm_index = %d\n", bl_pwm->index); |
| LCDPR("bl: pwm_method = %d\n", bl_pwm->pwm_method); |
| LCDPR("bl: pwm_port = %d\n", bl_pwm->pwm_port); |
| if (bl_pwm->pwm_port == BL_PWM_VS) { |
| LCDPR("bl: pwm_freq = %d x vfreq\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_cnt = %u\n", bl_pwm->pwm_cnt); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_reg0 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V0)); |
| LCDPR("bl: pwm_reg1 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V1)); |
| LCDPR("bl: pwm_reg2 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V2)); |
| LCDPR("bl: pwm_reg3 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V3)); |
| } else { |
| LCDPR("bl: pwm_freq = %uHz\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_cnt = %u\n", bl_pwm->pwm_cnt); |
| LCDPR("bl: pwm_pre_div = %u\n", bl_pwm->pwm_pre_div); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_reg = 0x%08x\n", lcd_cbus_read(pwm_reg[bl_pwm->pwm_port])); |
| } |
| LCDPR("bl: pwm_duty_max = %d\n", bl_pwm->pwm_duty_max); |
| LCDPR("bl: pwm_duty_min = %d\n", bl_pwm->pwm_duty_min); |
| LCDPR("bl: pwm_gpio = %d\n", bl_pwm->pwm_gpio); |
| LCDPR("bl: pwm_gpio_off = %d\n", bl_pwm->pwm_gpio_off); |
| } |
| LCDPR("bl: pwm_on_delay = %d\n", bconf->pwm_on_delay); |
| LCDPR("bl: pwm_off_delay = %d\n", bconf->pwm_off_delay); |
| LCDPR("bl: en_sequence_reverse = %d\n", bconf->en_sequence_reverse); |
| bl_pinmux_print(bconf); |
| break; |
| case BL_CTRL_PWM_COMBO: |
| if (bconf->bl_pwm_combo0) { |
| bl_pwm = bconf->bl_pwm_combo0; |
| LCDPR("bl: pwm_combo0_index = %d\n", bl_pwm->index); |
| LCDPR("bl: pwm_combo0_method = %d\n", bl_pwm->pwm_method); |
| LCDPR("bl: pwm_combo0_port = %d\n", bl_pwm->pwm_port); |
| if (bl_pwm->pwm_port == BL_PWM_VS) { |
| LCDPR("bl: pwm_combo0_freq = %d x vfreq\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_combo0_cnt = %u\n", bl_pwm->pwm_cnt); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_combo0_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_combo0_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_combo0_reg0 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V0)); |
| LCDPR("bl: pwm_combo0_reg1 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V1)); |
| LCDPR("bl: pwm_combo0_reg2 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V2)); |
| LCDPR("bl: pwm_combo0_reg3 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V3)); |
| } else { |
| LCDPR("bl: pwm_combo0_freq = %uHz\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_combo0_cnt = %u\n", bl_pwm->pwm_cnt); |
| LCDPR("bl: pwm_combo0_pre_div = %u\n", bl_pwm->pwm_pre_div); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_combo0_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_combo0_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_combo0_reg = 0x%08x\n", lcd_cbus_read(pwm_reg[bl_pwm->pwm_port])); |
| } |
| LCDPR("bl: pwm_combo0_duty_max = %d\n", bl_pwm->pwm_duty_max); |
| LCDPR("bl: pwm_combo0_duty_min = %d\n", bl_pwm->pwm_duty_min); |
| LCDPR("bl: pwm_combo0_gpio = %d\n", bl_pwm->pwm_gpio); |
| LCDPR("bl: pwm_combo0_gpio_off = %d\n", bl_pwm->pwm_gpio_off); |
| } |
| if (bconf->bl_pwm_combo1) { |
| bl_pwm = bconf->bl_pwm_combo1; |
| LCDPR("bl: pwm_combo1_index = %d\n", bl_pwm->index); |
| LCDPR("bl: pwm_combo1_method = %d\n", bl_pwm->pwm_method); |
| LCDPR("bl: pwm_combo1_port = %d\n", bl_pwm->pwm_port); |
| if (bl_pwm->pwm_port == BL_PWM_VS) { |
| LCDPR("bl: pwm_combo1_freq = %d x vfreq\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_combo1_cnt = %u\n", bl_pwm->pwm_cnt); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_combo1_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_combo1_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_combo1_reg0 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V0)); |
| LCDPR("bl: pwm_combo1_reg1 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V1)); |
| LCDPR("bl: pwm_combo1_reg2 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V2)); |
| LCDPR("bl: pwm_combo1_reg3 = 0x%08x\n", lcd_vcbus_read(VPU_VPU_PWM_V3)); |
| } else { |
| LCDPR("bl: pwm_combo1_freq = %uHz\n", bl_pwm->pwm_freq); |
| LCDPR("bl: pwm_combo1_cnt = %u\n", bl_pwm->pwm_cnt); |
| LCDPR("bl: pwm_combo1_pre_div = %u\n", bl_pwm->pwm_pre_div); |
| if (bl_pwm->pwm_duty_max > 100) |
| LCDPR("bl: pwm_combo1_duty = %d%%(%d)\n", bl_pwm->pwm_duty * 100 / 255, bl_pwm->pwm_duty); |
| else |
| LCDPR("bl: pwm_combo1_duty = %d%%(%d)\n", bl_pwm->pwm_duty, bl_pwm->pwm_duty); |
| |
| LCDPR("bl: pwm_combo1_reg = 0x%08x\n", lcd_cbus_read(pwm_reg[bl_pwm->pwm_port])); |
| } |
| LCDPR("bl: pwm_combo1_duty_max = %d\n", bl_pwm->pwm_duty_max); |
| LCDPR("bl: pwm_combo1_duty_min = %d\n", bl_pwm->pwm_duty_min); |
| LCDPR("bl: pwm_combo1_gpio = %d\n", bl_pwm->pwm_gpio); |
| LCDPR("bl: pwm_combo1_gpio_off = %d\n", bl_pwm->pwm_gpio_off); |
| } |
| LCDPR("bl: pwm_on_delay = %d\n", bconf->pwm_on_delay); |
| LCDPR("bl: pwm_off_delay = %d\n", bconf->pwm_off_delay); |
| LCDPR("bl: en_sequence_reverse = %d\n", bconf->en_sequence_reverse); |
| bl_pinmux_print(bconf); |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| if (ldim_drv) { |
| if (ldim_drv->config_print) |
| ldim_drv->config_print(); |
| } else { |
| LCDPR("bl: invalid local dimming driver\n"); |
| } |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| if (bl_extern) { |
| if (bl_extern->config_print) |
| bl_extern->config_print(); |
| } else { |
| LCDPR("bl: invalid bl extern driver\n"); |
| } |
| break; |
| #endif |
| |
| default: |
| LCDPR("bl: invalid backlight control method\n"); |
| break; |
| } |
| } |
| |
| static int bl_config_load_from_dts(const void *dt_blob, unsigned int index, struct bl_config_s *bconf) |
| { |
| int parent_offset, child_offset; |
| char propname[30]; |
| char *propdata; |
| char *p; |
| const char *str; |
| struct bl_pwm_config_s *bl_pwm; |
| struct bl_pwm_config_s *pwm_combo0, *pwm_combo1; |
| |
| bconf->method = BL_CTRL_MAX; /* default */ |
| parent_offset = fdt_path_offset(dt_blob, "/backlight"); |
| if (parent_offset < 0) { |
| LCDPR("bl: not find /backlight node %s\n", fdt_strerror(parent_offset)); |
| return -1; |
| } |
| propdata = (char *)fdt_getprop(dt_blob, parent_offset, "status", NULL); |
| if (propdata == NULL) { |
| LCDPR("bl: not find status, default to disabled\n"); |
| return -1; |
| } else { |
| if (strncmp(propdata, "okay", 2)) { |
| LCDPR("bl: status disabled\n"); |
| return -1; |
| } |
| } |
| |
| sprintf(propname,"/backlight/backlight_%d", index); |
| child_offset = fdt_path_offset(dt_blob, propname); |
| if (child_offset < 0) { |
| LCDERR("bl: not find %s node: %s\n", propname, fdt_strerror(child_offset)); |
| return -1; |
| } |
| |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_name", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_name\n"); |
| sprintf(bconf->name, "backlight_%d", index); |
| } else { |
| strcpy(bconf->name, propdata); |
| } |
| |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_level_default_uboot_kernel", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_level_default_uboot_kernel\n"); |
| bconf->level_default = BL_LEVEL_DEFAULT; |
| } else { |
| bconf->level_default = be32_to_cpup((u32*)propdata); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_level_attr", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_level_attr\n"); |
| bconf->level_max = BL_LEVEL_MAX; |
| bconf->level_min = BL_LEVEL_MIN; |
| bconf->level_mid = BL_LEVEL_MID; |
| bconf->level_mid_mapping = BL_LEVEL_MID_MAPPED; |
| } else { |
| bconf->level_max = be32_to_cpup((u32*)propdata); |
| bconf->level_min = be32_to_cpup((((u32*)propdata)+1)); |
| bconf->level_mid = be32_to_cpup((((u32*)propdata)+2)); |
| bconf->level_mid_mapping = be32_to_cpup((((u32*)propdata)+3)); |
| } |
| |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_ctrl_method", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_ctrl_method\n"); |
| bconf->method = BL_CTRL_MAX; |
| return -1; |
| } else { |
| bconf->method = be32_to_cpup((u32*)propdata); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_power_attr", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_power_attr\n"); |
| bconf->en_gpio = BL_GPIO_NUM_MAX; |
| bconf->en_gpio_on = LCD_GPIO_OUTPUT_HIGH; |
| bconf->en_gpio_off = LCD_GPIO_OUTPUT_LOW; |
| bconf->power_on_delay = 100; |
| bconf->power_off_delay = 30; |
| } else { |
| bconf->en_gpio = be32_to_cpup((u32*)propdata); |
| bconf->en_gpio_on = be32_to_cpup((((u32*)propdata)+1)); |
| bconf->en_gpio_off = be32_to_cpup((((u32*)propdata)+2)); |
| bconf->power_on_delay = be32_to_cpup((((u32*)propdata)+3)); |
| bconf->power_off_delay = be32_to_cpup((((u32*)propdata)+4)); |
| } |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bconf->bl_pwm = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm == NULL) { |
| LCDERR("bl: bl_pwm struct malloc error\n"); |
| return -1; |
| } |
| bl_pwm = bconf->bl_pwm; |
| bl_pwm->index = 0; |
| |
| bl_pwm->level_max = bconf->level_max; |
| bl_pwm->level_min = bconf->level_min; |
| |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_port", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_port\n"); |
| bl_pwm->pwm_port = BL_PWM_MAX; |
| } else { |
| bl_pwm->pwm_port = bl_pwm_str_to_pwm(propdata); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_attr", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_attr\n"); |
| bl_pwm->pwm_method = BL_PWM_POSITIVE; |
| if (bl_pwm->pwm_port == BL_PWM_VS) |
| bl_pwm->pwm_freq = BL_FREQ_VS_DEFAULT; |
| else |
| bl_pwm->pwm_freq = BL_FREQ_DEFAULT; |
| bl_pwm->pwm_duty_max = 80; |
| bl_pwm->pwm_duty_min = 20; |
| } else { |
| bl_pwm->pwm_method = be32_to_cpup((u32*)propdata); |
| bl_pwm->pwm_freq = be32_to_cpup((((u32*)propdata)+1)); |
| bl_pwm->pwm_duty_max = be32_to_cpup((((u32*)propdata)+2)); |
| bl_pwm->pwm_duty_min = be32_to_cpup((((u32*)propdata)+3)); |
| } |
| if (bl_pwm->pwm_port == BL_PWM_VS) { |
| if (bl_pwm->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", bl_pwm->pwm_freq); |
| bl_pwm->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (bl_pwm->pwm_freq > XTAL_HALF_FREQ_HZ) |
| bl_pwm->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_power", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_power\n"); |
| bl_pwm->pwm_gpio = BL_GPIO_NUM_MAX; |
| bl_pwm->pwm_gpio_off = LCD_GPIO_OUTPUT_LOW; |
| bconf->pwm_on_delay = 10; |
| bconf->pwm_off_delay = 10; |
| } else { |
| bl_pwm->pwm_gpio = be32_to_cpup((u32*)propdata); |
| bl_pwm->pwm_gpio_off = be32_to_cpup((((u32*)propdata)+1)); |
| bconf->pwm_on_delay = be32_to_cpup((((u32*)propdata)+2)); |
| bconf->pwm_off_delay = be32_to_cpup((((u32*)propdata)+3)); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_en_sequence_reverse", NULL); |
| if (propdata == NULL) { |
| LCDPR("bl: don't find bl_pwm_en_sequence_reverse\n"); |
| bconf->en_sequence_reverse = 0; |
| } else { |
| bconf->en_sequence_reverse = be32_to_cpup((u32*)propdata); |
| } |
| |
| bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; |
| /* bl_pwm_config_init(bl_pwm); */ |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bconf->bl_pwm_combo0 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo0 == NULL) { |
| LCDERR("bl: bl_pwm_combo0 struct malloc error\n"); |
| return -1; |
| } |
| bconf->bl_pwm_combo1 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo1 == NULL) { |
| LCDERR("bl: bl_pwm_combo1 struct malloc error\n"); |
| return -1; |
| } |
| pwm_combo0 = bconf->bl_pwm_combo0; |
| pwm_combo1 = bconf->bl_pwm_combo1; |
| pwm_combo0->index = 0; |
| pwm_combo1->index = 1; |
| |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_combo_level_mapping", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_combo_level_mapping\n"); |
| pwm_combo0->level_max = BL_LEVEL_MAX; |
| pwm_combo0->level_min = BL_LEVEL_MID; |
| pwm_combo1->level_max = BL_LEVEL_MID; |
| pwm_combo1->level_min = BL_LEVEL_MIN; |
| } else { |
| pwm_combo0->level_max = be32_to_cpup((u32*)propdata); |
| pwm_combo0->level_min = be32_to_cpup((((u32*)propdata)+1)); |
| pwm_combo1->level_max = be32_to_cpup((((u32*)propdata)+2)); |
| pwm_combo1->level_min = be32_to_cpup((((u32*)propdata)+3)); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_combo_port", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_combo_port\n"); |
| pwm_combo0->pwm_port = BL_PWM_MAX; |
| pwm_combo1->pwm_port = BL_PWM_MAX; |
| } else { |
| p = propdata; |
| str = p; |
| pwm_combo0->pwm_port = bl_pwm_str_to_pwm(str); |
| p += strlen(p) + 1; |
| str = p; |
| pwm_combo1->pwm_port = bl_pwm_str_to_pwm(str); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_combo_attr", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_combo_attr\n"); |
| pwm_combo0->pwm_method = BL_PWM_POSITIVE; |
| if (pwm_combo0->pwm_port == BL_PWM_VS) |
| pwm_combo0->pwm_freq = BL_FREQ_VS_DEFAULT; |
| else |
| pwm_combo0->pwm_freq = BL_FREQ_DEFAULT; |
| pwm_combo0->pwm_duty_max = 80; |
| pwm_combo0->pwm_duty_min = 20; |
| pwm_combo1->pwm_method = BL_PWM_POSITIVE; |
| if (pwm_combo1->pwm_port == BL_PWM_VS) |
| pwm_combo1->pwm_freq = BL_FREQ_VS_DEFAULT; |
| else |
| pwm_combo1->pwm_freq = BL_FREQ_DEFAULT; |
| pwm_combo1->pwm_duty_max = 80; |
| pwm_combo1->pwm_duty_min = 20; |
| } else { |
| pwm_combo0->pwm_method = be32_to_cpup((u32*)propdata); |
| pwm_combo0->pwm_freq = be32_to_cpup((((u32*)propdata)+1)); |
| pwm_combo0->pwm_duty_max = be32_to_cpup((((u32*)propdata)+2)); |
| pwm_combo0->pwm_duty_min = be32_to_cpup((((u32*)propdata)+3)); |
| pwm_combo1->pwm_method = be32_to_cpup((((u32*)propdata)+4)); |
| pwm_combo1->pwm_freq = be32_to_cpup((((u32*)propdata)+5)); |
| pwm_combo1->pwm_duty_max = be32_to_cpup((((u32*)propdata)+6)); |
| pwm_combo1->pwm_duty_min = be32_to_cpup((((u32*)propdata)+7)); |
| } |
| if (pwm_combo0->pwm_port == BL_PWM_VS) { |
| if (pwm_combo0->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", pwm_combo0->pwm_freq); |
| pwm_combo0->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (pwm_combo0->pwm_freq > XTAL_HALF_FREQ_HZ) |
| pwm_combo0->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| if (pwm_combo1->pwm_port == BL_PWM_VS) { |
| if (pwm_combo1->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", pwm_combo1->pwm_freq); |
| pwm_combo1->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (pwm_combo1->pwm_freq > XTAL_HALF_FREQ_HZ) |
| pwm_combo1->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_combo_power", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_pwm_combo_power\n"); |
| pwm_combo0->pwm_gpio = BL_GPIO_NUM_MAX; |
| pwm_combo0->pwm_gpio_off = LCD_GPIO_INPUT; |
| pwm_combo1->pwm_gpio = BL_GPIO_NUM_MAX; |
| pwm_combo1->pwm_gpio_off = LCD_GPIO_INPUT; |
| bconf->pwm_on_delay = 10; |
| bconf->pwm_off_delay = 10; |
| } else { |
| pwm_combo0->pwm_gpio = be32_to_cpup((u32*)propdata); |
| pwm_combo0->pwm_gpio_off = be32_to_cpup((((u32*)propdata)+1)); |
| pwm_combo1->pwm_gpio = be32_to_cpup((((u32*)propdata)+2)); |
| pwm_combo1->pwm_gpio_off = be32_to_cpup((((u32*)propdata)+3)); |
| bconf->pwm_on_delay = be32_to_cpup((((u32*)propdata)+4)); |
| bconf->pwm_off_delay = be32_to_cpup((((u32*)propdata)+5)); |
| } |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_pwm_en_sequence_reverse", NULL); |
| if (propdata == NULL) { |
| LCDPR("bl: don't find bl_pwm_en_sequence_reverse\n"); |
| bconf->en_sequence_reverse = 0; |
| } else { |
| bconf->en_sequence_reverse = be32_to_cpup((u32*)propdata); |
| } |
| |
| pwm_combo0->pwm_duty = pwm_combo0->pwm_duty_min; |
| pwm_combo1->pwm_duty = pwm_combo1->pwm_duty_min; |
| /* bl_pwm_config_init(pwm_combo0); |
| bl_pwm_config_init(pwm_combo1); */ |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| ldim_config_load_from_dts(dt_blob, child_offset); |
| aml_ldim_probe(dt_blob, 0); |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| /* get bl_extern_index from dts */ |
| propdata = (char *)fdt_getprop(dt_blob, child_offset, "bl_extern_index", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_extern_index\n"); |
| } else { |
| bconf->bl_extern_index = be32_to_cpup((u32*)propdata); |
| LCDPR("get bl_extern_index = %d\n", bconf->bl_extern_index); |
| } |
| aml_bl_extern_device_load(dt_blob, bconf->bl_extern_index); |
| break; |
| #endif |
| |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int bl_config_load_from_bsp(struct bl_config_s *bconf) |
| { |
| struct ext_lcd_config_s *ext_lcd = NULL; |
| char *panel_type = env_get("panel_type"); |
| unsigned int i = 0; |
| struct bl_pwm_config_s *bl_pwm; |
| struct bl_pwm_config_s *pwm_combo0, *pwm_combo1; |
| |
| if (panel_type == NULL) { |
| LCDERR("bl: no panel_type, use default backlight config\n"); |
| return -1; |
| } |
| for (i = 0; i < LCD_NUM_MAX; i++) { |
| ext_lcd = &ext_lcd_config[i]; |
| if (strcmp(ext_lcd->panel_type, panel_type) == 0) |
| break; |
| } |
| if (i >= LCD_NUM_MAX) { |
| LCDERR("bl: can't find %s, use default backlight config\n ", panel_type); |
| return -1; |
| } |
| |
| strcpy(bconf->name, panel_type); |
| bconf->level_default = ext_lcd->level_default; |
| bconf->level_min = ext_lcd->level_min; |
| bconf->level_max = ext_lcd->level_max; |
| bconf->level_mid = ext_lcd->level_mid; |
| bconf->level_mid_mapping = ext_lcd->level_mid_mapping; |
| |
| bconf->method = ext_lcd->bl_method; |
| |
| if (ext_lcd->bl_en_gpio >= BL_GPIO_NUM_MAX) |
| bconf->en_gpio = LCD_GPIO_MAX; |
| else |
| bconf->en_gpio = ext_lcd->bl_en_gpio; |
| bconf->en_gpio_on = ext_lcd->bl_en_gpio_on; |
| bconf->en_gpio_off = ext_lcd->bl_en_gpio_off; |
| bconf->power_on_delay = ext_lcd->bl_power_on_delay; |
| bconf->power_off_delay = ext_lcd->bl_power_off_delay; |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bconf->bl_pwm = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm == NULL) { |
| LCDERR("bl: bl_pwm struct malloc error\n"); |
| return -1; |
| } |
| bl_pwm = bconf->bl_pwm; |
| bl_pwm->index = 0; |
| |
| bl_pwm->level_max = bconf->level_max; |
| bl_pwm->level_min = bconf->level_min; |
| |
| bl_pwm->pwm_method = ext_lcd->pwm_method; |
| bl_pwm->pwm_port = ext_lcd->pwm_port; |
| bl_pwm->pwm_freq = ext_lcd->pwm_freq; |
| bl_pwm->pwm_duty_max = ext_lcd->pwm_duty_max; |
| bl_pwm->pwm_duty_min = ext_lcd->pwm_duty_min; |
| |
| bl_pwm->pwm_gpio = ext_lcd->pwm_gpio; |
| bl_pwm->pwm_gpio_off = ext_lcd->pwm_gpio_off; |
| bconf->pwm_on_delay = ext_lcd->pwm_on_delay; |
| bconf->pwm_off_delay = ext_lcd->pwm_off_delay; |
| |
| bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; |
| /* bl_pwm_config_init(bl_pwm); */ |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bconf->bl_pwm_combo0 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo0 == NULL) { |
| LCDERR("bl: bl_pwm_combo0 struct malloc error\n"); |
| return -1; |
| } |
| bconf->bl_pwm_combo1 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo1 == NULL) { |
| LCDERR("bl: bl_pwm_combo1 struct malloc error\n"); |
| return -1; |
| } |
| pwm_combo0 = bconf->bl_pwm_combo0; |
| pwm_combo1 = bconf->bl_pwm_combo1; |
| pwm_combo0->index = 0; |
| pwm_combo1->index = 1; |
| |
| pwm_combo0->level_max = ext_lcd->pwm_level_max; |
| pwm_combo0->level_min = ext_lcd->pwm_level_min; |
| pwm_combo1->level_max = ext_lcd->pwm2_level_max; |
| pwm_combo1->level_min = ext_lcd->pwm2_level_min; |
| |
| pwm_combo0->pwm_method = ext_lcd->pwm_method; |
| pwm_combo0->pwm_port = ext_lcd->pwm_port; |
| pwm_combo0->pwm_freq = ext_lcd->pwm_freq; |
| pwm_combo0->pwm_duty_max = ext_lcd->pwm_duty_max; |
| pwm_combo0->pwm_duty_min = ext_lcd->pwm_duty_min; |
| pwm_combo0->pwm_gpio = ext_lcd->pwm_gpio; |
| pwm_combo0->pwm_gpio_off = ext_lcd->pwm_gpio_off; |
| pwm_combo1->pwm_method = ext_lcd->pwm2_method; |
| pwm_combo1->pwm_port = ext_lcd->pwm2_port; |
| pwm_combo1->pwm_freq = ext_lcd->pwm2_freq; |
| pwm_combo1->pwm_duty_max = ext_lcd->pwm2_duty_max; |
| pwm_combo1->pwm_duty_min = ext_lcd->pwm2_duty_min; |
| pwm_combo1->pwm_gpio = ext_lcd->pwm2_gpio; |
| pwm_combo1->pwm_gpio_off = ext_lcd->pwm2_gpio_off; |
| bconf->pwm_on_delay = ext_lcd->pwm_on_delay; |
| bconf->pwm_off_delay = ext_lcd->pwm_off_delay; |
| |
| pwm_combo0->pwm_duty = pwm_combo0->pwm_duty_min; |
| pwm_combo1->pwm_duty = pwm_combo1->pwm_duty_min; |
| /* bl_pwm_config_init(pwm_combo0); |
| bl_pwm_config_init(pwm_combo1); */ |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| aml_ldim_probe(NULL, 1); |
| break; |
| #endif |
| #ifdef CONFIG_AML_BL_EXTERN |
| case BL_CTRL_EXTERN: |
| aml_bl_extern_device_load(NULL, bconf->bl_extern_index); |
| break; |
| #endif |
| default: |
| if (lcd_debug_print_flag) |
| LCDPR("bl: invalid backlight control method\n"); |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int bl_config_load_from_unifykey(const void *dt_blob, struct bl_config_s *bconf) |
| { |
| unsigned char *para; |
| int key_len, len; |
| unsigned char *p; |
| const char *str; |
| struct aml_lcd_unifykey_header_s bl_header; |
| struct bl_pwm_config_s *bl_pwm; |
| struct bl_pwm_config_s *pwm_combo0, *pwm_combo1; |
| int ret; |
| |
| para = (unsigned char *)malloc(sizeof(unsigned char) * LCD_UKEY_BL_SIZE); |
| if (!para) { |
| LCDERR("bl: %s: Not enough memory\n", __func__); |
| return -1; |
| } |
| |
| key_len = LCD_UKEY_BL_SIZE; |
| memset(para, 0, (sizeof(unsigned char) * key_len)); |
| ret = aml_lcd_unifykey_get("backlight", para, &key_len); |
| if (ret) { |
| free(para); |
| return -1; |
| } |
| |
| /* step 1: check header */ |
| len = LCD_UKEY_HEAD_SIZE; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| LCDERR("unifykey header length is incorrect\n"); |
| free(para); |
| return -1; |
| } |
| |
| aml_lcd_unifykey_header_check(para, &bl_header); |
| LCDPR("bl: unifykey version: 0x%04x\n", bl_header.version); |
| switch (bl_header.version) { |
| case 2: |
| len = 10 + 30 + 12 + 8 + 32 + 10; |
| break; |
| default: |
| len = 10 + 30 + 12 + 8 + 32; |
| break; |
| } |
| if (lcd_debug_print_flag) { |
| LCDPR("bl: unifykey header:\n"); |
| LCDPR("bl: crc32 = 0x%08x\n", bl_header.crc32); |
| LCDPR("bl: data_len = %d\n", bl_header.data_len); |
| LCDPR("bl: reserved = 0x%04x\n", bl_header.reserved); |
| } |
| |
| /* step 2: check backlight parameters */ |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| LCDERR("bl: unifykey length is incorrect\n"); |
| free(para); |
| return -1; |
| } |
| |
| /* basic: 30byte */ |
| p = para; |
| *(p + LCD_UKEY_BL_NAME - 1) = '\0'; /* ensure string ending */ |
| str = (const char *)(p + LCD_UKEY_HEAD_SIZE); |
| strcpy(bconf->name, str); |
| |
| /* level: 12byte */ |
| bconf->level_default = (*(p + LCD_UKEY_BL_LEVEL_UBOOT) | |
| ((*(p + LCD_UKEY_BL_LEVEL_UBOOT + 1)) << 8)); |
| bconf->level_max = (*(p + LCD_UKEY_BL_LEVEL_MAX) | |
| ((*(p + LCD_UKEY_BL_LEVEL_MAX + 1)) << 8)); |
| bconf->level_min = (*(p + LCD_UKEY_BL_LEVEL_MIN) | |
| ((*(p + LCD_UKEY_BL_LEVEL_MIN + 1)) << 8)); |
| bconf->level_mid = (*(p + LCD_UKEY_BL_LEVEL_MID) | |
| ((*(p + LCD_UKEY_BL_LEVEL_MID + 1)) << 8)); |
| bconf->level_mid_mapping = (*(p + LCD_UKEY_BL_LEVEL_MID_MAP) | |
| ((*(p + LCD_UKEY_BL_LEVEL_MID_MAP + 1)) << 8)); |
| |
| /* method: 8byte */ |
| bconf->method = *(p + LCD_UKEY_BL_METHOD); |
| bconf->en_gpio = *(p + LCD_UKEY_BL_EN_GPIO); |
| bconf->en_gpio_on = *(p + LCD_UKEY_BL_EN_GPIO_ON); |
| bconf->en_gpio_off = *(p + LCD_UKEY_BL_EN_GPIO_OFF); |
| bconf->power_on_delay = (*(p + LCD_UKEY_BL_ON_DELAY) | |
| ((*(p + LCD_UKEY_BL_ON_DELAY + 1)) << 8)); |
| bconf->power_off_delay = (*(p + LCD_UKEY_BL_OFF_DELAY) | |
| ((*(p + LCD_UKEY_BL_OFF_DELAY + 1)) << 8)); |
| |
| /* pwm: 32byte */ |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bconf->bl_pwm = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm == NULL) { |
| LCDERR("bl: bl_pwm struct malloc error\n"); |
| free(para); |
| return -1; |
| } |
| bl_pwm = bconf->bl_pwm; |
| bl_pwm->index = 0; |
| |
| bl_pwm->level_max = bconf->level_max; |
| bl_pwm->level_min = bconf->level_min; |
| |
| bconf->pwm_on_delay = (*(p + LCD_UKEY_BL_PWM_ON_DELAY) | |
| ((*(p + LCD_UKEY_BL_PWM_ON_DELAY + 1)) << 8)); |
| bconf->pwm_off_delay = (*(p + LCD_UKEY_BL_PWM_OFF_DELAY) | |
| ((*(p + LCD_UKEY_BL_PWM_OFF_DELAY + 1)) << 8)); |
| bl_pwm->pwm_method = *(p + LCD_UKEY_BL_PWM_METHOD); |
| bl_pwm->pwm_port = *(p + LCD_UKEY_BL_PWM_PORT); |
| bl_pwm->pwm_freq = (*(p + LCD_UKEY_BL_PWM_FREQ) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 1)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 2)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 3)) << 8)); |
| if (bl_pwm->pwm_port == BL_PWM_VS) { |
| if (bl_pwm->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", bl_pwm->pwm_freq); |
| bl_pwm->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (bl_pwm->pwm_freq > XTAL_HALF_FREQ_HZ) |
| bl_pwm->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| bl_pwm->pwm_duty_max = *(p + LCD_UKEY_BL_PWM_DUTY_MAX); |
| bl_pwm->pwm_duty_min = *(p + LCD_UKEY_BL_PWM_DUTY_MIN); |
| bl_pwm->pwm_gpio = *(p + LCD_UKEY_BL_PWM_GPIO); |
| bl_pwm->pwm_gpio_off = *(p + LCD_UKEY_BL_PWM_GPIO_OFF); |
| |
| if (bl_header.version == 2) |
| bconf->en_sequence_reverse = |
| (*(p + LCD_UKEY_BL_CUST_VAL_0) | |
| ((*(p + LCD_UKEY_BL_CUST_VAL_0 + 1)) << 8)); |
| else |
| bconf->en_sequence_reverse = 0; |
| |
| bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; |
| /* bl_pwm_config_init(bl_pwm); */ |
| break; |
| case BL_CTRL_PWM_COMBO: |
| bconf->bl_pwm_combo0 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo0 == NULL) { |
| LCDERR("bl: bl_pwm_combo0 struct malloc error\n"); |
| free(para); |
| return -1; |
| } |
| bconf->bl_pwm_combo1 = (struct bl_pwm_config_s *)malloc(sizeof(struct bl_pwm_config_s)); |
| if (bconf->bl_pwm_combo1 == NULL) { |
| LCDERR("bl: bl_pwm_combo1 struct malloc error\n"); |
| free(para); |
| return -1; |
| } |
| pwm_combo0 = bconf->bl_pwm_combo0; |
| pwm_combo1 = bconf->bl_pwm_combo1; |
| pwm_combo0->index = 0; |
| pwm_combo1->index = 1; |
| |
| bconf->pwm_on_delay = (*(p + LCD_UKEY_BL_PWM_ON_DELAY) | |
| ((*(p + LCD_UKEY_BL_PWM_ON_DELAY + 1)) << 8)); |
| bconf->pwm_off_delay = (*(p + LCD_UKEY_BL_PWM_OFF_DELAY) | |
| ((*(p + LCD_UKEY_BL_PWM_OFF_DELAY + 1)) << 8)); |
| pwm_combo0->pwm_method = *(p + LCD_UKEY_BL_PWM_METHOD); |
| pwm_combo0->pwm_port = *(p + LCD_UKEY_BL_PWM_PORT); |
| pwm_combo0->pwm_freq = (*(p + LCD_UKEY_BL_PWM_FREQ) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 1)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 2)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM_FREQ + 3)) << 8)); |
| if (pwm_combo0->pwm_port == BL_PWM_VS) { |
| if (pwm_combo0->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", pwm_combo0->pwm_freq); |
| pwm_combo0->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (pwm_combo0->pwm_freq > XTAL_HALF_FREQ_HZ) |
| pwm_combo0->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| pwm_combo0->pwm_duty_max = *(p + LCD_UKEY_BL_PWM_DUTY_MAX); |
| pwm_combo0->pwm_duty_min = *(p + LCD_UKEY_BL_PWM_DUTY_MIN); |
| pwm_combo0->pwm_gpio = *(p + LCD_UKEY_BL_PWM_GPIO); |
| pwm_combo0->pwm_gpio_off = *(p + LCD_UKEY_BL_PWM_GPIO_OFF); |
| pwm_combo1->pwm_method = *(p + LCD_UKEY_BL_PWM2_METHOD); |
| pwm_combo1->pwm_port = *(p + LCD_UKEY_BL_PWM2_PORT); |
| pwm_combo1->pwm_freq = (*(p + LCD_UKEY_BL_PWM2_FREQ) | |
| ((*(p + LCD_UKEY_BL_PWM2_FREQ + 1)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM2_FREQ + 2)) << 8) | |
| ((*(p + LCD_UKEY_BL_PWM2_FREQ + 3)) << 8)); |
| if (pwm_combo1->pwm_port == BL_PWM_VS) { |
| if (pwm_combo1->pwm_freq > 4) { |
| LCDERR("bl: bl_pwm_vs wrong freq %d\n", pwm_combo1->pwm_freq); |
| pwm_combo1->pwm_freq = BL_FREQ_VS_DEFAULT; |
| } |
| } else { |
| if (pwm_combo1->pwm_freq > XTAL_HALF_FREQ_HZ) |
| pwm_combo1->pwm_freq = XTAL_HALF_FREQ_HZ; |
| } |
| pwm_combo1->pwm_duty_max = *(p + LCD_UKEY_BL_PWM2_DUTY_MAX); |
| pwm_combo1->pwm_duty_min = *(p + LCD_UKEY_BL_PWM2_DUTY_MIN); |
| pwm_combo1->pwm_gpio = *(p + LCD_UKEY_BL_PWM2_GPIO); |
| pwm_combo1->pwm_gpio_off = *(p + LCD_UKEY_BL_PWM2_GPIO_OFF); |
| |
| pwm_combo0->level_max = (*(p + LCD_UKEY_BL_PWM_LEVEL_MAX) | |
| ((*(p + LCD_UKEY_BL_PWM_LEVEL_MAX + 1)) << 8)); |
| pwm_combo0->level_min = (*(p + LCD_UKEY_BL_PWM_LEVEL_MIN) | |
| ((*(p + LCD_UKEY_BL_PWM_LEVEL_MIN + 1)) << 8)); |
| pwm_combo1->level_max = (*(p + LCD_UKEY_BL_PWM2_LEVEL_MAX) | |
| ((*(p + LCD_UKEY_BL_PWM2_LEVEL_MAX + 1)) << 8)); |
| pwm_combo1->level_min = (*(p + LCD_UKEY_BL_PWM2_LEVEL_MIN) | |
| ((*(p + LCD_UKEY_BL_PWM2_LEVEL_MIN + 1)) << 8)); |
| |
| if (bl_header.version == 2) |
| bconf->en_sequence_reverse = (*(p + LCD_UKEY_BL_CUST_VAL_0) | |
| ((*(p + LCD_UKEY_BL_CUST_VAL_0 + 1)) << 8)); |
| else |
| bconf->en_sequence_reverse = 0; |
| |
| pwm_combo0->pwm_duty = pwm_combo0->pwm_duty_min; |
| pwm_combo1->pwm_duty = pwm_combo1->pwm_duty_min; |
| /* bl_pwm_config_init(pwm_combo0); |
| bl_pwm_config_init(pwm_combo1); */ |
| break; |
| #ifdef CONFIG_AML_LOCAL_DIMMING |
| case BL_CTRL_LOCAL_DIMMING: |
| if (bl_header.version == 2) { |
| ldim_config_load_from_unifykey(para); |
| } else { |
| LCDERR("bl: not support ldim for unifykey version: %d\n", |
| bl_header.version); |
| } |
| aml_ldim_probe(dt_blob, 2); |
| break; |
| #endif |
| default: |
| break; |
| } |
| |
| free(para); |
| return 0; |
| } |
| |
| static const char *bl_pinmux_str[] = { |
| "bl_pwm_on_pin", /* 0 */ |
| "bl_pwm_vs_on_pin", /* 1 */ |
| "bl_pwm_combo_0_on_pin", /* 2 */ |
| "bl_pwm_combo_1_on_pin", /* 3 */ |
| "bl_pwm_combo_0_vs_on_pin", /* 4 */ |
| "bl_pwm_combo_1_vs_on_pin", /* 5 */ |
| }; |
| |
| static int bl_pinmux_load_from_bsp(struct bl_config_s *bconf) |
| { |
| char propname[50]; |
| struct lcd_pinmux_ctrl_s *pinmux; |
| unsigned int i, j; |
| int pinmux_index = 0, set_cnt = 0, clr_cnt = 0; |
| struct bl_pwm_config_s *bl_pwm; |
| struct bl_pwm_config_s *pwm_combo0, *pwm_combo1; |
| |
| if (lcd_debug_print_flag) |
| LCDPR("bl: %s\n", __func__); |
| if (bconf->bl_pinmux == NULL) { |
| LCDERR("bl: %s: bl_pinmux is NULL for lcd.c\n", __func__); |
| return -1; |
| } |
| |
| switch (bconf->method) { |
| case BL_CTRL_PWM: |
| bl_pwm = bconf->bl_pwm; |
| if (bl_pwm->pwm_port == BL_PWM_VS) |
| pinmux_index = 1; |
| else |
| pinmux_index = 0; |
| sprintf(propname,"%s", bl_pinmux_str[pinmux_index]); |
| pinmux = bconf->bl_pinmux; |
| for (i = 0; i < LCD_PINMX_MAX; i++) { |
| if (strncmp(pinmux->name, "invalid", 7) == 0) |
| break; |
| if (strncmp(pinmux->name, propname, strlen(propname)) == 0) { |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_set[j][0] == LCD_PINMUX_END) |
| break; |
| bl_pwm->pinmux_set[j][0] = pinmux->pinmux_set[j][0]; |
| bl_pwm->pinmux_set[j][1] = pinmux->pinmux_set[j][1]; |
| set_cnt++; |
| } |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_clr[j][0] == LCD_PINMUX_END) |
| break; |
| bl_pwm->pinmux_clr[j][0] = pinmux->pinmux_clr[j][0]; |
| bl_pwm->pinmux_clr[j][1] = pinmux->pinmux_clr[j][1]; |
| clr_cnt++; |
| } |
| break; |
| } |
| pinmux++; |
| } |
| if (set_cnt < LCD_PINMUX_NUM) { |
| bl_pwm->pinmux_set[set_cnt][0] = LCD_PINMUX_END; |
| bl_pwm->pinmux_set[set_cnt][1] = 0x0; |
| } |
| if (clr_cnt < LCD_PINMUX_NUM) { |
| bl_pwm->pinmux_clr[clr_cnt][0] = LCD_PINMUX_END; |
| bl_pwm->pinmux_clr[clr_cnt][1] = 0x0; |
| } |
| break; |
| case BL_CTRL_PWM_COMBO: |
| pwm_combo0 = bconf->bl_pwm_combo0; |
| pwm_combo1 = bconf->bl_pwm_combo1; |
| if (pwm_combo0->pwm_port == BL_PWM_VS) |
| sprintf(propname,"%s", bl_pinmux_str[4]); |
| else |
| sprintf(propname,"%s", bl_pinmux_str[2]); |
| |
| pinmux = bconf->bl_pinmux; |
| for (i = 0; i < LCD_PINMX_MAX; i++) { |
| if (strncmp(pinmux->name, "invalid", 7) == 0) |
| break; |
| if (strncmp(pinmux->name, propname, strlen(propname)) == 0) { |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_set[j][0] == LCD_PINMUX_END) |
| break; |
| pwm_combo0->pinmux_set[j][0] = pinmux->pinmux_set[j][0]; |
| pwm_combo0->pinmux_set[j][1] = pinmux->pinmux_set[j][1]; |
| set_cnt++; |
| } |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_clr[j][0] == LCD_PINMUX_END) |
| break; |
| pwm_combo0->pinmux_clr[j][0] = pinmux->pinmux_clr[j][0]; |
| pwm_combo0->pinmux_clr[j][1] = pinmux->pinmux_clr[j][1]; |
| clr_cnt++; |
| } |
| break; |
| } |
| pinmux++; |
| } |
| if (set_cnt < LCD_PINMUX_NUM) { |
| pwm_combo0->pinmux_set[set_cnt][0] = LCD_PINMUX_END; |
| pwm_combo0->pinmux_set[set_cnt][1] = 0x0; |
| } |
| if (clr_cnt < LCD_PINMUX_NUM) { |
| pwm_combo0->pinmux_clr[clr_cnt][0] = LCD_PINMUX_END; |
| pwm_combo0->pinmux_clr[clr_cnt][1] = 0x0; |
| } |
| |
| if (pwm_combo1->pwm_port == BL_PWM_VS) |
| sprintf(propname,"%s", bl_pinmux_str[5]); |
| else |
| sprintf(propname,"%s", bl_pinmux_str[3]); |
| |
| pinmux = bconf->bl_pinmux; |
| set_cnt = 0; |
| clr_cnt = 0; |
| for (i = 0; i < LCD_PINMX_MAX; i++) { |
| if (strncmp(pinmux->name, "invalid", 7) == 0) |
| break; |
| if (strncmp(pinmux->name, propname, strlen(propname)) == 0) { |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_set[j][0] == LCD_PINMUX_END) |
| break; |
| pwm_combo1->pinmux_set[j][0] = pinmux->pinmux_set[j][0]; |
| pwm_combo1->pinmux_set[j][1] = pinmux->pinmux_set[j][1]; |
| set_cnt++; |
| } |
| for (j = 0; j < LCD_PINMUX_NUM; j++ ) { |
| if (pinmux->pinmux_clr[j][0] == LCD_PINMUX_END) |
| break; |
| pwm_combo1->pinmux_clr[j][0] = pinmux->pinmux_clr[j][0]; |
| pwm_combo1->pinmux_clr[j][1] = pinmux->pinmux_clr[j][1]; |
| clr_cnt++; |
| } |
| break; |
| } |
| pinmux++; |
| } |
| if (set_cnt < LCD_PINMUX_NUM) { |
| pwm_combo1->pinmux_set[set_cnt][0] = LCD_PINMUX_END; |
| pwm_combo1->pinmux_set[set_cnt][1] = 0x0; |
| } |
| if (clr_cnt < LCD_PINMUX_NUM) { |
| pwm_combo1->pinmux_clr[clr_cnt][0] = LCD_PINMUX_END; |
| pwm_combo1->pinmux_clr[clr_cnt][1] = 0x0; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (lcd_debug_print_flag) |
| bl_pinmux_print(bconf); |
| |
| return 0; |
| } |
| |
| static int bl_init_load_from_dts(const void *dt_blob, struct bl_config_s *bconf) |
| { |
| int parent_offset; |
| char *propdata; |
| char *p; |
| const char *str; |
| int i, ret = 0; |
| |
| parent_offset = fdt_path_offset(dt_blob, "/backlight"); |
| if (parent_offset < 0) { |
| LCDPR("bl: not find /backlight node %s\n", fdt_strerror(parent_offset)); |
| return -1; |
| } |
| propdata = (char *)fdt_getprop(dt_blob, parent_offset, "status", NULL); |
| if (propdata == NULL) { |
| LCDPR("bl: not find status, default to disabled\n"); |
| return -1; |
| } else { |
| if (strncmp(propdata, "okay", 2)) { |
| LCDPR("bl: status disabled\n"); |
| return -1; |
| } |
| } |
| |
| /* gpio */ |
| i = 0; |
| propdata = (char *)fdt_getprop(dt_blob, parent_offset, "bl_gpio_names", NULL); |
| if (propdata == NULL) { |
| LCDERR("bl: failed to get bl_gpio_names\n"); |
| } else { |
| p = propdata; |
| while (i < BL_GPIO_NUM_MAX) { |
| if (i > 0) |
| p += strlen(p) + 1; |
| str = p; |
| if (strlen(str) == 0) |
| break; |
| bl_gpio_probe(str, i); |
| i++; |
| } |
| } |
| |
| /* pinmux */ |
| ret = bl_pinmux_load_from_bsp(bconf); |
| |
| return ret; |
| } |
| |
| static int bl_init_load_from_bsp(struct bl_config_s *bconf) |
| { |
| int i, ret = 0; |
| |
| /* gpio */ |
| i = 0; |
| while (i < BL_GPIO_NUM_MAX) { |
| if (strcmp(bconf->gpio_name[i], "invalid") == 0) |
| break; |
| bl_gpio_probe(bconf->gpio_name[i], i); |
| i++; |
| } |
| |
| /* pinmux */ |
| ret = bl_pinmux_load_from_bsp(bconf); |
| |
| return ret; |
| } |
| |
| int bl_config_load(const void *dt_blob, int load_id) |
| { |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| unsigned int index; |
| char *bl_off_policy_str; |
| char *bl_level_str; |
| int ret; |
| |
| bl_status = 0; |
| |
| /* load bl config */ |
| if (load_id & 0x1) { /* dts */ |
| if (load_id & 0x10) { /* unifykey */ |
| if (lcd_debug_print_flag) |
| LCDPR("bl: load bl_config from unifykey\n"); |
| ret = bl_config_load_from_unifykey(dt_blob, lcd_drv->bl_config); |
| } else { /* dts */ |
| if (lcd_debug_print_flag) |
| LCDPR("bl: load bl_config from dts\n"); |
| index = lcd_drv->lcd_config->backlight_index; |
| if (index == 0xff) { |
| lcd_drv->bl_config->method = BL_CTRL_MAX; |
| LCDPR("bl: no backlight exist\n"); |
| return -1; |
| } |
| ret = bl_config_load_from_dts(dt_blob, index, lcd_drv->bl_config); |
| } |
| if (ret == 0) |
| bl_init_load_from_dts(dt_blob, lcd_drv->bl_config); |
| } else { /* bsp */ |
| if (load_id & 0x10) { /* unifykey */ |
| if (lcd_debug_print_flag) |
| LCDPR("bl: load bl_config from unifykey\n"); |
| ret = bl_config_load_from_unifykey(dt_blob, lcd_drv->bl_config); |
| } else { /* bsp */ |
| if (lcd_debug_print_flag) |
| LCDPR("bl: load bl_config from bsp\n"); |
| ret = bl_config_load_from_bsp(lcd_drv->bl_config); |
| } |
| if (ret == 0) |
| bl_init_load_from_bsp(lcd_drv->bl_config); |
| } |
| if (ret) { |
| lcd_drv->bl_config->method = BL_CTRL_MAX; |
| LCDPR("bl: invalid backlight config\n"); |
| return -1; |
| } |
| if (lcd_debug_print_flag) { |
| bl_config_print(); |
| } else { |
| LCDPR("bl: name: %s, method: %d\n", |
| lcd_drv->bl_config->name, |
| lcd_drv->bl_config->method); |
| } |
| |
| /* get bl_off_policy */ |
| bl_off_policy = BL_OFF_POLICY_NONE; |
| bl_off_policy_str = env_get("bl_off"); |
| if (bl_off_policy_str) { |
| if (strncmp(bl_off_policy_str, "none", 2) == 0) |
| bl_off_policy = BL_OFF_POLICY_NONE; |
| else if (strncmp(bl_off_policy_str, "always", 2) == 0) |
| bl_off_policy = BL_OFF_POLICY_ALWAYS; |
| else if (strncmp(bl_off_policy_str, "once", 2) == 0) |
| bl_off_policy = BL_OFF_POLICY_ONCE; |
| LCDPR("bl: bl_off_policy: %s\n", bl_off_policy_str); |
| } |
| |
| /* get bl_level */ |
| bl_level_str = env_get("bl_level"); |
| if (bl_level_str != NULL) { |
| lcd_drv->bl_config->level_default = (int)simple_strtoul(bl_level_str, NULL, 10); |
| LCDPR("bl: bl_level: %d\n", lcd_drv->bl_config->level_default); |
| } |
| |
| return 0; |
| } |
| |