backlight: ldim: add fault reset handle for iw7027 [1/1]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Wed, 31 Oct 2018 05:52:37 +0000 (13:52 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 12 Dec 2018 03:10:09 +0000 (19:10 -0800)
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 <evoke.zhang@amlogic.com>
drivers/amlogic/media/vout/backlight/aml_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h
drivers/amlogic/media/vout/lcd/lcd_common.c
include/linux/amlogic/media/vout/lcd/aml_ldim.h

index d1925b0..e912a18 100644 (file)
@@ -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;
index 187b723..6c123d1 100644 (file)
 #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) {
index b2c0225..037a3d0 100644 (file)
@@ -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;
index bb5e4e6..7ec078d 100644 (file)
@@ -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,
index dfd58f7..0875bde 100644 (file)
@@ -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;
 
index 3982e72..4da7d47 100644 (file)
@@ -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)
index 72cf7ef..6638083 100644 (file)
@@ -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;