From 54448c8d8c56761dfadd052cd2bb53ce0024db35 Mon Sep 17 00:00:00 2001 From: Jan Bobek Date: Fri, 28 Jul 2023 20:46:26 +0000 Subject: [PATCH] feat(NvDisplayControllerDxe): use custom EDID blob for display Expose an instance of EFI_EDID_OVERRIDE_PROTOCOL to force the UEFI display driver to use a custom EDID binary blob. This is useful e.g. for use cases where the attached display device is fixed and known in compile-time, but does not support reading EDID in runtime. Additionally, include EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG in the attributes to force the display output to be activated even when the driver fails to detect any attached display device. The included EDID binary blob is taken from: VESA Enhanced EDID Standard, Release A, Rev.2 (EDID 1.4); Appendix A (Sample EDIDs), Example 2. Signed-off-by: Jan Bobek --- .../NvDisplayControllerDxe.c | 80 +++++++++++++++++++ .../NvDisplayControllerDxe.inf | 1 + 2 files changed, 81 insertions(+) diff --git a/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.c b/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.c index e07b021c02..89525b298c 100644 --- a/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.c +++ b/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -1247,6 +1248,76 @@ DisplayStart ( return Status; } +/** + Retrieves an EDID override for a given controller child handle. + + The current implementation simply returns a single fixed EDID with + no respect to what child handle is passed in. + + @param[in] This Instance of the installed EFI_EDID_OVERRIDE_PROTOCOL. + @param[in] ChildHandle Child controller handle to retrieve EDID for. + @param[out] Attributes Additional attributes of the EDID override. + @param[out] EdidSize Size of the overriding EDID. + @param[out] Edid Pointer to the overriding EDID. + + @retval EFI_SUCCESS Overriding EDID returned successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid (NULL). + @retval EFI_OUT_OF_RESOURCES Not enough memory available. +*/ +STATIC +EFI_STATUS +EFIAPI +EfiEdidOverrideProtocolGetEdid ( + IN EFI_EDID_OVERRIDE_PROTOCOL *CONST This, + IN EFI_HANDLE *CONST ChildHandle, + OUT UINT32 *CONST Attributes, + OUT UINTN *CONST EdidSize, + OUT UINT8 **CONST Edid + ) +{ + /* VESA Enhanced EDID Standard, Release A, Rev.2; Appendix A, Example 2. */ + STATIC CONST UINT8 EdidBuffer[] = { + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x43, 0x07, 0xF2, 0x01, 0x00, 0x00, 0x00, + 0xFF, 0x11, 0x01, 0x04, 0xA2, 0x4F, 0x00, 0x78, 0x1E, 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, + 0x0F, 0x50, 0x54, 0x20, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C, + 0x04, 0x05, 0x0F, 0x48, 0x42, 0x00, 0x00, 0x1E, 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C, 0x16, 0x20, + 0x58, 0x2C, 0x25, 0x00, 0x0F, 0x48, 0x42, 0x00, 0x00, 0x9E, 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, + 0x1E, 0x20, 0x6E, 0x28, 0x55, 0x00, 0x0F, 0x48, 0x42, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x41, 0x42, 0x43, 0x20, 0x4C, 0x43, 0x44, 0x34, 0x37, 0x77, 0x0A, 0x20, 0x20, 0x01, 0xCB, + + 0x02, 0x03, 0x18, 0x72, 0x47, 0x90, 0x85, 0x04, 0x03, 0x02, 0x07, 0x06, 0x23, 0x09, 0x07, 0x07, + 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x8E, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, + 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x00, 0x18, 0x8E, 0x0A, 0xD0, 0x8A, + 0x20, 0xE0, 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x18, 0x8E, 0x0A, + 0xA0, 0x14, 0x51, 0xF0, 0x16, 0x00, 0x26, 0x7C, 0x43, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x00, 0x98, + 0x8E, 0x0A, 0xA0, 0x14, 0x51, 0xF0, 0x16, 0x00, 0x26, 0x7C, 0x43, 0x00, 0x04, 0x03, 0x00, 0x00, + 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + }; + + if ((Attributes == NULL) || (EdidSize == NULL) || (Edid == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Edid = (UINT8 *)AllocateCopyPool (sizeof (EdidBuffer), EdidBuffer); + if (*Edid == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *EdidSize = sizeof (EdidBuffer); + + /* Activate display output even if no attached monitor can be + detected. */ + *Attributes = EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG; + + return EFI_SUCCESS; +} + +STATIC EFI_EDID_OVERRIDE_PROTOCOL mEfiEdidOverrideProtocol = { + .GetEdid = EfiEdidOverrideProtocolGetEdid +}; + /** Callback that will be invoked at various phases of the driver initialization @@ -1278,6 +1349,15 @@ DeviceDiscoveryNotify ( CONST BOOLEAN OnExitBootServices = FALSE; switch (Phase) { + case DeviceDiscoveryDriverStart: + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverHandle, + &gEfiEdidOverrideProtocolGuid, + &mEfiEdidOverrideProtocol, + NULL + ); + return Status; + case DeviceDiscoveryDriverBindingSupported: Platform = TegraGetPlatform (); if (Platform != TEGRA_PLATFORM_SILICON) { diff --git a/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.inf b/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.inf index d1a8e529d2..4996c5ba12 100644 --- a/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.inf +++ b/Silicon/NVIDIA/Drivers/NvDisplayControllerDxe/NvDisplayControllerDxe.inf @@ -54,6 +54,7 @@ [Protocols] gEdkiiNonDiscoverableDeviceProtocolGuid gEfiDevicePathProtocolGuid + gEfiEdidOverrideProtocolGuid gEfiGraphicsOutputProtocolGuid gNVIDIAClockNodeProtocolGuid gNVIDIANonDiscoverableDeviceProtocolGuid