/** @file This module is for Hybrid Graphics Feature PEI pre-initialize. ;****************************************************************************** ;* Copyright (c) 2015 - 2021, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include #include //[-start-210722-QINGLIN0002-add]// //[-start-210802-QINGLIN0007-modify]// //[-start-210908-QINGLIN0055-modify]// #if defined(S570_SUPPORT) //[-end-210908-QINGLIN0055-modify]// #include #include #endif //[-end-210802-QINGLIN0007-modify]// //[-end-210722-QINGLIN0002-add]// //[-start-210831-GEORGE0001-add]// #if defined(S77014_SUPPORT) || defined(S77014IAH_SUPPORT) #include #endif //[-end-210831-GEORGE0001-add]// // // Function Prototypes // STATIC EFI_STATUS HybridGraphicsPeiInitialize ( IN OUT CHIPSET_CONFIGURATION *SystemConfiguration, IN OUT SA_SETUP *SaSetup ); STATIC EFI_STATUS CreateHgInfoDataHob ( IN OUT HG_INFORMATION_DATA_HOB **HgData, IN CHIPSET_CONFIGURATION SystemConfiguration, IN SA_SETUP SaSetup ); STATIC HG_MODE SetHgModeValue ( IN SA_SETUP SaSetup ); STATIC VOID MxmDgpuPowerEnableSequence ( IN H2O_HYBRID_GRAPHICS_PPI HgPpi, IN OUT HG_INFORMATION_DATA_HOB *HgData ); // // PEI Hybrid Graphics PPI Function Prototypes // BOOLEAN EFIAPI HgGpioRead ( IN UINT32 Gpio, IN BOOLEAN Active ); VOID EFIAPI HgGpioWrite ( IN UINT32 Gpio, IN BOOLEAN Active, IN BOOLEAN Level ); VOID EFIAPI Stall ( IN UINTN Microseconds ); EFI_STATUS EFIAPI HybridGraphicsInitNotify ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ); // // Module globals // STATIC H2O_HYBRID_GRAPHICS_PPI mH2OHybridGraphicsPpi = { HgGpioRead, HgGpioWrite, Stall }; STATIC EFI_PEI_PPI_DESCRIPTOR mPpiListHybridGraphics = { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gH2OHybridGraphicsPpiGuid, &mH2OHybridGraphicsPpi }; STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gHybridGraphicsReadyForPowerSequenceInit, HybridGraphicsInitNotify }; //[-start-210722-QINGLIN0002-add]// #if defined(S570_SUPPORT) EFI_STATUS EFIAPI LfcProjectLibDisableDgpuPwrSignal ( VOID ) { GpioSetOutputValue (GPIO_VER2_LP_GPP_D0, 0); // Set dGPU PST pin to low MicroSecondDelay(2000); GpioSetOutputValue (GPIO_VER2_LP_GPP_B7, 0); // Set dGPU PWREN pin to low return EFI_SUCCESS; } EFI_STATUS EFIAPI LfcProjectLibSetDgpuTimeSequence ( VOID ) { UINT32 Count = 0, VGAPowerGood = 0; for (Count = 0; Count < 100; Count++) { GpioGetInputValue(GPIO_VER2_LP_GPP_H9, &VGAPowerGood); if (VGAPowerGood) { // Set PXS_RST to high GpioSetOutputValue (GPIO_VER2_LP_GPP_D0, 1); break; } MicroSecondDelay(1000); // Delay 1ms } if (Count >= 100) { // Dgpu Time Sequence has some errors, and turn off Power Enable/Reset Signal. LfcProjectLibDisableDgpuPwrSignal (); for (Count = 0; Count < 6; Count++) { IoWrite8(0x80, 0xEE); MicroSecondDelay(2500000); IoWrite8(0x80, 0xEF); MicroSecondDelay(2500000); } } return EFI_SUCCESS; } //[-start-210802-QINGLIN0007-modify]// EFI_STATUS LfcProjectCheckDgpuPower ( SA_SETUP *SaSetup ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 UmaAndDisType; OemSvcLfcGetBoardID (GPU_ID, &UmaAndDisType); if ((SaSetup->PrimaryDisplay == 0)||(UmaAndDisType == GPU_ID_UMA_ONLY)) { LfcProjectLibDisableDgpuPwrSignal(); return EFI_UNSUPPORTED; } // // Read the dGPU Power Good status. // if (FeaturePcdGet (PcdHybridGraphicsSupported) && FeaturePcdGet (PcdNvidiaOptimusSupported)) { LfcProjectLibSetDgpuTimeSequence(); } return Status; } //[-end-210802-QINGLIN0007-modify]// #endif //[-end-210722-QINGLIN0002-add]// //[-start-210830-GEORGE0001-add]// #if defined(S77014_SUPPORT) || defined(S77014IAH_SUPPORT) EFI_STATUS EFIAPI LfcProjectLibDisableDgpuPwrSignal ( VOID ) { GpioSetOutputValue (GPIO_VER2_LP_GPP_H13, 0); // Set dGPU PST pin to low MicroSecondDelay(2000); GpioSetOutputValue (GPIO_VER2_LP_GPP_E11, 0); // Set dGPU PWREN pin to low return EFI_SUCCESS; } EFI_STATUS EFIAPI LfcProjectLibSetDgpuTimeSequence ( VOID ) { UINT32 Count = 0, VGAPowerGood = 0; for (Count = 0; Count < 100; Count++) { GpioGetInputValue(GPIO_VER2_LP_GPP_D18, &VGAPowerGood); if (VGAPowerGood) { // Set PXS_RST to high GpioSetOutputValue (GPIO_VER2_LP_GPP_H13, 1); break; } MicroSecondDelay(1000); // Delay 1ms } if (Count >= 100) { // Dgpu Time Sequence has some errors, and turn off Power Enable/Reset Signal. LfcProjectLibDisableDgpuPwrSignal (); for (Count = 0; Count < 6; Count++) { IoWrite8(0x80, 0xEE); MicroSecondDelay(2500000); IoWrite8(0x80, 0xEF); MicroSecondDelay(2500000); } } return EFI_SUCCESS; } EFI_STATUS LfcProjectCheckDgpuPower ( SA_SETUP *SaSetup ) { EFI_STATUS Status = EFI_SUCCESS; UINT32 BoardID12, BoardID13; UINT8 UmaAndDisType; GpioGetInputValue (GPIO_VER2_LP_GPP_F15, &BoardID12); GpioGetInputValue (GPIO_VER2_LP_GPP_F16, &BoardID13); UmaAndDisType |= (UINT8)(BoardID12 << 1); UmaAndDisType |= (UINT8)(BoardID13 << 0); #if defined(S77014_SUPPORT) if ((SaSetup->PrimaryDisplay == 0) || (UmaAndDisType == 0)) #elif defined(S77014IAH_SUPPORT) if ((SaSetup->PrimaryDisplay == 0) || (UmaAndDisType == 0) || (UmaAndDisType == 1)) #endif { LfcProjectLibDisableDgpuPwrSignal(); return EFI_UNSUPPORTED; } // // Read the dGPU Power Good status. // if (FeaturePcdGet (PcdHybridGraphicsSupported) && FeaturePcdGet (PcdNvidiaOptimusSupported)) { LfcProjectLibSetDgpuTimeSequence(); } return Status; } #endif //[-end-210830-GEORGE0001-add]// /** Hybrid Graphics PEIM entry point. Register HG notify callback function. @param[in] FileHandle Handle of the file being invoked. @param[in] PeiServices It's a general purpose services available to every PEIM. @retval EFI_SUCCESS Register notify successfully. @retval Others Register notify unsuccessfully. **/ EFI_STATUS HybridGraphicsPeiInitEntry ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; // // Register HG initialization callback. // Status = PeiServicesNotifyPpi (&mNotifyList); return EFI_SUCCESS; } /** This callback function will create HG information HOB and do power enable sequence. @param[in] PeiServices Pointer to PEI Services Table. @param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that caused this function to execute. @param[in] Ppi Pointer to the PPI data associated with this function. @retval EFI_SUCCESS HG initialize successfully. @retval Others Some error occurs when initializing HG. **/ EFI_STATUS EFIAPI HybridGraphicsInitNotify ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; HG_INFORMATION_DATA_HOB *HgData; CHIPSET_CONFIGURATION SystemConfiguration; SA_SETUP SaSetup; // // Install Hybrid Graphics PPI for module dependency, // Hybrid Graphics PEI module must be dispatched before SA initialize PEI module, // so must add dependency in SA initialize PEI module. // PeiServicesInstallPpi (&mPpiListHybridGraphics); if (FeaturePcdGet (PcdHybridGraphicsSupported)) { // // Get Setup Variable and SA platform policy PPI. // Status = HybridGraphicsPeiInitialize (&SystemConfiguration, &SaSetup); if (EFI_ERROR (Status)) { return Status; } //[-start-210722-QINGLIN0002-add]// //[-start-210830-GEORGE0001-modify]// //[-start-210908-QINGLIN0055-modify]// #if defined(S570_SUPPORT) || defined(S77014_SUPPORT) || defined(S77014IAH_SUPPORT) //[-end-210908-QINGLIN0055-modify]// //[-end-210830-GEORGE0001-modify]// Status = LfcProjectCheckDgpuPower(&SaSetup); #endif //[-end-210722-QINGLIN0002-add]// // // Create Hybrid Graphics information data HOB // Status = CreateHgInfoDataHob (&HgData, SystemConfiguration, SaSetup); if (EFI_ERROR (Status)) { return Status; } //[-start-210802-QINGLIN0007-modify]// //[-start-210908-QINGLIN0055-modify]// //#ifndef S570_SUPPORT #if !defined(S570_SUPPORT) //[-end-210908-QINGLIN0055-modify]// // // Base on HG mode to power enable the discrete GPU or not. // MxmDgpuPowerEnableSequence (mH2OHybridGraphicsPpi, HgData); #endif //[-end-210802-QINGLIN0007-modify]// return EFI_SUCCESS; } return EFI_UNSUPPORTED; } /** Prepare variable data. @param[in, out] SystemConfiguration It's a pointer to Setup variable. @param[in, out] SaSetup It's a pointer to SaSetup variable. @retval EFI_SUCCESS Get variable data successfully. @retval Others Get variable data unsuccessfully. **/ STATIC EFI_STATUS HybridGraphicsPeiInitialize ( IN OUT CHIPSET_CONFIGURATION *SystemConfiguration, IN OUT SA_SETUP *SaSetup ) { EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; EFI_STATUS Status; UINTN VariableSize; // // Locate PEI Read Only Variable PPI // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&VariableServices ); if (EFI_ERROR (Status)) { return Status; } // // Get Setup Variable // VariableSize = PcdGet32 (PcdSetupConfigSize); Status = VariableServices->GetVariable ( VariableServices, L"Setup", &gSystemConfigurationGuid, NULL, &VariableSize, SystemConfiguration ); if (EFI_ERROR (Status)) { return Status; } // // Get SA Setup Variable // VariableSize = sizeof (SA_SETUP); Status = VariableServices->GetVariable ( VariableServices, SA_SETUP_VARIABLE_NAME, &gSaSetupVariableGuid, NULL, &VariableSize, SaSetup ); if (EFI_ERROR (Status)) { return Status; } return EFI_SUCCESS; } /** Based on PCD data to set HG related information data, then through HOB pass to DXE driver. @param[in, out] HgData The pointer to HG information data HOB. @param[in] SystemConfiguration The pointer to Setup variable. @param[in] SaSetup The pointer to SaSetup variable. @retval EFI_SUCCESS Created HG information data HOB successfully. @retval Others Created HG information data HOB unsuccessfully. **/ STATIC EFI_STATUS CreateHgInfoDataHob ( IN OUT HG_INFORMATION_DATA_HOB **HgData, IN CHIPSET_CONFIGURATION SystemConfiguration, IN SA_SETUP SaSetup ) { EFI_STATUS Status; Status = PeiServicesCreateHob ( EFI_HOB_TYPE_GUID_EXTENSION, sizeof (HG_INFORMATION_DATA_HOB), HgData ); if (EFI_ERROR (Status)) { return Status; } (**HgData).EfiHobGuidType.Name = gH2OHgInformationDataHobGuid; (**HgData).DgpuSelExist = PcdGetBool (PcdHgDgpuSelExist); (**HgData).DgpuPwrOkExist = PcdGetBool (PcdHgDgpuPwrOkExist); (**HgData).DgpuEdidSelExist = PcdGetBool (PcdHgDgpuEdidSelExist); (**HgData).DgpuPwmSelExist = PcdGetBool (PcdHgDgpuPwmSelExist); (**HgData).DgpuPrsntExist = PcdGetBool (PcdHgDgpuPrsntExist); (**HgData).DgpuGpioSupport = PcdGetBool (PcdHgDgpuGpioSupport); (**HgData).DgpuPwrOkGpioNo = PcdGet32 (PcdHgDgpuPwrOkGpioNo); (**HgData).DgpuHoldRstGpioNo = PcdGet32 (PcdHgDgpuHoldRstGpioNo); (**HgData).DgpuSelGpioNo = PcdGet32 (PcdHgDgpuSelGpioNo); (**HgData).DgpuPwrEnableGpioNo = PcdGet32 (PcdHgDgpuPwrEnableGpioNo); (**HgData).DgpuEdidSelGpioNo = PcdGet32 (PcdHgDgpuEdidSelGpioNo); (**HgData).DgpuPwmSelGpioNo = PcdGet32 (PcdHgDgpuPwmSelGpioNo); (**HgData).DgpuPrsntGpioNo = PcdGet32 (PcdHgDgpuPrsntGpioNo); (**HgData).DgpuPwrOkActive = PcdGetBool (PcdHgDgpuPwrOkActive); (**HgData).DgpuHoldRstActive = PcdGetBool (PcdHgDgpuHoldRstActive); (**HgData).DgpuSelActive = PcdGetBool (PcdHgDgpuSelActive); (**HgData).DgpuPwrEnableActive = PcdGetBool (PcdHgDgpuPwrEnableActive); (**HgData).DgpuEdidSelActive = PcdGetBool (PcdHgDgpuEdidSelActive); (**HgData).DgpuPwmSelActive = PcdGetBool (PcdHgDgpuPwmSelActive); (**HgData).DgpuPrsntActive = PcdGetBool (PcdHgDgpuPrsntActive); (**HgData).Dgpu2GpioSupport = PcdGetBool (PcdHgDgpu2GpioSupport); (**HgData).Dgpu2PwrOkGpioNo = PcdGet32 (PcdHgDgpu2PwrOkGpioNo); (**HgData).Dgpu2HoldRstGpioNo = PcdGet32 (PcdHgDgpu2HoldRstGpioNo); (**HgData).Dgpu2PwrEnableGpioNo = PcdGet32 (PcdHgDgpu2PwrEnableGpioNo); (**HgData).Dgpu2PrsntGpioNo = PcdGet32 (PcdHgDgpu2PrsntGpioNo); (**HgData).Dgpu2PwrOkActive = PcdGetBool (PcdHgDgpu2PwrOkActive); (**HgData).Dgpu2HoldRstActive = PcdGetBool (PcdHgDgpu2HoldRstActive); (**HgData).Dgpu2PwrEnableActive = PcdGetBool (PcdHgDgpu2PwrEnableActive); (**HgData).Dgpu2PrsntActive = PcdGetBool (PcdHgDgpu2PrsntActive); (**HgData).Dgpu2PrsntExist = PcdGetBool (PcdHgDgpu2PrsntExist); (**HgData).DelayAfterPwrEn = SaSetup.DelayAfterPwrEn; (**HgData).DelayAfterHoldReset = SaSetup.DelayAfterHoldReset; // // System Configuration variables to set HG mode default value, // 0 = HgModeDisabled, 1 = HgModeMuxed, 2 = HgModeMuxless, 3 = HgModeDgpu. // (**HgData).HgMode = SetHgModeValue (SaSetup); (**HgData).HgSlot = SystemConfiguration.HgSlot; (**HgData).BootType = SystemConfiguration.BootType; (**HgData).PannelScaling = SystemConfiguration.PannelScaling; if (PcdGetBool (PcdUseCrbHgDefaultSettings) && (PcdGet16 (PcdCrbSkuId) == 1)) { if (SystemConfiguration.HgSlot == PEG) { // // Use RC default Settings // PcdSet8S (PcdPcie1GpioSupport, 1); (**HgData).DgpuGpioSupport = PcdGet8 (PcdPcie1GpioSupport); (**HgData).DgpuHoldRstActive = PcdGetBool (PcdPegSlot1RstGpioPolarity); (**HgData).DgpuHoldRstGpioNo = PcdGet32 (PcdPegSlot1RstGpioNo); (**HgData).DgpuPwrEnableActive = PcdGetBool (PcdPegSlot1PwrEnableGpioPolarity); (**HgData).DgpuPwrEnableGpioNo = PcdGet32 (PcdPegSlot1PwrEnableGpioNo); } else if (SystemConfiguration.HgSlot == PCH) { PcdSet8S (PcdPcie1GpioSupport, 1); (**HgData).DgpuGpioSupport = PcdGet8 (PcdPcie1GpioSupport); (**HgData).DgpuHoldRstActive = PcdGetBool (PcdPchPCIeSlot3RstGpioPolarity); (**HgData).DgpuHoldRstGpioNo = PcdGet32 (PcdPchPCIeSlot3RstGpioNo); (**HgData).DgpuPwrEnableActive = PcdGetBool (PcdPchPCIeSlot3PwrEnableGpioPolarity); (**HgData).DgpuPwrEnableGpioNo = PcdGet32 (PcdPchPCIeSlot3PwrEnableGpioNo); } } else if (PcdGetBool (PcdUseCrbHgDefaultSettings) && (PcdGet16 (PcdCrbSkuId) == 2)) { (**HgData).DgpuGpioSupport = PcdGet8 (PcdPcie1GpioSupport); (**HgData).DgpuHoldRstActive = PcdGetBool (PcdPcie1HoldRstActive); (**HgData).DgpuHoldRstGpioNo = PcdGet32 (PcdPcie1HoldRstGpioNo); (**HgData).DgpuPwrEnableActive = PcdGetBool (PcdPcie1PwrEnableActive); (**HgData).DgpuPwrEnableGpioNo = PcdGet32 (PcdPcie1PwrEnableGpioNo); } return EFI_SUCCESS; } /** Based on PrimaryDisplay setting to update HG mode. @param[in] SaSetup SaSetup variable data. @retval HgModeDisabled HG mode should be set to disabled on internal graphics only platform, and should not power enable the discrete GPU. @retval HgModeMuxless HG mode should be set to Muxless on dual graphics platform, dual graphics platform ever used multiplexer to choose VGA output that called Muxed, Muxless indicate the platform doesn't have multiplexer and every output just go through internal GPU. @retval HgModeDgpu HG mode should be set to discrete GPU on discrete graphics only platform, if the discrete GPU used MXM interface, discrete GPU should be powered on. **/ STATIC HG_MODE SetHgModeValue ( IN SA_SETUP SaSetup ) { HG_MODE HgMode; // // Set HG mode default // HgMode = HgModeDisabled; // // Base on System Configuration variable data to change HG mode // if (SaSetup.PrimaryDisplay == DisplayModeHg) { HgMode = HgModeMuxless; } if ((SaSetup.PrimaryDisplay == DisplayModeDgpu) || (SaSetup.PrimaryDisplay == DisplayModeAuto) || (SaSetup.PrimaryDisplay == DisplayModePci) || (SaSetup.InternalGraphics == IgdDisable)) { HgMode = HgModeDgpu; } if (SaSetup.PrimaryDisplay == DisplayModeIgpu) { HgMode = HgModeDisabled; } return HgMode; } /** Power enable MXM (Mobile PCI Express Module) interface discrete GPU in this function, and provide a hook point for OEM to customization. @param[in] HgPpi Hybrid Graphics PPI Function for HG GPIO read/write and stall. @param[in, out] HgData The pointer to HG information data HOB. @retval None. **/ STATIC VOID MxmDgpuPowerEnableSequence ( IN H2O_HYBRID_GRAPHICS_PPI HgPpi, IN OUT HG_INFORMATION_DATA_HOB *HgData ) { BOOLEAN DgpuMode; BOOLEAN Dgpu2Exist; EFI_STATUS Status; DgpuMode = Inactive; Dgpu2Exist = FALSE; // // OEM service hook for OEM customization, // base on project own discrete GPU power enable sequence to enable the GPU, // and OEM can base on HG mode variable to do different sequence, // or base on SKU ID to change HG mode or any HG information data HOB too. // DEBUG_OEM_SVC ((DEBUG_INFO, "Pei OemChipsetServices Call:OemSvcMxmDgpuPowerSequence \n")); Status = OemSvcMxmDgpuPowerSequence (); DEBUG_OEM_SVC ((DEBUG_INFO, "Pei OemChipsetServices OemSvcMxmDgpuPowerSequence Status: %r\n", Status)); if (!EFI_ERROR (Status)) { // // If return EFI_SUCCESS, it means MXM GPU power sequence already done and success, // doesn't need do anythings else in this function, so just return. // return; } // // If return EFI_UNSUPPORTED, it means the OEM service doesn't do anything then returned go through here. // If return EFI_MEDIA_CHANGED, it means the OEM service change the HG information data HOB, // but still need MXM GPU power enable sequence in this function. // if (HgData->DgpuGpioSupport == HgGpioNotSupported) { return; } // // Detect slave MXM GPU status. // if (HgData->Dgpu2GpioSupport) { Dgpu2Exist = TRUE; } // // If this platform used GPIO to control MXM interface discrete GPU power, // through default sequence to power enable the GPU for CRB. // if (HgData->HgMode == HgModeDisabled) { // // If can not detect GPU on MXM slot or HG mode disable (internal only SKU), // make sure the GPU power down, and select internal GPU to control output. // if (HgPpi.GpioRead (HgData->DgpuPwrEnableGpioNo, HgData->DgpuPwrEnableActive) == Active) { // // If GPIO default set discrete GPU power enable, // through the power down sequence to disable the discrete GPU. // Power down sequence: (1) Active DgpuHoldRst // (2) Inactive DgpuPwrEnable // HgPpi.GpioWrite (HgData->DgpuHoldRstGpioNo, HgData->DgpuHoldRstActive, Active); HgPpi.GpioWrite (HgData->DgpuPwrEnableGpioNo, HgData->DgpuPwrEnableActive, Inactive); } else { HgPpi.GpioWrite (HgData->DgpuHoldRstGpioNo, HgData->DgpuHoldRstActive, Inactive); } if (Dgpu2Exist) { if (HgPpi.GpioRead (HgData->Dgpu2PwrEnableGpioNo, HgData->Dgpu2PwrEnableActive) == Active) { HgPpi.GpioWrite (HgData->Dgpu2HoldRstGpioNo, HgData->Dgpu2HoldRstActive, Active); HgPpi.GpioWrite (HgData->Dgpu2PwrEnableGpioNo, HgData->Dgpu2PwrEnableActive, Inactive); } else { HgPpi.GpioWrite (HgData->Dgpu2HoldRstGpioNo, HgData->Dgpu2HoldRstActive, Inactive); } } HgData->HgMode = HgModeDisabled; } else { // // Power enable the discrete GPU when dual VGA mode (HG) or discrete GPU only mode. // Power enable sequence: (1) Active DgpuHoldRst => Delay 100ms // (2) Active DgpuPwrEnable => Delay 300ms // (3) Inactive DgpuHoldRst => Delay 100ms // The delay time after GPIO active or inactive that can tune by project for optimization. // if ((HgPpi.GpioRead (HgData->DgpuPwrEnableGpioNo, HgData->DgpuPwrEnableActive) == Inactive) || (Dgpu2Exist && (HgPpi.GpioRead (HgData->DgpuPwrEnableGpioNo, HgData->DgpuPwrEnableActive) == Inactive))) { HgPpi.GpioWrite (HgData->DgpuHoldRstGpioNo, HgData->DgpuHoldRstActive, Active); if (Dgpu2Exist) { HgPpi.GpioWrite (HgData->Dgpu2HoldRstGpioNo, HgData->Dgpu2HoldRstActive, Active); } HgPpi.Stall (HgData->DelayAfterHoldReset * 1000); HgPpi.GpioWrite (HgData->DgpuPwrEnableGpioNo, HgData->DgpuPwrEnableActive, Active); if (Dgpu2Exist) { HgPpi.GpioWrite (HgData->Dgpu2PwrEnableGpioNo, HgData->Dgpu2PwrEnableActive, Active); } HgPpi.Stall (HgData->DelayAfterPwrEn * 1000); HgPpi.GpioWrite (HgData->DgpuHoldRstGpioNo, HgData->DgpuHoldRstActive, Inactive); if (Dgpu2Exist) { HgPpi.GpioWrite (HgData->Dgpu2HoldRstGpioNo, HgData->Dgpu2HoldRstActive, Inactive); } HgPpi.Stall (HgData->DelayAfterHoldReset * 1000); } else { HgPpi.GpioWrite (HgData->DgpuHoldRstGpioNo, HgData->DgpuHoldRstActive, Inactive); if (Dgpu2Exist) { HgPpi.GpioWrite (HgData->Dgpu2HoldRstGpioNo, HgData->Dgpu2HoldRstActive, Inactive); } HgPpi.Stall (HgData->DelayAfterHoldReset * 1000); } // // PEG bridge device (0/1/0 or 0/1/1 or 0/1/2) offset 0xBA (SLOTSTS - Slot Status) // Bit 6 (Presence Detect State (PDS)) 0: Slot Empty, 1: Card present in slot. // After MXM GPU power enable sequence, this bit should be set to high. // } // // Select the discrete GPU to control output when discrete GPU only platform, // or select the internal GPU to control output when internal GPU only or dual VGA platform. // if (HgData->HgMode == HgModeDgpu) { DgpuMode = Active; } if (HgData->DgpuSelExist) { HgPpi.GpioWrite (HgData->DgpuSelGpioNo, HgData->DgpuSelActive, DgpuMode); } if (HgData->DgpuEdidSelExist) { HgPpi.GpioWrite (HgData->DgpuEdidSelGpioNo, HgData->DgpuEdidSelActive, DgpuMode); } if (HgData->DgpuPwmSelExist) { HgPpi.GpioWrite (HgData->DgpuPwmSelGpioNo, HgData->DgpuPwmSelActive, DgpuMode); } } /** This function can read GPIO data. @param[in] Gpio GPIO pin number. @param[in] Active GPIO pin is high active or low active. **/ BOOLEAN EFIAPI HgGpioRead ( IN UINT32 Gpio, IN BOOLEAN Active ) { EFI_STATUS Status; UINT32 Value; Status = GpioGetOutputValue (Gpio, &Value); ASSERT_EFI_ERROR (Status); if ((Active & BIT0) == Inactive) { Value = ~Value; } return (BOOLEAN)(Value & BIT0); } /** This function can program GPIO. @param[in] Gpio GPIO pin number. @param[in] Active GPIO pin is high active or low active. @param[in] Level Active or Inactive this GPIO pin. **/ VOID EFIAPI HgGpioWrite ( IN UINT32 Gpio, IN BOOLEAN Active, IN BOOLEAN Level ) { EFI_STATUS Status; if ((Active & BIT0) == Inactive) { Level = (~Level) & BIT0; } Status = GpioSetOutputValue (Gpio, (UINT32)Level); ASSERT_EFI_ERROR (Status); } /** Waits for at least the given number of microseconds. @param[in] Microseconds Desired length of time to wait **/ VOID EFIAPI Stall ( IN UINTN Microseconds ) { MicroSecondDelay (Microseconds); }