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