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