1 /** @file
2
3 Copyright (c) 2011-2014, 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 "LcdGraphicsOutputDxe.h"
15
16 BOOLEAN mDisplayInitialized = FALSE;
17
18 LCD_MODE LcdModes[] = {
19 {
20 0, 640, 480,
21 9, 4,
22 96, 16, 48,
23 2, 10, 33
24 },
25 {
26 1, 800, 600,
27 11, 2,
28 120, 56, 64,
29 5, 37, 22
30 },
31 {
32 2, 1024, 768,
33 6, 2,
34 96, 16, 48,
35 2, 10, 33
36 },
37 };
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 {
48 0xF800, //RedMask;
49 0x7E0, //GreenMask;
50 0x1F, //BlueMask;
51 0x0//ReservedMask
52 }, // PixelInformation
53 0, // PixelsPerScanLine
54 },
55 { // Mode
56 3, // MaxMode;
57 0, // Mode;
58 NULL, // Info;
59 0, // SizeOfInfo;
60 0, // FrameBufferBase;
61 0 // FrameBufferSize;
62 },
63 { // Gop
64 LcdGraphicsQueryMode, // QueryMode
65 LcdGraphicsSetMode, // SetMode
66 LcdGraphicsBlt, // Blt
67 NULL // *Mode
68 },
69 { // DevicePath
70 {
71 {
72 HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
73 { (UINT8) (sizeof(VENDOR_DEVICE_PATH)), (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8) },
74 },
75 // Hardware Device Path for Lcd
76 EFI_CALLER_ID_GUID // Use the driver's GUID
77 },
78 {
79 END_DEVICE_PATH_TYPE,
80 END_ENTIRE_DEVICE_PATH_SUBTYPE,
81 { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0}
82 }
83 }
84 };
85
86 EFI_STATUS
LcdInstanceContructor(OUT LCD_INSTANCE ** NewInstance)87 LcdInstanceContructor (
88 OUT LCD_INSTANCE** NewInstance
89 )
90 {
91 LCD_INSTANCE* Instance;
92
93 Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
94 if (Instance == NULL) {
95 return EFI_OUT_OF_RESOURCES;
96 }
97
98 Instance->Gop.Mode = &Instance->Mode;
99 Instance->Mode.Info = &Instance->ModeInfo;
100
101 *NewInstance = Instance;
102 return EFI_SUCCESS;
103 }
104
105 EFI_STATUS
LcdPlatformGetVram(OUT EFI_PHYSICAL_ADDRESS * VramBaseAddress,OUT UINTN * VramSize)106 LcdPlatformGetVram (
107 OUT EFI_PHYSICAL_ADDRESS* VramBaseAddress,
108 OUT UINTN* VramSize
109 )
110 {
111 EFI_STATUS Status;
112 EFI_CPU_ARCH_PROTOCOL *Cpu;
113 UINTN MaxSize;
114
115 MaxSize = 0x500000;
116 *VramSize = MaxSize;
117
118 // Allocate VRAM from DRAM
119 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES((MaxSize)), VramBaseAddress);
120 if (EFI_ERROR(Status)) {
121 return Status;
122 }
123
124 // Ensure the Cpu architectural protocol is already installed
125 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
126 ASSERT_EFI_ERROR(Status);
127
128 // Mark the VRAM as un-cacheable. The VRAM is inside the DRAM, which is cacheable.
129 Status = Cpu->SetMemoryAttributes (Cpu, *VramBaseAddress, *VramSize, EFI_MEMORY_UC);
130 if (EFI_ERROR(Status)) {
131 gBS->FreePool (VramBaseAddress);
132 return Status;
133 }
134
135 return EFI_SUCCESS;
136 }
137
138 EFI_STATUS
DssSetMode(UINT32 VramBaseAddress,UINTN ModeNumber)139 DssSetMode (
140 UINT32 VramBaseAddress,
141 UINTN ModeNumber
142 )
143 {
144 // Make sure the interface clock is running
145 MmioWrite32 (CM_ICLKEN_DSS, EN_DSS);
146
147 // Stop the functional clocks
148 MmioAnd32 (CM_FCLKEN_DSS, ~(EN_DSS1 | EN_DSS2 | EN_TV));
149
150 // Program the DSS clock divisor
151 MmioWrite32 (CM_CLKSEL_DSS, 0x1000 | (LcdModes[ModeNumber].DssDivisor));
152
153 // Start the functional clocks
154 MmioOr32 (CM_FCLKEN_DSS, (EN_DSS1 | EN_DSS2 | EN_TV));
155
156 // Wait for DSS to stabilize
157 gBS->Stall(1);
158
159 // Reset the subsystem
160 MmioWrite32(DSS_SYSCONFIG, DSS_SOFTRESET);
161 while (!(MmioRead32 (DSS_SYSSTATUS) & DSS_RESETDONE));
162
163 // Configure LCD parameters
164 MmioWrite32 (DISPC_SIZE_LCD,
165 ((LcdModes[ModeNumber].HorizontalResolution - 1)
166 | ((LcdModes[ModeNumber].VerticalResolution - 1) << 16))
167 );
168 MmioWrite32 (DISPC_TIMING_H,
169 ( (LcdModes[ModeNumber].HSync - 1)
170 | ((LcdModes[ModeNumber].HFrontPorch - 1) << 8)
171 | ((LcdModes[ModeNumber].HBackPorch - 1) << 20))
172 );
173 MmioWrite32 (DISPC_TIMING_V,
174 ( (LcdModes[ModeNumber].VSync - 1)
175 | ((LcdModes[ModeNumber].VFrontPorch - 1) << 8)
176 | ((LcdModes[ModeNumber].VBackPorch - 1) << 20))
177 );
178
179 // Set the framebuffer to only load frames (no gamma tables)
180 MmioAnd32 (DISPC_CONFIG, CLEARLOADMODE);
181 MmioOr32 (DISPC_CONFIG, LOAD_FRAME_ONLY);
182
183 // Divisor for the pixel clock
184 MmioWrite32(DISPC_DIVISOR, ((1 << 16) | LcdModes[ModeNumber].DispcDivisor) );
185
186 // Set up the graphics layer
187 MmioWrite32 (DISPC_GFX_PRELD, 0x2D8);
188 MmioWrite32 (DISPC_GFX_BA0, VramBaseAddress);
189 MmioWrite32 (DISPC_GFX_SIZE,
190 ((LcdModes[ModeNumber].HorizontalResolution - 1)
191 | ((LcdModes[ModeNumber].VerticalResolution - 1) << 16))
192 );
193
194 MmioWrite32(DISPC_GFX_ATTR, (GFXENABLE | RGB16 | BURSTSIZE16));
195
196 // Start it all
197 MmioOr32 (DISPC_CONTROL, (LCDENABLE | ACTIVEMATRIX | DATALINES24 | BYPASS_MODE | LCDENABLESIGNAL));
198 MmioOr32 (DISPC_CONTROL, GOLCD);
199
200 return EFI_SUCCESS;
201 }
202
203 EFI_STATUS
HwInitializeDisplay(UINTN VramBaseAddress,UINTN VramSize)204 HwInitializeDisplay (
205 UINTN VramBaseAddress,
206 UINTN VramSize
207 )
208 {
209 EFI_STATUS Status;
210 UINT8 Data;
211 EFI_TPL OldTpl;
212 EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
213
214 // Enable power lines used by TFP410
215 Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
216 ASSERT_EFI_ERROR (Status);
217
218 OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
219 Data = VAUX_DEV_GRP_P1;
220 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VPLL2_DEV_GRP), 1, &Data);
221 ASSERT_EFI_ERROR(Status);
222
223 Data = VAUX_DEDICATED_18V;
224 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VPLL2_DEDICATED), 1, &Data);
225 ASSERT_EFI_ERROR (Status);
226
227 // Power up TFP410 (set GPIO2 on TPS - for BeagleBoard-xM)
228 Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATADIR1), 1, &Data);
229 ASSERT_EFI_ERROR (Status);
230 Data |= BIT2;
231 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATADIR1), 1, &Data);
232 ASSERT_EFI_ERROR (Status);
233
234 Data = BIT2;
235 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, SETGPIODATAOUT1), 1, &Data);
236 ASSERT_EFI_ERROR (Status);
237
238 gBS->RestoreTPL(OldTpl);
239
240 // Power up TFP410 (set GPIO 170 - for older BeagleBoards)
241 MmioAnd32 (GPIO6_BASE + GPIO_OE, ~BIT10);
242 MmioOr32 (GPIO6_BASE + GPIO_SETDATAOUT, BIT10);
243
244 return EFI_SUCCESS;
245 }
246
247 EFI_STATUS
InitializeDisplay(IN LCD_INSTANCE * Instance)248 InitializeDisplay (
249 IN LCD_INSTANCE* Instance
250 )
251 {
252 EFI_STATUS Status;
253 UINTN VramSize;
254 EFI_PHYSICAL_ADDRESS VramBaseAddress;
255
256 Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
257 if (EFI_ERROR (Status)) {
258 return Status;
259 }
260
261 Instance->Mode.FrameBufferBase = VramBaseAddress;
262 Instance->Mode.FrameBufferSize = VramSize;
263
264 Status = HwInitializeDisplay((UINTN)VramBaseAddress, VramSize);
265 if (!EFI_ERROR (Status)) {
266 mDisplayInitialized = TRUE;
267 }
268
269 return Status;
270 }
271
272 EFI_STATUS
273 EFIAPI
LcdGraphicsQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber,OUT UINTN * SizeOfInfo,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ** Info)274 LcdGraphicsQueryMode (
275 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
276 IN UINT32 ModeNumber,
277 OUT UINTN *SizeOfInfo,
278 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
279 )
280 {
281 LCD_INSTANCE *Instance;
282
283 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
284
285 if (!mDisplayInitialized) {
286 InitializeDisplay (Instance);
287 }
288
289 // Error checking
290 if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
291 DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
292 return EFI_INVALID_PARAMETER;
293 }
294
295 *Info = AllocateCopyPool(sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), &Instance->ModeInfo);
296 if (*Info == NULL) {
297 return EFI_OUT_OF_RESOURCES;
298 }
299
300 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
301
302 (*Info)->Version = 0;
303 (*Info)->HorizontalResolution = LcdModes[ModeNumber].HorizontalResolution;
304 (*Info)->VerticalResolution = LcdModes[ModeNumber].VerticalResolution;
305 (*Info)->PixelFormat = PixelBltOnly;
306
307 return EFI_SUCCESS;
308 }
309
310 EFI_STATUS
311 EFIAPI
LcdGraphicsSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber)312 LcdGraphicsSetMode (
313 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
314 IN UINT32 ModeNumber
315 )
316 {
317 LCD_INSTANCE *Instance;
318
319 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
320
321 if (ModeNumber >= Instance->Mode.MaxMode) {
322 return EFI_UNSUPPORTED;
323 }
324
325 if (!mDisplayInitialized) {
326 InitializeDisplay (Instance);
327 }
328
329 DssSetMode((UINT32)Instance->Mode.FrameBufferBase, ModeNumber);
330
331 Instance->Mode.Mode = ModeNumber;
332 Instance->ModeInfo.HorizontalResolution = LcdModes[ModeNumber].HorizontalResolution;
333 Instance->ModeInfo.VerticalResolution = LcdModes[ModeNumber].VerticalResolution;
334
335 return EFI_SUCCESS;
336 }
337
338 EFI_STATUS
339 EFIAPI
LcdGraphicsOutputDxeInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)340 LcdGraphicsOutputDxeInitialize (
341 IN EFI_HANDLE ImageHandle,
342 IN EFI_SYSTEM_TABLE *SystemTable
343 )
344 {
345 EFI_STATUS Status = EFI_SUCCESS;
346 LCD_INSTANCE* Instance;
347
348 Status = LcdInstanceContructor (&Instance);
349 if (EFI_ERROR(Status)) {
350 goto EXIT;
351 }
352
353 // Install the Graphics Output Protocol and the Device Path
354 Status = gBS->InstallMultipleProtocolInterfaces(
355 &Instance->Handle,
356 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
357 &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
358 NULL
359 );
360
361 if (EFI_ERROR(Status)) {
362 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
363 goto EXIT;
364 }
365
366 // Register for an ExitBootServicesEvent
367 // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
368 // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
369 /*Status = gBS->CreateEvent (
370 EVT_SIGNAL_EXIT_BOOT_SERVICES,
371 TPL_NOTIFY,
372 LcdGraphicsExitBootServicesEvent, NULL,
373 &Instance->ExitBootServicesEvent
374 );
375
376 if (EFI_ERROR(Status)) {
377 DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
378 goto EXIT_ERROR_UNINSTALL_PROTOCOL;
379 }*/
380
381 // To get here, everything must be fine, so just exit
382 goto EXIT;
383
384 //EXIT_ERROR_UNINSTALL_PROTOCOL:
385 /* The following function could return an error message,
386 * however, to get here something must have gone wrong already,
387 * so preserve the original error, i.e. don't change
388 * the Status variable, even it fails to uninstall the protocol.
389 */
390 /* gBS->UninstallMultipleProtocolInterfaces (
391 Instance->Handle,
392 &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
393 &gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path
394 NULL
395 );*/
396
397 EXIT:
398 return Status;
399
400 }
401