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