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