| /** @file |
| |
| Copyright (c) 2011, ARM Ltd. All rights reserved.<BR> |
| This program and the accompanying materials |
| are licensed and made available under the terms and conditions of the BSD License |
| which accompanies this distribution. The full text of the license may be found at |
| http://opensource.org/licenses/bsd-license.php |
| |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. |
| |
| **/ |
| |
| #include "LcdGraphicsOutputDxe.h" |
| |
| BOOLEAN mDisplayInitialized = FALSE; |
| |
| LCD_MODE LcdModes[] = { |
| { |
| 0, 640, 480, |
| 9, 4, |
| 96, 16, 48, |
| 2, 10, 33 |
| }, |
| { |
| 1, 800, 600, |
| 11, 2, |
| 120, 56, 64, |
| 5, 37, 22 |
| }, |
| { |
| 2, 1024, 768, |
| 6, 2, |
| 96, 16, 48, |
| 2, 10, 33 |
| }, |
| }; |
| |
| LCD_INSTANCE mLcdTemplate = { |
| LCD_INSTANCE_SIGNATURE, |
| NULL, // Handle |
| { // ModeInfo |
| 0, // Version |
| 0, // HorizontalResolution |
| 0, // VerticalResolution |
| PixelBltOnly, // PixelFormat |
| { |
| 0xF800, //RedMask; |
| 0x7E0, //GreenMask; |
| 0x1F, //BlueMask; |
| 0x0//ReservedMask |
| }, // PixelInformation |
| 0, // PixelsPerScanLine |
| }, |
| { // Mode |
| 3, // MaxMode; |
| 0, // Mode; |
| NULL, // Info; |
| 0, // SizeOfInfo; |
| 0, // FrameBufferBase; |
| 0 // FrameBufferSize; |
| }, |
| { // Gop |
| LcdGraphicsQueryMode, // QueryMode |
| LcdGraphicsSetMode, // SetMode |
| LcdGraphicsBlt, // Blt |
| NULL // *Mode |
| }, |
| { // DevicePath |
| { |
| { |
| HARDWARE_DEVICE_PATH, HW_VENDOR_DP, |
| (UINT8) (sizeof(VENDOR_DEVICE_PATH)), |
| (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8), |
| }, |
| // Hardware Device Path for Lcd |
| EFI_CALLER_ID_GUID // Use the driver's GUID |
| }, |
| |
| { |
| END_DEVICE_PATH_TYPE, |
| END_ENTIRE_DEVICE_PATH_SUBTYPE, |
| sizeof(EFI_DEVICE_PATH_PROTOCOL), |
| 0 |
| } |
| } |
| }; |
| |
| EFI_STATUS |
| LcdInstanceContructor ( |
| OUT LCD_INSTANCE** NewInstance |
| ) |
| { |
| LCD_INSTANCE* Instance; |
| |
| Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate); |
| if (Instance == NULL) { |
| return EFI_OUT_OF_RESOURCES; |
| } |
| |
| Instance->Gop.Mode = &Instance->Mode; |
| Instance->Mode.Info = &Instance->ModeInfo; |
| |
| *NewInstance = Instance; |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| LcdPlatformGetVram ( |
| OUT EFI_PHYSICAL_ADDRESS* VramBaseAddress, |
| OUT UINTN* VramSize |
| ) |
| { |
| EFI_STATUS Status; |
| EFI_CPU_ARCH_PROTOCOL *Cpu; |
| UINTN MaxSize; |
| |
| MaxSize = 0x500000; |
| *VramSize = MaxSize; |
| |
| // Allocate VRAM from DRAM |
| Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES((MaxSize)), VramBaseAddress); |
| if (EFI_ERROR(Status)) { |
| return Status; |
| } |
| |
| // Ensure the Cpu architectural protocol is already installed |
| Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); |
| ASSERT_EFI_ERROR(Status); |
| |
| // Mark the VRAM as un-cacheable. The VRAM is inside the DRAM, which is cacheable. |
| Status = Cpu->SetMemoryAttributes (Cpu, *VramBaseAddress, *VramSize, EFI_MEMORY_UC); |
| if (EFI_ERROR(Status)) { |
| gBS->FreePool (VramBaseAddress); |
| return Status; |
| } |
| |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| DssSetMode ( |
| UINT32 VramBaseAddress, |
| UINTN ModeNumber |
| ) |
| { |
| // Make sure the interface clock is running |
| MmioWrite32 (CM_ICLKEN_DSS, EN_DSS); |
| |
| // Stop the functional clocks |
| MmioAnd32 (CM_FCLKEN_DSS, ~(EN_DSS1 | EN_DSS2 | EN_TV)); |
| |
| // Program the DSS clock divisor |
| MmioWrite32 (CM_CLKSEL_DSS, 0x1000 | (LcdModes[ModeNumber].DssDivisor)); |
| |
| // Start the functional clocks |
| MmioOr32 (CM_FCLKEN_DSS, (EN_DSS1 | EN_DSS2 | EN_TV)); |
| |
| // Wait for DSS to stabilize |
| gBS->Stall(1); |
| |
| // Reset the subsystem |
| MmioWrite32(DSS_SYSCONFIG, DSS_SOFTRESET); |
| while (!(MmioRead32 (DSS_SYSSTATUS) & DSS_RESETDONE)); |
| |
| // Configure LCD parameters |
| MmioWrite32 (DISPC_SIZE_LCD, |
| ((LcdModes[ModeNumber].HorizontalResolution - 1) |
| | ((LcdModes[ModeNumber].VerticalResolution - 1) << 16)) |
| ); |
| MmioWrite32 (DISPC_TIMING_H, |
| ( (LcdModes[ModeNumber].HSync - 1) |
| | ((LcdModes[ModeNumber].HFrontPorch - 1) << 8) |
| | ((LcdModes[ModeNumber].HBackPorch - 1) << 20)) |
| ); |
| MmioWrite32 (DISPC_TIMING_V, |
| ( (LcdModes[ModeNumber].VSync - 1) |
| | ((LcdModes[ModeNumber].VFrontPorch - 1) << 8) |
| | ((LcdModes[ModeNumber].VBackPorch - 1) << 20)) |
| ); |
| |
| // Set the framebuffer to only load frames (no gamma tables) |
| MmioAnd32 (DISPC_CONFIG, CLEARLOADMODE); |
| MmioOr32 (DISPC_CONFIG, LOAD_FRAME_ONLY); |
| |
| // Divisor for the pixel clock |
| MmioWrite32(DISPC_DIVISOR, ((1 << 16) | LcdModes[ModeNumber].DispcDivisor) ); |
| |
| // Set up the graphics layer |
| MmioWrite32 (DISPC_GFX_PRELD, 0x2D8); |
| MmioWrite32 (DISPC_GFX_BA0, VramBaseAddress); |
| MmioWrite32 (DISPC_GFX_SIZE, |
| ((LcdModes[ModeNumber].HorizontalResolution - 1) |
| | ((LcdModes[ModeNumber].VerticalResolution - 1) << 16)) |
| ); |
| |
| MmioWrite32(DISPC_GFX_ATTR, (GFXENABLE | RGB16 | BURSTSIZE16)); |
| |
| // Start it all |
| MmioOr32 (DISPC_CONTROL, (LCDENABLE | ACTIVEMATRIX | DATALINES24 | BYPASS_MODE | LCDENABLESIGNAL)); |
| MmioOr32 (DISPC_CONTROL, GOLCD); |
| |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| HwInitializeDisplay ( |
| UINTN VramBaseAddress, |
| UINTN VramSize |
| ) |
| { |
| EFI_STATUS Status; |
| UINT8 Data; |
| EFI_TPL OldTpl; |
| EMBEDDED_EXTERNAL_DEVICE *gTPS65950; |
| |
| // Enable power lines used by TFP410 |
| Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); |
| ASSERT_EFI_ERROR (Status); |
| |
| OldTpl = gBS->RaiseTPL(TPL_NOTIFY); |
| Data = VAUX_DEV_GRP_P1; |
| Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VPLL2_DEV_GRP), 1, &Data); |
| ASSERT_EFI_ERROR(Status); |
| |
| Data = VAUX_DEDICATED_18V; |
| Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VPLL2_DEDICATED), 1, &Data); |
| ASSERT_EFI_ERROR (Status); |
| |
| // Power up TFP410 (set GPIO2 on TPS - for BeagleBoard-xM) |
| Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATADIR1), 1, &Data); |
| ASSERT_EFI_ERROR (Status); |
| Data |= BIT2; |
| Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATADIR1), 1, &Data); |
| ASSERT_EFI_ERROR (Status); |
| |
| Data = BIT2; |
| Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, SETGPIODATAOUT1), 1, &Data); |
| ASSERT_EFI_ERROR (Status); |
| |
| gBS->RestoreTPL(OldTpl); |
| |
| // Power up TFP410 (set GPIO 170 - for older BeagleBoards) |
| MmioAnd32 (GPIO6_BASE + GPIO_OE, ~BIT10); |
| MmioOr32 (GPIO6_BASE + GPIO_SETDATAOUT, BIT10); |
| |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| InitializeDisplay ( |
| IN LCD_INSTANCE* Instance |
| ) |
| { |
| EFI_STATUS Status; |
| UINTN VramSize; |
| EFI_PHYSICAL_ADDRESS VramBaseAddress; |
| |
| Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize); |
| if (EFI_ERROR (Status)) { |
| return Status; |
| } |
| |
| Instance->Mode.FrameBufferBase = VramBaseAddress; |
| Instance->Mode.FrameBufferSize = VramSize; |
| |
| Status = HwInitializeDisplay((UINTN)VramBaseAddress, VramSize); |
| if (!EFI_ERROR (Status)) { |
| mDisplayInitialized = TRUE; |
| } |
| |
| return Status; |
| } |
| |
| EFI_STATUS |
| EFIAPI |
| LcdGraphicsQueryMode ( |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, |
| IN UINT32 ModeNumber, |
| OUT UINTN *SizeOfInfo, |
| OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info |
| ) |
| { |
| LCD_INSTANCE *Instance; |
| |
| Instance = LCD_INSTANCE_FROM_GOP_THIS(This); |
| |
| if (!mDisplayInitialized) { |
| InitializeDisplay (Instance); |
| } |
| |
| // Error checking |
| if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) { |
| DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber )); |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| *Info = AllocateCopyPool(sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), &Instance->ModeInfo); |
| if (*Info == NULL) { |
| return EFI_OUT_OF_RESOURCES; |
| } |
| |
| *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); |
| |
| (*Info)->Version = 0; |
| (*Info)->HorizontalResolution = LcdModes[ModeNumber].HorizontalResolution; |
| (*Info)->VerticalResolution = LcdModes[ModeNumber].VerticalResolution; |
| (*Info)->PixelFormat = PixelBltOnly; |
| |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| EFIAPI |
| LcdGraphicsSetMode ( |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, |
| IN UINT32 ModeNumber |
| ) |
| { |
| LCD_INSTANCE *Instance; |
| |
| Instance = LCD_INSTANCE_FROM_GOP_THIS(This); |
| |
| if (ModeNumber >= Instance->Mode.MaxMode) { |
| return EFI_UNSUPPORTED; |
| } |
| |
| if (!mDisplayInitialized) { |
| InitializeDisplay (Instance); |
| } |
| |
| DssSetMode((UINT32)Instance->Mode.FrameBufferBase, ModeNumber); |
| |
| Instance->Mode.Mode = ModeNumber; |
| Instance->ModeInfo.HorizontalResolution = LcdModes[ModeNumber].HorizontalResolution; |
| Instance->ModeInfo.VerticalResolution = LcdModes[ModeNumber].VerticalResolution; |
| |
| return EFI_SUCCESS; |
| } |
| |
| EFI_STATUS |
| EFIAPI |
| LcdGraphicsOutputDxeInitialize ( |
| IN EFI_HANDLE ImageHandle, |
| IN EFI_SYSTEM_TABLE *SystemTable |
| ) |
| { |
| EFI_STATUS Status = EFI_SUCCESS; |
| LCD_INSTANCE* Instance; |
| |
| Status = LcdInstanceContructor (&Instance); |
| if (EFI_ERROR(Status)) { |
| goto EXIT; |
| } |
| |
| // Install the Graphics Output Protocol and the Device Path |
| Status = gBS->InstallMultipleProtocolInterfaces( |
| &Instance->Handle, |
| &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, |
| &gEfiDevicePathProtocolGuid, &Instance->DevicePath, |
| NULL |
| ); |
| |
| if (EFI_ERROR(Status)) { |
| DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status)); |
| goto EXIT; |
| } |
| |
| // Register for an ExitBootServicesEvent |
| // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly, |
| // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration. |
| /*Status = gBS->CreateEvent ( |
| EVT_SIGNAL_EXIT_BOOT_SERVICES, |
| TPL_NOTIFY, |
| LcdGraphicsExitBootServicesEvent, NULL, |
| &Instance->ExitBootServicesEvent |
| ); |
| |
| if (EFI_ERROR(Status)) { |
| DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status)); |
| goto EXIT_ERROR_UNINSTALL_PROTOCOL; |
| }*/ |
| |
| // To get here, everything must be fine, so just exit |
| goto EXIT; |
| |
| //EXIT_ERROR_UNINSTALL_PROTOCOL: |
| /* The following function could return an error message, |
| * however, to get here something must have gone wrong already, |
| * so preserve the original error, i.e. don't change |
| * the Status variable, even it fails to uninstall the protocol. |
| */ |
| /* gBS->UninstallMultipleProtocolInterfaces ( |
| Instance->Handle, |
| &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol |
| &gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path |
| NULL |
| );*/ |
| |
| EXIT: |
| return Status; |
| |
| } |