author | Evoke Zhang <evoke.zhang@amlogic.com> | 2019-04-25 02:39:13 (GMT) |
---|---|---|
committer | Jianxin Pan <jianxin.pan@amlogic.com> | 2019-05-22 05:11:19 (GMT) |
commit | 207be3e45d9059748b9e9ebf06684fe3619f37c1 (patch) | |
tree | 49fd26f0b8ffe8d41aea7292b2f6e2c1fe0c7006 | |
parent | 3dcf1c8d25d5b169e8223296a2c9f9adc7a8837c (diff) | |
download | common-207be3e45d9059748b9e9ebf06684fe3619f37c1.zip common-207be3e45d9059748b9e9ebf06684fe3619f37c1.tar.gz common-207be3e45d9059748b9e9ebf06684fe3619f37c1.tar.bz2 |
lcd: support custom vx1 hw filter [1/1]
PD#SWPL-8785
Problem:
fixed vx1 hw filter maybe cause some panel display normal
Solution:
add custom vx1 hw filter support
for panel ini:
if_attr_8=0x1 #vx1 hw filter period(0=default setting)
if_attr_9=0x0 #vx1 hw filter cnt(0=default setting)
for dts:
hw_filter = <0x1 0x0>; /* period(0=default), cnt(0=default) */
Verify:
x301
Change-Id: I4ce5f8fe4294331d6ec0026fa7736c6d3397c05e
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_common.h | 3 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_debug.c | 86 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c | 29 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 48 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 25 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/lcd/lcd_vout.c | 4 | ||||
-rw-r--r-- | include/linux/amlogic/media/vout/lcd/lcd_vout.h | 7 |
7 files changed, 190 insertions, 12 deletions
diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 1c571c1..32dc89c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -39,7 +39,8 @@ /* 20190115: tl1 tcon all interface support */ /* 20190225: optimize unifykey read flow to avoid crash */ /* 20190308: add more panel clk_ss_level step for tl1 */ -#define LCD_DRV_VERSION "20190308" +/* 20190520: add vbyone hw filter user define support */ +#define LCD_DRV_VERSION "20190520" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 8df144b..734ace3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -359,6 +359,8 @@ static int lcd_info_print_vbyone(char *buf, int offset) "phy_preem 0x%x\n" "intr_en %u\n" "vsync_intr_en %u\n" + "hw_filter_time 0x%x\n" + "hw_filter_cnt 0x%x\n" "ctrl_flag 0x%x\n\n", vx1_conf->lane_count, vx1_conf->region_num, @@ -369,6 +371,8 @@ static int lcd_info_print_vbyone(char *buf, int offset) vx1_conf->phy_preem, vx1_conf->intr_en, vx1_conf->vsync_intr_en, + vx1_conf->hw_filter_time, + vx1_conf->hw_filter_cnt, vx1_conf->ctrl_flag); if (vx1_conf->ctrl_flag & 0x1) { n = lcd_debug_info_len(len + offset); @@ -731,7 +735,7 @@ static int lcd_reg_print_lvds(char *buf, int offset) return len; } -static int lcd_reg_print_vbyone(char *buf, int offset) +static int lcd_reg_print_vbyone_txl(char *buf, int offset) { unsigned int reg; int n, len = 0; @@ -786,6 +790,66 @@ static int lcd_reg_print_vbyone(char *buf, int offset) return len; } +static int lcd_reg_print_vbyone_tl1(char *buf, int offset) +{ + unsigned int reg; + int n, len = 0; + + lcd_reg_print_serializer((buf+len), (len+offset)); + + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, "\nvbyone regs:\n"); + n = lcd_debug_info_len(len + offset); + reg = VBO_STATUS_L; + len += snprintf((buf+len), n, + "VX1_STATUS [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + + n = lcd_debug_info_len(len + offset); + reg = VBO_INFILTER_TICK_PERIOD_H; + len += snprintf((buf+len), n, + "VBO_INFILTER_TICK_PERIOD_H [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_INFILTER_TICK_PERIOD_L; + len += snprintf((buf+len), n, + "VBO_INFILTER_TICK_PERIOD_L [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_INSGN_CTRL; + len += snprintf((buf+len), n, + "VBO_INSGN_CTRL [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + + n = lcd_debug_info_len(len + offset); + reg = VBO_FSM_HOLDER_L; + len += snprintf((buf+len), n, + "VX1_FSM_HOLDER_L [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_FSM_HOLDER_H; + len += snprintf((buf+len), n, + "VX1_FSM_HOLDER_H [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_INTR_STATE_CTRL; + len += snprintf((buf+len), n, + "VX1_INTR_STATE_CTRL [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_INTR_UNMASK; + len += snprintf((buf+len), n, + "VX1_INTR_UNMASK [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = VBO_INTR_STATE; + len += snprintf((buf+len), n, + "VX1_INTR_STATE [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + + return len; +} + static int lcd_reg_print_mipi(char *buf, int offset) { unsigned int reg; @@ -3479,7 +3543,7 @@ static ssize_t lcd_vx1_debug_store(struct class *class, vx1_conf->cdr_training_hold = val[3]; lcd_debug_config_update(); } else { - pr_info("set vbyone ctrl_flag: 0x%x\n", + pr_info("vbyone ctrl_flag: 0x%x\n", vx1_conf->ctrl_flag); pr_info("power_on_reset_delay: %dms\n", vx1_conf->power_on_reset_delay); @@ -3492,6 +3556,20 @@ static ssize_t lcd_vx1_debug_store(struct class *class, #else return -EINVAL; #endif + } else if (buf[0] == 'f') { /* filter */ + ret = sscanf(buf, "filter %x %x", &val[0], &val[1]); + if (ret == 2) { + pr_info("set vbyone hw_filter_time: 0x%x, hw_filter_cnt: 0x%x\n", + val[0], val[1]); + vx1_conf->hw_filter_time = val[0]; + vx1_conf->hw_filter_cnt = val[1]; + lcd_debug_config_update(); + } else { + pr_info("vbyone hw_filter_time: 0x%x, hw_filter_cnt: 0x%x\n", + vx1_conf->hw_filter_time, + vx1_conf->hw_filter_cnt); + return -EINVAL; + } } else { ret = sscanf(buf, "%d %d %d", &vx1_conf->lane_count, &vx1_conf->region_num, &vx1_conf->byte_mode); @@ -4462,7 +4540,7 @@ static struct lcd_debug_info_if_s lcd_debug_info_if_lvds = { static struct lcd_debug_info_if_s lcd_debug_info_if_vbyone = { .interface_print = lcd_info_print_vbyone, - .reg_dump_interface = lcd_reg_print_vbyone, + .reg_dump_interface = lcd_reg_print_vbyone_txl, .reg_dump_phy = lcd_reg_print_phy_analog, .class_attrs = lcd_debug_class_attrs_vbyone, }; @@ -4501,6 +4579,8 @@ int lcd_debug_probe(void) lcd_debug_info_reg = &lcd_debug_info_reg_tl1; lcd_debug_info_if_lvds.reg_dump_phy = lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_vbyone.reg_dump_interface = + lcd_reg_print_vbyone_tl1; lcd_debug_info_if_vbyone.reg_dump_phy = lcd_reg_print_phy_analog_tl1; lcd_debug_info_if_mlvds.reg_dump_phy = diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 4bf4862..424ca35 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -258,6 +258,7 @@ static int lcd_set_vframe_rate_hint(int duration) /* update vinfo */ info->sync_duration_num = duration_num; info->sync_duration_den = duration_den; + lcd_drv->fr_mode = 1; lcd_framerate_automation_set_mode(); #endif @@ -282,9 +283,15 @@ static int lcd_set_vframe_rate_end_hint(void) LCDPR("%s: return mode = %s, policy = %d\n", __func__, info->name, lcd_drv->fr_auto_policy); + if (lcd_drv->fr_mode == 0) { + LCDPR("%s: fr_mode is invalid, exit\n", __func__); + return 0; + } + /* update vinfo */ info->sync_duration_num = lcd_drv->std_duration.duration_num; info->sync_duration_den = lcd_drv->std_duration.duration_den; + lcd_drv->fr_mode = 0; lcd_framerate_automation_set_mode(); } @@ -842,6 +849,22 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_control.vbyone_config->phy_preem); } } + ret = of_property_read_u32_array(child, "hw_filter", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get hw_filter\n"); + } else { + pconf->lcd_control.vbyone_config->hw_filter_time = + para[0]; + pconf->lcd_control.vbyone_config->hw_filter_cnt = + para[1]; + if (lcd_debug_print_flag) { + LCDPR("vbyone hw_filter=0x%x 0x%x\n", + pconf->lcd_control.vbyone_config->hw_filter_time, + pconf->lcd_control.vbyone_config->hw_filter_cnt); + } + } break; case LCD_MIPI: ret = of_property_read_u32_array(child, "mipi_attr", @@ -1120,6 +1143,12 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) pconf->lcd_control.vbyone_config->vsync_intr_en = (*(p + LCD_UKEY_IF_ATTR_7) | ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; + pconf->lcd_control.vbyone_config->hw_filter_time = + *(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8); + pconf->lcd_control.vbyone_config->hw_filter_cnt = + *(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8); } } else LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 657b7a9..8dd95cb 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -519,16 +519,55 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, static void lcd_vbyone_hw_filter(int flag) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vbyone_config_s *vx1_conf; + unsigned int temp, period; + unsigned int tick_period[] = { + 0xfffff, + 0xff, /* 1: 0.8us */ + 0x1ff, /* 2: 1.7us */ + 0x3ff, /* 3: 3.4us */ + 0x7ff, /* 4: 6.9us */ + 0xfff, /* 5: 13.8us */ + 0x1fff, /* 6: 27us */ + 0x3fff, /* 7: 55us */ + 0x7fff, /* 8: 110us */ + 0xffff, /* 9: 221us */ + 0x1ffff, /* 10: 441us */ + 0x3ffff, /* 11: 883us */ + 0x7ffff, /* 12: 1.76ms */ + 0xfffff, /* 13: 3.53ms */ + }; + vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: case LCD_CHIP_TM2: if (flag) { - lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xffff); - lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0xf); - lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); - lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + period = vx1_conf->hw_filter_time & 0xff; + if (period >= + (sizeof(tick_period) / sizeof(unsigned int))) + period = tick_period[0]; + else + period = tick_period[period]; + temp = period & 0xffff; + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, temp); + temp = (period >> 16) & 0xf; + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, temp); + /* hpd */ + temp = vx1_conf->hw_filter_cnt & 0xf; + temp = (temp == 0) ? 0x7 : temp; + lcd_vcbus_setb(VBO_INSGN_CTRL, temp, 8, 4); + /* lockn */ + temp = (vx1_conf->hw_filter_cnt >> 8) & 0xf; + temp = (temp == 0) ? 0x7 : temp; + lcd_vcbus_setb(VBO_INSGN_CTRL, temp, 12, 4); } else { + temp = (vx1_conf->hw_filter_time >> 8) & 0x1; + if (temp) { + LCDPR("%s: %d bypass for debug\n", + __func__, flag); + break; + } lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); @@ -752,6 +791,7 @@ void lcd_vbyone_interrupt_enable(int flag) lcd_vcbus_write(VBO_INTR_UNMASK, 0x0); /* release hold in FSM_ACQ */ lcd_vcbus_setb(VBO_FSM_HOLDER_L, 0, 0, 16); + lcd_vbyone_hw_filter(0); lcd_vx1_intr_request = 0; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index b692ed4..81319ce 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -520,6 +520,7 @@ static int lcd_set_vframe_rate_hint(int duration) /* update vinfo */ info->sync_duration_num = duration_num; info->sync_duration_den = duration_den; + lcd_drv->fr_mode = 1; lcd_framerate_automation_set_mode(); #endif @@ -552,9 +553,15 @@ static int lcd_set_vframe_rate_end_hint(void) LCDPR("%s: return mode = %s, policy = %d\n", __func__, info->name, lcd_drv->fr_auto_policy); + if (lcd_drv->fr_mode == 0) { + LCDPR("%s: fr_mode is invalid, exit\n", __func__); + return 0; + } + /* update vinfo */ info->sync_duration_num = lcd_drv->std_duration.duration_num; info->sync_duration_den = lcd_drv->std_duration.duration_den; + lcd_drv->fr_mode = 0; lcd_framerate_automation_set_mode(); } @@ -1006,6 +1013,20 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, vx1_conf->cdr_training_hold); } } + ret = of_property_read_u32_array(child, "hw_filter", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get hw_filter\n"); + } else { + vx1_conf->hw_filter_time = para[0]; + vx1_conf->hw_filter_cnt = para[1]; + if (lcd_debug_print_flag) { + LCDPR("vbyone hw_filter=0x%x 0x%x\n", + vx1_conf->hw_filter_time, + vx1_conf->hw_filter_cnt); + } + } break; case LCD_MLVDS: mlvds_conf = pconf->lcd_control.mlvds_config; @@ -1229,6 +1250,10 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)) & 0xff; vx1_conf->vsync_intr_en = (*(p + LCD_UKEY_IF_ATTR_7) | ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; + vx1_conf->hw_filter_time = *(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8); + vx1_conf->hw_filter_cnt = *(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8); } } else if (pconf->lcd_basic.lcd_type == LCD_LVDS) { if (lcd_header.version == 2) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 0974804..c5880b3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -113,6 +113,9 @@ static struct vbyone_config_s lcd_vbyone_config = { .power_on_reset_delay = VX1_PWR_ON_RESET_DLY_DFT, .hpd_data_delay = VX1_HPD_DATA_DELAY_DFT, .cdr_training_hold = VX1_CDR_TRAINING_HOLD_DFT, + + .hw_filter_time = 0, + .hw_filter_cnt = 0, }; static struct mlvds_config_s lcd_mlvds_config = { @@ -1325,6 +1328,7 @@ static int lcd_config_probe(struct platform_device *pdev) lcd_driver->lcd_mute_state = 0; lcd_driver->lcd_mute_flag = 0; lcd_driver->lcd_resume_type = 1; /* default workqueue */ + lcd_driver->fr_mode = 0; lcd_driver->viu_sel = LCD_VIU_SEL_NONE; lcd_driver->vsync_none_timer_flag = 0; lcd_driver->power_ctrl = lcd_power_ctrl; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index e70d678..bc7a64b 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -259,10 +259,8 @@ struct vbyone_config_s { unsigned int hpd_data_delay; /* ms */ unsigned int cdr_training_hold; /* ms */ /* hw filter */ - unsigned int hpd_hw_filter_time; /* ms */ - unsigned int hpd_hw_filter_cnt; - unsigned int lockn_hw_filter_time; /* ms */ - unsigned int lockn_hw_filter_cnt; + unsigned int hw_filter_time; + unsigned int hw_filter_cnt; }; /* mipi-dsi config */ @@ -501,6 +499,7 @@ struct aml_lcd_drv_s { struct class *lcd_debug_class; int fr_auto_policy; + int fr_mode; struct lcd_duration_s std_duration; void (*driver_init_pre)(void); |