]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
ArmPlatformPkg/SP804TimerLib: Checked both Metronome and Performance timers are initi...
[mirror_edk2.git] / ArmPlatformPkg / Drivers / LcdGraphicsOutputDxe / LcdGraphicsOutputDxe.c
CommitLineData
1e57a462 1/** @file\r
2\r
3 Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12 **/\r
13\r
14#include <PiDxe.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/DevicePathLib.h>\r
17#include <Library/UefiBootServicesTableLib.h>\r
18#include <Library/UefiRuntimeServicesTableLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20\r
21#include <Guid/GlobalVariable.h>\r
22\r
23#include "LcdGraphicsOutputDxe.h"\r
24\r
25/**********************************************************************\r
26 *\r
27 * This file implements the Graphics Output protocol on ArmVersatileExpress\r
28 * using the Lcd controller\r
29 *\r
30 **********************************************************************/\r
31\r
32//\r
33// Global variables\r
34//\r
35\r
36BOOLEAN mDisplayInitialized = FALSE;\r
37\r
38LCD_INSTANCE mLcdTemplate = {\r
39 LCD_INSTANCE_SIGNATURE,\r
40 NULL, // Handle\r
41 { // ModeInfo\r
42 0, // Version\r
43 0, // HorizontalResolution\r
44 0, // VerticalResolution\r
45 PixelBltOnly, // PixelFormat\r
46 0, // PixelInformation\r
47 0, // PixelsPerScanLine\r
48 },\r
49 {\r
50 0, // MaxMode;\r
51 0, // Mode;\r
52 NULL, // Info;\r
53 0, // SizeOfInfo;\r
54 0, // FrameBufferBase;\r
55 0 // FrameBufferSize;\r
56 },\r
57 { // Gop\r
58 LcdGraphicsQueryMode, // QueryMode\r
59 LcdGraphicsSetMode, // SetMode\r
60 LcdGraphicsBlt, // Blt\r
61 NULL // *Mode\r
62 },\r
63 { // DevicePath\r
64 {\r
65 {\r
66 HARDWARE_DEVICE_PATH, HW_VENDOR_DP,\r
67 (UINT8) (sizeof(VENDOR_DEVICE_PATH)),\r
68 (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8),\r
69 },\r
70 // Hardware Device Path for Lcd\r
71 EFI_CALLER_ID_GUID // Use the driver's GUID\r
72 },\r
73\r
74 {\r
75 END_DEVICE_PATH_TYPE,\r
76 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
77 sizeof(EFI_DEVICE_PATH_PROTOCOL),\r
78 0\r
79 }\r
80 },\r
81 (EFI_EVENT) NULL // ExitBootServicesEvent\r
82};\r
83\r
84EFI_STATUS\r
85LcdInstanceContructor (\r
86 OUT LCD_INSTANCE** NewInstance\r
87 )\r
88{\r
89 LCD_INSTANCE* Instance;\r
90\r
91 Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);\r
92 if (Instance == NULL) {\r
93 return EFI_OUT_OF_RESOURCES;\r
94 }\r
95\r
96 Instance->Gop.Mode = &Instance->Mode;\r
97 Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();\r
98 Instance->Mode.Info = &Instance->ModeInfo;\r
99\r
100 *NewInstance = Instance;\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104//\r
105// Function Definitions\r
106//\r
107\r
108EFI_STATUS\r
109InitializeDisplay (\r
110 IN LCD_INSTANCE* Instance\r
111 )\r
112{\r
113 EFI_STATUS Status = EFI_SUCCESS;\r
114 EFI_PHYSICAL_ADDRESS VramBaseAddress;\r
115 UINTN VramSize;\r
116\r
117 Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);\r
118 if (EFI_ERROR(Status)) {\r
119 return Status;\r
120 }\r
121\r
122 // Setup the LCD\r
123 Status = LcdInitialize (VramBaseAddress);\r
124 if (EFI_ERROR(Status)) {\r
125 goto EXIT_ERROR_LCD_SHUTDOWN;\r
126 }\r
127\r
128 Status = LcdPlatformInitializeDisplay (Instance->Handle);\r
129 if (EFI_ERROR(Status)) {\r
130 goto EXIT_ERROR_LCD_SHUTDOWN;\r
131 }\r
132\r
133 // Setup all the relevant mode information\r
134 Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
135 Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;\r
1e57a462 136\r
137 // Set the flag before changing the mode, to avoid infinite loops\r
138 mDisplayInitialized = TRUE;\r
139\r
140 // All is ok, so don't deal with any errors\r
141 goto EXIT;\r
142\r
143EXIT_ERROR_LCD_SHUTDOWN:\r
144 DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));\r
145 LcdShutdown ();\r
146\r
147EXIT:\r
148 return Status;\r
149}\r
150\r
151EFI_STATUS\r
152EFIAPI\r
153LcdGraphicsOutputDxeInitialize (\r
154 IN EFI_HANDLE ImageHandle,\r
155 IN EFI_SYSTEM_TABLE *SystemTable\r
156 )\r
157{\r
158 EFI_STATUS Status = EFI_SUCCESS;\r
159 LCD_INSTANCE* Instance;\r
160\r
161 Status = LcdInstanceContructor (&Instance);\r
162 if (EFI_ERROR(Status)) {\r
163 goto EXIT;\r
164 }\r
165\r
166 // Install the Graphics Output Protocol and the Device Path\r
167 Status = gBS->InstallMultipleProtocolInterfaces(\r
168 &Instance->Handle,\r
169 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,\r
170 &gEfiDevicePathProtocolGuid, &Instance->DevicePath,\r
171 NULL\r
172 );\r
173\r
174 if (EFI_ERROR(Status)) {\r
175 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));\r
176 goto EXIT;\r
177 }\r
178\r
179 // Register for an ExitBootServicesEvent\r
180 // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,\r
181 // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.\r
182 Status = gBS->CreateEvent (\r
183 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
184 TPL_NOTIFY,\r
185 LcdGraphicsExitBootServicesEvent, NULL,\r
186 &Instance->ExitBootServicesEvent\r
187 );\r
188\r
189 if (EFI_ERROR(Status)) {\r
190 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));\r
191 goto EXIT_ERROR_UNINSTALL_PROTOCOL;\r
192 }\r
193\r
194 // To get here, everything must be fine, so just exit\r
195 goto EXIT;\r
196\r
197EXIT_ERROR_UNINSTALL_PROTOCOL:\r
198 /* The following function could return an error message,\r
199 * however, to get here something must have gone wrong already,\r
200 * so preserve the original error, i.e. don't change\r
201 * the Status variable, even it fails to uninstall the protocol.\r
202 */\r
203 gBS->UninstallMultipleProtocolInterfaces (\r
204 Instance->Handle,\r
205 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol\r
206 &gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path\r
207 NULL\r
208 );\r
209\r
210EXIT:\r
211 return Status;\r
212\r
213}\r
214\r
215/***************************************\r
216 * This function should be called\r
217 * on Event: ExitBootServices\r
218 * to free up memory, stop the driver\r
219 * and uninstall the protocols\r
220 ***************************************/\r
221VOID\r
222LcdGraphicsExitBootServicesEvent (\r
223 IN EFI_EVENT Event,\r
224 IN VOID *Context\r
225 )\r
226{\r
d8c4bb9a
OM
227 // By default, this PCD is FALSE. But if a platform starts a predefined OS that\r
228 // does not use a framebuffer then we might want to disable the display controller\r
229 // to avoid to display corrupted information on the screen.\r
230 if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {\r
231 // Turn-off the Display controller\r
232 LcdShutdown ();\r
233 }\r
1e57a462 234}\r
235\r
236/***************************************\r
237 * GraphicsOutput Protocol function, mapping to\r
238 * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode\r
239 ***************************************/\r
240EFI_STATUS\r
241EFIAPI\r
242LcdGraphicsQueryMode (\r
243 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
244 IN UINT32 ModeNumber,\r
245 OUT UINTN *SizeOfInfo,\r
246 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
247 )\r
248{\r
249 EFI_STATUS Status = EFI_SUCCESS;\r
250 LCD_INSTANCE *Instance;\r
251\r
252 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);\r
253\r
254 // Setup the hardware if not already done\r
255 if( !mDisplayInitialized ) {\r
256 Status = InitializeDisplay(Instance);\r
257 if (EFI_ERROR(Status)) {\r
258 goto EXIT;\r
259 }\r
260 }\r
261\r
262 // Error checking\r
263 if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {\r
264 DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));\r
265 Status = EFI_INVALID_PARAMETER;\r
266 goto EXIT;\r
267 }\r
268\r
269 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
270 if (*Info == NULL) {\r
271 Status = EFI_OUT_OF_RESOURCES;\r
272 goto EXIT;\r
273 }\r
274\r
275 *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
276\r
277 Status = LcdPlatformQueryMode (ModeNumber,*Info);\r
278 if (EFI_ERROR(Status)) {\r
279 FreePool(*Info);\r
280 }\r
281\r
282EXIT:\r
283 return Status;\r
284}\r
285\r
286/***************************************\r
287 * GraphicsOutput Protocol function, mapping to\r
288 * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode\r
289 ***************************************/\r
290EFI_STATUS\r
291EFIAPI\r
292LcdGraphicsSetMode (\r
293 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
294 IN UINT32 ModeNumber\r
295 )\r
296{\r
297 EFI_STATUS Status = EFI_SUCCESS;\r
298 EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;\r
1d7b547e
OM
299 LCD_INSTANCE* Instance;\r
300 LCD_BPP Bpp;\r
1e57a462 301\r
302 Instance = LCD_INSTANCE_FROM_GOP_THIS (This);\r
303\r
304 // Setup the hardware if not already done\r
305 if(!mDisplayInitialized) {\r
306 Status = InitializeDisplay (Instance);\r
307 if (EFI_ERROR(Status)) {\r
308 goto EXIT;\r
309 }\r
310 }\r
311\r
312 // Check if this mode is supported\r
313 if( ModeNumber >= This->Mode->MaxMode ) {\r
314 DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));\r
315 Status = EFI_UNSUPPORTED;\r
316 goto EXIT;\r
317 }\r
318\r
319 // Set the oscillator frequency to support the new mode\r
320 Status = LcdPlatformSetMode (ModeNumber);\r
321 if (EFI_ERROR(Status)) {\r
322 Status = EFI_DEVICE_ERROR;\r
323 goto EXIT;\r
324 }\r
325\r
326 // Update the UEFI mode information\r
327 This->Mode->Mode = ModeNumber;\r
328 LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);\r
1d7b547e
OM
329 Status = LcdPlatformGetBpp(ModeNumber, &Bpp);\r
330 if (EFI_ERROR(Status)) {\r
331 DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));\r
332 goto EXIT;\r
333 }\r
334 This->Mode->FrameBufferSize = Instance->ModeInfo.VerticalResolution\r
335 * Instance->ModeInfo.PixelsPerScanLine\r
336 * GetBytesPerPixel(Bpp);\r
1e57a462 337\r
338 // Set the hardware to the new mode\r
339 Status = LcdSetMode (ModeNumber);\r
340 if (EFI_ERROR(Status)) {\r
341 Status = EFI_DEVICE_ERROR;\r
342 goto EXIT;\r
343 }\r
344\r
345 // The UEFI spec requires that we now clear the visible portions of the output display to black.\r
346\r
347 // Set the fill colour to black\r
348 SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
349\r
350 // Fill the entire visible area with the same colour.\r
351 Status = This->Blt (\r
352 This,\r
353 &FillColour,\r
354 EfiBltVideoFill,\r
355 0,\r
356 0,\r
357 0,\r
358 0,\r
359 This->Mode->Info->HorizontalResolution,\r
360 This->Mode->Info->VerticalResolution,\r
361 0);\r
362\r
363EXIT:\r
364 return Status;\r
365}\r
366\r
367UINTN\r
368GetBytesPerPixel (\r
369 IN LCD_BPP Bpp\r
370 )\r
371{\r
372 switch(Bpp) {\r
373 case LCD_BITS_PER_PIXEL_24:\r
374 return 4;\r
375\r
376 case LCD_BITS_PER_PIXEL_16_565:\r
377 case LCD_BITS_PER_PIXEL_16_555:\r
378 case LCD_BITS_PER_PIXEL_12_444:\r
379 return 2;\r
380\r
381 case LCD_BITS_PER_PIXEL_8:\r
382 case LCD_BITS_PER_PIXEL_4:\r
383 case LCD_BITS_PER_PIXEL_2:\r
384 case LCD_BITS_PER_PIXEL_1:\r
385 return 1;\r
386\r
387 default:\r
388 return 0;\r
389 }\r
390}\r