1 /**
2 
3   Copyright (c) 2012, ARM Ltd. All rights reserved.
4 
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <PiDxe.h>
16 
17 #include <Library/ArmPlatformSysConfigLib.h>
18 #include <Library/IoLib.h>
19 #include <Library/PcdLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/LcdPlatformLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 
25 #include <Protocol/Cpu.h>
26 #include <Protocol/EdidDiscovered.h>
27 #include <Protocol/EdidActive.h>
28 
29 #include <ArmPlatform.h>
30 
31 typedef struct {
32   UINT32                     Mode;
33   UINT32                     HorizontalResolution;
34   UINT32                     VerticalResolution;
35   LCD_BPP                    Bpp;
36   UINT32                     OscFreq;
37 
38   // These are used by HDLCD
39   UINT32                     HSync;
40   UINT32                     HBackPorch;
41   UINT32                     HFrontPorch;
42   UINT32                     VSync;
43   UINT32                     VBackPorch;
44   UINT32                     VFrontPorch;
45 } LCD_RESOLUTION;
46 
47 
48 LCD_RESOLUTION mResolutions[] = {
49   { // Mode 0 : VGA : 640 x 480 x 24 bpp
50     VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, VGA_OSC_FREQUENCY,
51     VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
52     VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
53   },
54   { // Mode 1 : SVGA : 800 x 600 x 24 bpp
55     SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, SVGA_OSC_FREQUENCY,
56     SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
57     SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
58   },
59   { // Mode 2 : XGA : 1024 x 768 x 24 bpp
60     XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, XGA_OSC_FREQUENCY,
61     XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
62     XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
63   },
64   { // Mode 3 : SXGA : 1280 x 1024 x 24 bpp
65     SXGA, SXGA_H_RES_PIXELS, SXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (SXGA_OSC_FREQUENCY/2),
66     SXGA_H_SYNC, SXGA_H_BACK_PORCH, SXGA_H_FRONT_PORCH,
67     SXGA_V_SYNC, SXGA_V_BACK_PORCH, SXGA_V_FRONT_PORCH
68   },
69   { // Mode 4 : UXGA : 1600 x 1200 x 24 bpp
70     UXGA, UXGA_H_RES_PIXELS, UXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (UXGA_OSC_FREQUENCY/2),
71     UXGA_H_SYNC, UXGA_H_BACK_PORCH, UXGA_H_FRONT_PORCH,
72     UXGA_V_SYNC, UXGA_V_BACK_PORCH, UXGA_V_FRONT_PORCH
73   },
74   { // Mode 5 : HD : 1920 x 1080 x 24 bpp
75     HD, HD_H_RES_PIXELS, HD_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (HD_OSC_FREQUENCY/2),
76     HD_H_SYNC, HD_H_BACK_PORCH, HD_H_FRONT_PORCH,
77     HD_V_SYNC, HD_V_BACK_PORCH, HD_V_FRONT_PORCH
78   }
79 };
80 
81 EFI_EDID_DISCOVERED_PROTOCOL  mEdidDiscovered = {
82   0,
83   NULL
84 };
85 
86 EFI_EDID_ACTIVE_PROTOCOL      mEdidActive = {
87   0,
88   NULL
89 };
90 
91 EFI_STATUS
LcdPlatformInitializeDisplay(IN EFI_HANDLE Handle)92 LcdPlatformInitializeDisplay (
93   IN EFI_HANDLE   Handle
94   )
95 {
96   EFI_STATUS  Status;
97 
98   // Set the FPGA multiplexer to select the video output from the motherboard or the daughterboard
99   Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, ARM_VE_DAUGHTERBOARD_1_SITE);
100   if (EFI_ERROR(Status)) {
101     return Status;
102   }
103 
104   // Install the EDID Protocols
105   Status = gBS->InstallMultipleProtocolInterfaces (
106     &Handle,
107     &gEfiEdidDiscoveredProtocolGuid,  &mEdidDiscovered,
108     &gEfiEdidActiveProtocolGuid,      &mEdidActive,
109     NULL
110   );
111 
112   return Status;
113 }
114 
115 EFI_STATUS
LcdPlatformGetVram(OUT EFI_PHYSICAL_ADDRESS * VramBaseAddress,OUT UINTN * VramSize)116 LcdPlatformGetVram (
117   OUT EFI_PHYSICAL_ADDRESS*  VramBaseAddress,
118   OUT UINTN*                 VramSize
119   )
120 {
121   EFI_STATUS              Status;
122   EFI_CPU_ARCH_PROTOCOL  *Cpu;
123   EFI_ALLOCATE_TYPE       AllocationType;
124 
125   // Set the vram size
126   *VramSize = LCD_VRAM_SIZE;
127 
128   *VramBaseAddress = (EFI_PHYSICAL_ADDRESS)LCD_VRAM_CORE_TILE_BASE;
129 
130   // Allocate the VRAM from the DRAM so that nobody else uses it.
131   if (*VramBaseAddress == 0) {
132     AllocationType = AllocateAnyPages;
133   } else {
134     AllocationType = AllocateAddress;
135   }
136   Status = gBS->AllocatePages (AllocationType, EfiBootServicesData, EFI_SIZE_TO_PAGES(((UINTN)LCD_VRAM_SIZE)), VramBaseAddress);
137   if (EFI_ERROR(Status)) {
138     return Status;
139   }
140 
141   // Ensure the Cpu architectural protocol is already installed
142   Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
143   ASSERT_EFI_ERROR(Status);
144 
145   // Mark the VRAM as un-cacheable. The VRAM is inside the DRAM, which is cacheable.
146   Status = Cpu->SetMemoryAttributes (Cpu, *VramBaseAddress, *VramSize, EFI_MEMORY_UC);
147   ASSERT_EFI_ERROR(Status);
148   if (EFI_ERROR(Status)) {
149     gBS->FreePool (VramBaseAddress);
150     return Status;
151   }
152 
153   return EFI_SUCCESS;
154 }
155 
156 UINT32
LcdPlatformGetMaxMode(VOID)157 LcdPlatformGetMaxMode (
158   VOID
159   )
160 {
161   //
162   // The following line will report correctly the total number of graphics modes
163   // that could be supported by the graphics driver:
164   //
165   return (sizeof(mResolutions) / sizeof(LCD_RESOLUTION));
166 }
167 
168 EFI_STATUS
LcdPlatformSetMode(IN UINT32 ModeNumber)169 LcdPlatformSetMode (
170   IN UINT32                         ModeNumber
171   )
172 {
173   EFI_STATUS            Status;
174 
175   if (ModeNumber >= LcdPlatformGetMaxMode ()) {
176     return EFI_INVALID_PARAMETER;
177   }
178 
179   // Set the video mode oscillator
180   do {
181     Status = ArmPlatformSysConfigSetDevice (SYS_CFG_OSC_SITE1, PcdGet32(PcdHdLcdVideoModeOscId), mResolutions[ModeNumber].OscFreq);
182   } while (Status == EFI_TIMEOUT);
183   if (EFI_ERROR(Status)) {
184     ASSERT_EFI_ERROR (Status);
185     return Status;
186   }
187 
188   // Set the DVI into the new mode
189   do {
190     Status = ArmPlatformSysConfigSet (SYS_CFG_DVIMODE, mResolutions[ModeNumber].Mode);
191   } while (Status == EFI_TIMEOUT);
192   if (EFI_ERROR(Status)) {
193     ASSERT_EFI_ERROR (Status);
194     return Status;
195   }
196 
197   // Set the multiplexer
198   Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, ARM_VE_DAUGHTERBOARD_1_SITE);
199   if (EFI_ERROR(Status)) {
200     ASSERT_EFI_ERROR (Status);
201     return Status;
202   }
203 
204   return Status;
205 }
206 
207 EFI_STATUS
LcdPlatformQueryMode(IN UINT32 ModeNumber,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info)208 LcdPlatformQueryMode (
209   IN  UINT32                                ModeNumber,
210   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
211   )
212 {
213   if (ModeNumber >= LcdPlatformGetMaxMode ()) {
214     return EFI_INVALID_PARAMETER;
215   }
216 
217   Info->Version = 0;
218   Info->HorizontalResolution = mResolutions[ModeNumber].HorizontalResolution;
219   Info->VerticalResolution = mResolutions[ModeNumber].VerticalResolution;
220   Info->PixelsPerScanLine = mResolutions[ModeNumber].HorizontalResolution;
221 
222   switch (mResolutions[ModeNumber].Bpp) {
223     case LCD_BITS_PER_PIXEL_24:
224       Info->PixelFormat                   = PixelRedGreenBlueReserved8BitPerColor;
225       Info->PixelInformation.RedMask      = LCD_24BPP_RED_MASK;
226       Info->PixelInformation.GreenMask    = LCD_24BPP_GREEN_MASK;
227       Info->PixelInformation.BlueMask     = LCD_24BPP_BLUE_MASK;
228       Info->PixelInformation.ReservedMask = LCD_24BPP_RESERVED_MASK;
229       break;
230 
231     case LCD_BITS_PER_PIXEL_16_555:
232     case LCD_BITS_PER_PIXEL_16_565:
233     case LCD_BITS_PER_PIXEL_12_444:
234     case LCD_BITS_PER_PIXEL_8:
235     case LCD_BITS_PER_PIXEL_4:
236     case LCD_BITS_PER_PIXEL_2:
237     case LCD_BITS_PER_PIXEL_1:
238     default:
239       // These are not supported
240       ASSERT(FALSE);
241       break;
242   }
243 
244   return EFI_SUCCESS;
245 }
246 
247 EFI_STATUS
LcdPlatformGetTimings(IN UINT32 ModeNumber,OUT UINT32 * HRes,OUT UINT32 * HSync,OUT UINT32 * HBackPorch,OUT UINT32 * HFrontPorch,OUT UINT32 * VRes,OUT UINT32 * VSync,OUT UINT32 * VBackPorch,OUT UINT32 * VFrontPorch)248 LcdPlatformGetTimings (
249   IN  UINT32                              ModeNumber,
250   OUT UINT32*                             HRes,
251   OUT UINT32*                             HSync,
252   OUT UINT32*                             HBackPorch,
253   OUT UINT32*                             HFrontPorch,
254   OUT UINT32*                             VRes,
255   OUT UINT32*                             VSync,
256   OUT UINT32*                             VBackPorch,
257   OUT UINT32*                             VFrontPorch
258   )
259 {
260   if (ModeNumber >= LcdPlatformGetMaxMode ()) {
261     return EFI_INVALID_PARAMETER;
262   }
263 
264   *HRes           = mResolutions[ModeNumber].HorizontalResolution;
265   *HSync          = mResolutions[ModeNumber].HSync;
266   *HBackPorch     = mResolutions[ModeNumber].HBackPorch;
267   *HFrontPorch    = mResolutions[ModeNumber].HFrontPorch;
268   *VRes           = mResolutions[ModeNumber].VerticalResolution;
269   *VSync          = mResolutions[ModeNumber].VSync;
270   *VBackPorch     = mResolutions[ModeNumber].VBackPorch;
271   *VFrontPorch    = mResolutions[ModeNumber].VFrontPorch;
272 
273   return EFI_SUCCESS;
274 }
275 
276 EFI_STATUS
LcdPlatformGetBpp(IN UINT32 ModeNumber,OUT LCD_BPP * Bpp)277 LcdPlatformGetBpp (
278   IN  UINT32                              ModeNumber,
279   OUT LCD_BPP  *                          Bpp
280   )
281 {
282   if (ModeNumber >= LcdPlatformGetMaxMode ()) {
283     return EFI_INVALID_PARAMETER;
284   }
285 
286   *Bpp = mResolutions[ModeNumber].Bpp;
287 
288   return EFI_SUCCESS;
289 }
290