高通Android UEFI中的LCD分析(2):关键的函数
背景
在启动流程分析中,看到了几个经常出现的函数,这里实际分析一下有关的实现。以搞清楚高通做了什么,以及我们能做什么。
重要函数
MDPPlatformConfigure
基本上,只要是涉及显示配置的有关工作都是由这个函数完成的。这个函数会在显示的流程中多次调用。
路径:BOOT.XF.4.1\boot_images\QcomPkg\SocPkg\KamortaPkg\Library\MDPPlatformLib\MDPPlatformLib.c
/**********************************************************************************************
*
* FUNCTION: MDPPlatformConfigure()
*
* DESCRIPTION:
* The function is used to configure display, control power and brightness etc.
*
***********************************************************************************************/
MDP_Status MDPPlatformConfigure(MDP_Display_IDType eDisplayId, MDPPlatformConfigType eConfig, MDPPlatformParams *pPlatformParams)
{
MDP_Status eStatus = MDP_STATUS_OK;
MDPPlatformConfigType ePlatformConfig;
/* Static information, initial once during the first call */
static bool32 bInitFlag = FALSE;
static bool32 bDetectPanel = FALSE;
static bool32 bPanelConfigDone = FALSE;
static MDPPlatformInfo sPlatformInfo;
static Panel_PowerCtrlParams sPanelPowerCtrl;
static MDPPlatformPanelInfo sPlatformPanel;
if (FALSE == bInitFlag) // 如果没有初始化,就初始化一次,将所有的参数全部设为 0(FALSE)
{
MDP_OSAL_MEMZERO(&sPlatformInfo, sizeof(MDPPlatformInfo));
MDP_OSAL_MEMZERO(&sPanelPowerCtrl, sizeof(Panel_PowerCtrlParams));
MDP_OSAL_MEMZERO(&sPlatformPanel, sizeof(MDPPlatformPanelInfo));
bInitFlag = TRUE;
}
// 针对一些配置进行特殊处理,Get remapped platform configuration enum
/*
如果是 MDPPLATFORM_CONFIG_POWERUP 、MDPPLATFORM_CONFIG_POWERDOWN、 MDPPLATFORM_CONFIG_POWERDOWN
MDPPLATFORM_CONFIG_SETBACKLIGHT、MDPPLATFORM_CONFIG_RESETPANEL
那么: 在待会的 switch 中, 认为是 MDPPLATFORM_CONFIG_BYPASS而不执行(看下面的switch)
*/
ePlatformConfig = PlatformConfigRemap(&sPlatformInfo, eConfig);
// 读取平台ID(如果之前没有读过,就不解释这块的内容了,典型的static 变量的用法) Read the platform ID once
if (FALSE == sPlatformInfo.bPlatformDetected)
{
if (MDP_STATUS_OK == ReadPlatformIDAndChipID(&sPlatformInfo.sEFIPlatformType, &sPlatformInfo.sEFIChipSetId, &sPlatformInfo.sEFIChipSetFamily))
{
// 修改 uPanelOverride 为 实际的ID ,可以实现 固定 Panel
UINT32 uPanelOverride = 0;
sPlatformInfo.bPlatformDetected = TRUE;
// Read the display panel ID override, it will be checked later during detection
if ((MDP_STATUS_OK == MDP_Display_GetVariable_Integer (PANEL_OVERRIDE_STRINGNAME, &uPanelOverride)) &&
(uPanelOverride > 0))
{
sPlatformInfo.uPanelIdOverride = (uint32) uPanelOverride;
}
}
}
// 由于这个函数支持了很多种配置类型,因此统一在这里进行处理。
switch (ePlatformConfig)
{
case MDPPLATFORM_CONFIG_SW_RENDERER: ... break;
case MDPPLATFORM_CONFIG_GETPANELCONFIG: ... break;
case MDPPLATFORM_CONFIG_POWERUP: ... break;
case MDPPLATFORM_CONFIG_GETPANELDTINFO: ... break;
case MDPPLATFORM_CONFIG_GETPANELLIST: ... break;
case MDPPLATFORM_CONFIG_GETPANELSUPPORTFLAGS: ... break;
case MDPPLATFORM_CONFIG_POWERDOWN: ... break;
case MDPPLATFORM_CONFIG_SETBACKLIGHT: ... break;
case MDPPLATFORM_CONFIG_GETPANELID: ... break;
case MDPPLATFORM_CONFIG_GETPLATFORMINFO:... break;
case MDPPLATFORM_CONFIG_RESETPANEL: ... break;
case MDPPLATFORM_CONFIG_SETGPIOSTATE: ... break;
case MDPPLATFORM_CONFIG_GETPANELXMLINFO:... break;
case MDPPLATFORM_CONFIG_BYPASS: ... break;
{
eStatus = MDP_STATUS_OK;// SW Render Bypass mode
}
break;
default:
eStatus = MDP_STATUS_BAD_PARAM;
break;
}
return eStatus;
}
我们重点看看switch中的处理内容。
MDPPLATFORM_CONFIG_SW_RENDERER
软件渲染
/* Setup display panel configurations according to CDT */
if (FALSE == bPanelConfigDone) // 如果之前没有执行过,则执行
{
// 这个函数很重要
SetupPlatformPanelConfig(eDisplayId, &sPlatformPanel, &sPlatformInfo, &bDetectPanel);
bPanelConfigDone = TRUE;
// 这个函数也很重要
if (MDP_STATUS_OK != FindPanelIndex(&sPlatformPanel))
{
DEBUG((EFI_D_ERROR, "DisplayDxe: FindPanelIndex: No Panel Id=%d found\n", sPlatformPanel.eSelectedPanel));
}
}
if (TRUE == sPlatformInfo.bSWRender)
{
// SW Render mode is enabled already, just return the status
// 如果已经进行过软件渲染了,就写回参数中。不需要做什么
pPlatformParams->sPlatformInfo.bSWRender = TRUE;
}
else if ((EFI_PLATFORMINFO_TYPE_UNKNOWN == sPlatformInfo.sEFIPlatformType.platform) ||
(EFI_PLATFORMINFO_TYPE_VIRTIO == sPlatformInfo.sEFIPlatformType.platform) ||
(TRUE == pPlatformParams->sPlatformInfo.bSWRenderOverrride) ||
(TRUE == PcdGetBool(PcdDisplayForceSwRenderer)))
{
// 为模拟设备和未知平台进行软件渲染。Force SW render mode for emulation and unknown platforms
pPlatformParams->sPlatformInfo.bSWRender = TRUE;
// 保存 被 调用者 的 重写请求 Store that an override has been requested by the caller
sPlatformInfo.bSWRenderOverrride = pPlatformParams->sPlatformInfo.bSWRenderOverrride;
// 设置软件渲染 为 开启状态 Cache that SW Rendering is enabled
sPlatformInfo.bSWRender = TRUE;
DEBUG((EFI_D_ERROR, "DisplayDxe: SW renderer mode enabled!\n"));
}
else
{
// Force SW render mode off
sPlatformInfo.bSWRender = FALSE;
// Report SW render mode is disabled
pPlatformParams->sPlatformInfo.bSWRender = FALSE;
}
SetupPlatformPanelConfig
/*
* List of supported panels. The ones with XML data have UEFI support and the rest are only supported by kernel.
* These are applicable for fastboot overrides of the panel configuration.
*/
const PanelDTInfoType fastBootPanelList[] =
{
/*Supported Panels*/
PANEL_CREATE_ENTRY("panel_ili9891p_720p_vid",
MDPPLATFORM_PANEL_ILI9881P_720P_VIDEO,
"qcom,mdss_dsi_ili9881p_720p_vid:",
DISP_INTF_DSI, DISP_TOPOLOGY_CONFIG_NONE,
DISP_TIMING_CONFIG_NONE,PLL_OVERRIDE_NONE,
DISP_MODE_SINGLE_DSI,
DISP_MODE_SINGLE_DSI,
DISP_MODE_SINGLE_DSI),
/*End of Table, DO NOT ADD PANEL BELOW THIS*/
PANEL_CREATE_ENTRY("",
MDPPLATFORM_PANEL_NONE,
"",
DISP_INTF_NONE,
DISP_TOPOLOGY_CONFIG_NONE,
DISP_TIMING_CONFIG_NONE,
PLL_OVERRIDE_NONE,
DISP_MODE_NONE,
DISP_MODE_DUAL_DSI | DISP_MODE_SKIP_BOOTLOADER,
DISP_MODE_DUAL_DSI | DISP_MODE_SKIP_BOOTLOADER),
};
/**********************************************************************************************
*
* FUNCTION: SetupPlatformPanelConfig()
*
* DESCRIPTION:
* The function can get the display panel that is being used.
*
***********************************************************************************************/
static void SetupPlatformPanelConfig(MDP_Display_IDType eDisplayId,
MDPPlatformPanelInfo *pPlatformPanel,
MDPPlatformInfo *pPlatformInfo,
bool32 *pDetectPanel)
{
PlatformDSIDetectParams *pPanelList = NULL;
uint32 uPanelCnt = 0;
uint32 uPanelID = 0;
// 判断 用于 强制填充的Panelid 是否储存于 已知的 Panel列表中(fastBootPanelList)。有则 使用这个参数
/*
注:如果需要添加 新Panel, 则添加 到 fastBootPanelList 中即可
*/
if (TRUE == Panel_CheckOverride(eDisplayId, pPlatformPanel, pPlatformInfo))
{
//Use configuration set by panel override
}
else if (TRUE == pPlatformInfo->bSWRender)
{
//use dummy panel for sw rendering
pPlatformPanel->eSelectedPanel = MDPPLATFORM_PANEL_NONE;
}
else
{
// Parse sub-revision specific info to determine the platform type
uint32 uHardwareVersionSubtype = pPlatformInfo->sEFIPlatformType.subtype;
// Report the proper information depending on the display.
switch (pPlatformInfo->sEFIPlatformType.platform)
{
case EFI_PLATFORMINFO_TYPE_CDP:
case EFI_PLATFORMINFO_TYPE_MTP:
case EFI_PLATFORMINFO_TYPE_IDP:
case EFI_PLATFORMINFO_TYPE_QRD:
case EFI_PLATFORMINFO_TYPE_ATP:
pPanelList = &uefiPanelList[0]; // Panel #0 - TD4330 single dsi video fhd
uPanelCnt = PANEL_LIST_LENGTH(uefiPanelList);
// If the panel ID override is enabled and within range, force that panel configuration.
if ((pPlatformInfo->uPanelIdOverride & PANEL_OVERRIDE_ENABLE_MASK) &&
(PANEL_OVERRIDE_PANELID(pPlatformInfo->uPanelIdOverride) < uPanelCnt))
{
pPanelList = &uefiPanelList[PANEL_OVERRIDE_PANELID(pPlatformInfo->uPanelIdOverride)];
DEBUG((EFI_D_ERROR, "DisplayDxe: Panel override enabled (Index: %d ID:0x%x)\n", PANEL_OVERRIDE_PANELID(pPlatformInfo->uPanelIdOverride), uPanelID));
}
else if (uHardwareVersionSubtype == 0x03) //#panel 2: nt36525 truly video panel
{
pPanelList = &uefiPanelList[2];
uPanelCnt = 1;
}
else
{
// No override and it is not SW render - select default panel for power up and trigger dynamic detection
*pDetectPanel = TRUE;
}
pPlatformPanel->eSelectedPanel = pPanelList->eSelectedPanel;
uPanelID = ((pPanelList->panelIdCommands[1].expectedReadback[0] << 8) |
pPanelList->panelIdCommands[2].expectedReadback[0]);
pPlatformPanel->uPanelId = uPanelID;
pPlatformInfo->uPrimaryPanelId = uPanelID;
break;
case EFI_PLATFORMINFO_TYPE_RUMI:
default:
pPlatformPanel->eSelectedPanel = MDPPLATFORM_PANEL_NONE;
break;
}
}
}
FindPanelIndex
选择Panel时序,
// BOOT.XF.4.1/boot_images/QcomPkgSocPkg/KamortaPkg/Library/MDPPlatformLib/MDPPlatformLibPanelConfig.h
MDPPlatformPanelFunctionTable sMDPPlatformPanelFunction[MDPPLATFORM_PANEL_MAX] =
{
{
MDPPLATFORM_PANEL_NONE, // ePanelSelected
NULL, NULL, NULL, NULL, NULL, NULL, NULL
},
{ /* Kamorta Panel */
/* 注:如果需要添加 新Panel, 则添加 到 sMDPPlatformPanelFunction 中即可 */
MDPPLATFORM_PANEL_ILI9881P_720P_VIDEO, // ePanelSelected
"Panel_ili9881p_720p_vid.xml", // pPanelXmlConfig
Panel_Default_PowerUp, // pPanel_PowerUp
Panel_Default_PowerDown, // pPanel_PowerDown
Panel_Default_Reset, // pPanel_Reset
Panel_Default_Peripheral_Power, // pPanel_Peripheral_Power
Panel_Default_Brightness_Enable, // pPanel_Brightness_Enable
Panel_Default_Brightness_Level // pPanel_Brightness_Level
},
};
/**********************************************************************************************
*
* FUNCTION: FindPanelIndex()
*
* DESCRIPTION:
* The function convert panel id into Index to panel table index
*
***********************************************************************************************/
static MDP_Status FindPanelIndex(MDPPlatformPanelInfo *pPlatformPanel)
{
MDP_Status eStatus = MDP_STATUS_NO_RESOURCES;
MDPPlatformPanelFunctionTable *panelTable = sMDPPlatformPanelFunction;
UINT32 uIndex = 0;
for (uIndex = 0; uIndex < MDPPLATFORM_PANEL_MAX; uIndex++)
{
if (panelTable == NULL)
{
break;
}
else if (panelTable->ePanelSelected == pPlatformPanel->eSelectedPanel)
{
pPlatformPanel->uSelectedPanelIndex = uIndex;
eStatus = MDP_STATUS_OK;
break;
}
panelTable++;
}
return eStatus;
}
MDPPLATFORM_CONFIG_GETPANELCONFIG
获取Panel配置,在这里可以支持双屏: MDP_DISPLAY_PRIMARY / MDP_DISPLAY_EXTERNAL。
// BOOT.XF.4.1\boot_images\QcomPkg\Include\Library\MDPSystem.h
/* PCD values for the PCD entry gQcomTokenSpaceGuid.PcdExtDisplayType
*/
typedef enum
{
PCD_EXTERNAL_DISPLAY_NONE = 0,
PCD_EXTERNAL_DISPLAY_DP = 1,
PCD_EXTERNAL_DISPLAY_HDMI = 2,
PCD_EXTERNAL_DISPLAY_MAX,
PCD_EXTERNAL_DISPLAY_FORCE_32BIT = 0x7FFFFFFF
} ExternalDisplayPCDType;
static PlatformDSIDetectParams uefiPanelList[] = {
/* Panel #0 - ILI9881P 720P dsi video */
{
0x06, // uCmdType
0x05, // total number of retry on failures
{
{{0xDA, 0x00}, // address to read ID1
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // expected readback
},
{{0xDB, 0x00}, // address to read ID2
{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // expected readback
},
{{0xDC, 0x00}, // address to read ID3
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // expected readback
}
},
0, // Lane remap order {0, 1, 2, 3}
NULL, // psPanelCfg (panel configuration)
0, // uPanelCfgSize
MDPPLATFORM_PANEL_ILI9881P_720x1440_VIDEO, // eSelectedPanel
0 // uFlags
},
};
// Retrieve panel configuration (could be dependent on the interface)
switch (eDisplayId)
{
case MDP_DISPLAY_PRIMARY: // 主屏
{
uint32 uPanelID = 0;
PlatformDSIDetectParams *pPanelList = &uefiPanelList[0];
uint32 uPanelCnt = PANEL_LIST_LENGTH(uefiPanelList);
// 如果之前成功识别过屏幕,则使用识别的屏幕,否则尝试用 DynamicDSIPanelDetection 识别屏幕。
if ((TRUE == bDetectPanel) &&
(MDP_STATUS_OK == DynamicDSIPanelDetection(&sPlatformPanel, &uPanelID, pPanelList, uPanelCnt)))
// 重要的函数
{
/* Detected */
sPlatformPanel.uPanelId = uPanelID;
sPlatformInfo.uPrimaryPanelId = uPanelID;
/*
* need redo mapping eSelectedPanle to uSelectedPanleIndex in case of newer
* eSelectedPanel detected
*/
// 之前提到这个函数,这里就不说了,只是用来判断识别到的屏幕是否在支持的清单中
if (MDP_STATUS_OK != FindPanelIndex(&sPlatformPanel))
{
DEBUG((EFI_D_ERROR, "DisplayDxe: FindPanelIndex: No Panel Id=%d found\n", sPlatformPanel.eSelectedPanel));
}
}
// Get the panel xml configurations.
// 解析 Panel对应的 xml 文件 作为 Panel 属性(实际上这块我不知道是怎么实现的)
if(MDP_STATUS_OK != GetPanelXmlConfig(&sPlatformPanel))
{
pPlatformParams->sPlatformPanel.pPanelXMLConfig = (int8 *)dummy_xmldata;
pPlatformParams->sPlatformPanel.uConfigSize = sizeof (dummy_xmldata);
}
else // 如果解析 xml 不成功,那么就 使用 上次的 Panel 属性
{
/* Copy the panel configurations to pPlatformParams->sPlatformPanel */
MDP_OSAL_MEMCPY(&pPlatformParams->sPlatformPanel, &sPlatformPanel, sizeof(MDPPlatformPanelInfo));
}
}
break;
case MDP_DISPLAY_EXTERNAL: // 拓展屏
/*
从 PCD 获取一个 32位的值,这个值现在是 0 : PCD_EXTERNAL_DISPLAY_NONE
BOOT.XF.4.1/boot_images/QcomPkg/QcomPkg.dec:762:
gQcomTokenSpaceGuid.PcdExtDisplayType|0|UINT32|0x00000809
*/
switch (PcdGet32(PcdExtDisplayType))
{
case PCD_EXTERNAL_DISPLAY_DP: // 如果拓展屏 是 DP(没懂)
pPlatformParams->sDPConfig.bInvertPlugPolarity = DP_USBPlugInvertedOrientation();
// For Nazgul, DP Phy lane to pad connection is the reverse of DP alt mode over usb type-c spec defined mapping
pPlatformParams->sDPConfig.bReversePhyDataPath = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DynamicDSIPanelDetection
在这个函数中实现了多屏识别,通过读取Panel的软件ID实现。
/**********************************************************************************************
*
* FUNCTION: DynamicDSIPanelDetection()
*
* DESCRIPTION:
* Detect DSI panels by doing a DSI read specific to each panels.
* This function could be used as sample for OEM to detect DSI panels,
* it is not a complete implementation of all possible combinations of read
* commands that could be needed for this detection.
*
* Return success only if a DSI panel was correctly detected and the information
* is updated in pPlatformParams->sPlatformPanel
*
***********************************************************************************************/
static MDP_Status DynamicDSIPanelDetection(MDPPlatformPanelInfo *pPlatformPanel, uint32 *puPanelID, PlatformDSIDetectParams *pPanelList, uint32 uPanelCnt)
{
MDP_Status Status = MDP_STATUS_NOT_SUPPORTED;
bool32 bDumpPanelId = FALSE;
if (MDP_STATUS_OK == DSIDriver_MinimalInit()) // do minimal DSI init
{
uint8 panelID[PLATFORM_PANEL_ID_MAX_COMMANDS];
uint32 uPanelIndex;
bool32 bMatch = FALSE;
uint32 uPrevClkConfig = 0;
// go through all possible panels
for (uPanelIndex = 0; uPanelIndex < uPanelCnt; uPanelIndex++)
{
uint8 readback[DSI_READ_READBACK_SIZE];
uint32 readSize = sizeof(readback);
int iCommandIndex = 0;
uint32 uClkConfig = (MDPPLATFORM_PANEL_DETECT_FLAG_CLOCK_FORCEHS &
pPanelList[uPanelIndex].uFlags);
// Check if there is any change in the clock config and set it accordingly
if (uPrevClkConfig != uClkConfig)
{
if (MDP_STATUS_OK != DSIDriver_ConfigClockLane(uClkConfig))
{
DEBUG((EFI_D_ERROR, "Display: DSIDriver_ConfigClockLane failed\n"));
}
uPrevClkConfig = uClkConfig;
}
// Reprogram the DSI lane swap based on remap order
if (MDP_STATUS_OK != DSIDriver_RemapLane(pPanelList[uPanelIndex].uLaneRemapOrder))
{
DEBUG((EFI_D_WARN, "Display: DSIDriver_RemapLane failed\n"));
}
// Allow debug option to scan panel registers (used to help generate a uniquie panel ID for detection)
if (TRUE == bDumpPanelId)
{
DsiPanelDumpRegisters();
// Dump just once
bDumpPanelId = FALSE;
}
// clear the panel ID
MDP_OSAL_MEMZERO(panelID, PLATFORM_PANEL_ID_MAX_COMMANDS);
// for each possible panel ID read
for(iCommandIndex = 0; iCommandIndex<PLATFORM_PANEL_ID_MAX_COMMANDS; iCommandIndex++)
{
uint32 uRetryCount = 0;
// if read command is 0, then stop reading panel ID
if ((0 == pPanelList[uPanelIndex].panelIdCommands[iCommandIndex].address[0]) &&
(0 == pPanelList[uPanelIndex].panelIdCommands[iCommandIndex].address[1]) )
{
break;
}
// DSI read
bMatch = FALSE;
uRetryCount = 0;
do
{
// clear the readback buffer
MDP_OSAL_MEMZERO(&readback[0], readSize);
readSize = sizeof(readback);
Status = DSIDriver_Read(pPanelList[uPanelIndex].uCmdType,
pPanelList[uPanelIndex].panelIdCommands[iCommandIndex].address,
sizeof(pPanelList[uPanelIndex].panelIdCommands[iCommandIndex].address),
readback,
&readSize);
uRetryCount++;
} while((uRetryCount < pPanelList[uPanelIndex].uTotalRetry) &&
((MDP_STATUS_OK != Status) ||
(0 == readSize)));
if ((uRetryCount <= pPanelList[uPanelIndex].uTotalRetry) &&
(0 != readSize))
{
// Read was successful, now check the data is what we expect
if (0 == CompareMem(readback, pPanelList[uPanelIndex].panelIdCommands[iCommandIndex].expectedReadback, readSize))
{
panelID[iCommandIndex] = readback[0]; // store the first byte of readback as panel ID
bMatch = TRUE; // mark one panel ID matched
}
}
// if any panel ID is not matched, then go to detect next panel in the list
if(FALSE == bMatch)
{
break;
}
}
// if all panel IDs are matched for a specific panel, store settings and stop
if(TRUE == bMatch)
{
// store matched panel configuration xml data
pPlatformPanel->eSelectedPanel = pPanelList[uPanelIndex].eSelectedPanel;
// return the final combined panel ID
*puPanelID = (panelID[0]<<16) | (panelID[1]<<8) | (panelID[2]);
Status = MDP_STATUS_OK;
DEBUG((EFI_D_WARN, "Detected panel id:%08x\n", *puPanelID));
break;
}
else
{
DEBUG((EFI_D_WARN, "Dynamic-Detected panel Failed\n"));
Status = MDP_STATUS_FAILED;
}
}
// Close the DSI context opened in DSIDriver_MinimalInit()
DSIDriver_Close();
}
return Status;
}
MDPPLATFORM_CONFIG_POWERUP
对支持的平台类型进行上电:
- 针对主屏,使用屏对应的上电时序
- 针对拓展屏,使用默认的拓展屏上电策略。
switch (eDisplayId)
{
case MDP_DISPLAY_PRIMARY:
// Config based on the platform
switch (sPlatformInfo.sEFIPlatformType.platform)
{
case EFI_PLATFORMINFO_TYPE_CDP:
case EFI_PLATFORMINFO_TYPE_MTP:
case EFI_PLATFORMINFO_TYPE_QRD:
case EFI_PLATFORMINFO_TYPE_IDP:
case EFI_PLATFORMINFO_TYPE_ATP:
{
// Primary Power Sequence
if (NULL != sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_PowerUp)
{
if (MDP_STATUS_OK != (eStatus = sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_PowerUp(eDisplayId, &sPanelPowerCtrl)))
{
DEBUG((EFI_D_WARN, "DisplayDxe: Primary Power Up Sequence failed (%d)\n", eStatus));
}
}
if (NULL != sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Peripheral_Power)
{
if (MDP_STATUS_OK != (eStatus = sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Peripheral_Power(eDisplayId, &sPanelPowerCtrl, TRUE)))
{
DEBUG((EFI_D_WARN, "DisplayDxe: Secondary Power Up Sequence failed (%d)\n", eStatus));
}
}
break;
}
default:
break;
}
break;
case MDP_DISPLAY_EXTERNAL:
// Config based on the platform
switch (sPlatformInfo.sEFIPlatformType.platform)
{
case EFI_PLATFORMINFO_TYPE_CDP:
case EFI_PLATFORMINFO_TYPE_MTP:
case EFI_PLATFORMINFO_TYPE_QRD:
case EFI_PLATFORMINFO_TYPE_IDP:
case EFI_PLATFORMINFO_TYPE_ATP:
eStatus = ExternalPanel_Default_PowerUp(eDisplayId, &sPanelPowerCtrl);
break;
default:
break;
}
break;
default:
break;
}
MDPPLATFORM_CONFIG_GETPANELDTINFO
获取支持的所有屏幕
if (NULL == pPlatformParams)
eStatus = MDP_STATUS_BAD_PARAM;
else
pPlatformParams->psPanelDTInfo = (PanelDTInfoType*)&fastBootPanelList;
MDPPLATFORM_CONFIG_GETPANELLIST
如果屏幕存在,则拷贝到输出数组中。
uint32 i = 0;
while (MDPPLATFORM_PANEL_NONE != fastBootPanelList[i].ePanel)
{
//Copy Panel ID
pPlatformParams->sPanelList.ePanel[i] = fastBootPanelList[i].ePanel;
i++;
}
pPlatformParams->sPanelList.uCount = i;
MDPPLATFORM_CONFIG_GETPANELSUPPORTFLAGS
类似于MDPPLATFORM_CONFIG_GETPANELLIST,只是获取的是对应的标志位。
//Lookup panel
int32 i = PANEL_LIST_LENGTH(fastBootPanelList) - 1;
while (0 <= i)
{
if (pPlatformParams->sPanelSupport.ePanel == fastBootPanelList[i].ePanel)
{
if ((DISP_TOPOLOGY_CONFIG_NONE == pPlatformParams->sPanelSupport.uModeIndex) ||
(pPlatformParams->sPanelSupport.uModeIndex > DISPLAY_MODE_MAX))
{
pPlatformParams->sPanelSupport.uFlags = fastBootPanelList[i].uModeFlags[0];
}
else
{
pPlatformParams->sPanelSupport.uFlags = fastBootPanelList[i].uModeFlags[pPlatformParams->sPanelSupport.uModeIndex-1];
}
break;
}
i--;
}
MDPPLATFORM_CONFIG_POWERDOWN
类似MDPPLATFORM_CONFIG_POWERUP。不介绍了。
MDPPLATFORM_CONFIG_SETBACKLIGHT
设置主屏背光,不支持拓展屏背光。
// Handle backlight level
switch (eDisplayId)
{
case MDP_DISPLAY_PRIMARY:
switch (sPlatformInfo.sEFIPlatformType.platform)
{
case EFI_PLATFORMINFO_TYPE_CDP:
case EFI_PLATFORMINFO_TYPE_MTP:
case EFI_PLATFORMINFO_TYPE_QRD:
case EFI_PLATFORMINFO_TYPE_IDP:
case EFI_PLATFORMINFO_TYPE_ATP:
// 如果 之前背光还没配置,就配置
if (FALSE == sPanelPowerCtrl.bBacklightEnabled)
{
if (NULL != sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Brightness_Enable)
{
if (MDP_STATUS_OK != (eStatus = sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Brightness_Enable(eDisplayId, &sPanelPowerCtrl)))
{
DEBUG((EFI_D_WARN, "MDPPlatformConfig: Backlight enabled failed\n"));
}
}
sPanelPowerCtrl.bBacklightEnabled = TRUE;
}
// 执行背光
if (NULL != sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Brightness_Level)
{
if (MDP_STATUS_OK != (eStatus = sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Brightness_Level(eDisplayId, &pPlatformParams->sBacklightConfig)))
{
DEBUG((EFI_D_WARN, "MDPPlatformConfig: Backlight level control failed\n"));
}
}
break;
default:
break;
}
break;
case MDP_DISPLAY_EXTERNAL: // 不支持拓展屏的背光控制
eStatus = MDP_STATUS_NOT_SUPPORTED;
break;
default:
break;
}
MDPPLATFORM_CONFIG_GETPANELID
什么都没做。
MDPPLATFORM_CONFIG_GETPLATFORMINFO
获取当前的MDPPLATFORM
MDP_OSAL_MEMCPY(&pPlatformParams->sPlatformInfo, &sPlatformInfo, sizeof(MDPPlatformInfo));
MDPPLATFORM_CONFIG_RESETPANEL
如果复位脚存在,就按照配置的复位时序将Panel复位。
不支持拓展屏的复位。
if (pPlatformParams->sPlatformPanelReset.uResetGpio == 0)
{
sPanelPowerCtrl.uResetGpio = DEFAULT_DISP_RESET_GPIO;
pPlatformParams->sPlatformPanelReset.uResetGpio = DEFAULT_DISP_RESET_GPIO;
}
else
{
sPanelPowerCtrl.uResetGpio = pPlatformParams->sPlatformPanelReset.uResetGpio;
}
switch (eDisplayId)
{
case MDP_DISPLAY_PRIMARY:
// Config based on the platform
switch (sPlatformInfo.sEFIPlatformType.platform)
{
case EFI_PLATFORMINFO_TYPE_CDP:
case EFI_PLATFORMINFO_TYPE_MTP:
case EFI_PLATFORMINFO_TYPE_QRD:
case EFI_PLATFORMINFO_TYPE_IDP:
case EFI_PLATFORMINFO_TYPE_ATP:
if (NULL != sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Reset)
{
if (MDP_STATUS_OK != (eStatus = sMDPPlatformPanelFunction[sPlatformPanel.uSelectedPanelIndex].pPanel_Reset(&pPlatformParams->sPlatformPanelReset)))
{
DEBUG((EFI_D_WARN, "MDPPlatformConfig: Panel reset failed (%d)\n", eStatus));
}
}
break;
default:
break;
}
break;
case MDP_DISPLAY_EXTERNAL:
eStatus = MDP_STATUS_NOT_SUPPORTED;
break;
default:
break;
}
MDPPLATFORM_CONFIG_SETGPIOSTATE
设置MDP的Gpio为默认的设置状态,这些GPIO必须是TLMM(Top Level ),不支持PMIC、PMI类型的GPIO。
eStatus = SetDefaultGPIOState(&pPlatformParams->sGPIOState);
MDPPLATFORM_CONFIG_GETPANELXMLINFO
获取当前的XML信息
// Return the raw xml information if it is within range.
if (pPlatformParams->sPanelXMLInfo.uIndex >= PANEL_LIST_LENGTH(uefiPanelList))
{
eStatus = MDP_STATUS_FAILED;
}
else
{
MDPPlatformPanelInfo sPlatformPanelInfo;
MDP_OSAL_MEMZERO(&sPlatformPanelInfo, sizeof(MDPPlatformPanelInfo));
sPlatformPanelInfo.eSelectedPanel = uefiPanelList[pPlatformParams->sPanelXMLInfo.uIndex].eSelectedPanel;
if (MDP_STATUS_OK != FindPanelIndex(&sPlatformPanelInfo))
{
DEBUG((EFI_D_ERROR, "DisplayDxe: GETPANELXMLINFO: FindPanelIndex: No Panel Id=%d found\n", sPlatformPanelInfo.eSelectedPanel));
}
if(MDP_STATUS_OK == GetPanelXmlConfig(&sPlatformPanelInfo))
{
pPlatformParams->sPanelXMLInfo.pPanelXMLConfig = (int8*)sPlatformPanelInfo.pPanelXMLConfig;
pPlatformParams->sPanelXMLInfo.uPanelXMLSize = sPlatformPanelInfo.uConfigSize;
}
else
{
pPlatformParams->sPanelXMLInfo.pPanelXMLConfig = (int8 *)dummy_xmldata;
pPlatformParams->sPanelXMLInfo.uPanelXMLSize = sizeof (dummy_xmldata);
}
}
MDPPLATFORM_CONFIG_BYPASS
刚刚已经说了,不做处理;只是单纯返回成功。
附录:OpenProtocol 和LocateProtocol() 的区别
一句话总结: OpenProtocol() 需要传入handle 作为参数, 而LocateProtocol 不需要。
LocateProtocol() 和 OpenProtocol() 都是找到一个自己想要的interface。
对于consumer(driver)来说,可以通过GUID 在handle database 里面找到自己想要的protocol, 对于service protocol 如果在handle database 里面只存在一份instance(实列,即函数实现), consumer 可以使用LocateProtocol() 来达到目的。
如果在handle database 里面,多个handle 上面都有我们想要找的那个protocol , 那么我们可以先用LocateHandleBuffer() 找到所有符合条件的handle(handle
上面有我们想要找的protocol) , 然后通过通过OpenProtocol()在一个特定的handle 上面找到我们想要的protocol.
函数原型如下:
/**
Returns the first protocol instance that matches the given protocol.
@param[in] Protocol Provides the protocol to search for.
@param[in] Registration Optional registration key returned from
RegisterProtocolNotify().
@param[out] Interface On return, a pointer to the first interface that matches Protocol and
Registration.
@retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in
Interface.
@retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
Registration.
@retval EFI_INVALID_PARAMETER Interface is NULL.
Protocol is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL)(
IN EFI_GUID *Protocol,
IN VOID *Registration, OPTIONAL
OUT VOID **Interface
);
可以看到 LocateProtocol 只需要传入一个参数(GUID) 即可。
而对于OpenProtocol ,传入的第一个参数即为Handle
/**
Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the
handle, it opens the protocol on behalf of the calling agent.
@param[in] Handle The handle for the protocol interface that is being opened.
@param[in] Protocol The published unique identifier of the protocol.
@param[out] Interface Supplies the address where a pointer to the corresponding Protocol
Interface is returned.
@param[in] AgentHandle The handle of the agent that is opening the protocol interface
specified by Protocol and Interface.
@param[in] ControllerHandle If the agent that is opening a protocol is a driver that follows the
UEFI Driver Model, then this parameter is the controller handle
that requires the protocol interface. If the agent does not follow
the UEFI Driver Model, then this parameter is optional and may
be NULL.
@param[in] Attributes The open mode of the protocol interface specified by Handle
and Protocol.
@retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the
protocol interface was returned in Interface.
@retval EFI_UNSUPPORTED Handle does not support Protocol.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment.
@retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent
handle is the same as AgentHandle.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL)(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface, OPTIONAL
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
);
典型用法举例:
//
// Retrieve the array of handles that support Protocol
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
Protocol,
NULL,
&NoHandles,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Allocate array of protocol instances
//
Status = gBS->AllocatePool (
EfiBootServicesData,
NoHandles * sizeof (VOID *),
(VOID **)Buffer
);
if (EFI_ERROR (Status)) {
//
// Free the handle buffer
//
gBS->FreePool (HandleBuffer);
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (*Buffer, NoHandles * sizeof (VOID *));
//
// Lookup Protocol on each handle in HandleBuffer to fill in the array of
// protocol instances. Handle case where protocol instance was present when
// LocateHandleBuffer() was called, but is not present when HandleProtocol()
// is called.
//
for (Index = 0, *NoProtocols = 0; Index < NoHandles; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
Protocol,
&((*Buffer)[*NoProtocols])
);
if (!EFI_ERROR (Status)) {
(*NoProtocols)++;
}
}
即分两步:
1. 先找到所有符合条件的Handle
Retrieve the array of handles that support Protocol
2. 然后从每个符合条件的handler 中取出自己想要的protocol (interface)
Lookup Protocol on each handle in HandleBuffer to fill in the array of
protocol instances. Handle case where protocol instance was present when
LocateHandleBuffer() was called, but is not present when HandleProtocol()
is called.
附录:UEFI基础——PCD
PCD的全称是Platform Configuration Database,它是一个存放了UEFI下可访问数据的数据库。
它的特点是可以在UEFI存在的大部分时间内访问,在UEFI实战——在库中使用全局变量中就曾经介绍过通过PCD来传递全局变量。这里说是大部分时间内,那是因为在诸如SEC阶段,以及PEI、DXE阶段的早期,某些PCD相关的模块还没有加载起来之前,这些类型的PCD还是不能访问的。
高通Android UEFI中的LCD分析(2):关键的函数的更多相关文章
- 高通Android display架构分析
目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...
- 高通Android display分析【转】
本文转载自:http://blog.csdn.net/zhangchiytu/article/details/6777039 高通7系列硬件架构分析 如上图,高通7系列 Display的硬件部分主要由 ...
- 高通平台msm8909 LK 实现LCD 兼容
前段时间小米出现红米note2 换屏门,现在我们公司也要上演了:有两个供应商提供不同IC 的LCD panel. 软件区分的办法是读取LCD IC 的ID 寄存器,下面解析高通平台LK中LCD兼容的过 ...
- 高通Android平台硬件调试之Camera篇
之前一段时间有幸在高通android平台上调试2款camera sensor,一款是OV的5M YUV sensor,支持jpeg out,同时也支持AF,调试比较比较简单,因为别的项目已经在使用了, ...
- 高通android开发摘要
一部分是开源的,可以从codeaurora.org上下载,还有一部分是高通产权的,需要从高通的网站上下载. 将高通产权的代码放到:vendor/qcom/proprietary 1. 设置bms一些参 ...
- 高通 android平台LCD驱动分析
目前手机芯片厂家提供的源码里包含整个LCD驱动框架,一般厂家会定义一个xxx_fb.c的源文件,注册一个平台设备和平台驱动,在驱动的probe函数中来调用register_framebuffer(), ...
- 高通Android camera运行流程【转】
本文转载自:http://blog.csdn.net/unicornkylin/article/details/13293295 1.总体架构 Android Camera 框架从整体上看是一个 cl ...
- 高通公司 MSM8K GPT异常原因分析无法开机的问题
问题分析过程如下面: 一. MSM8916台gpt概率问题:采用QPST emmc software download下载软件工具后,无法开机.例如下面的附图: log分析是userdata分区未成功 ...
- 高通android开发缩写
1.TLMM MSM TLMM pinmux controller,Qualcomm MSM integrates a GPIO and Pin mux/config hardware, (TOP L ...
- 【AT91SAM3S】SAM3S-EK Demo工程中,LCD驱动程序的加载(函数指针结构体)
为了调试LCD,在英倍特的板子上烧Atmel的sam3s-ek_demo_1.4_source示例代码.LCD显示正常了,却找不到LCD的驱动究竟在哪. 花了好久,追踪到了这个执行过程. 进入main ...
随机推荐
- Pod入门知识(4)
一.Pod是什么? 官方文档:https://kubernetes.io/docs/concepts/workloads/pods/ Pod 是 Kubernetes 中的最小调度单元,k8s 是通过 ...
- Spirng 当中 Bean的作用域
Spirng 当中 Bean的作用域 @ 目录 Spirng 当中 Bean的作用域 每博一文案 1. Spring6 当中的 Bean的作用域 1.2 singleton 默认 1.3 protot ...
- 五、Doris数据分布
在 Doris 中,数据都以表(Table)的形式进行逻辑上的描述 名词解释 数据分布:数据分布是将数据划分为子集, 按一定规则, 均衡地分布在不同节点上,以期最大限度地利用集群的并发性能 短查询:s ...
- ITIL4之四维模型
ITIL4的一个核心概念.它定义了四个维度(图中的1~4),这四个维度旨在确保组织能够在多方面考虑其服务提供,从而更有效地创造和交付价值. 四维模型的整合流程 确立价值载体:明确信息服务提供商的价值主 ...
- vue路由跳转的三种方式
目录 1.router-link [实现跳转最简单的方法] 2.this.$router.push({ path:'/user'}) 3.this.$router.replace{path:'/' } ...
- 第十届山东省大学生程序设计竞赛题解(A、F、M、C)
部分代码define了long long,请记得开long long A. Calandar 把年份.月份.单个的天数全都乘以对应的系数转化成单个的天数即可,注意最后的结果有可能是负数,要转化成正数. ...
- JDK源码阅读-------自学笔记(十)(java.lang.Integer包装类初探)
自动装箱和拆箱 JDK1.5后,Java引入了自动装箱(autoboxing)/拆箱(unboxing) 自动装箱 基本数据类型在需要时自动转化为对象 自动装箱 对象在需要时自动转化为基本数据类型 注 ...
- uniapp-vue3-oadmin手机后台实例|vite5.x+uniapp多端仿ios管理系统
原创vue3+uniapp+uni-ui跨端仿ios桌面后台OA管理模板Uni-Vue3-WeOS. uniapp-vue3-os一款基于uni-app+vite5.x+pinia等技术开发的仿ios ...
- RHEL7.9安装Podman4.1.1并部署Redis集群
原文链接:RHEL7.9安装Podman4.1.1并部署Redis集群-语雀 环境 操作系统 cat /etc/redhat-release Red Hat Enterprise Linux Serv ...
- C# WinForm控件及其子控件转成图片(支持带滚动条的长截图)
概述(Overview) 参考了网上的分析,感觉都不太理想:1.一个控件内如果包含多个子控件时没有考虑顺序问题:2.超出控件可显示区域时不能长截图,有滚动条会多余截取了滚动条.这个随笔旨在解决这个问题 ...