818 lines
26 KiB
C
818 lines
26 KiB
C
/** @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 <HybridGraphicsPei.h>
|
|
#include <Pins/GpioPinsVer4S.h>
|
|
//[-start-210722-QINGLIN0002-add]//
|
|
//[-start-210802-QINGLIN0007-modify]//
|
|
//[-start-210908-QINGLIN0055-modify]//
|
|
#if defined(S570_SUPPORT)
|
|
//[-end-210908-QINGLIN0055-modify]//
|
|
#include <Pins/GpioPinsVer2Lp.h>
|
|
#include <Library/OemSvcLfcPeiGetBoardID.h>
|
|
#endif
|
|
//[-end-210802-QINGLIN0007-modify]//
|
|
//[-end-210722-QINGLIN0002-add]//
|
|
//[-start-210831-GEORGE0001-add]//
|
|
#if defined(S77014_SUPPORT) || defined(S77014IAH_SUPPORT)
|
|
#include <Pins/GpioPinsVer2Lp.h>
|
|
#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);
|
|
}
|