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