summaryrefslogtreecommitdiff
authorEvoke 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)
commit207be3e45d9059748b9e9ebf06684fe3619f37c1 (patch)
tree49fd26f0b8ffe8d41aea7292b2f6e2c1fe0c7006
parent3dcf1c8d25d5b169e8223296a2c9f9adc7a8837c (diff)
downloadcommon-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>
Diffstat
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_common.h3
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_debug.c86
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c29
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c48
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c25
-rw-r--r--drivers/amlogic/media/vout/lcd/lcd_vout.c4
-rw-r--r--include/linux/amlogic/media/vout/lcd/lcd_vout.h7
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",
+ &para[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",
+ &para[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);