QcomModulePkg: Disable display when DT doesn't exist

Disable display when /reserved-memory/splash_region DT node doesn't exist

Change-Id: Id9bad6623195d17f1076f08b021ad202cc516a7a
diff --git a/QcomModulePkg/Include/Protocol/EFIDisplayPwr.h b/QcomModulePkg/Include/Protocol/EFIDisplayPwr.h
new file mode 100644
index 0000000..84eae92
--- /dev/null
+++ b/QcomModulePkg/Include/Protocol/EFIDisplayPwr.h
@@ -0,0 +1,144 @@
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __EFIDISPLAYPWR_H__
+#define __EFIDISPLAYPWR_H__
+
+/*===========================================================================
+  INCLUDE FILES
+===========================================================================*/
+
+/*===========================================================================
+  MACRO DECLARATIONS
+===========================================================================*/
+/** @ingroup efi_displayPwr_constants
+  Protocol version.
+*/
+#define EFI_DISPLAY_POWER_PROTOCOL_REVISION    0x0000000000010000
+
+/** @} */ /* end_addtogroup efi_displayPwr_constants */
+
+/*  Protocol GUID definition */
+/** @ingroup efi_displayPwr_protocol */
+#define EFI_DISPLAY_POWER_PROTOCOL_GUID  \
+    {0xf352021d, 0x9593, 0x4432, {0xbf, 0x4, 0x67, 0xb9, 0xf3, 0xb7, 0x60, 0x8}}
+
+/** @cond */
+/*===========================================================================
+  EXTERNAL VARIABLES
+===========================================================================*/
+/**
+  External reference to the Display Power Protocol GUID.
+*/
+extern EFI_GUID gEfiDisplayPowerStateProtocolGuid;
+
+/*===========================================================================
+  TYPE DEFINITIONS
+===========================================================================*/
+/**
+  Protocol declaration.
+*/
+typedef struct _EFI_DISPLAY_POWER_PROTOCOL  EFI_DISPLAY_POWER_PROTOCOL;
+/** @endcond */
+
+/** @ingroup efi_displayPwr_data_types
+  Display state.
+*/
+typedef enum /** @cond */_EFI_DISPLAY_POWER_STATE/** @endcond */ {
+  EfiDisplayPowerStateUnknown = 0,
+  /**< Indicates the power state has not yet been initialized. */
+  EfiDisplayPowerStateOff,
+  /**< Power off both the backlight and display. */
+  EfiDisplayPowerStateOn,
+  /**< Power on both the backlight and display. */
+} EFI_DISPLAY_POWER_STATE;
+/** @} */ /* end_addtogroup efi_displayPwr_data_types */
+
+/*===========================================================================
+  FUNCTION DEFINITIONS
+===========================================================================*/
+/* EFI_DISPLAY_POWER_SETDISPLAYPOWERSTATE */
+/** @ingroup efi_displayPwr_set_display_power_state
+  @par Summary
+  Modifies the power state of the display and backlight.
+
+  @param[in]  This        Pointer to the EFI_DISPLAY_POWER_PROTOCOL instance.
+  @param[in]  PowerState  Display state; see #EFI_DISPLAY_POWER_STATE for
+                          details.
+
+  @return
+  EFI_SUCCESS           -- Function returned successfully.
+  EFI_INVALID_PARAMETER -- Parameter passed is incorrect.
+  EFI_DEVICE_ERROR      -- Physical device reported an error.
+*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DISPLAY_POWER_SETDISPLAYPOWERSTATE)(
+  IN EFI_DISPLAY_POWER_PROTOCOL             *This,
+  IN EFI_DISPLAY_POWER_STATE                PowerState
+  );
+
+/* EFI_DISPLAY_POWER_GETDISPLAYPOWERSTATE */
+/** @ingroup efi_displayPwr_get_display_power_state
+  @par Summary
+  Retrieves the current power state of the display and backlight.
+
+  @param[in]  This        Pointer to the EFI_DISPLAY_POWER_PROTOCOL instance.
+  @param[out] PowerState  Display state; see #EFI_DISPLAY_POWER_STATE for
+                          details.
+
+  @return
+  EFI_SUCCESS           -- Function returned successfully.
+  EFI_INVALID_PARAMETER -- Parameter passed is incorrect.
+  EFI_DEVICE_ERROR      -- Physical device reported an error.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_DISPLAY_POWER_GETDISPLAYPOWERSTATE)(
+  IN EFI_DISPLAY_POWER_PROTOCOL             *This,
+  OUT EFI_DISPLAY_POWER_STATE               *PowerState
+  );
+
+/*===========================================================================
+  PROTOCOL INTERFACE
+===========================================================================*/
+/** @ingroup efi_displayPwr_protocol
+  @par Summary
+  This protocol allows modification and query of the display power state.
+
+  @par Parameters
+  @inputprotoparams{display_power_proto_params.tex}
+*/
+
+typedef struct _EFI_DISPLAY_POWER_PROTOCOL {
+  UINT32                                        Revision;
+  EFI_DISPLAY_POWER_SETDISPLAYPOWERSTATE        SetDisplayPowerState;
+  EFI_DISPLAY_POWER_GETDISPLAYPOWERSTATE        GetDisplayPowerState;
+} EFI_DISPLAY_POWER_PROTOCOL;
+
+#endif  /* __EFIDISPLAYPWR_H__ */
diff --git a/QcomModulePkg/Library/BootLib/BootLib.inf b/QcomModulePkg/Library/BootLib/BootLib.inf
old mode 100755
new mode 100644
index 486c2fd..9a635b8
--- a/QcomModulePkg/Library/BootLib/BootLib.inf
+++ b/QcomModulePkg/Library/BootLib/BootLib.inf
@@ -151,6 +151,7 @@
 	gEfiNandPartiGuidProtocolGuid
 	gEfiDDRGetInfoProtocolGuid
 	gEfiKernelProtocolGuid
+	gEfiDisplayPowerStateProtocolGuid
 
 [FixedPcd]
 	gArmTokenSpaceGuid.PcdSystemMemoryBase
diff --git a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
index 11b63fc..cdbd73f 100644
--- a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
+++ b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
@@ -39,6 +39,7 @@
 #include <Protocol/EFIChipInfoTypes.h>
 #include <Protocol/EFIDDRGetConfig.h>
 #include <Protocol/EFIRng.h>
+#include <Protocol/EFIDisplayPwr.h>
 #include <Library/PartialGoods.h>
 #include <Library/FdtRw.h>
 
@@ -144,6 +145,31 @@
   return Status;
 }
 
+STATIC VOID
+DisableDisplay (VOID)
+{
+  EFI_STATUS                     Status           = EFI_SUCCESS;
+  EFI_DISPLAY_POWER_PROTOCOL    *pDispPwrProtocol = NULL;
+
+  Status = gBS->LocateProtocol (&gEfiDisplayPowerStateProtocolGuid,
+                                NULL,
+                                (VOID **)&pDispPwrProtocol);
+
+  if ((EFI_SUCCESS != Status) ||
+      (NULL        == pDispPwrProtocol)) {
+    DEBUG ((EFI_D_ERROR,
+           "ERROR: Unable to get display power protocol,Status=%d\n", Status));
+  }
+  else {
+    Status = pDispPwrProtocol->SetDisplayPowerState (pDispPwrProtocol,
+                                                     EfiDisplayPowerStateOff);
+    if (EFI_SUCCESS != Status) {
+      DEBUG ((EFI_D_ERROR,
+             "ERROR: Fail to turn display off,Status=%d\n", Status));
+    }
+  }
+}
+
 STATIC EFI_STATUS
 UpdateSplashMemInfo (VOID *fdt)
 {
@@ -169,9 +195,19 @@
   /* Get offset of the splash memory reservation node */
   ret = FdtPathOffset (fdt, "/reserved-memory/splash_region");
   if (ret < 0) {
-    DEBUG ((EFI_D_ERROR, "ERROR: Could not get splash memory region node\n"));
+    DEBUG ((EFI_D_WARN, "Splash region not found in device tree, " \
+                        "powering down the display and controller\n"));
+
+    /*
+     * This function call leads to the following:
+     * 1) Turn off display power
+     * 2) Disable display clocks
+     * 3) Reset display TE/RST pin
+     */
+    DisableDisplay ();
     return EFI_NOT_FOUND;
   }
+
   offset = ret;
   DEBUG ((EFI_D_VERBOSE, "FB mem node name: %a\n",
           fdt_get_name (fdt, offset, NULL)));
diff --git a/QcomModulePkg/QcomModulePkg.dec b/QcomModulePkg/QcomModulePkg.dec
index 51d6490..b216645 100644
--- a/QcomModulePkg/QcomModulePkg.dec
+++ b/QcomModulePkg/QcomModulePkg.dec
@@ -142,6 +142,8 @@
   gEfiDDRGetInfoProtocolGuid =         { 0x1a7c0eb8, 0x5646, 0x45f7, { 0xab, 0x20, 0xea, 0xe5, 0xda, 0x46, 0x40, 0xa2 } }
   # Display Utils Protocol
   gQcomDisplayUtilsProtocolGuid =      { 0xc0dd69ac, 0x76ba, 0x11e6, { 0xab, 0x24, 0x1f, 0xc7, 0xf5, 0x57, 0x5f, 0x19 } }
+  # Display Power Protocol
+  gEfiDisplayPowerStateProtocolGuid =  { 0xf352021d, 0x9593, 0x4432, { 0xbf, 0x04, 0x67, 0xb9, 0xf3, 0xb7, 0x60, 0x08 } }
   # Multithreading Kernel protocol for UEFI
   gEfiKernelProtocolGuid =             { 0xB5062BE7, 0x170B, 0x4A32, { 0xBE, 0x21, 0x68, 0x92, 0x62, 0xFF, 0x43, 0x99 } }