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