From 9d1103c2da079af458e1b51dedf15150086c8250 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 31 Oct 2018 13:52:37 +0800 Subject: [PATCH] backlight: ldim: add fault reset handle for iw7027 [1/1] PD#SWPL-1161 Problem: sometims iw7027 work failure, need reset to recovery Solution: add reset handler triggered by fault pin Verify: txlx r311 Change-Id: I9c65f0b982ac5e52ff9bd5e43f9df516df2af184 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/backlight/aml_bl.c | 45 +++++-- .../media/vout/backlight/aml_ldim/iw7027_bl.c | 142 +++++++++++++++------ .../media/vout/backlight/aml_ldim/ldim_dev_drv.c | 23 +++- .../media/vout/backlight/aml_ldim/ldim_drv.c | 1 + .../media/vout/backlight/aml_ldim/ldim_drv.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_common.c | 8 +- include/linux/amlogic/media/vout/lcd/aml_ldim.h | 1 + 7 files changed, 161 insertions(+), 62 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index d1925b0..e912a18 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -2288,12 +2288,34 @@ static struct notifier_block aml_bl_off_nb = { .priority = LCD_PRIORITY_POWER_BL_OFF, }; +static inline int aml_bl_pwm_vs_lcd_update(struct bl_pwm_config_s *bl_pwm) +{ + unsigned int cnt; + + if (bl_pwm == NULL) { + BLERR("%s: bl_pwm is null\n", __func__); + return 0; + } + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + if (brightness_bypass) + bl_set_duty_pwm(bl_pwm); + else + aml_bl_update_status(bl_drv->bldev); + } + + return 0; +} + static int aml_bl_lcd_update_notifier(struct notifier_block *nb, unsigned long event, void *data) { struct bl_pwm_config_s *bl_pwm = NULL; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + unsigned int *frame_rate; #endif /* If we aren't interested in this event, skip it immediately */ @@ -2308,13 +2330,8 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, case BL_CTRL_PWM: if (bl_drv->bconf->bl_pwm->pwm_port == BL_PWM_VS) { bl_pwm = bl_drv->bconf->bl_pwm; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); } break; case BL_CTRL_PWM_COMBO: @@ -2322,16 +2339,16 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, bl_pwm = bl_drv->bconf->bl_pwm_combo0; else if (bl_drv->bconf->bl_pwm_combo1->pwm_port == BL_PWM_VS) bl_pwm = bl_drv->bconf->bl_pwm_combo1; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING case BL_CTRL_LOCAL_DIMMING: + if (data) { + frame_rate = (unsigned int *)data; + ldim_drv->vsync_change_flag = + (unsigned char)(*frame_rate); + } if (ldim_drv->pwm_vs_update) ldim_drv->pwm_vs_update(); break; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 187b723..6c123d1d 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -46,9 +46,11 @@ #define IW7027_REG_CHIPID 0x7f #define IW7027_CHIPID 0x28 -#define IW7027_POWER_ON 0 -#define IW7027_POWER_RESET 1 +#define VSYNC_INFO_FREQUENT 30 + static int iw7027_on_flag; +static unsigned short vsync_cnt; +static unsigned short fault_cnt; static DEFINE_MUTEX(iw7027_spi_mutex); @@ -247,8 +249,6 @@ static int iw7027_hw_init_on(void) unsigned char reg_chk, reg_duty_chk; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - /* step 1: system power_on */ ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); @@ -295,8 +295,6 @@ static int iw7027_hw_init_on(void) } LDIMPR("%s: calibration done: [%d] = %x\n", __func__, i, reg_duty_chk); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -304,15 +302,11 @@ static int iw7027_hw_init_off(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -387,6 +381,48 @@ static int iw7027_spi_dump_dim(char *buf) return len; } +static int fault_cnt_save; +static int fault_check_cnt; +static int iw7027_fault_handler(unsigned int gpio) +{ + unsigned int val; + + if (gpio >= BL_GPIO_NUM_MAX) + return 0; + + if (fault_check_cnt++ > 200) { /* clear fault flag for a cycle */ + fault_check_cnt = 0; + fault_cnt = 0; + fault_cnt_save = 0; + } + + if (ldim_debug_print) { + if (vsync_cnt == 0) { + LDIMPR("%s: fault_cnt: %d, fault_check_cnt: %d\n", + __func__, fault_cnt, fault_check_cnt); + } + } + + val = ldim_gpio_get(gpio); + if (val == 0) + return 0; + + fault_cnt++; + if (fault_cnt_save != fault_cnt) { + fault_cnt_save = fault_cnt; + LDIMPR("%s: fault_cnt: %d\n", __func__, fault_cnt); + } + if (fault_cnt <= 10) { + iw7027_wreg(bl_iw7027->spi, 0x61, 0x0f); + } else { + iw7027_hw_init_on(); + fault_cnt = 0; + fault_cnt_save = 0; + } + + return -1; +} + static unsigned int dim_max, dim_min; static inline unsigned int iw7027_get_value(unsigned int level) { @@ -397,7 +433,6 @@ static inline unsigned int iw7027_get_value(unsigned int level) return val; } -static int smr_cnt; static int iw7027_smr(unsigned short *buf, unsigned char len) { int i; @@ -405,22 +440,22 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) unsigned short *mapping, num; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (smr_cnt++ >= 30) - smr_cnt = 0; + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; if (iw7027_on_flag == 0) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); return 0; } num = ldim_drv->ldev_conf->bl_regnum; if (len != num) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: data len %d invalid\n", __func__, len); return -1; } if (val_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: val_brightness is null\n", __func__); return -1; } @@ -431,9 +466,16 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) dim_max = ldim_drv->ldev_conf->dim_max; dim_min = ldim_drv->ldev_conf->dim_min; + if (ldim_drv->vsync_change_flag == 50) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd7); + ldim_drv->vsync_change_flag = 0; + } else if (ldim_drv->vsync_change_flag == 60) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd3); + ldim_drv->vsync_change_flag = 0; + } if (bl_iw7027->test_mode) { if (test_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("test_brightness is null\n"); return 0; } @@ -458,18 +500,51 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) iw7027_wregs(bl_iw7027->spi, 0x40, val_brightness, (num * 2)); + if (ldim_drv->ldev_conf->fault_check) + iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + mutex_unlock(&iw7027_spi_mutex); + return 0; } +static int iw7027_check(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + int ret = 0; + + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; + + if (iw7027_on_flag == 0) { + if (vsync_cnt == 0) + LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); + return 0; + } + + mutex_lock(&iw7027_spi_mutex); + + if (ldim_drv->ldev_conf->fault_check) + ret = iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + + mutex_unlock(&iw7027_spi_mutex); + + return ret; +} + static int iw7027_power_on(void) { if (iw7027_on_flag) { LDIMPR("%s: iw7027 is already on, exit\n", __func__); return 0; } + + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); iw7027_on_flag = 1; + vsync_cnt = 0; + fault_cnt = 0; + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -477,8 +552,10 @@ static int iw7027_power_on(void) static int iw7027_power_off(void) { + mutex_lock(&iw7027_spi_mutex); iw7027_on_flag = 0; iw7027_hw_init_off(); + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -492,11 +569,7 @@ static ssize_t iw7027_show(struct class *class, int ret = 0; int i; - if (!strcmp(attr->attr.name, "mode")) { - ret = sprintf(buf, "0x%02x\n", bl->spi->mode); - } else if (!strcmp(attr->attr.name, "speed")) { - ret = sprintf(buf, "%d\n", bl->spi->max_speed_hz); - } else if (!strcmp(attr->attr.name, "test")) { + if (!strcmp(attr->attr.name, "test")) { ret = sprintf(buf, "test mode=%d\n", bl->test_mode); } else if (!strcmp(attr->attr.name, "brightness")) { if (test_brightness == NULL) { @@ -511,13 +584,15 @@ static ssize_t iw7027_show(struct class *class, ret = sprintf(buf, "iw7027 status:\n" "dev_index = %d\n" "on_flag = %d\n" + "fault_cnt = %d\n" "en_on = %d\n" "en_off = %d\n" "cs_hold_delay = %d\n" "cs_clk_delay = %d\n" "dim_max = 0x%03x\n" "dim_min = 0x%03x\n", - ldim_drv->dev_index, iw7027_on_flag, + ldim_drv->dev_index, + iw7027_on_flag, fault_cnt, ldim_drv->ldev_conf->en_gpio_on, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->cs_hold_delay, @@ -546,19 +621,9 @@ static ssize_t iw7027_store(struct class *class, int i; if (!strcmp(attr->attr.name, "init")) { + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); - } else if (!strcmp(attr->attr.name, "mode")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->mode = val; - else - LDIMERR("%s: invalid args\n", __func__); - } else if (!strcmp(attr->attr.name, "speed")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->max_speed_hz = val*1000; - else - LDIMERR("%s: invalid args\n", __func__); + mutex_unlock(&iw7027_spi_mutex); } else if (!strcmp(attr->attr.name, "reg")) { if (buf[0] == 'w') { i = sscanf(buf, "w %x %x", &val, &val2); @@ -605,9 +670,7 @@ static ssize_t iw7027_store(struct class *class, } static struct class_attribute iw7027_class_attrs[] = { - __ATTR(init, 0644, iw7027_show, iw7027_store), - __ATTR(mode, 0644, iw7027_show, iw7027_store), - __ATTR(speed, 0644, iw7027_show, iw7027_store), + __ATTR(init, 0644, NULL, iw7027_store), __ATTR(reg, 0644, iw7027_show, iw7027_store), __ATTR(test, 0644, iw7027_show, iw7027_store), __ATTR(brightness, 0644, iw7027_show, iw7027_store), @@ -623,6 +686,7 @@ static int iw7027_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) ldim_drv->device_power_on = iw7027_power_on; ldim_drv->device_power_off = iw7027_power_off; ldim_drv->device_bri_update = iw7027_smr; + ldim_drv->device_bri_check = iw7027_check; return 0; } @@ -636,6 +700,8 @@ int ldim_dev_iw7027_probe(struct aml_ldim_driver_s *ldim_drv) } iw7027_on_flag = 0; + vsync_cnt = 0; + fault_cnt = 0; bl_iw7027 = kzalloc(sizeof(struct iw7027_s), GFP_KERNEL); if (bl_iw7027 == NULL) { diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index b2c0225..037a3d0 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -321,12 +321,21 @@ static int ldim_pwm_pinmux_ctrl(int status) static int ldim_pwm_vs_update(void) { - struct bl_pwm_config_s *bl_pwm = NULL; + struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.pwm_config; + unsigned int cnt; int ret = 0; - bl_pwm = &ldim_dev_config.pwm_config; - bl_pwm_config_init(bl_pwm); - ldim_set_duty_pwm(bl_pwm); + if (bl_pwm->pwm_port != BL_PWM_VS) + return 0; + + if (ldim_debug_print) + LDIMPR("%s\n", __func__); + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + } return ret; } @@ -466,9 +475,11 @@ static void ldim_dev_config_print(void) LDIMPR("%s:\n", __func__); pr_info("valid_flag = %d\n" - "dev_index = %d\n", + "dev_index = %d\n" + "vsync_change_flag = %d\n", ldim_drv->valid_flag, - ldim_drv->dev_index); + ldim_drv->dev_index, + ldim_drv->vsync_change_flag); if (ldim_drv->ldev_conf == NULL) { LDIMERR("%s: device config is null\n", __func__); return; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index bb5e4e6..7ec078d 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -1745,6 +1745,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, + .vsync_change_flag = 0, .pinmux_flag = 0xff, .ldim_conf = &ldim_config, .ldev_conf = NULL, diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index dfd58f7..0875bde 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -24,7 +24,8 @@ /*20180730: algorithm clear up */ /*20180820: pq tooling support, espically optimize some alg parameters */ /*20181101: fix ldim_op_func null mistake, add new spi api support */ -#define LDIM_DRV_VER "20181101" +/*20181203: add 50/60hz change & iw7027 error handle support */ +#define LDIM_DRV_VER "20181203" extern unsigned char ldim_debug_print; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 3982e72..4da7d47 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -1073,7 +1073,7 @@ int lcd_vmode_change(struct lcd_config_s *pconf) void lcd_venc_change(struct lcd_config_s *pconf) { - unsigned int htotal, vtotal; + unsigned int htotal, vtotal, frame_rate; htotal = lcd_vcbus_read(ENCL_VIDEO_MAX_PXCNT) + 1; vtotal = lcd_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; @@ -1091,8 +1091,10 @@ void lcd_venc_change(struct lcd_config_s *pconf) pconf->lcd_basic.v_period); } - if (pconf->lcd_basic.v_period != vtotal) - aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, NULL); + frame_rate = (pconf->lcd_timing.sync_duration_num * 100) / + pconf->lcd_timing.sync_duration_den; + frame_rate = (frame_rate + 50) / 100; + aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, &frame_rate); } void lcd_if_enable_retry(struct lcd_config_s *pconf) diff --git a/include/linux/amlogic/media/vout/lcd/aml_ldim.h b/include/linux/amlogic/media/vout/lcd/aml_ldim.h index 72cf7ef..6638083 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_ldim.h +++ b/include/linux/amlogic/media/vout/lcd/aml_ldim.h @@ -92,6 +92,7 @@ struct aml_ldim_driver_s { unsigned char valid_flag; unsigned char dev_index; unsigned char static_pic_flag; + unsigned char vsync_change_flag; unsigned char pinmux_flag; struct ldim_config_s *ldim_conf; -- 2.7.4