zoukankan      html  css  js  c++  java
  • 高通Android UEFI中的LCD分析(2):关键的函数

    # 高通Android UEFI中的LCD分析(2):关键的函数

    背景

    在启动流程分析中,看到了几个经常出现的函数,这里实际分析一下有关的实现。以搞清楚高通做了什么,以及我们能做什么。

    重要函数

    MDPPlatformConfigure

    基本上,只要是涉及显示配置的有关工作都是由这个函数完成的。这个函数会在显示的流程中多次调用。

    路径:BOOT.XF.4.1oot_imagesQcomPkgSocPkgKamortaPkgLibraryMDPPlatformLibMDPPlatformLib.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
    ", 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!
    "));
    }
    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)
    ", 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.1oot_imagesQcomPkgIncludeLibraryMDPSystem.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
    ", 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
    "));
            }
            
            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
    "));
          }
    
          // 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
    ", *puPanelID));
            break;
          }
          else
          {
            DEBUG((EFI_D_WARN, "Dynamic-Detected panel Failed
    "));
            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)
    ", 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)
    ", 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
    "));
                            }
                        }
    
                        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
    "));
                        }
                    }
                    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)
    ", 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
    ", 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() 的区别

    https://blog.csdn.net/robinsongsog/article/details/96431166

    一句话总结: 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还是不能访问的。

    如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
    若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
    博客地址:https://www.cnblogs.com/schips/
  • 相关阅读:
    haproxy的使用
    zookeeper 的多线程和单线程库使用对比
    zookeeper 简介
    将博客搬至CSDN
    Sublime Text 添加eclipse快捷键
    Atom编辑器添加eclipse快捷键
    Linux安装mysql教程
    设计模式
    设计模式
    设计模式
  • 原文地址:https://www.cnblogs.com/schips/p/qualcomm_uefi_display_important_functions.html
Copyright © 2011-2022 走看看