/** @file ARM Mali DP 500/550/650 display controller driver Copyright (c) 2017-2018, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include "ArmMaliDp.h" // CORE_ID of the MALI DP STATIC UINT32 mDpDeviceId; /** Disable the graphics layer This is done by clearing the EN bit of the LG_CONTROL register. **/ STATIC VOID LayerGraphicsDisable (VOID) { MmioAnd32 (DP_BASE + DP_DE_LG_CONTROL, ~DP_DE_LG_ENABLE); } /** Enable the graphics layer This is done by setting the EN bit of the LG_CONTROL register. **/ STATIC VOID LayerGraphicsEnable (VOID) { MmioOr32 (DP_BASE + DP_DE_LG_CONTROL, DP_DE_LG_ENABLE); } /** Set the frame address of the graphics layer. @param[in] FrameBaseAddress Address of the data buffer to be used as a framebuffer. **/ STATIC VOID LayerGraphicsSetFrame ( IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress ) { // Disable the graphics layer. LayerGraphicsDisable (); // Set up memory address of the data buffer for graphics layer. // write lower bits of the address. MmioWrite32 ( DP_BASE + DP_DE_LG_PTR_LOW, DP_DE_LG_PTR_LOW_MASK & FrameBaseAddress ); // Write higher bits of the address. MmioWrite32 ( DP_BASE + DP_DE_LG_PTR_HIGH, (UINT32)(FrameBaseAddress >> DP_DE_LG_PTR_HIGH_SHIFT) ); // Enable the graphics layer. LayerGraphicsEnable (); } /** Configures various graphics layer characteristics. @param[in] UefiGfxPixelFormat This must be either PixelBlueGreenRedReserved8BitPerColor OR PixelRedGreenBlueReserved8BitPerColor @param[in] HRes Horizontal resolution of the graphics layer. @param[in] VRes Vertical resolution of the graphics layer. **/ STATIC VOID LayerGraphicsConfig ( IN CONST EFI_GRAPHICS_PIXEL_FORMAT UefiGfxPixelFormat, IN CONST UINT32 HRes, IN CONST UINT32 VRes ) { UINT32 PixelFormat; // Disable the graphics layer before configuring any settings. LayerGraphicsDisable (); // Setup graphics layer size. MmioWrite32 (DP_BASE + DP_DE_LG_IN_SIZE, FRAME_IN_SIZE (HRes, VRes)); // Setup graphics layer composition size. MmioWrite32 (DP_BASE + DP_DE_LG_CMP_SIZE, FRAME_CMP_SIZE (HRes, VRes)); // Setup memory stride (total visible pixels on a line * 4). MmioWrite32 (DP_BASE + DP_DE_LG_H_STRIDE, (HRes * sizeof (UINT32))); // Set the format. // In PixelBlueGreenRedReserved8BitPerColor format, byte 0 represents blue, // byte 1 represents green, byte 2 represents red, and byte 3 is reserved // which is equivalent to XRGB format of the DP500/DP550/DP650. Whereas // PixelRedGreenBlueReserved8BitPerColor is equivalent to XBGR of the // DP500/DP550/DP650. if (UefiGfxPixelFormat == PixelBlueGreenRedReserved8BitPerColor) { PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XRGB_8888 : DP_PIXEL_FORMAT_XRGB_8888; } else { PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XBGR_8888 : DP_PIXEL_FORMAT_XBGR_8888; } MmioWrite32 (DP_BASE + DP_DE_LG_FORMAT, PixelFormat); // Enable graphics layer. LayerGraphicsEnable (); } /** Configure timing information of the display. @param[in] Horizontal Pointer to horizontal timing parameters. (Resolution, Sync, Back porch, Front porch) @param[in] Vertical Pointer to vertical timing parameters. (Resolution, Sync, Back porch, Front porch) **/ STATIC VOID SetDisplayEngineTiming ( IN CONST SCAN_TIMINGS * CONST Horizontal, IN CONST SCAN_TIMINGS * CONST Vertical ) { UINTN RegHIntervals; UINTN RegVIntervals; UINTN RegSyncControl; UINTN RegHVActiveSize; if (mDpDeviceId == MALIDP_500) { // MALI DP500 timing registers. RegHIntervals = DP_BASE + DP_DE_DP500_H_INTERVALS; RegVIntervals = DP_BASE + DP_DE_DP500_V_INTERVALS; RegSyncControl = DP_BASE + DP_DE_DP500_SYNC_CONTROL; RegHVActiveSize = DP_BASE + DP_DE_DP500_HV_ACTIVESIZE; } else { // MALI DP550/DP650 timing registers. RegHIntervals = DP_BASE + DP_DE_H_INTERVALS; RegVIntervals = DP_BASE + DP_DE_V_INTERVALS; RegSyncControl = DP_BASE + DP_DE_SYNC_CONTROL; RegHVActiveSize = DP_BASE + DP_DE_HV_ACTIVESIZE; } // Horizontal back porch and front porch. MmioWrite32 ( RegHIntervals, H_INTERVALS (Horizontal->FrontPorch, Horizontal->BackPorch) ); // Vertical back porch and front porch. MmioWrite32 ( RegVIntervals, V_INTERVALS (Vertical->FrontPorch, Vertical->BackPorch) ); // Sync control, Horizontal and Vertical sync. MmioWrite32 ( RegSyncControl, SYNC_WIDTH (Horizontal->Sync, Vertical->Sync) ); // Set up Horizontal and Vertical area size. MmioWrite32 ( RegHVActiveSize, HV_ACTIVE (Horizontal->Resolution, Vertical->Resolution) ); } /** Return CORE_ID of the ARM Mali DP. @retval 0xFFF No Mali DP found. @retval 0x500 Mali DP core id for DP500. @retval 0x550 Mali DP core id for DP550. @retval 0x650 Mali DP core id for DP650. **/ STATIC UINT32 ArmMaliDpGetCoreId ( ) { UINT32 DpCoreId; // First check for DP500 as register offset for DP550/DP650 CORE_ID // is beyond 3K/4K register space of the DP500. DpCoreId = MmioRead32 (DP_BASE + DP_DE_DP500_CORE_ID); DpCoreId >>= DP_DE_DP500_CORE_ID_SHIFT; if (DpCoreId == MALIDP_500) { return DpCoreId; } // Check for DP550 or DP650. DpCoreId = MmioRead32 (DP_BASE + DP_DC_CORE_ID); DpCoreId >>= DP_DC_CORE_ID_SHIFT; if ((DpCoreId == MALIDP_550) || (DpCoreId == MALIDP_650)) { return DpCoreId; } return MALIDP_NOT_PRESENT; } /** Check for presence of MALI. This function returns success if the platform implements DP500/DP550/DP650 ARM Mali display processor. @retval EFI_SUCCESS DP500/DP550/DP650 display processor found on the platform. @retval EFI_NOT_FOUND DP500/DP550/DP650 display processor not found on the platform. **/ EFI_STATUS LcdIdentify (VOID) { DEBUG ((DEBUG_WARN, "Probing ARM Mali DP500/DP550/DP650 at base address 0x%p\n", DP_BASE )); if (mDpDeviceId == 0) { mDpDeviceId = ArmMaliDpGetCoreId (); } if (mDpDeviceId == MALIDP_NOT_PRESENT) { DEBUG ((DEBUG_WARN, "ARM Mali DP not found...\n")); return EFI_NOT_FOUND; } DEBUG ((DEBUG_WARN, "Found ARM Mali DP %x\n", mDpDeviceId)); return EFI_SUCCESS; } /** Initialize platform display. @param[in] FrameBaseAddress Address of the frame buffer. @retval EFI_SUCCESS Display initialization successful. @retval !(EFI_SUCCESS) Display initialization failure. **/ EFI_STATUS LcdInitialize ( IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress ) { DEBUG ((DEBUG_WARN, "Framebuffer base address = %p\n", FrameBaseAddress)); if (mDpDeviceId == 0) { mDpDeviceId = ArmMaliDpGetCoreId (); } if (mDpDeviceId == MALIDP_NOT_PRESENT) { DEBUG ((DEBUG_ERROR, "ARM Mali DP initialization failed," "no ARM Mali DP present\n")); return EFI_NOT_FOUND; } // We are using graphics layer of the Mali DP as a main framebuffer. LayerGraphicsSetFrame (FrameBaseAddress); return EFI_SUCCESS; } /** Set ARM Mali DP in cofiguration mode. The ARM Mali DP must be in the configuration mode for configuration of the H_INTERVALS, V_INTERVALS, SYNC_CONTROL and HV_ACTIVESIZE. **/ STATIC VOID SetConfigurationMode (VOID) { // Request configuration Mode. if (mDpDeviceId == MALIDP_500) { MmioOr32 (DP_BASE + DP_DE_DP500_CONTROL, DP_DE_DP500_CONTROL_CONFIG_REQ); } else { MmioOr32 (DP_BASE + DP_DC_CONTROL, DP_DC_CONTROL_CM_ACTIVE); } } /** Set ARM Mali DP in normal mode. Normal mode is the main operating mode of the display processor in which display layer data is fetched from framebuffer and displayed. **/ STATIC VOID SetNormalMode (VOID) { // Disable configuration Mode. if (mDpDeviceId == MALIDP_500) { MmioAnd32 (DP_BASE + DP_DE_DP500_CONTROL, ~DP_DE_DP500_CONTROL_CONFIG_REQ); } else { MmioAnd32 (DP_BASE + DP_DC_CONTROL, ~DP_DC_CONTROL_CM_ACTIVE); } } /** Set the global configuration valid flag. Any new configuration parameters written to the display engine are not activated until the global configuration valid flag is set in the CONFIG_VALID register. **/ STATIC VOID SetConfigValid (VOID) { if (mDpDeviceId == MALIDP_500) { MmioOr32 (DP_BASE + DP_DP500_CONFIG_VALID, DP_DC_CONFIG_VALID); } else { MmioOr32 (DP_BASE + DP_DC_CONFIG_VALID, DP_DC_CONFIG_VALID); } } /** Set requested mode of the display. @param[in] ModeNumber Display mode number. @retval EFI_SUCCESS Display mode set successful. @retval EFI_DEVICE_ERROR Display mode not found/supported. **/ EFI_STATUS LcdSetMode ( IN CONST UINT32 ModeNumber ) { EFI_STATUS Status; SCAN_TIMINGS *Horizontal; SCAN_TIMINGS *Vertical; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo; // Get the display mode timings and other relevant information. Status = LcdPlatformGetTimings ( ModeNumber, &Horizontal, &Vertical ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } ASSERT (Horizontal != NULL); ASSERT (Vertical != NULL); // Get the pixel format information. Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } // Request configuration mode. SetConfigurationMode (); // Configure the graphics layer. LayerGraphicsConfig ( ModeInfo.PixelFormat, Horizontal->Resolution, Vertical->Resolution ); // Set the display engine timings. SetDisplayEngineTiming (Horizontal, Vertical); // After configuration, set Mali DP in normal mode. SetNormalMode (); // Any parameters written to the display engine are not activated until // CONFIG_VALID is set. SetConfigValid (); return EFI_SUCCESS; } /** This function de-initializes the display. **/ VOID LcdShutdown (VOID) { // Disable graphics layer. LayerGraphicsDisable (); }