/** @file
*
* Copyright (c) 2018 - 2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
#include
#include
#include
#include
#include
#include
typedef struct {
UINT32 OscFreq;
SCAN_TIMINGS Horizontal;
SCAN_TIMINGS Vertical;
} DISPLAY_MODE;
STATIC DISPLAY_MODE mDisplayModes[] = {
{
// SVGA : 800 x 600 x 24 bpp.
SVGA_OSC_FREQUENCY,
{SVGA_H_RES_PIXELS, SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH},
{SVGA_V_RES_PIXELS, SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH}
}
};
STATIC CONST UINT32 mMaxMode = ARRAY_SIZE (mDisplayModes);
/** HDLCD platform specific initialization function.
@param[in] Handle Handle to the LCD device instance.
@retval EFI_SUCCESS Plaform library initialized successfully.
@retval EFI_UNSUPPORTED PcdGopPixelFormat must be
PixelRedGreenBlueReserved8BitPerColor OR
PixelBlueGreenRedReserved8BitPerColor
any other format is not supported.
@retval other Other errors.
**/
EFI_STATUS
LcdPlatformInitializeDisplay (
IN EFI_HANDLE Handle
)
{
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
// PixelBitMask and PixelBltOnly pixel formats are not supported.
PixelFormat = FixedPcdGet32 (PcdGopPixelFormat);
if (PixelFormat != PixelRedGreenBlueReserved8BitPerColor &&
PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
ASSERT (PixelFormat == PixelRedGreenBlueReserved8BitPerColor ||
PixelFormat == PixelBlueGreenRedReserved8BitPerColor);
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/** Allocate VRAM memory in DRAM for the framebuffer
The allocated address can be used to set the framebuffer.
@param[out] VramBaseAddress A pointer to the framebuffer address.
@param[out] VramSize A pointer to the size of the framebuffer
in bytes
@retval EFI_SUCCESS Framebuffer memory allocated successfully.
@retval other Other errors.
**/
EFI_STATUS
LcdPlatformGetVram (
OUT EFI_PHYSICAL_ADDRESS *VramBaseAddress,
OUT UINTN *VramSize
)
{
EFI_STATUS Status;
EFI_CPU_ARCH_PROTOCOL *Cpu;
ASSERT (VramBaseAddress != NULL);
ASSERT (VramSize != NULL);
// Set the VRAM size.
*VramSize = (UINTN)FixedPcdGet32 (PcdArmLcdDdrFrameBufferSize);
// Check if base address is already reserved for the framebuffer.
*VramBaseAddress =
(EFI_PHYSICAL_ADDRESS)FixedPcdGet64 (PcdArmLcdDdrFrameBufferBase);
if (*VramBaseAddress == 0) {
// If not already reserved, attempt to allocate the VRAM from the DRAM.
Status = gBS->AllocatePages (
AllocateAnyPages,
EfiReservedMemoryType,
EFI_SIZE_TO_PAGES (*VramSize),
VramBaseAddress);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "HdLcdArmSgi: Failed to allocate memory for"
"frame buffer.\n"));
ASSERT_EFI_ERROR (Status);
return Status;
}
}
// Ensure the Cpu architectural protocol is already installed
Status = gBS->LocateProtocol (
&gEfiCpuArchProtocolGuid,
NULL,
(VOID **)&Cpu);
ASSERT_EFI_ERROR (Status);
// The VRAM is inside the DRAM, which is cacheable.
// Mark the VRAM as write-combining (uncached) and non-executable.
Status = Cpu->SetMemoryAttributes (
Cpu,
*VramBaseAddress,
*VramSize,
EFI_MEMORY_WC | EFI_MEMORY_XP);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
gBS->FreePages (*VramBaseAddress, EFI_SIZE_TO_PAGES (*VramSize));
}
return Status;
}
/** Return total number of modes supported.
@retval UINT32 Mode Number.
**/
UINT32
LcdPlatformGetMaxMode (VOID)
{
return mMaxMode;
}
/** Set the requested display mode.
@param[in] ModeNumber Mode Number.
@retval EFI_SUCCESS Mode set successfully.
@retval EFI_INVALID_PARAMETER Requested mode not found.
**/
EFI_STATUS
LcdPlatformSetMode (
IN UINT32 ModeNumber
)
{
if (ModeNumber >= mMaxMode) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/** Return information for the requested mode number.
@param[in] ModeNumber Mode Number.
@param[out] Info Pointer for returned mode information
(on success).
@retval EFI_SUCCESS Mode information for the requested mode
returned successfully.
@retval EFI_INVALID_PARAMETER Requested mode not found.
**/
EFI_STATUS
LcdPlatformQueryMode (
IN UINT32 ModeNumber,
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
)
{
if (ModeNumber >= mMaxMode) {
return EFI_INVALID_PARAMETER;
}
ASSERT (Info != NULL);
Info->Version = 0;
Info->HorizontalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution;
Info->VerticalResolution = mDisplayModes[ModeNumber].Vertical.Resolution;
Info->PixelsPerScanLine = mDisplayModes[ModeNumber].Horizontal.Resolution;
Info->PixelFormat = FixedPcdGet32 (PcdGopPixelFormat);
return EFI_SUCCESS;
}
/** Return display timing information for the requested mode number.
@param[in] ModeNumber Mode Number.
@param[out] Horizontal Pointer to horizontal timing parameters.
(Resolution, Sync, Back porch, Front porch)
@param[out] Vertical Pointer to vertical timing parameters.
(Resolution, Sync, Back porch, Front porch)
@retval EFI_SUCCESS Display timing information for the requested
mode returned successfully.
@retval EFI_INVALID_PARAMETER Requested mode not found.
**/
EFI_STATUS
LcdPlatformGetTimings (
IN UINT32 ModeNumber,
OUT SCAN_TIMINGS **Horizontal,
OUT SCAN_TIMINGS **Vertical
)
{
if (ModeNumber >= mMaxMode) {
return EFI_INVALID_PARAMETER;
}
ASSERT (Horizontal != NULL);
ASSERT (Vertical != NULL);
*Horizontal = &mDisplayModes[ModeNumber].Horizontal;
*Vertical = &mDisplayModes[ModeNumber].Vertical;
// Pretend that clock probing and get timings are successful for SGI FVP
return EFI_SUCCESS;
}
/** Return bits per pixel information for a mode number.
@param[in] ModeNumber Mode Number.
@param[out] Bpp Pointer to bits per pixel information.
@retval EFI_SUCCESS Bits per pixel information for the requested
mode returned successfully.
@retval EFI_INVALID_PARAMETER Requested mode not found.
**/
EFI_STATUS
LcdPlatformGetBpp (
IN UINT32 ModeNumber,
OUT LCD_BPP *Bpp
)
{
if (ModeNumber >= mMaxMode) {
return EFI_INVALID_PARAMETER;
}
ASSERT (Bpp != NULL);
*Bpp = LcdBitsPerPixel_24;
return EFI_SUCCESS;
}