]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
LcdGraphicsOutputDxe: Fix BltVideoFill for non-32-bit architectures
[mirror_edk2.git] / ArmPlatformPkg / Drivers / LcdGraphicsOutputDxe / LcdGraphicsOutputDxe.c
CommitLineData
1e57a462 1/** @file\r
2\r
3 Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
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
46 0, // PixelInformation\r
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
67 (UINT8) (sizeof(VENDOR_DEVICE_PATH)),\r
68 (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8),\r
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
77 sizeof(EFI_DEVICE_PATH_PROTOCOL),\r
78 0\r
79 }\r
80 },\r
81 (EFI_EVENT) NULL // ExitBootServicesEvent\r
82};\r
83\r
84EFI_STATUS\r
85LcdInstanceContructor (\r
86 OUT LCD_INSTANCE** NewInstance\r
87 )\r
88{\r
89 LCD_INSTANCE* Instance;\r
90\r
91 Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);\r
92 if (Instance == NULL) {\r
93 return EFI_OUT_OF_RESOURCES;\r
94 }\r
95\r
96 Instance->Gop.Mode = &Instance->Mode;\r
97 Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();\r
98 Instance->Mode.Info = &Instance->ModeInfo;\r
99\r
100 *NewInstance = Instance;\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104//\r
105// Function Definitions\r
106//\r
107\r
108EFI_STATUS\r
109InitializeDisplay (\r
110 IN LCD_INSTANCE* Instance\r
111 )\r
112{\r
113 EFI_STATUS Status = EFI_SUCCESS;\r
114 EFI_PHYSICAL_ADDRESS VramBaseAddress;\r
115 UINTN VramSize;\r
116\r
117 Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);\r
118 if (EFI_ERROR(Status)) {\r
119 return Status;\r
120 }\r
121\r
122 // Setup the LCD\r
123 Status = LcdInitialize (VramBaseAddress);\r
124 if (EFI_ERROR(Status)) {\r
125 goto EXIT_ERROR_LCD_SHUTDOWN;\r
126 }\r
127\r
128 Status = LcdPlatformInitializeDisplay (Instance->Handle);\r
129 if (EFI_ERROR(Status)) {\r
130 goto EXIT_ERROR_LCD_SHUTDOWN;\r
131 }\r
132\r
133 // Setup all the relevant mode information\r
134 Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
135 Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;\r
136 Instance->Gop.Mode->FrameBufferSize = VramSize;\r
137\r
138 // Set the flag before changing the mode, to avoid infinite loops\r
139 mDisplayInitialized = TRUE;\r
140\r
141 // All is ok, so don't deal with any errors\r
142 goto EXIT;\r
143\r
144EXIT_ERROR_LCD_SHUTDOWN:\r
145 DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));\r
146 LcdShutdown ();\r
147\r
148EXIT:\r
149 return Status;\r
150}\r
151\r
152EFI_STATUS\r
153EFIAPI\r
154LcdGraphicsOutputDxeInitialize (\r
155 IN EFI_HANDLE ImageHandle,\r
156 IN EFI_SYSTEM_TABLE *SystemTable\r
157 )\r
158{\r
159 EFI_STATUS Status = EFI_SUCCESS;\r
160 LCD_INSTANCE* Instance;\r
161\r
162 Status = LcdInstanceContructor (&Instance);\r
163 if (EFI_ERROR(Status)) {\r
164 goto EXIT;\r
165 }\r
166\r
167 // Install the Graphics Output Protocol and the Device Path\r
168 Status = gBS->InstallMultipleProtocolInterfaces(\r
169 &Instance->Handle,\r
170 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,\r
171 &gEfiDevicePathProtocolGuid, &Instance->DevicePath,\r
172 NULL\r
173 );\r
174\r
175 if (EFI_ERROR(Status)) {\r
176 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));\r
177 goto EXIT;\r
178 }\r
179\r
180 // Register for an ExitBootServicesEvent\r
181 // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,\r
182 // i.e. it will free up all 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, NULL,\r
187 &Instance->ExitBootServicesEvent\r
188 );\r
189\r
190 if (EFI_ERROR(Status)) {\r
191 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));\r
192 goto EXIT_ERROR_UNINSTALL_PROTOCOL;\r
193 }\r
194\r
195 // To get here, everything must be fine, so just exit\r
196 goto EXIT;\r
197\r
198EXIT_ERROR_UNINSTALL_PROTOCOL:\r
199 /* The following function could return an error message,\r
200 * however, to get here something must have gone wrong already,\r
201 * so preserve the original error, i.e. don't change\r
202 * the Status variable, even it fails to uninstall the protocol.\r
203 */\r
204 gBS->UninstallMultipleProtocolInterfaces (\r
205 Instance->Handle,\r
206 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol\r
207 &gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path\r
208 NULL\r
209 );\r
210\r
211EXIT:\r
212 return Status;\r
213\r
214}\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 //TODO: Implement me\r
229}\r
230\r
231/***************************************\r
232 * GraphicsOutput Protocol function, mapping to\r
233 * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode\r
234 ***************************************/\r
235EFI_STATUS\r
236EFIAPI\r
237LcdGraphicsQueryMode (\r
238 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
239 IN UINT32 ModeNumber,\r
240 OUT UINTN *SizeOfInfo,\r
241 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
242 )\r
243{\r
244 EFI_STATUS Status = EFI_SUCCESS;\r
245 LCD_INSTANCE *Instance;\r
246\r
247 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);\r
248\r
249 // Setup the hardware if not already done\r
250 if( !mDisplayInitialized ) {\r
251 Status = InitializeDisplay(Instance);\r
252 if (EFI_ERROR(Status)) {\r
253 goto EXIT;\r
254 }\r
255 }\r
256\r
257 // Error checking\r
258 if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {\r
259 DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));\r
260 Status = EFI_INVALID_PARAMETER;\r
261 goto EXIT;\r
262 }\r
263\r
264 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
265 if (*Info == NULL) {\r
266 Status = EFI_OUT_OF_RESOURCES;\r
267 goto EXIT;\r
268 }\r
269\r
270 *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
271\r
272 Status = LcdPlatformQueryMode (ModeNumber,*Info);\r
273 if (EFI_ERROR(Status)) {\r
274 FreePool(*Info);\r
275 }\r
276\r
277EXIT:\r
278 return Status;\r
279}\r
280\r
281/***************************************\r
282 * GraphicsOutput Protocol function, mapping to\r
283 * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode\r
284 ***************************************/\r
285EFI_STATUS\r
286EFIAPI\r
287LcdGraphicsSetMode (\r
288 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
289 IN UINT32 ModeNumber\r
290 )\r
291{\r
292 EFI_STATUS Status = EFI_SUCCESS;\r
293 EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;\r
294 LCD_INSTANCE* Instance;\r
295\r
296 Instance = LCD_INSTANCE_FROM_GOP_THIS (This);\r
297\r
298 // Setup the hardware if not already done\r
299 if(!mDisplayInitialized) {\r
300 Status = InitializeDisplay (Instance);\r
301 if (EFI_ERROR(Status)) {\r
302 goto EXIT;\r
303 }\r
304 }\r
305\r
306 // Check if this mode is supported\r
307 if( ModeNumber >= This->Mode->MaxMode ) {\r
308 DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));\r
309 Status = EFI_UNSUPPORTED;\r
310 goto EXIT;\r
311 }\r
312\r
313 // Set the oscillator frequency to support the new mode\r
314 Status = LcdPlatformSetMode (ModeNumber);\r
315 if (EFI_ERROR(Status)) {\r
316 Status = EFI_DEVICE_ERROR;\r
317 goto EXIT;\r
318 }\r
319\r
320 // Update the UEFI mode information\r
321 This->Mode->Mode = ModeNumber;\r
322 LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);\r
323\r
324 // Set the hardware to the new mode\r
325 Status = LcdSetMode (ModeNumber);\r
326 if (EFI_ERROR(Status)) {\r
327 Status = EFI_DEVICE_ERROR;\r
328 goto EXIT;\r
329 }\r
330\r
331 // The UEFI spec requires that we now clear the visible portions of the output display to black.\r
332\r
333 // Set the fill colour to black\r
334 SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
335\r
336 // Fill the entire visible area with the same colour.\r
337 Status = This->Blt (\r
338 This,\r
339 &FillColour,\r
340 EfiBltVideoFill,\r
341 0,\r
342 0,\r
343 0,\r
344 0,\r
345 This->Mode->Info->HorizontalResolution,\r
346 This->Mode->Info->VerticalResolution,\r
347 0);\r
348\r
349EXIT:\r
350 return Status;\r
351}\r
352\r
353UINTN\r
354GetBytesPerPixel (\r
355 IN LCD_BPP Bpp\r
356 )\r
357{\r
358 switch(Bpp) {\r
359 case LCD_BITS_PER_PIXEL_24:\r
360 return 4;\r
361\r
362 case LCD_BITS_PER_PIXEL_16_565:\r
363 case LCD_BITS_PER_PIXEL_16_555:\r
364 case LCD_BITS_PER_PIXEL_12_444:\r
365 return 2;\r
366\r
367 case LCD_BITS_PER_PIXEL_8:\r
368 case LCD_BITS_PER_PIXEL_4:\r
369 case LCD_BITS_PER_PIXEL_2:\r
370 case LCD_BITS_PER_PIXEL_1:\r
371 return 1;\r
372\r
373 default:\r
374 return 0;\r
375 }\r
376}\r