1 /** @file
2
3 Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #include <PiDxe.h>
15
16 #include <Library/ArmPlatformSysConfigLib.h>
17 #include <Library/IoLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/LcdPlatformLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22
23 #include <Protocol/Cpu.h>
24 #include <Protocol/EdidDiscovered.h>
25 #include <Protocol/EdidActive.h>
26
27 #include <ArmPlatform.h>
28
29 typedef struct {
30 UINT32 Mode;
31 UINT32 HorizontalResolution;
32 UINT32 VerticalResolution;
33 LCD_BPP Bpp;
34 UINT32 OscFreq;
35
36 UINT32 HSync;
37 UINT32 HBackPorch;
38 UINT32 HFrontPorch;
39 UINT32 VSync;
40 UINT32 VBackPorch;
41 UINT32 VFrontPorch;
42 } LCD_RESOLUTION;
43
44
45 LCD_RESOLUTION mResolutions[] = {
46 { // Mode 0 : VGA : 640 x 480 x 24 bpp
47 VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, VGA_OSC_FREQUENCY,
48 VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
49 VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
50 },
51 { // Mode 1 : SVGA : 800 x 600 x 24 bpp
52 SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, SVGA_OSC_FREQUENCY,
53 SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
54 SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
55 },
56 { // Mode 2 : XGA : 1024 x 768 x 24 bpp
57 XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, XGA_OSC_FREQUENCY,
58 XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
59 XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
60 },
61 { // Mode 3 : SXGA : 1280 x 1024 x 24 bpp
62 SXGA, SXGA_H_RES_PIXELS, SXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (SXGA_OSC_FREQUENCY/2),
63 SXGA_H_SYNC, SXGA_H_BACK_PORCH, SXGA_H_FRONT_PORCH,
64 SXGA_V_SYNC, SXGA_V_BACK_PORCH, SXGA_V_FRONT_PORCH
65 },
66 { // Mode 4 : UXGA : 1600 x 1200 x 24 bpp
67 UXGA, UXGA_H_RES_PIXELS, UXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (UXGA_OSC_FREQUENCY/2),
68 UXGA_H_SYNC, UXGA_H_BACK_PORCH, UXGA_H_FRONT_PORCH,
69 UXGA_V_SYNC, UXGA_V_BACK_PORCH, UXGA_V_FRONT_PORCH
70 },
71 { // Mode 5 : HD : 1920 x 1080 x 24 bpp
72 HD, HD_H_RES_PIXELS, HD_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (HD_OSC_FREQUENCY/2),
73 HD_H_SYNC, HD_H_BACK_PORCH, HD_H_FRONT_PORCH,
74 HD_V_SYNC, HD_V_BACK_PORCH, HD_V_FRONT_PORCH
75 },
76 { // Mode 6 : VGA : 640 x 480 x 16 bpp (565 Mode)
77 VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, VGA_OSC_FREQUENCY,
78 VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
79 VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
80 },
81 { // Mode 7 : SVGA : 800 x 600 x 16 bpp (565 Mode)
82 SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, SVGA_OSC_FREQUENCY,
83 SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
84 SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
85 },
86 { // Mode 8 : XGA : 1024 x 768 x 16 bpp (565 Mode)
87 XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, XGA_OSC_FREQUENCY,
88 XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
89 XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
90 },
91 { // Mode 9 : VGA : 640 x 480 x 15 bpp
92 VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, VGA_OSC_FREQUENCY,
93 VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
94 VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
95 },
96 { // Mode 10 : SVGA : 800 x 600 x 15 bpp
97 SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, SVGA_OSC_FREQUENCY,
98 SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
99 SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
100 },
101 { // Mode 11 : XGA : 1024 x 768 x 15 bpp
102 XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, XGA_OSC_FREQUENCY,
103 XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
104 XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
105 },
106 { // Mode 12 : XGA : 1024 x 768 x 15 bpp - All the timing info is derived from Linux Kernel Driver Settings
107 XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, 63500000,
108 XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
109 XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
110 },
111 { // Mode 13 : VGA : 640 x 480 x 12 bpp (444 Mode)
112 VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, VGA_OSC_FREQUENCY,
113 VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
114 VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
115 },
116 { // Mode 14 : SVGA : 800 x 600 x 12 bpp (444 Mode)
117 SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, SVGA_OSC_FREQUENCY,
118 SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
119 SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
120 },
121 { // Mode 15 : XGA : 1024 x 768 x 12 bpp (444 Mode)
122 XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, XGA_OSC_FREQUENCY,
123 XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
124 XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
125 }
126 };
127
128 EFI_EDID_DISCOVERED_PROTOCOL mEdidDiscovered = {
129 0,
130 NULL
131 };
132
133 EFI_EDID_ACTIVE_PROTOCOL mEdidActive = {
134 0,
135 NULL
136 };
137
138
139 EFI_STATUS
LcdPlatformInitializeDisplay(IN EFI_HANDLE Handle)140 LcdPlatformInitializeDisplay (
141 IN EFI_HANDLE Handle
142 )
143 {
144 EFI_STATUS Status;
145
146 // Set the FPGA multiplexer to select the video output from the motherboard or the daughterboard
147 Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, PL111_CLCD_SITE);
148 if (!EFI_ERROR(Status)) {
149 // Install the EDID Protocols
150 Status = gBS->InstallMultipleProtocolInterfaces(
151 &Handle,
152 &gEfiEdidDiscoveredProtocolGuid, &mEdidDiscovered,
153 &gEfiEdidActiveProtocolGuid, &mEdidActive,
154 NULL
155 );
156 }
157
158 return Status;
159 }
160
161 EFI_STATUS
LcdPlatformGetVram(OUT EFI_PHYSICAL_ADDRESS * VramBaseAddress,OUT UINTN * VramSize)162 LcdPlatformGetVram (
163 OUT EFI_PHYSICAL_ADDRESS* VramBaseAddress,
164 OUT UINTN* VramSize
165 )
166 {
167 EFI_STATUS Status;
168 EFI_CPU_ARCH_PROTOCOL *Cpu;
169
170 Status = EFI_SUCCESS;
171
172 // Is it on the motherboard or on the daughterboard?
173 switch(PL111_CLCD_SITE) {
174
175 case ARM_VE_MOTHERBOARD_SITE:
176 *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) PL111_CLCD_VRAM_MOTHERBOARD_BASE;
177 *VramSize = LCD_VRAM_SIZE;
178 break;
179
180 case ARM_VE_DAUGHTERBOARD_1_SITE:
181 *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) LCD_VRAM_CORE_TILE_BASE;
182 *VramSize = LCD_VRAM_SIZE;
183
184 // Allocate the VRAM from the DRAM so that nobody else uses it.
185 Status = gBS->AllocatePages( AllocateAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(((UINTN)LCD_VRAM_SIZE)), VramBaseAddress);
186 if (EFI_ERROR(Status)) {
187 return Status;
188 }
189
190 // Ensure the Cpu architectural protocol is already installed
191 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
192 ASSERT_EFI_ERROR(Status);
193
194 // Mark the VRAM as un-cachable. The VRAM is inside the DRAM, which is cachable.
195 Status = Cpu->SetMemoryAttributes(Cpu, *VramBaseAddress, *VramSize, EFI_MEMORY_UC);
196 ASSERT_EFI_ERROR(Status);
197 if (EFI_ERROR(Status)) {
198 gBS->FreePool(VramBaseAddress);
199 return Status;
200 }
201 break;
202
203 default:
204 // Unsupported site
205 Status = EFI_UNSUPPORTED;
206 break;
207 }
208
209 return Status;
210 }
211
212 UINT32
LcdPlatformGetMaxMode(VOID)213 LcdPlatformGetMaxMode (
214 VOID
215 )
216 {
217 // The following line will report correctly the total number of graphics modes
218 // supported by the PL111CLCD.
219 //return (sizeof(mResolutions) / sizeof(CLCD_RESOLUTION)) - 1;
220
221 // However, on some platforms it is desirable to ignore some graphics modes.
222 // This could be because the specific implementation of PL111 has certain limitations.
223
224 // Set the maximum mode allowed
225 return (PcdGet32(PcdPL111LcdMaxMode));
226 }
227
228 EFI_STATUS
LcdPlatformSetMode(IN UINT32 ModeNumber)229 LcdPlatformSetMode (
230 IN UINT32 ModeNumber
231 )
232 {
233 EFI_STATUS Status;
234 UINT32 LcdSite;
235 UINT32 OscillatorId;
236 SYS_CONFIG_FUNCTION Function;
237 UINT32 SysId;
238
239 if (ModeNumber >= LcdPlatformGetMaxMode ()) {
240 return EFI_INVALID_PARAMETER;
241 }
242
243 LcdSite = PL111_CLCD_SITE;
244
245 switch(LcdSite) {
246 case ARM_VE_MOTHERBOARD_SITE:
247 Function = SYS_CFG_OSC;
248 OscillatorId = PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID;
249 break;
250 case ARM_VE_DAUGHTERBOARD_1_SITE:
251 Function = SYS_CFG_OSC_SITE1;
252 OscillatorId = (UINT32)PcdGet32(PcdPL111LcdVideoModeOscId);
253 break;
254 default:
255 return EFI_UNSUPPORTED;
256 }
257
258 // Set the video mode oscillator
259 Status = ArmPlatformSysConfigSetDevice (Function, OscillatorId, mResolutions[ModeNumber].OscFreq);
260 if (EFI_ERROR(Status)) {
261 ASSERT_EFI_ERROR (Status);
262 return Status;
263 }
264
265 // The FVP foundation model does not have an LCD.
266 // On the FVP models the GIC variant in encoded in bits [15:12].
267 // Note: The DVI Mode is not modelled by RTSM or FVP models.
268 SysId = MmioRead32 (ARM_VE_SYS_ID_REG);
269 if (SysId != ARM_RTSM_SYS_ID) {
270 // Take out the FVP GIC variant to reduce the permutations.
271 SysId &= ~ARM_FVP_SYS_ID_VARIANT_MASK;
272 if (SysId != ARM_FVP_BASE_BOARD_SYS_ID) {
273 // Set the DVI into the new mode
274 Status = ArmPlatformSysConfigSet (SYS_CFG_DVIMODE, mResolutions[ModeNumber].Mode);
275 if (EFI_ERROR(Status)) {
276 ASSERT_EFI_ERROR (Status);
277 return Status;
278 }
279 }
280 }
281
282 // Set the multiplexer
283 Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, LcdSite);
284 if (EFI_ERROR(Status)) {
285 ASSERT_EFI_ERROR (Status);
286 return Status;
287 }
288
289 return Status;
290 }
291
292 EFI_STATUS
LcdPlatformQueryMode(IN UINT32 ModeNumber,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info)293 LcdPlatformQueryMode (
294 IN UINT32 ModeNumber,
295 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
296 )
297 {
298 if (ModeNumber >= LcdPlatformGetMaxMode ()) {
299 return EFI_INVALID_PARAMETER;
300 }
301
302 Info->Version = 0;
303 Info->HorizontalResolution = mResolutions[ModeNumber].HorizontalResolution;
304 Info->VerticalResolution = mResolutions[ModeNumber].VerticalResolution;
305 Info->PixelsPerScanLine = mResolutions[ModeNumber].HorizontalResolution;
306
307 switch (mResolutions[ModeNumber].Bpp) {
308 case LCD_BITS_PER_PIXEL_24:
309 Info->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
310 Info->PixelInformation.RedMask = LCD_24BPP_RED_MASK;
311 Info->PixelInformation.GreenMask = LCD_24BPP_GREEN_MASK;
312 Info->PixelInformation.BlueMask = LCD_24BPP_BLUE_MASK;
313 Info->PixelInformation.ReservedMask = LCD_24BPP_RESERVED_MASK;
314 break;
315
316 case LCD_BITS_PER_PIXEL_16_555:
317 case LCD_BITS_PER_PIXEL_16_565:
318 case LCD_BITS_PER_PIXEL_12_444:
319 case LCD_BITS_PER_PIXEL_8:
320 case LCD_BITS_PER_PIXEL_4:
321 case LCD_BITS_PER_PIXEL_2:
322 case LCD_BITS_PER_PIXEL_1:
323 default:
324 // These are not supported
325 ASSERT(FALSE);
326 break;
327 }
328
329 return EFI_SUCCESS;
330 }
331
332 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)333 LcdPlatformGetTimings (
334 IN UINT32 ModeNumber,
335 OUT UINT32* HRes,
336 OUT UINT32* HSync,
337 OUT UINT32* HBackPorch,
338 OUT UINT32* HFrontPorch,
339 OUT UINT32* VRes,
340 OUT UINT32* VSync,
341 OUT UINT32* VBackPorch,
342 OUT UINT32* VFrontPorch
343 )
344 {
345 if (ModeNumber >= LcdPlatformGetMaxMode ()) {
346 return EFI_INVALID_PARAMETER;
347 }
348
349 *HRes = mResolutions[ModeNumber].HorizontalResolution;
350 *HSync = mResolutions[ModeNumber].HSync;
351 *HBackPorch = mResolutions[ModeNumber].HBackPorch;
352 *HFrontPorch = mResolutions[ModeNumber].HFrontPorch;
353 *VRes = mResolutions[ModeNumber].VerticalResolution;
354 *VSync = mResolutions[ModeNumber].VSync;
355 *VBackPorch = mResolutions[ModeNumber].VBackPorch;
356 *VFrontPorch = mResolutions[ModeNumber].VFrontPorch;
357
358 return EFI_SUCCESS;
359 }
360
361 EFI_STATUS
LcdPlatformGetBpp(IN UINT32 ModeNumber,OUT LCD_BPP * Bpp)362 LcdPlatformGetBpp (
363 IN UINT32 ModeNumber,
364 OUT LCD_BPP * Bpp
365 )
366 {
367 if (ModeNumber >= LcdPlatformGetMaxMode ()) {
368 return EFI_INVALID_PARAMETER;
369 }
370
371 *Bpp = mResolutions[ModeNumber].Bpp;
372
373 return EFI_SUCCESS;
374 }
375