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