]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
ArmPlatformPkg/PL180MciDxe: check PrimeCell ID before initializing
[mirror_edk2.git] / ArmPlatformPkg / Drivers / LcdGraphicsOutputDxe / LcdGraphicsOutputDxe.c
CommitLineData
1e57a462 1/** @file\r
2\r
b0fdce95 3 Copyright (c) 2011-2014, 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
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
b0fdce95 46 { 0 }, // PixelInformation\r
1e57a462 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
b0fdce95 67 { (UINT8) (sizeof(VENDOR_DEVICE_PATH)), (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8) },\r
1e57a462 68 },\r
69 // Hardware Device Path for Lcd\r
70 EFI_CALLER_ID_GUID // Use the driver's GUID\r
71 },\r
72\r
73 {\r
74 END_DEVICE_PATH_TYPE,\r
75 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
b0fdce95 76 { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }\r
1e57a462 77 }\r
78 },\r
79 (EFI_EVENT) NULL // ExitBootServicesEvent\r
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
89 Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);\r
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
116 if (EFI_ERROR(Status)) {\r
117 return Status;\r
118 }\r
119\r
120 // Setup the LCD\r
121 Status = LcdInitialize (VramBaseAddress);\r
122 if (EFI_ERROR(Status)) {\r
123 goto EXIT_ERROR_LCD_SHUTDOWN;\r
124 }\r
125\r
126 Status = LcdPlatformInitializeDisplay (Instance->Handle);\r
127 if (EFI_ERROR(Status)) {\r
128 goto EXIT_ERROR_LCD_SHUTDOWN;\r
129 }\r
130\r
131 // Setup all the relevant mode information\r
132 Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
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
142 DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));\r
143 LcdShutdown ();\r
144\r
145EXIT:\r
146 return Status;\r
147}\r
148\r
149EFI_STATUS\r
150EFIAPI\r
151LcdGraphicsOutputDxeInitialize (\r
152 IN EFI_HANDLE ImageHandle,\r
153 IN EFI_SYSTEM_TABLE *SystemTable\r
154 )\r
155{\r
156 EFI_STATUS Status = EFI_SUCCESS;\r
157 LCD_INSTANCE* Instance;\r
158\r
159 Status = LcdInstanceContructor (&Instance);\r
160 if (EFI_ERROR(Status)) {\r
161 goto EXIT;\r
162 }\r
163\r
91c38d4e
RC
164 // Install the Graphics Output Protocol and the Device Path\r
165 Status = gBS->InstallMultipleProtocolInterfaces(\r
166 &Instance->Handle,\r
167 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,\r
168 &gEfiDevicePathProtocolGuid, &Instance->DevicePath,\r
169 NULL\r
170 );\r
171\r
172 if (EFI_ERROR(Status)) {\r
173 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));\r
174 goto EXIT;\r
175 }\r
176\r
177 // Register for an ExitBootServicesEvent\r
178 // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,\r
179 // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.\r
180 Status = gBS->CreateEvent (\r
181 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
182 TPL_NOTIFY,\r
183 LcdGraphicsExitBootServicesEvent, NULL,\r
184 &Instance->ExitBootServicesEvent\r
185 );\r
186\r
187 if (EFI_ERROR(Status)) {\r
188 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));\r
189 goto EXIT_ERROR_UNINSTALL_PROTOCOL;\r
190 }\r
191\r
192 // To get here, everything must be fine, so just exit\r
193 goto EXIT;\r
1e57a462 194\r
195EXIT_ERROR_UNINSTALL_PROTOCOL:\r
91c38d4e
RC
196 /* The following function could return an error message,\r
197 * however, to get here something must have gone wrong already,\r
198 * so preserve the original error, i.e. don't change\r
199 * the Status variable, even it fails to uninstall the protocol.\r
200 */\r
201 gBS->UninstallMultipleProtocolInterfaces (\r
202 Instance->Handle,\r
203 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol\r
204 &gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path\r
205 NULL\r
206 );\r
1e57a462 207\r
208EXIT:\r
91c38d4e 209 return Status;\r
1e57a462 210\r
211}\r
212\r
213/***************************************\r
214 * This function should be called\r
215 * on Event: ExitBootServices\r
216 * to free up memory, stop the driver\r
217 * and uninstall the protocols\r
218 ***************************************/\r
219VOID\r
220LcdGraphicsExitBootServicesEvent (\r
221 IN EFI_EVENT Event,\r
222 IN VOID *Context\r
223 )\r
224{\r
d8c4bb9a
OM
225 // By default, this PCD is FALSE. But if a platform starts a predefined OS that\r
226 // does not use a framebuffer then we might want to disable the display controller\r
227 // to avoid to display corrupted information on the screen.\r
228 if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {\r
229 // Turn-off the Display controller\r
230 LcdShutdown ();\r
231 }\r
1e57a462 232}\r
233\r
234/***************************************\r
235 * GraphicsOutput Protocol function, mapping to\r
236 * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode\r
237 ***************************************/\r
238EFI_STATUS\r
239EFIAPI\r
240LcdGraphicsQueryMode (\r
241 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
91c38d4e
RC
242 IN UINT32 ModeNumber,\r
243 OUT UINTN *SizeOfInfo,\r
244 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
245 )\r
1e57a462 246{\r
91c38d4e
RC
247 EFI_STATUS Status = EFI_SUCCESS;\r
248 LCD_INSTANCE *Instance;\r
1e57a462 249\r
91c38d4e 250 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);\r
1e57a462 251\r
252 // Setup the hardware if not already done\r
253 if( !mDisplayInitialized ) {\r
254 Status = InitializeDisplay(Instance);\r
255 if (EFI_ERROR(Status)) {\r
256 goto EXIT;\r
257 }\r
258 }\r
259\r
91c38d4e
RC
260 // Error checking\r
261 if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {\r
262 DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));\r
263 Status = EFI_INVALID_PARAMETER;\r
264 goto EXIT;\r
265 }\r
1e57a462 266\r
91c38d4e 267 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
1e57a462 268 if (*Info == NULL) {\r
269 Status = EFI_OUT_OF_RESOURCES;\r
270 goto EXIT;\r
271 }\r
272\r
273 *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
274\r
275 Status = LcdPlatformQueryMode (ModeNumber,*Info);\r
276 if (EFI_ERROR(Status)) {\r
277 FreePool(*Info);\r
278 }\r
279\r
280EXIT:\r
91c38d4e 281 return Status;\r
1e57a462 282}\r
283\r
284/***************************************\r
285 * GraphicsOutput Protocol function, mapping to\r
286 * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode\r
287 ***************************************/\r
288EFI_STATUS\r
289EFIAPI\r
290LcdGraphicsSetMode (\r
291 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
91c38d4e
RC
292 IN UINT32 ModeNumber\r
293 )\r
1e57a462 294{\r
91c38d4e
RC
295 EFI_STATUS Status = EFI_SUCCESS;\r
296 EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;\r
297 LCD_INSTANCE* Instance;\r
298 LCD_BPP Bpp;\r
1e57a462 299\r
91c38d4e 300 Instance = LCD_INSTANCE_FROM_GOP_THIS (This);\r
1e57a462 301\r
302 // Setup the hardware if not already done\r
303 if(!mDisplayInitialized) {\r
304 Status = InitializeDisplay (Instance);\r
305 if (EFI_ERROR(Status)) {\r
306 goto EXIT;\r
307 }\r
308 }\r
309\r
310 // Check if this mode is supported\r
311 if( ModeNumber >= This->Mode->MaxMode ) {\r
312 DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));\r
313 Status = EFI_UNSUPPORTED;\r
314 goto EXIT;\r
315 }\r
316\r
91c38d4e 317 // Set the oscillator frequency to support the new mode\r
1e57a462 318 Status = LcdPlatformSetMode (ModeNumber);\r
319 if (EFI_ERROR(Status)) {\r
320 Status = EFI_DEVICE_ERROR;\r
321 goto EXIT;\r
322 }\r
323\r
91c38d4e
RC
324 // Update the UEFI mode information\r
325 This->Mode->Mode = ModeNumber;\r
326 LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);\r
327 Status = LcdPlatformGetBpp(ModeNumber, &Bpp);\r
328 if (EFI_ERROR(Status)) {\r
329 DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));\r
330 goto EXIT;\r
331 }\r
332 This->Mode->FrameBufferSize = Instance->ModeInfo.VerticalResolution\r
333 * Instance->ModeInfo.PixelsPerScanLine\r
334 * GetBytesPerPixel(Bpp);\r
1e57a462 335\r
336 // Set the hardware to the new mode\r
91c38d4e 337 Status = LcdSetMode (ModeNumber);\r
1e57a462 338 if (EFI_ERROR(Status)) {\r
339 Status = EFI_DEVICE_ERROR;\r
340 goto EXIT;\r
341 }\r
342\r
91c38d4e 343 // The UEFI spec requires that we now clear the visible portions of the output display to black.\r
1e57a462 344\r
345 // Set the fill colour to black\r
346 SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
347\r
348 // Fill the entire visible area with the same colour.\r
349 Status = This->Blt (\r
350 This,\r
351 &FillColour,\r
352 EfiBltVideoFill,\r
353 0,\r
354 0,\r
355 0,\r
356 0,\r
357 This->Mode->Info->HorizontalResolution,\r
358 This->Mode->Info->VerticalResolution,\r
359 0);\r
360\r
361EXIT:\r
91c38d4e 362 return Status;\r
1e57a462 363}\r
364\r
365UINTN\r
366GetBytesPerPixel (\r
367 IN LCD_BPP Bpp\r
368 )\r
369{\r
370 switch(Bpp) {\r
371 case LCD_BITS_PER_PIXEL_24:\r
372 return 4;\r
373\r
374 case LCD_BITS_PER_PIXEL_16_565:\r
375 case LCD_BITS_PER_PIXEL_16_555:\r
376 case LCD_BITS_PER_PIXEL_12_444:\r
377 return 2;\r
378\r
379 case LCD_BITS_PER_PIXEL_8:\r
380 case LCD_BITS_PER_PIXEL_4:\r
381 case LCD_BITS_PER_PIXEL_2:\r
382 case LCD_BITS_PER_PIXEL_1:\r
383 return 1;\r
384\r
385 default:\r
386 return 0;\r
387 }\r
388}\r