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