MTK 平台LCM ESD客制化及代码分析和案例
参考文档:
[FAQ14251]如何配置LCM ESD Check——读寄存器方式
https://onlinesso.mediatek.com/FAQ/SW/FAQ14251
[FAQ14273]MT6735/MT6753/MT6580 ESD问题攻略——外部TE方式
https://onlinesso.mediatek.com/FAQ/SW/FAQ14273
[FAQ14880]LCM ESD Check 问题处理流程
https://onlinesso.mediatek.com/FAQ/SW/FAQ14880
[FAQ13728]MT6735通过读寄存器方式做ESD,客制化需求----多个返回值
https://onlinesso.mediatek.com/FAQ/SW/FAQ13728
一.LCM ESD客制化方法
alps/kernel-3.18/drivers/misc/mediatek/lcm/xxx/xxx.c
alps/vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/xxx/xxx.c
static void lcm_get_params(LCM_PARAMS *params)
{
……
/* Esd Check方法1 : Read from lcm */
params->dsi.esd_check_enable = 1;
params->dsi.customization_esd_check_enable = 1;
params->dsi.lcm_esd_check_table[0].cmd = 0x0A; //具体是哪个寄存器由FAE告知
params->dsi.lcm_esd_check_table[0].count = 1;
params->dsi.lcm_esd_check_table[0].para_list[0] = 0x1C; //读取寄存器的正确值也由FAE告知,寄存器的值要配置正确,否则会不断地esd recovery
/* Esd Check方法2 : EXT TE */
//params->dsi.esd_check_enable = 1;
//params->dsi.customization_esd_check_enable = 0;
}
二.MT6580 LCM ESD check流程分析
alps/kernel-3.18/drivers/misc/mediatek/video/mt6580/videox/primary_display.c
int primary_display_init(char *lcm_name, unsigned int lcm_fps)
{
......
primary_display_esd_check_task =
kthread_create(primary_display_esd_check_worker_kthread,
NULL, "display_esd_check");
......
//这里根据LCM中配置的params->dsi.esd_check_enable是否等于1来判断是否开启primary_display_esd_check_worker_kthread线程
if (_need_do_esd_check())
wake_up_process(primary_display_esd_check_task);
......
}
unsigned int _need_do_esd_check(void)
{
int ret = 0;
#ifdef CONFIG_OF
if ((pgc->plcm->params->dsi.esd_check_enable == 1)
&& (islcmconnected == 1))
ret = 1;
#else
if (pgc->plcm->params->dsi.esd_check_enable == 1)
ret = 1;
#endif
return ret;
}
static int primary_display_esd_check_worker_kthread(void *data)
{
......
//定义esd recovery重试的次数
int esd_try_cnt = 5;
......
//这里每2秒扫描一次
msleep(2000); /* esd check and pull clock lane every 2s */
......
//执行esd check判断是否要进行esd recovery,关于primary_display_esd_check函数的分析在下面会讲到
ret = primary_display_esd_check();
if (ret == 1) {
pr_debug("[ESD]esd check fail, will do esd recovery\n");
i = esd_try_cnt;
while (i--) {
DISPCHECK("[ESD]esd recovery try:%d\n", i);
//执行恢复动作,重新初始化显示屏参数,关于primary_display_esd_recovery函数的分析在下面有讲到
primary_display_esd_recovery();
//执行完恢复动作后,再次进行esd check,如果检测到的lcm寄存器的值正常,则不会再进行recovery的动作;否则会连续进行recovery和esd check,若在规定的5次内recovery均不成功,就会执行primary_display_esd_check_enable(0)关闭primary_display_esd_check_worker_kthread线程。
ret = primary_display_esd_check();
if (ret == 0) {
pr_debug
("[ESD]esd recovery success\n");
break;
}
pr_debug("[ESD]after esd recovery, esd check still fail\n");
if (i == 0) {
DISPERR(
"[ESD]after esd recovery %d times, esd check still fail, disable esd check\n",
esd_try_cnt);
primary_display_esd_check_enable(0);
}
}
}
......
}
/* ESD CHECK FUNCTION */
/* return 1: esd check fail */
/* return 0: esd check pass */
int primary_display_esd_check(void)
{
……
/* Esd Check : EXT TE */
//使用TE的方式进行esd check的时候,需要在lcm的驱动中定义esd_check_enable为1,customization_esd_check_enable为0,lcm的初始化参数也要匹配TE的,主控这边的TE GPIO口需要配置正确
if (pgc->plcm->params->dsi.customization_esd_check_enable == 0) {
MMProfileLogEx(ddp_mmp_get_events()->esd_extte,
MMProfileFlagStart, 0, 0);
if (primary_display_is_video_mode()) {
primary_display_switch_esd_mode(1);
/* use cmdq to pull DSI clk lane*/
if (primary_display_cmdq_enabled()) {
_primary_path_lock(__func__);
/* 0.create esd check cmdq */
cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &(pgc->cmdq_handle_config_esd));
_primary_path_unlock(__func__);
/* 1.reset*/
cmdqRecReset(pgc->cmdq_handle_config_esd);
/* wait stream eof first */
ret = cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_DISP_RDMA0_EOF);
cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
_primary_path_lock(__func__);
/* 2.stop dsi vdo mode */
dpmgr_path_build_cmdq(pgc->dpmgr_handle,
pgc->cmdq_handle_config_esd, CMDQ_STOP_VDO_MODE, 0);
/* 3.pull DSI clock lane */
DSI_sw_clk_trail_cmdq(0, pgc->cmdq_handle_config_esd);
DSI_manual_enter_HS(pgc->cmdq_handle_config_esd);
/* 4.start dsi vdo mode */
dpmgr_path_build_cmdq(pgc->dpmgr_handle,
pgc->cmdq_handle_config_esd, CMDQ_START_VDO_MODE, 0);
/* 5. trigger path */
cmdqRecClearEventToken(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ENABLE);
_primary_path_unlock(__func__);
cmdqRecFlush(pgc->cmdq_handle_config_esd);
cmdqRecDestroy(pgc->cmdq_handle_config_esd);
pgc->cmdq_handle_config_esd = NULL;
}
if (_need_register_eint()) {
MMProfileLogEx(ddp_mmp_get_events()->esd_extte,
MMProfileFlagPulse, 1, 1);
if (wait_event_interruptible_timeout
(esd_ext_te_wq,
atomic_read(&esd_ext_te_event),
HZ / 2) > 0) {
ret = 0; /* esd check pass */
} else {
ret = 1; /* esd check fail */
}
atomic_set(&esd_ext_te_event, 0);
}
primary_display_switch_esd_mode(0);
} else {
MMProfileLogEx(ddp_mmp_get_events()->esd_extte,
MMProfileFlagPulse, 0, 1);
if (dpmgr_wait_event_timeout
(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC,
HZ / 2) > 0) {
ret = 0; /* esd check pass */
} else {
ret = 1; /* esd check fail */
}
}
MMProfileLogEx(ddp_mmp_get_events()->esd_extte,
MMProfileFlagEnd, 0, ret);
/* _primary_path_unlock(__func__); */
goto done;
}
/* / Esd Check : Read from lcm */
//读LCM寄存器方式进行esd check和recovery
MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagStart, 0,
primary_display_cmdq_enabled());
if (primary_display_cmdq_enabled()) {
_primary_path_lock(__func__);
MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm,
MMProfileFlagPulse, 0, 1);
/* 0.create esd check cmdq */
cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK,
&(pgc->cmdq_handle_config_esd));
dpmgr_path_build_cmdq(pgc->dpmgr_handle,
pgc->cmdq_handle_config_esd,
CMDQ_ESD_ALLC_SLOT, 0);
MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm,
MMProfileFlagPulse, 0, 2);
DISPCHECK("[ESD]ESD config thread=%p\n", pgc->cmdq_handle_config_esd);
_primary_path_unlock(__func__);
/* 1.use cmdq to read from lcm */
//发CMDQ_ESD_CHECK_READ的命令读取lcm的寄存器数据,_esd_check_config_handle_vdo函数在下面会讲到
if (primary_display_is_video_mode())
ret = _esd_check_config_handle_vdo();
else
ret = _esd_check_config_handle_cmd();
MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm,
MMProfileFlagPulse,
primary_display_is_video_mode(), 3);
if (ret == 1) {
/* cmdq fail */
if (_need_wait_esd_eof()) {
/* Need set esd check eof synctoken to let trigger loop go. */
cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_ESD_EOF);
}
/* do dsi reset */
dpmgr_path_build_cmdq(pgc->dpmgr_handle,
pgc->cmdq_handle_config_esd,
CMDQ_DSI_RESET, 0);
goto destroy_cmdq;
}
34. lcm ESD
最新推荐文章于 2024-09-09 18:45:02 发布
本文介绍了MTK平台LCM静电防护(ESD)的客制化方法,包括通过读取寄存器和外部TE方式实现ESD检查。详细分析了代码流程,涉及LCM驱动的`lcm_get_params`函数,以及`primary_display_esd_check_worker_kthread`线程的工作原理,解释了如何进行ESD检查、恢复和重试机制。
摘要由CSDN通过智能技术生成