Skip to content

Commit

Permalink
lcd: support custom vx1 hw filter [1/1]
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Evoke Zhang authored and jianxinpan committed May 22, 2019
1 parent 3dcf1c8 commit 207be3e
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 12 deletions.
3 changes: 2 additions & 1 deletion drivers/amlogic/media/vout/lcd/lcd_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
86 changes: 83 additions & 3 deletions drivers/amlogic/media/vout/lcd/lcd_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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 =
Expand Down
29 changes: 29 additions & 0 deletions drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();
}
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 44 additions & 4 deletions drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
Expand Down
25 changes: 25 additions & 0 deletions drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions drivers/amlogic/media/vout/lcd/lcd_vout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions include/linux/amlogic/media/vout/lcd/lcd_vout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 207be3e

Please sign in to comment.