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