[DESCRIPTION]
现在LCM功能越来越多,有些功能需要通过写寄存器的方式进行实时控制。这样就需要在lcm driver中额外客制化一个接口进行控制,但是由于对平台机制了解不够,导致客制化后,系统会发生低概率的HWT&SWT重启问题。
[SOLUTION]
平台本身就有一个写寄存器接口可以参考(primary_display_setbacklight)。
这里简单实现一个开关CABC(动态背光节能技术)功能的接口。
primary_display.c
int primary_display_setcbac(unsigned int enbale)
{
int ret = 0;
static unsigned int last_enable;
if (last_enable == enbale)
return 0;
_primary_path_switch_dst_lock();
_primary_path_lock(__func__);
if (pgc->state == DISP_SLEPT) {
DISPERR("Sleep State set cabc invald\n");
}
else {
primary_display_idlemgr_kick(__func__, 0);
if (primary_display_cmdq_enabled()) {
if (primary_display_is_video_mode()) {
disp_lcm_set_cabc(pgc->plcm, NULL, enbale);
} else {
_set_cabc_by_cmdq(enbale);
}
}
last_enable = enbale;
}
_primary_path_unlock(__func__);
_primary_path_switch_dst_unlock();
return 0;
}
int _set_cabc_by_cmdq(unsigned int enbale)
{
int ret = 0;
cmdqRecHandle cmdq_handle_cabc = NULL;
ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_cabc);
DISPDBG("primary cabc, handle=%p\n", cmdq_handle_cabc);
if (ret != 0) {
DISPERR("fail to create primary cmdq handle for cabc\n");
return -1;
}
if (primary_display_is_video_mode()) {
cmdqRecReset(cmdq_handle_cabc);
disp_lcm_set_cabc(pgc->plcm, cmdq_handle_cabc, enbale);
_cmdq_flush_config_handle_mira(cmdq_handle_cabc, 1);
DISPCHECK("[BL]_set_cabc_by_cmdq ret=%d\n", ret);
} else {
cmdqRecReset(cmdq_handle_cabc);
cmdqRecWait(cmdq_handle_cabc, CMDQ_SYNC_TOKEN_CABC_EOF);
_cmdq_handle_clear_dirty(cmdq_handle_cabc);
_cmdq_insert_wait_frame_done_token_mira(cmdq_handle_cabc);
disp_lcm_set_cabc(pgc->plcm, cmdq_handle_cabc, enbale);
cmdqRecSetEventToken(cmdq_handle_cabc, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
cmdqRecSetEventToken(cmdq_handle_cabc, CMDQ_SYNC_TOKEN_CABC_EOF);
_cmdq_flush_config_handle_mira(cmdq_handle_cabc, 1);
DISPCHECK("[BL]_set_cabc_by_cmdq ret=%d\n", ret);
}
cmdqRecDestroy(cmdq_handle_cabc);
cmdq_handle_cabc = NULL;
return ret;
}
disp_lcm.h
int disp_lcm_set_cabc(disp_lcm_handle *plcm, void *handle, unsigned int enable);
disp_lcm.c
int disp_lcm_set_cabc(disp_lcm_handle *plcm, void *handle, unsigned int enable)
{
LCM_DRIVER *lcm_drv = NULL;
DISPFUNC();
if (_is_lcm_inited(plcm)) {
lcm_drv = plcm->drv;
if (lcm_drv->set_cabc_cmdq) {
lcm_drv->set_cabc_cmdq(handle, enable);
} else {
DISPERR("FATAL ERROR, lcm_drv->set_cabc is null\n");
return -1;
}
return 0;
}
else {
DISPERR("lcm_drv is null\n");
return -1;
}
}
lcm_drv.h
typedef struct {
...
void (*set_cabc_cmdq)(void *handle, unsigned int enable);
..
} LCM_DRIVER;
lcm driver:
#define dsi_set_cmdq_V22(cmdq, cmd, count, ppara, force_update) \
lcm_util.dsi_set_cmdq_V22(cmdq, cmd, count, ppara, force_update)
static void lcm_cabc_cmdq(void *handle, unsigned int enable){
unsigned int cmd = 0x53; //CABC enable register
unsigned char count = 1;
unsigned char value = (enable == 0 ? 0 : 1);
dsi_set_cmdq_V22(handle, cmd, count, &value, 1);
}
LCM_DRIVER xxxx_lcm_drv = {
.name = "xxx",
...
.set_cabc_cmdq = lcm_cabc_cmdq
...
};