ArmPlatformPkg: Add support for PL111 Lcd driver
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:12:38 +0000 (11:12 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:12:38 +0000 (11:12 +0000)
This driver implements the interface for the PL111 Lcd controller.
The LcdPlatformLib allows to set the platform specific requirements
needed by the platform for setting the LCD (oscillators, etc).

ArmPlatformPkg/ArmVExpressPkg: Implement LcdPlatformLib

This library exports the supported resolutions. It also allocates the
memory for the framebuffer and send the correct settings to the VExpress
motherboard microcontroller.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11786 6f19259b-4bc3-4df7-8a09-765794883524

13 files changed:
ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc
ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.fdf
ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
ArmPlatformPkg/ArmVExpressPkg/Include/Platform/CTA9x4/ArmPlatform.h
ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c [new file with mode: 0644]
ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf [new file with mode: 0644]
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h [new file with mode: 0644]
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf [new file with mode: 0644]
ArmPlatformPkg/Include/Drivers/PL111Lcd.h [new file with mode: 0644]
ArmPlatformPkg/Include/Library/LcdPlatformLib.h [new file with mode: 0644]

index 628c407..0d6a028 100644 (file)
   
   ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
   NorFlashPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
+  LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
 
 #
 # Assume everything is fixed at build
   gArmTokenSpaceGuid.PcdLinuxAtag|"rdinit=/bin/ash debug earlyprintk console=ttyAMA0,38400 mem=1G"
   gArmTokenSpaceGuid.PcdFdtDP|L""
 
-  #
-  # ARM PL111 Colour LCD Controller
-  #
-  gArmVExpressTokenSpaceGuid.PcdPL111RegistersBaseMotherboard|0x1001F000
-  gArmVExpressTokenSpaceGuid.PcdPL111RegistersBaseDaughterboard|0x10020000
-  gArmVExpressTokenSpaceGuid.PcdPL111VRamBaseMotherboard|0x4C000000
-  gArmVExpressTokenSpaceGuid.PcdPL111VRamBaseDaughterboard|0x64000000
-  gArmVExpressTokenSpaceGuid.PcdPL111VRamSize|0x800000
-  
   #
   # ARM L2x0 PCDs
   #
   ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
   ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
   ArmPlatformPkg/Drivers/SP804TimerDxe/SP804TimerDxe.inf
+  ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
 
   #
   # Semi-hosting filesystem
index 1932df4..e1571e0 100644 (file)
@@ -161,6 +161,7 @@ READ_LOCK_STATUS   = TRUE
   INF ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
   INF ArmPlatformPkg/Drivers/SP804TimerDxe/SP804TimerDxe.inf
   INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
+  INF ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
 
   #
   # Semi-hosting filesystem
index db2ae55..307e672 100644 (file)
 [PcdsFeatureFlag.common]
 
 [PcdsFixedAtBuild.common]
+  #
+  # MaxMode must be one number higher than the actual max mode,
+  # i.e. for actual maximum mode 2, set the value to 3.
+  #
+  # For a list of mode numbers look in LcdArmVExpress.c
+  #
+  gArmVExpressTokenSpaceGuid.PcdPL111MaxMode|3|UINT32|0x00000003
index 3dc622e..1b64392 100644 (file)
@@ -54,6 +54,8 @@
 // DRAM\r
 #define ARM_VE_DRAM_BASE                        0x60000000\r
 #define ARM_VE_DRAM_SZ                          0x40000000\r
+// Inside the DRAM we allocate a section for the VRAM (Video RAM)\r
+#define LCD_VRAM_CORE_TILE_BASE                 0x64000000\r
 \r
 // External AXI between daughterboards (Logic Tile)\r
 #define ARM_VE_EXT_AXI_BASE                     0xE0000000\r
 // PL310 L2x0 Cache Controller Base Address\r
 //#define ARM_VE_L2x0_CTLR_BASE                 0x1E00A000\r
 \r
+/***********************************************************************************\r
+   Select between Motherboard and Core Tile peripherals\r
+************************************************************************************/\r
+\r
+// Specify which PL111 to use\r
+//#define PL111_CLCD_BASE                       PL111_CLCD_MOTHERBOARD_BASE\r
+#define PL111_CLCD_BASE                         PL111_CLCD_CORE_TILE_BASE\r
+\r
 /***********************************************************************************\r
    Peripherals' misc settings\r
 ************************************************************************************/\r
 #define ARM_VE_DECPROT_BIT_SMC_TZASC_LOCK       (1 << 5)\r
 \r
 \r
+// PL111 Lcd\r
+#define PL111_CLCD_CORE_TILE_VIDEO_MODE_OSC_ID  1\r
+\r
 /***********************************************************************************\r
 // Interrupt Map\r
 ************************************************************************************/\r
diff --git a/ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c b/ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c
new file mode 100644 (file)
index 0000000..6ae5da9
--- /dev/null
@@ -0,0 +1,336 @@
+/** @file\r
+\r
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/ArmPlatformSysConfigLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/LcdPlatformLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/Cpu.h>\r
+\r
+#include <ArmPlatform.h>\r
+\r
+#define PL111_CLCD_SITE ARM_VE_DAUGHTERBOARD_1_SITE\r
+\r
+typedef struct {\r
+  UINT32                     Mode;\r
+  UINT32                     HorizontalResolution;\r
+  UINT32                     VerticalResolution;\r
+  LCD_BPP                    Bpp;\r
+  UINT32                     OscFreq;\r
+\r
+  UINT32                     HSync;\r
+  UINT32                     HBackPorch;\r
+  UINT32                     HFrontPorch;\r
+  UINT32                     VSync;\r
+  UINT32                     VBackPorch;\r
+  UINT32                     VFrontPorch;\r
+} LCD_RESOLUTION;\r
+\r
+\r
+LCD_RESOLUTION mResolutions[] = {\r
+    { // Mode 0 : VGA : 640 x 480 x 24 bpp\r
+        VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, VGA_OSC_FREQUENCY,\r
+        VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,\r
+        VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 1 : SVGA : 800 x 600 x 24 bpp\r
+        SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, SVGA_OSC_FREQUENCY,\r
+        SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,\r
+        SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 2 : XGA : 1024 x 768 x 24 bpp\r
+        XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, XGA_OSC_FREQUENCY,\r
+        XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,\r
+        XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 3 : SXGA : 1280 x 1024 x 24 bpp\r
+        SXGA, SXGA_H_RES_PIXELS, SXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (SXGA_OSC_FREQUENCY/2),\r
+        SXGA_H_SYNC, SXGA_H_BACK_PORCH, SXGA_H_FRONT_PORCH,\r
+        SXGA_V_SYNC, SXGA_V_BACK_PORCH, SXGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 4 : UXGA : 1600 x 1200 x 24 bpp\r
+        UXGA, UXGA_H_RES_PIXELS, UXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (UXGA_OSC_FREQUENCY/2),\r
+        UXGA_H_SYNC, UXGA_H_BACK_PORCH, UXGA_H_FRONT_PORCH,\r
+        UXGA_V_SYNC, UXGA_V_BACK_PORCH, UXGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 5 : HD : 1920 x 1080 x 24 bpp\r
+        HD, HD_H_RES_PIXELS, HD_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (HD_OSC_FREQUENCY/2),\r
+        HD_H_SYNC, HD_H_BACK_PORCH, HD_H_FRONT_PORCH,\r
+        HD_V_SYNC, HD_V_BACK_PORCH, HD_V_FRONT_PORCH\r
+    },\r
+    { // Mode 6 : VGA : 640 x 480 x 16 bpp (565 Mode)\r
+        VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, VGA_OSC_FREQUENCY,\r
+        VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,\r
+        VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 7 : SVGA : 800 x 600 x 16 bpp (565 Mode)\r
+        SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, SVGA_OSC_FREQUENCY,\r
+        SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,\r
+        SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 8 : XGA : 1024 x 768 x 16 bpp (565 Mode)\r
+        XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, XGA_OSC_FREQUENCY,\r
+        XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,\r
+        XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 9 : VGA : 640 x 480 x 15 bpp\r
+        VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, VGA_OSC_FREQUENCY,\r
+        VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,\r
+        VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 10 : SVGA : 800 x 600 x 15 bpp\r
+        SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, SVGA_OSC_FREQUENCY,\r
+        SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,\r
+        SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 11 : XGA : 1024 x 768 x 15 bpp\r
+        XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, XGA_OSC_FREQUENCY,\r
+        XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,\r
+        XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 12 : XGA : 1024 x 768 x 15 bpp - All the timing info is derived from Linux Kernel Driver Settings\r
+        XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, 63500000,\r
+        XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,\r
+        XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 13 : VGA : 640 x 480 x 12 bpp (444 Mode)\r
+        VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, VGA_OSC_FREQUENCY,\r
+        VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,\r
+        VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 14 : SVGA : 800 x 600 x 12 bpp (444 Mode)\r
+        SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, SVGA_OSC_FREQUENCY,\r
+        SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,\r
+        SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH\r
+    },\r
+    { // Mode 15 : XGA : 1024 x 768 x 12 bpp (444 Mode)\r
+        XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, XGA_OSC_FREQUENCY,\r
+        XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,\r
+        XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH\r
+    }\r
+};\r
+\r
+EFI_STATUS\r
+LcdPlatformInitializeDisplay (\r
+  VOID\r
+  ) {\r
+  // Set the FPGA multiplexer to select the video output from the motherboard or the daughterboard\r
+  return ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, PL111_CLCD_SITE);\r
+}\r
+\r
+EFI_STATUS\r
+LcdPlatformGetVram (\r
+  OUT EFI_PHYSICAL_ADDRESS*  VramBaseAddress,\r
+  OUT UINTN*                 VramSize\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_CPU_ARCH_PROTOCOL  *Cpu;\r
+\r
+  // Is it on the motherboard or on the daughterboard?\r
+  switch(PL111_CLCD_SITE) {\r
+\r
+  case ARM_VE_MOTHERBOARD_SITE:\r
+    *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) PL111_CLCD_VRAM_MOTHERBOARD_BASE;\r
+    *VramSize = LCD_VRAM_SIZE;\r
+    break;\r
+\r
+  case ARM_VE_DAUGHTERBOARD_1_SITE:\r
+    *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) LCD_VRAM_CORE_TILE_BASE;\r
+    *VramSize = LCD_VRAM_SIZE;\r
+\r
+    // Allocate the VRAM from the DRAM so that nobody else uses it.\r
+    Status = gBS->AllocatePages( AllocateAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(((UINTN)LCD_VRAM_SIZE)), VramBaseAddress);\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+\r
+    // Ensure the Cpu architectural protocol is already installed\r
+    Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    // Mark the VRAM as un-cachable. The VRAM is inside the DRAM, which is cachable.\r
+    Status = Cpu->SetMemoryAttributes(Cpu, *VramBaseAddress, *VramSize, EFI_MEMORY_UC);\r
+    ASSERT_EFI_ERROR(Status);\r
+    if (EFI_ERROR(Status)) {\r
+      gBS->FreePool(VramBaseAddress);\r
+      return Status;\r
+    }\r
+    break;\r
+\r
+  default:\r
+    // Unsupported site\r
+    Status = EFI_UNSUPPORTED;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+UINT32\r
+LcdPlatformGetMaxMode (\r
+  VOID\r
+  )\r
+{\r
+  // The following line will report correctly the total number of graphics modes\r
+  // supported by the PL111CLCD.\r
+  //return (sizeof(mResolutions) / sizeof(CLCD_RESOLUTION)) - 1;\r
+\r
+  // However, on some platforms it is desirable to ignore some graphics modes.\r
+  // This could be because the specific implementation of PL111 has certain limitations.\r
+\r
+  // Set the maximum mode allowed\r
+  return (PcdGet32(PcdPL111MaxMode));\r
+}\r
+\r
+EFI_STATUS\r
+LcdPlatformSetMode (\r
+  IN UINT32                         ModeNumber\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINT32                LcdSite;\r
+  UINT32                OscillatorId;\r
+  SYS_CONFIG_FUNCTION   Function;\r
+\r
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  LcdSite = PL111_CLCD_SITE;\r
+\r
+  switch(LcdSite) {\r
+  case ARM_VE_MOTHERBOARD_SITE:\r
+    Function = SYS_CFG_OSC;\r
+    OscillatorId = PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID;\r
+    break;\r
+  case ARM_VE_DAUGHTERBOARD_1_SITE:\r
+    Function = SYS_CFG_OSC_SITE1;\r
+    OscillatorId = PL111_CLCD_CORE_TILE_VIDEO_MODE_OSC_ID;\r
+    break;\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  // Set the video mode oscillator\r
+  Status = ArmPlatformSysConfigSetDevice (Function, OscillatorId, mResolutions[ModeNumber].OscFreq);\r
+  if (EFI_ERROR(Status)) {\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  // Set the DVI into the new mode\r
+  Status = ArmPlatformSysConfigSet (SYS_CFG_DVIMODE, mResolutions[ModeNumber].Mode);\r
+  if (EFI_ERROR(Status)) {\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  // Set the multiplexer\r
+  Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, LcdSite);\r
+  if (EFI_ERROR(Status)) {\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+LcdPlatformQueryMode (\r
+  IN  UINT32                                ModeNumber,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info\r
+  )\r
+{\r
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Info->Version = 0;\r
+  Info->HorizontalResolution = mResolutions[ModeNumber].HorizontalResolution;\r
+  Info->VerticalResolution = mResolutions[ModeNumber].VerticalResolution;\r
+  Info->PixelsPerScanLine = mResolutions[ModeNumber].HorizontalResolution;\r
+\r
+  switch (mResolutions[ModeNumber].Bpp) {\r
+    case LCD_BITS_PER_PIXEL_24:\r
+      Info->PixelFormat                   = PixelRedGreenBlueReserved8BitPerColor;\r
+      Info->PixelInformation.RedMask      = LCD_24BPP_RED_MASK;\r
+      Info->PixelInformation.GreenMask    = LCD_24BPP_GREEN_MASK;\r
+      Info->PixelInformation.BlueMask     = LCD_24BPP_BLUE_MASK;\r
+      Info->PixelInformation.ReservedMask = LCD_24BPP_RESERVED_MASK;\r
+      break;\r
+\r
+    case LCD_BITS_PER_PIXEL_16_555:\r
+    case LCD_BITS_PER_PIXEL_16_565:\r
+    case LCD_BITS_PER_PIXEL_12_444:\r
+    case LCD_BITS_PER_PIXEL_8:\r
+    case LCD_BITS_PER_PIXEL_4:\r
+    case LCD_BITS_PER_PIXEL_2:\r
+    case LCD_BITS_PER_PIXEL_1:\r
+    default:\r
+      // These are not supported\r
+      ASSERT(FALSE);\r
+      break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LcdPlatformGetTimings (\r
+  IN  UINT32                              ModeNumber,\r
+  OUT UINT32*                             HRes,\r
+  OUT UINT32*                             HSync,\r
+  OUT UINT32*                             HBackPorch,\r
+  OUT UINT32*                             HFrontPorch,\r
+  OUT UINT32*                             VRes,\r
+  OUT UINT32*                             VSync,\r
+  OUT UINT32*                             VBackPorch,\r
+  OUT UINT32*                             VFrontPorch\r
+  )\r
+{\r
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *HRes           = mResolutions[ModeNumber].HorizontalResolution;\r
+  *HSync          = mResolutions[ModeNumber].HSync;\r
+  *HBackPorch     = mResolutions[ModeNumber].HBackPorch;\r
+  *HFrontPorch    = mResolutions[ModeNumber].HFrontPorch;\r
+  *VRes           = mResolutions[ModeNumber].VerticalResolution;\r
+  *VSync          = mResolutions[ModeNumber].VSync;\r
+  *VBackPorch     = mResolutions[ModeNumber].VBackPorch;\r
+  *VFrontPorch    = mResolutions[ModeNumber].VFrontPorch;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LcdPlatformGetBpp (\r
+  IN  UINT32                              ModeNumber,\r
+  OUT LCD_BPP  *                          Bpp\r
+  )\r
+{\r
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Bpp = mResolutions[ModeNumber].Bpp;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf b/ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
new file mode 100644 (file)
index 0000000..6edca3b
--- /dev/null
@@ -0,0 +1,47 @@
+#/** @file
+#  
+#  Component discription file for ArmVeGraphicsDxe module
+#  
+#  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#  
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PL111LcdArmVExpressLib
+  FILE_GUID                      = b7f06f20-496f-11e0-a8e8-0002a5d5c51b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = LcdPlatformLib
+  
+[Sources.common]
+  PL111LcdArmVExpress.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  ArmPlatformSysConfigLib
+
+[Guids]
+
+[Protocols]
+
+[FeaturePcd]
+
+[FixedPcd.common]
+  gArmVExpressTokenSpaceGuid.PcdPL111MaxMode
+  
+[Pcd.common]
+
+[Depex]
diff --git a/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c b/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
new file mode 100644 (file)
index 0000000..679ccc8
--- /dev/null
@@ -0,0 +1,885 @@
+/** @file
+
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution.  The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#include <PiDxe.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include <ArmPlatform.h>
+#include "LcdGraphicsOutputDxe.h"
+
+extern BOOLEAN mDisplayInitialized;
+
+//
+// Function Definitions
+//
+
+STATIC
+EFI_STATUS
+VideoCopyNoHorizontalOverlap (
+  IN UINTN          BitsPerPixel,
+  IN volatile VOID  *FrameBufferBase,
+  IN UINT32         HorizontalResolution,
+  IN UINTN          SourceX,
+  IN UINTN          SourceY,
+  IN UINTN          DestinationX,
+  IN UINTN          DestinationY,
+  IN UINTN          Width,
+  IN UINTN          Height
+)
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+  UINTN         SourceLine;
+  UINTN         DestinationLine;
+  UINTN         WidthInBytes;
+  UINTN         LineCount;
+  INTN          Step;
+  VOID          *SourceAddr;
+  VOID          *DestinationAddr;
+
+  if( DestinationY <= SourceY ) {
+    // scrolling up (or horizontally but without overlap)
+    SourceLine       = SourceY;
+    DestinationLine  = DestinationY;
+    Step             = 1;
+  } else {
+    // scrolling down
+    SourceLine       = SourceY + Height;
+    DestinationLine  = DestinationY + Height;
+    Step             = -1;
+  }
+
+  switch (BitsPerPixel) {
+
+  case LCD_BITS_PER_PIXEL_24:
+
+    WidthInBytes = Width * 4;
+
+    for( LineCount = 0; LineCount < Height; LineCount++ ) {
+      // Update the start addresses of source & destination using 32bit pointer arithmetic
+      SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+      // Update the line numbers
+      SourceLine      += Step;
+      DestinationLine += Step;
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_12_444:
+
+    WidthInBytes = Width * 2;
+
+    for( LineCount = 0; LineCount < Height; LineCount++ ) {
+      // Update the start addresses of source & destination using 16bit pointer arithmetic
+      SourceAddr      = (VOID *)((UINT16 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+      // Update the line numbers
+      SourceLine      += Step;
+      DestinationLine += Step;
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+    // break;
+
+  }
+
+  EXIT:
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+VideoCopyHorizontalOverlap (
+  IN UINTN          BitsPerPixel,
+  IN volatile VOID  *FrameBufferBase,
+  UINT32            HorizontalResolution,
+  IN UINTN          SourceX,
+  IN UINTN          SourceY,
+  IN UINTN          DestinationX,
+  IN UINTN          DestinationY,
+  IN UINTN          Width,
+  IN UINTN          Height
+)
+{
+  EFI_STATUS      Status = EFI_SUCCESS;
+
+  UINT32 *PixelBuffer32bit;
+  UINT32 *SourcePixel32bit;
+  UINT32 *DestinationPixel32bit;
+
+  UINT16 *PixelBuffer16bit;
+  UINT16 *SourcePixel16bit;
+  UINT16 *DestinationPixel16bit;
+
+  UINT32          SourcePixelY;
+  UINT32          DestinationPixelY;
+  UINTN           SizeIn32Bits;
+  UINTN           SizeIn16Bits;
+
+  switch (BitsPerPixel) {
+
+  case LCD_BITS_PER_PIXEL_24:
+    // Allocate a temporary buffer
+
+    PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
+
+    if (PixelBuffer32bit == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    SizeIn32Bits = Width * 4;
+
+    // Copy from the video ram (source region) to a temp buffer
+    for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
+         SourcePixelY < SourceY + Height;
+         SourcePixelY++, DestinationPixel32bit += Width)
+    {
+      // Update the start address of line Y (source)
+      SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+    }
+
+    // Copy from the temp buffer to the video ram (destination region)
+    for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
+         DestinationPixelY < DestinationY + Height;
+         DestinationPixelY++, SourcePixel32bit += Width)
+    {
+      // Update the start address of line Y (target)
+      DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
+
+      // Copy the entire line Y from the temp buffer to video ram
+      CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+    }
+
+    // Free up the allocated memory
+    FreePool((VOID *) PixelBuffer32bit);
+
+    break;
+
+
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Allocate a temporary buffer
+    PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
+
+    if (PixelBuffer16bit == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
+
+    SizeIn16Bits = Width * 2;
+
+    for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
+         SourcePixelY < SourceY + Height;
+         SourcePixelY++, DestinationPixel16bit += Width)
+    {
+      // Calculate the source address:
+      SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+      // Copy the entire line Y from Video to the temp buffer
+      CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+    }
+
+    // Copy from the temp buffer into the destination area of the Video Memory
+
+    for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
+         DestinationPixelY < DestinationY + Height;
+         DestinationPixelY++, SourcePixel16bit += Width)
+    {
+      // Calculate the target address:
+      DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from the temp buffer to Video
+      CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+    }
+
+    // Free the allocated memory
+    FreePool((VOID *) PixelBuffer16bit);
+
+    break;
+
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+    // break;
+
+  }
+
+EXIT:
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoFill (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *EfiSourcePixel,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_PIXEL_BITMASK*  PixelInformation;
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  VOID            *FrameBufferBase;
+  VOID            *DestinationAddr;
+  UINT16          *DestinationPixel16bit;
+  UINT16          Pixel16bit;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINTN           WidthInBytes;
+
+  Status           = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      // Calculate the target address using 32bit pointer arithmetic:
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationX);
+
+      // Fill the entire line
+      SetMemN( DestinationAddr, WidthInBytes, *((UINTN *)EfiSourcePixel));
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+//      | ( 0                           & PixelInformation->ReservedMask )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      >> 4) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     << 4) & PixelInformation->BlueMask     )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToBltBuffer (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  EFI_PIXEL_BITMASK  *PixelInformation;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
+  VOID   *FrameBufferBase;
+  VOID            *SourceAddr;
+  VOID            *DestinationAddr;
+  UINT16 *SourcePixel16bit;
+  UINT16          Pixel16bit;
+  UINT32          SourcePixelX;
+  UINT32          SourceLine;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINT32          BltBufferHorizontalResolution;
+  UINTN           WidthInBytes;
+
+  Status = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    // Delta is not zero and it is different from the width.
+    // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+    BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+  } else {
+    BltBufferHorizontalResolution = Width;
+  }
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Access each line inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      // Calculate the source and target addresses using 32bit pointer arithmetic:
+      SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution          + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)BltBuffer       + DestinationLine * BltBufferHorizontalResolution + DestinationX);
+
+      // Copy the entire line
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >>  7 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >>  2);
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) <<  3 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        // There is no info for the Reserved byte, so we set it to zero
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 8 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >> 3);
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 3 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 4 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   )     );
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 4 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltBufferToVideo (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  EFI_PIXEL_BITMASK  *PixelInformation;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
+  VOID   *FrameBufferBase;
+  VOID            *SourceAddr;
+  VOID            *DestinationAddr;
+  UINT16 *DestinationPixel16bit;
+  UINT32          SourcePixelX;
+  UINT32          SourceLine;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINT32          BltBufferHorizontalResolution;
+  UINTN           WidthInBytes;
+
+  Status = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    // Delta is not zero and it is different from the width.
+    // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+    BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+  } else {
+    BltBufferHorizontalResolution = Width;
+  }
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+       SourceLine < SourceY + Height;
+       SourceLine++, DestinationLine++)
+    {
+      // Calculate the source and target addresses using 32bit pointer arithmetic:
+      SourceAddr      = (VOID *)((UINT32 *)BltBuffer       + SourceLine      * BltBufferHorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution          + DestinationX);
+
+      // Copy the entire row Y
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+       SourceLine < SourceY + Height;
+       SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel  = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+      //            | ( 0                                & PixelInformation->ReservedMask )
+            );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2  least significant bits
+        // There is no room for the Reserved byte so we ignore that completely
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+           );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      << 4) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >> 4) & PixelInformation->BlueMask     )
+  //            | ( 0                               & PixelInformation->ReservedMask )
+           );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToVideo (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  VOID   *FrameBufferBase;
+
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  //
+  // BltVideo to BltVideo:
+  //
+  //  Source is the Video Memory,
+  //  Destination is the Video Memory
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  // The UEFI spec currently states:
+  // "There is no limitation on the overlapping of the source and destination rectangles"
+  // Therefore, we must be careful to avoid overwriting the source data
+  if( SourceY == DestinationY ) {
+    // Copying within the same height, e.g. horizontal shift
+    if( SourceX == DestinationX ) {
+      // Nothing to do
+      Status = EFI_SUCCESS;
+    } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
+      // There is overlap
+      Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+    } else {
+      // No overlap
+      Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+    }
+  } else {
+    // Copying from different heights
+    Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+  }
+
+  return Status;
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
+ *
+ * PRESUMES: 1 pixel = 4 bytes (32bits)
+ *  ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsBlt (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+       IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+       IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION   BltOperation,
+       IN UINTN                               SourceX,
+       IN UINTN                               SourceY,
+       IN UINTN                               DestinationX,
+       IN UINTN                               DestinationY,
+       IN UINTN                               Width,
+       IN UINTN                               Height,
+       IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+       EFI_STATUS         Status;
+       UINT32             HorizontalResolution;
+  UINT32             VerticalResolution;
+       LCD_INSTANCE*      Instance;
+
+  Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
+
+  // Setup the hardware if not already done
+  if (!mDisplayInitialized) {
+    Status = InitializeDisplay (Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  VerticalResolution   = This->Mode->Info->VerticalResolution;
+
+  DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
+      BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
+
+  // Check we have reasonable parameters
+       if (Width == 0 || Height == 0) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
+               Status = EFI_INVALID_PARAMETER;
+               goto EXIT;
+       }
+
+       if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
+         ASSERT( BltBuffer != NULL);
+       }
+
+       /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
+         DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
+         Status = EFI_INVALID_PARAMETER;
+         goto EXIT;
+       }*/
+
+       // If we are reading data out of the video buffer, check that the source area is within the display limits
+       if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
+    if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
+      DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
+      DEBUG((DEBUG_INFO, "                      - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
+      DEBUG((DEBUG_INFO, "                      - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
+      Status = EFI_INVALID_PARAMETER;
+      goto EXIT;
+    }
+       }
+
+       // If we are writing data into the video buffer, that the destination area is within the display limits
+       if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
+    if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
+      DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
+      DEBUG((DEBUG_INFO, "                      - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
+      DEBUG((DEBUG_INFO, "                      - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
+      Status = EFI_INVALID_PARAMETER;
+      goto EXIT;
+    }
+       }
+
+  //
+  // Perform the Block Transfer Operation
+  //
+
+       switch (BltOperation) {
+       case EfiBltVideoFill:
+         Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+               break;
+
+       case EfiBltVideoToBltBuffer:
+         Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+    break;
+
+  case EfiBltBufferToVideo:
+    Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+               break;
+
+       case EfiBltVideoToVideo:
+         Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+               break;
+
+       case EfiGraphicsOutputBltOperationMax:
+       default:
+               DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
+               Status = EFI_INVALID_PARAMETER;
+               break;
+       }
+
+EXIT:
+       return Status;
+}
diff --git a/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c b/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
new file mode 100644 (file)
index 0000000..a4ab6a6
--- /dev/null
@@ -0,0 +1,379 @@
+/** @file
+
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution.  The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#include <PiDxe.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include <ArmPlatform.h>
+#include "LcdGraphicsOutputDxe.h"
+
+/**********************************************************************
+ *
+ *  This file implements the Graphics Output protocol on ArmVersatileExpress
+ *  using the Lcd controller
+ *
+ **********************************************************************/
+
+//
+// Global variables
+//
+
+BOOLEAN mDisplayInitialized = FALSE;
+
+LCD_INSTANCE mLcdTemplate = {
+  LCD_INSTANCE_SIGNATURE,
+  NULL, // Handle
+  { // ModeInfo
+    0, // Version
+    0, // HorizontalResolution
+    0, // VerticalResolution
+    PixelBltOnly, // PixelFormat
+    0, // PixelInformation
+    0, // PixelsPerScanLine
+  },
+  {
+    0, // MaxMode;
+    0, // Mode;
+    NULL, // Info;
+    0, // SizeOfInfo;
+    0, // FrameBufferBase;
+    0 // FrameBufferSize;
+  },
+  { // Gop
+    LcdGraphicsQueryMode,  // QueryMode
+    LcdGraphicsSetMode,    // SetMode
+    LcdGraphicsBlt,        // Blt
+    NULL                     // *Mode
+  },
+  { // DevicePath
+    {
+      {
+        HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
+        (UINT8) (sizeof(VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+      },
+      // Hardware Device Path for Lcd
+      EFI_CALLER_ID_GUID // Use the driver's GUID
+    },
+
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      sizeof(EFI_DEVICE_PATH_PROTOCOL),
+      0
+    }
+  },
+  (EFI_EVENT) NULL // ExitBootServicesEvent
+};
+
+EFI_STATUS
+LcdInstanceContructor (
+  OUT LCD_INSTANCE** NewInstance
+  )
+{
+  LCD_INSTANCE* Instance;
+
+  Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
+  if (Instance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Instance->Gop.Mode          = &Instance->Mode;
+  Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
+  Instance->Mode.Info         = &Instance->ModeInfo;
+
+  *NewInstance = Instance;
+  return EFI_SUCCESS;
+}
+
+//
+// Function Definitions
+//
+
+EFI_STATUS
+InitializeDisplay (
+  IN LCD_INSTANCE* Instance
+  )
+{
+  EFI_STATUS             Status = EFI_SUCCESS;
+  EFI_PHYSICAL_ADDRESS   VramBaseAddress;
+  UINTN                  VramSize;
+
+  Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Setup the LCD
+  Status = LcdInitialize (VramBaseAddress);
+  if (EFI_ERROR(Status)) {
+    goto EXIT_ERROR_LCD_SHUTDOWN;
+  }
+
+  Status = LcdPlatformInitializeDisplay ();
+  if (EFI_ERROR(Status)) {
+    goto EXIT_ERROR_LCD_SHUTDOWN;
+  }
+
+  // Setup all the relevant mode information
+  Instance->Gop.Mode->SizeOfInfo      = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+  Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
+  Instance->Gop.Mode->FrameBufferSize = VramSize;
+
+  // Set the flag before changing the mode, to avoid infinite loops
+  mDisplayInitialized = TRUE;
+
+  // All is ok, so don't deal with any errors
+  goto EXIT;
+
+EXIT_ERROR_LCD_SHUTDOWN:
+  DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
+  LcdShutdown ();
+
+EXIT:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsOutputDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+  LCD_INSTANCE* Instance;
+
+  Status = LcdInstanceContructor (&Instance);
+  if (EFI_ERROR(Status)) {
+    goto EXIT;
+  }
+
+       // Install the Graphics Output Protocol and the Device Path
+       Status = gBS->InstallMultipleProtocolInterfaces(
+                       &Instance->Handle,
+                       &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
+                       &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,
+                       NULL
+          );
+
+       if (EFI_ERROR(Status)) {
+         DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
+               goto EXIT;
+       }
+
+       // Register for an ExitBootServicesEvent
+       // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
+       // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
+       Status = gBS->CreateEvent (
+           EVT_SIGNAL_EXIT_BOOT_SERVICES,
+           TPL_NOTIFY,
+           LcdGraphicsExitBootServicesEvent, NULL,
+                       &Instance->ExitBootServicesEvent
+                       );
+
+       if (EFI_ERROR(Status)) {
+         DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
+               goto EXIT_ERROR_UNINSTALL_PROTOCOL;
+       }
+
+       // To get here, everything must be fine, so just exit
+       goto EXIT;
+
+EXIT_ERROR_UNINSTALL_PROTOCOL:
+       /* The following function could return an error message,
+        * however, to get here something must have gone wrong already,
+        * so preserve the original error, i.e. don't change
+        * the Status variable, even it fails to uninstall the protocol.
+        */
+       gBS->UninstallMultipleProtocolInterfaces (
+           Instance->Handle,
+           &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
+           &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,     // Uninstall device path
+           NULL
+           );
+
+EXIT:
+       return Status;
+
+}
+
+/***************************************
+ * This function should be called
+ * on Event: ExitBootServices
+ * to free up memory, stop the driver
+ * and uninstall the protocols
+ ***************************************/
+VOID
+LcdGraphicsExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+       //TODO: Implement me
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
+ ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsQueryMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL            *This,
+       IN UINT32                                  ModeNumber,
+       OUT UINTN                                  *SizeOfInfo,
+       OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   **Info
+       )
+{
+       EFI_STATUS Status = EFI_SUCCESS;
+       LCD_INSTANCE *Instance;
+
+       Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
+
+  // Setup the hardware if not already done
+  if( !mDisplayInitialized ) {
+    Status = InitializeDisplay(Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+       // Error checking
+       if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
+         DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
+               Status = EFI_INVALID_PARAMETER;
+               goto EXIT;
+       }
+
+       *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (*Info == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  Status = LcdPlatformQueryMode (ModeNumber,*Info);
+  if (EFI_ERROR(Status)) {
+    FreePool(*Info);
+  }
+
+EXIT:
+       return Status;
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
+ ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsSetMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
+       IN UINT32                         ModeNumber
+       )
+{
+       EFI_STATUS                      Status               = EFI_SUCCESS;
+       EFI_GRAPHICS_OUTPUT_BLT_PIXEL   FillColour;
+       LCD_INSTANCE* Instance;
+
+       Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
+
+  // Setup the hardware if not already done
+  if(!mDisplayInitialized) {
+    Status = InitializeDisplay (Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+  // Check if this mode is supported
+  if( ModeNumber >= This->Mode->MaxMode ) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
+    Status = EFI_UNSUPPORTED;
+    goto EXIT;
+  }
+
+       // Set the oscillator frequency to support the new mode
+  Status = LcdPlatformSetMode (ModeNumber);
+  if (EFI_ERROR(Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+       // Update the UEFI mode information
+       This->Mode->Mode = ModeNumber;
+       LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
+
+  // Set the hardware to the new mode
+       Status = LcdSetMode (ModeNumber);
+  if (EFI_ERROR(Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+       // The UEFI spec requires that we now clear the visible portions of the output display to black.
+
+  // Set the fill colour to black
+  SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+  // Fill the entire visible area with the same colour.
+  Status = This->Blt (
+      This,
+      &FillColour,
+      EfiBltVideoFill,
+      0,
+      0,
+      0,
+      0,
+      This->Mode->Info->HorizontalResolution,
+      This->Mode->Info->VerticalResolution,
+      0);
+
+EXIT:
+       return Status;
+}
+
+UINTN
+GetBytesPerPixel (
+  IN  LCD_BPP       Bpp
+  )
+{
+  switch(Bpp) {
+  case LCD_BITS_PER_PIXEL_24:
+    return 4;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_12_444:
+    return 2;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+    return 1;
+
+  default:
+    return 0;
+  }
+}
diff --git a/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h b/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h
new file mode 100644 (file)
index 0000000..8886bed
--- /dev/null
@@ -0,0 +1,124 @@
+/** @file\r
+\r
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __ARM_VE_GRAPHICS_DXE_H__\r
+#define __ARM_VE_GRAPHICS_DXE_H__\r
+\r
+\r
+#include <Base.h>\r
+#include <Library/UefiLib.h>\r
+#include <Protocol/DevicePath.h>\r
+\r
+#include <Library/LcdPlatformLib.h>\r
+\r
+//\r
+// Device structures\r
+//\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH            Guid;\r
+  EFI_DEVICE_PATH_PROTOCOL      End;\r
+} LCD_GRAPHICS_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  UINTN                                 Signature;\r
+  EFI_HANDLE                            Handle;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  ModeInfo;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE     Mode;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL          Gop;\r
+  LCD_GRAPHICS_DEVICE_PATH              DevicePath;\r
+  EFI_EVENT                             ExitBootServicesEvent;\r
+} LCD_INSTANCE;\r
+\r
+#define LCD_INSTANCE_SIGNATURE  SIGNATURE_32('l', 'c', 'd', '0')\r
+\r
+#define LCD_INSTANCE_FROM_GOP_THIS(a)     CR (a, LCD_INSTANCE, Gop, LCD_INSTANCE_SIGNATURE)\r
+\r
+//\r
+// Function Prototypes\r
+//\r
+\r
+VOID\r
+LcdGraphicsExitBootServicesEvent (\r
+    IN EFI_EVENT  Event,\r
+    IN VOID       *Context\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LcdGraphicsQueryMode (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,\r
+  IN  UINT32                                ModeNumber,\r
+  OUT UINTN                                 *SizeOfInfo,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LcdGraphicsSetMode (\r
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL  *This,\r
+  IN UINT32                        ModeNumber\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LcdGraphicsBlt (\r
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,\r
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer,     OPTIONAL\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,\r
+  IN UINTN                              SourceX,\r
+  IN UINTN                              SourceY,\r
+  IN UINTN                              DestinationX,\r
+  IN UINTN                              DestinationY,\r
+  IN UINTN                              Width,\r
+  IN UINTN                              Height,\r
+  IN UINTN                              Delta           OPTIONAL\r
+);\r
+\r
+UINTN\r
+GetBytesPerPixel (\r
+  IN  LCD_BPP       Bpp\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GraphicsOutputDxeInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+);\r
+\r
+EFI_STATUS\r
+InitializeDisplay (\r
+  IN LCD_INSTANCE* Instance\r
+);\r
+\r
+EFI_STATUS\r
+LcdIndentify (\r
+  VOID\r
+);\r
+\r
+EFI_STATUS\r
+LcdInitialize (\r
+  EFI_PHYSICAL_ADDRESS  VramBaseAddress\r
+);\r
+\r
+EFI_STATUS\r
+LcdSetMode (\r
+  IN UINT32  ModeNumber\r
+);\r
+\r
+VOID\r
+LcdShutdown (\r
+  VOID\r
+);\r
+\r
+#endif /* __ARM_VE_GRAPHICS_DXE_H__ */\r
diff --git a/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c b/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c
new file mode 100644 (file)
index 0000000..c92dd3d
--- /dev/null
@@ -0,0 +1,140 @@
+/** @file  PL111Lcd.c\r
+\r
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/LcdPlatformLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Drivers/PL111Lcd.h>\r
+\r
+#include "LcdGraphicsOutputDxe.h"\r
+\r
+/**********************************************************************\r
+ *\r
+ *  This file contains all the bits of the PL111 that are\r
+ *  platform independent.\r
+ *\r
+ **********************************************************************/\r
+\r
+EFI_STATUS\r
+PL111Indentify (\r
+  VOID\r
+  )\r
+{\r
+  // Check if this is a PrimeCell Peripheral\r
+  if (    ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_0 ) != 0x0D )\r
+       || ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_1 ) != 0xF0 )\r
+       || ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_2 ) != 0x05 )\r
+       || ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_3 ) != 0xB1 ) ) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  // Check if this PrimeCell Peripheral is the PL111 LCD\r
+  if (    ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_0 ) != 0x11 )\r
+       || ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_1 ) != 0x11 )\r
+       || ( (MmioRead8( PL111_REG_CLCD_PERIPH_ID_2 ) & 0xF) != 0x04 )\r
+       || ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_3 ) != 0x00 ) ) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LcdInitialize (\r
+  IN EFI_PHYSICAL_ADDRESS   VramBaseAddress\r
+  )\r
+{\r
+  EFI_STATUS  Status = EFI_SUCCESS;\r
+\r
+  // Check if the PL111 is fitted on this motherboard\r
+  Status = PL111Indentify();\r
+  if (EFI_ERROR( Status )) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  // Define start of the VRAM. This never changes for any graphics mode\r
+  MmioWrite32(PL111_REG_LCD_UP_BASE, (UINT32) VramBaseAddress);\r
+  MmioWrite32(PL111_REG_LCD_LP_BASE, 0); // We are not using a double buffer\r
+\r
+  // Disable all interrupts from the PL111\r
+  MmioWrite32(PL111_REG_LCD_IMSC, 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LcdSetMode (\r
+  IN UINT32  ModeNumber\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINT32            HRes;\r
+  UINT32            HSync;\r
+  UINT32            HBackPorch;\r
+  UINT32            HFrontPorch;\r
+  UINT32            VRes;\r
+  UINT32            VSync;\r
+  UINT32            VBackPorch;\r
+  UINT32            VFrontPorch;\r
+  UINT32            LcdControl;\r
+  LCD_BPP           LcdBpp;\r
+\r
+  // Set the video mode timings and other relevant information\r
+  Status = LcdPlatformGetTimings (ModeNumber,\r
+                                  &HRes,&HSync,&HBackPorch,&HFrontPorch,\r
+                                  &VRes,&VSync,&VBackPorch,&VFrontPorch);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR( Status )) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Status = LcdPlatformGetBpp (ModeNumber,&LcdBpp);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR( Status )) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  // Disable the CLCD_LcdEn bit\r
+  LcdControl = MmioRead32( PL111_REG_LCD_CONTROL);\r
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl & ~1);\r
+\r
+  // Set Timings\r
+  MmioWrite32 (PL111_REG_LCD_TIMING_0, HOR_AXIS_PANEL(HBackPorch, HFrontPorch, HSync, HRes));\r
+  MmioWrite32 (PL111_REG_LCD_TIMING_1, VER_AXIS_PANEL(VBackPorch, VFrontPorch, VSync, VRes));\r
+  MmioWrite32 (PL111_REG_LCD_TIMING_2, CLK_SIG_POLARITY(HRes));\r
+  MmioWrite32 (PL111_REG_LCD_TIMING_3, 0);\r
+\r
+  // PL111_REG_LCD_CONTROL\r
+  LcdControl = PL111_CTRL_LCD_EN | PL111_CTRL_LCD_BPP(LcdBpp) | PL111_CTRL_LCD_TFT | PL111_CTRL_BGR;\r
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl);\r
+\r
+  // Turn on power to the LCD Panel\r
+  LcdControl |= PL111_CTRL_LCD_PWR;\r
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+LcdShutdown (\r
+  VOID\r
+  )\r
+{\r
+  // Nothing to do in terms of hardware.\r
+  // We could switch off the monitor display if required\r
+\r
+  //TODO: ImplementMe\r
+}\r
diff --git a/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf b/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
new file mode 100644 (file)
index 0000000..ae571d8
--- /dev/null
@@ -0,0 +1,60 @@
+#/** @file
+#  
+#  Component discription file for ArmVeGraphicsDxe module
+#  
+#  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#  
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PL111LcdGraphicsDxe
+  FILE_GUID                      = 407B4008-BF5B-11DF-9547-CF16E0D72085
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = LcdGraphicsOutputDxeInitialize
+
+[Sources.common]
+  LcdGraphicsOutputDxe.c
+  LcdGraphicsOutputBlt.c
+  PL111Lcd.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  UefiLib
+  BaseLib
+  DebugLib
+  TimerLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  IoLib
+  BaseMemoryLib
+  LcdPlatformLib
+
+[Guids]
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
+  gEfiGraphicsOutputProtocolGuid
+
+[FixedPcd.common]
+[Pcd.common]
+
+
+[Depex]
+  gEfiCpuArchProtocolGuid
diff --git a/ArmPlatformPkg/Include/Drivers/PL111Lcd.h b/ArmPlatformPkg/Include/Drivers/PL111Lcd.h
new file mode 100644 (file)
index 0000000..80d5639
--- /dev/null
@@ -0,0 +1,142 @@
+/** @file  PL111Lcd.h
+
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution.  The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#ifndef _PL111LCD_H__
+#define _PL111LCD_H__
+
+#include <ArmPlatform.h>
+
+/**********************************************************************
+ *
+ *  This header file contains all the bits of the PL111 that are
+ *  platform independent.
+ *
+ **********************************************************************/
+
+// Controller Register Offsets
+#define PL111_REG_LCD_TIMING_0            (PL111_CLCD_BASE + 0x000)
+#define PL111_REG_LCD_TIMING_1            (PL111_CLCD_BASE + 0x004)
+#define PL111_REG_LCD_TIMING_2            (PL111_CLCD_BASE + 0x008)
+#define PL111_REG_LCD_TIMING_3            (PL111_CLCD_BASE + 0x00C)
+#define PL111_REG_LCD_UP_BASE             (PL111_CLCD_BASE + 0x010)
+#define PL111_REG_LCD_LP_BASE             (PL111_CLCD_BASE + 0x014)
+#define PL111_REG_LCD_CONTROL             (PL111_CLCD_BASE + 0x018)
+#define PL111_REG_LCD_IMSC                (PL111_CLCD_BASE + 0x01C)
+#define PL111_REG_LCD_RIS                 (PL111_CLCD_BASE + 0x020)
+#define PL111_REG_LCD_MIS                 (PL111_CLCD_BASE + 0x024)
+#define PL111_REG_LCD_ICR                 (PL111_CLCD_BASE + 0x028)
+#define PL111_REG_LCD_UP_CURR             (PL111_CLCD_BASE + 0x02C)
+#define PL111_REG_LCD_LP_CURR             (PL111_CLCD_BASE + 0x030)
+#define PL111_REG_LCD_PALETTE             (PL111_CLCD_BASE + 0x200)
+
+// Identification Register Offsets
+#define PL111_REG_CLCD_PERIPH_ID_0        (PL111_CLCD_BASE + 0xFE0)
+#define PL111_REG_CLCD_PERIPH_ID_1        (PL111_CLCD_BASE + 0xFE4)
+#define PL111_REG_CLCD_PERIPH_ID_2        (PL111_CLCD_BASE + 0xFE8)
+#define PL111_REG_CLCD_PERIPH_ID_3        (PL111_CLCD_BASE + 0xFEC)
+#define PL111_REG_CLCD_P_CELL_ID_0        (PL111_CLCD_BASE + 0xFF0)
+#define PL111_REG_CLCD_P_CELL_ID_1        (PL111_CLCD_BASE + 0xFF4)
+#define PL111_REG_CLCD_P_CELL_ID_2        (PL111_CLCD_BASE + 0xFF8)
+#define PL111_REG_CLCD_P_CELL_ID_3        (PL111_CLCD_BASE + 0xFFC)
+
+/**********************************************************************/
+
+// Register components (register bits)
+
+// This should make life easier to program specific settings in the different registers
+// by simplifying the setting up of the individual bits of each register
+// and then assembling the final register value.
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define HOR_AXIS_PANEL(hbp,hfp,hsw,hor_res) (UINT32)(((UINT32)(hbp) << 24) | ((UINT32)(hfp) << 16) | ((UINT32)(hsw) << 8) | (((UINT32)((hor_res)/16)-1) << 2))
+
+// Register: PL111_REG_LCD_TIMING_1
+#define VER_AXIS_PANEL(vbp,vfp,vsw,ver_res) (UINT32)(((UINT32)(vbp) << 24) | ((UINT32)(vfp) << 16) | ((UINT32)(vsw) << 10) | ((ver_res)-1))
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_SHIFT_PCD_HI            27
+#define PL111_BIT_SHIFT_BCD               26
+#define PL111_BIT_SHIFT_CPL               16
+#define PL111_BIT_SHIFT_IOE               14
+#define PL111_BIT_SHIFT_IPC               13
+#define PL111_BIT_SHIFT_IHS               12
+#define PL111_BIT_SHIFT_IVS               11
+#define PL111_BIT_SHIFT_ACB               6
+#define PL111_BIT_SHIFT_CLKSEL            5
+#define PL111_BIT_SHIFT_PCD_LO            0
+
+#define PL111_BCD                         (1 << 26)
+#define PL111_IPC                         (1 << 13)
+#define PL111_IHS                         (1 << 12)
+#define PL111_IVS                         (1 << 11)
+
+#define CLK_SIG_POLARITY(hor_res)         (UINT32)(PL111_BCD | PL111_IPC | PL111_IHS | PL111_IVS | (((hor_res)-1) << 16))
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_SHIFT_LEE               16
+#define PL111_BIT_SHIFT_LED               0
+
+#define PL111_CTRL_WATERMARK              (1 << 16)
+#define PL111_CTRL_LCD_V_COMP             (1 << 12)
+#define PL111_CTRL_LCD_PWR                (1 << 11)
+#define PL111_CTRL_BEPO                   (1 << 10)
+#define PL111_CTRL_BEBO                   (1 << 9)
+#define PL111_CTRL_BGR                    (1 << 8)
+#define PL111_CTRL_LCD_DUAL               (1 << 7)
+#define PL111_CTRL_LCD_MONO_8             (1 << 6)
+#define PL111_CTRL_LCD_TFT                (1 << 5)
+#define PL111_CTRL_LCD_BW                 (1 << 4)
+#define PL111_CTRL_LCD_1BPP               (0 << 1)
+#define PL111_CTRL_LCD_2BPP               (1 << 1)
+#define PL111_CTRL_LCD_4BPP               (2 << 1)
+#define PL111_CTRL_LCD_8BPP               (3 << 1)
+#define PL111_CTRL_LCD_16BPP              (4 << 1)
+#define PL111_CTRL_LCD_24BPP              (5 << 1)
+#define PL111_CTRL_LCD_16BPP_565          (6 << 1)
+#define PL111_CTRL_LCD_12BPP_444          (7 << 1)
+#define PL111_CTRL_LCD_BPP(Bpp)           ((Bpp) << 1)
+#define PL111_CTRL_LCD_EN                 1
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define PL111_LCD_TIMING_0_HBP(hbp)       (((hbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_0_HFP(hfp)       (((hfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_0_HSW(hsw)       (((hsw) & 0xFF) << 8)
+#define PL111_LCD_TIMING_0_PPL(ppl)       (((hsw) & 0x3F) << 2)
+
+// Register: PL111_REG_LCD_TIMING_1
+#define PL111_LCD_TIMING_1_VBP(vbp)       (((vbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_1_VFP(vfp)       (((vfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_1_VSW(vsw)       (((vsw) & 0x3F) << 10)
+#define PL111_LCD_TIMING_1_LPP(lpp)        ((lpp) & 0xFC)
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_MASK_PCD_HI             0xF8000000
+#define PL111_BIT_MASK_BCD                0x04000000
+#define PL111_BIT_MASK_CPL                0x03FF0000
+#define PL111_BIT_MASK_IOE                0x00004000
+#define PL111_BIT_MASK_IPC                0x00002000
+#define PL111_BIT_MASK_IHS                0x00001000
+#define PL111_BIT_MASK_IVS                0x00000800
+#define PL111_BIT_MASK_ACB                0x000007C0
+#define PL111_BIT_MASK_CLKSEL             0x00000020
+#define PL111_BIT_MASK_PCD_LO             0x0000001F
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_MASK_LEE                0x00010000
+#define PL111_BIT_MASK_LED                0x0000007F
+
+#endif /* _PL111LCD_H__ */
diff --git a/ArmPlatformPkg/Include/Library/LcdPlatformLib.h b/ArmPlatformPkg/Include/Library/LcdPlatformLib.h
new file mode 100644 (file)
index 0000000..93afa63
--- /dev/null
@@ -0,0 +1,205 @@
+/** @file\r
+\r
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution.  The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ **/\r
+\r
+#ifndef __LCDPLATFORMLIB_H\r
+#define __LCDPLATFORMLIB_H\r
+\r
+#include <Protocol/GraphicsOutput.h>\r
+\r
+#define LCD_VRAM_SIZE                     SIZE_8MB\r
+\r
+//\r
+// Modes definitions\r
+//\r
+#define VGA                               0\r
+#define SVGA                              1\r
+#define XGA                               2\r
+#define SXGA                              3\r
+#define UXGA                              4\r
+#define HD                                5\r
+\r
+//\r
+// VGA Mode: 640 x 480\r
+//\r
+#define VGA_H_RES_PIXELS                  640\r
+#define VGA_V_RES_PIXELS                  480\r
+#define VGA_OSC_FREQUENCY                 23750000  /* 0x016A6570 */\r
+\r
+#define VGA_H_SYNC                        ( 80 - 1)\r
+#define VGA_H_FRONT_PORCH                 ( 16 - 1)\r
+#define VGA_H_BACK_PORCH                  ( 64 - 1)\r
+\r
+#define VGA_V_SYNC                        (  4 - 1)\r
+#define VGA_V_FRONT_PORCH                 (  3 - 1)\r
+#define VGA_V_BACK_PORCH                  ( 13 - 1)\r
+\r
+//\r
+// SVGA Mode: 800 x 600\r
+//\r
+#define SVGA_H_RES_PIXELS                 800\r
+#define SVGA_V_RES_PIXELS                 600\r
+#define SVGA_OSC_FREQUENCY                38250000  /* 0x0247A610 */\r
+\r
+#define SVGA_H_SYNC                       ( 80 - 1)\r
+#define SVGA_H_FRONT_PORCH                ( 32 - 1)\r
+#define SVGA_H_BACK_PORCH                 (112 - 1)\r
+\r
+#define SVGA_V_SYNC                       (  4 - 1)\r
+#define SVGA_V_FRONT_PORCH                (  3 - 1)\r
+#define SVGA_V_BACK_PORCH                 ( 17 - 1)\r
+\r
+//\r
+// XGA Mode: 1024 x 768\r
+//\r
+#define XGA_H_RES_PIXELS                  1024\r
+#define XGA_V_RES_PIXELS                  768\r
+#define XGA_OSC_FREQUENCY                 63500000  /* 0x03C8EEE0 */\r
+\r
+#define XGA_H_SYNC                        (104 - 1)\r
+#define XGA_H_FRONT_PORCH                 ( 48 - 1)\r
+#define XGA_H_BACK_PORCH                  (152 - 1)\r
+\r
+#define XGA_V_SYNC                        (  4 - 1)\r
+#define XGA_V_FRONT_PORCH                 (  3 - 1)\r
+#define XGA_V_BACK_PORCH                  ( 23 - 1)\r
+\r
+//\r
+// SXGA Mode: 1280 x 1024\r
+//\r
+#define SXGA_H_RES_PIXELS                 1280\r
+#define SXGA_V_RES_PIXELS                 1024\r
+#define SXGA_OSC_FREQUENCY                109000000  /* 0x067F3540 */\r
+\r
+#define SXGA_H_SYNC                       (136 - 1)\r
+#define SXGA_H_FRONT_PORCH                ( 80 - 1)\r
+#define SXGA_H_BACK_PORCH                 (216 - 1)\r
+\r
+#define SXGA_V_SYNC                       (  7 - 1)\r
+#define SXGA_V_FRONT_PORCH                (  3 - 1)\r
+#define SXGA_V_BACK_PORCH                 ( 29 - 1)\r
+\r
+//\r
+// UXGA Mode: 1600 x 1200\r
+//\r
+#define UXGA_H_RES_PIXELS                 1600\r
+#define UXGA_V_RES_PIXELS                 1200\r
+#define UXGA_OSC_FREQUENCY                161000000  /* 0x0998AA40 */\r
+\r
+#define UXGA_H_SYNC                       (168 - 1)\r
+#define UXGA_H_FRONT_PORCH                (112 - 1)\r
+#define UXGA_H_BACK_PORCH                 (280 - 1)\r
+\r
+#define UXGA_V_SYNC                       (  4 - 1)\r
+#define UXGA_V_FRONT_PORCH                (  3 - 1)\r
+#define UXGA_V_BACK_PORCH                 ( 38 - 1)\r
+\r
+//\r
+// HD Mode: 1920 x 1080\r
+//\r
+#define HD_H_RES_PIXELS                   1920\r
+#define HD_V_RES_PIXELS                   1080\r
+#define HD_OSC_FREQUENCY                  173000000  /* 0x0A4FC540 */\r
+\r
+#define HD_H_SYNC                         (200 - 1)\r
+#define HD_H_FRONT_PORCH                  (128 - 1)\r
+#define HD_H_BACK_PORCH                   (328 - 1)\r
+\r
+#define HD_V_SYNC                         (  5 - 1)\r
+#define HD_V_FRONT_PORCH                  (  3 - 1)\r
+#define HD_V_BACK_PORCH                   ( 32 - 1)\r
+\r
+//\r
+// Colour Masks\r
+//\r
+\r
+#define LCD_24BPP_RED_MASK              0x00FF0000\r
+#define LCD_24BPP_GREEN_MASK            0x0000FF00\r
+#define LCD_24BPP_BLUE_MASK             0x000000FF\r
+#define LCD_24BPP_RESERVED_MASK         0xFF000000\r
+\r
+#define LCD_16BPP_555_RED_MASK          0x00007C00\r
+#define LCD_16BPP_555_GREEN_MASK        0x000003E0\r
+#define LCD_16BPP_555_BLUE_MASK         0x0000001F\r
+#define LCD_16BPP_555_RESERVED_MASK     0x00000000\r
+\r
+#define LCD_16BPP_565_RED_MASK          0x0000F800\r
+#define LCD_16BPP_565_GREEN_MASK        0x000007E0\r
+#define LCD_16BPP_565_BLUE_MASK         0x0000001F\r
+#define LCD_16BPP_565_RESERVED_MASK     0x00008000\r
+\r
+#define LCD_12BPP_444_RED_MASK          0x00000F00\r
+#define LCD_12BPP_444_GREEN_MASK        0x000000F0\r
+#define LCD_12BPP_444_BLUE_MASK         0x0000000F\r
+#define LCD_12BPP_444_RESERVED_MASK     0x0000F000\r
+\r
+\r
+// The enumeration indexes maps the PL111 LcdBpp values used in the LCD Control Register\r
+typedef enum {\r
+  LCD_BITS_PER_PIXEL_1 = 0,\r
+  LCD_BITS_PER_PIXEL_2,\r
+  LCD_BITS_PER_PIXEL_4,\r
+  LCD_BITS_PER_PIXEL_8,\r
+  LCD_BITS_PER_PIXEL_16_555,\r
+  LCD_BITS_PER_PIXEL_24,\r
+  LCD_BITS_PER_PIXEL_16_565,\r
+  LCD_BITS_PER_PIXEL_12_444\r
+} LCD_BPP;\r
+\r
+\r
+EFI_STATUS\r
+LcdPlatformInitializeDisplay (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+LcdPlatformGetVram (\r
+  OUT EFI_PHYSICAL_ADDRESS*                 VramBaseAddress,\r
+  OUT UINTN*                                VramSize\r
+  );\r
+\r
+UINT32\r
+LcdPlatformGetMaxMode (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+LcdPlatformSetMode (\r
+  IN UINT32                                 ModeNumber\r
+  );\r
+\r
+EFI_STATUS\r
+LcdPlatformQueryMode (\r
+  IN  UINT32                                ModeNumber,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info\r
+  );\r
+\r
+EFI_STATUS\r
+LcdPlatformGetTimings (\r
+  IN  UINT32                              ModeNumber,\r
+  OUT UINT32*                             HRes,\r
+  OUT UINT32*                             HSync,\r
+  OUT UINT32*                             HBackPorch,\r
+  OUT UINT32*                             HFrontPorch,\r
+  OUT UINT32*                             VRes,\r
+  OUT UINT32*                             VSync,\r
+  OUT UINT32*                             VBackPorch,\r
+  OUT UINT32*                             VFrontPorch\r
+  );\r
+\r
+EFI_STATUS\r
+LcdPlatformGetBpp (\r
+  IN  UINT32                                ModeNumber,\r
+  OUT LCD_BPP*                              Bpp\r
+  );\r
+\r
+#endif\r