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 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 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 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 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 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 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 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 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