Home | History | Annotate | Download | only in LcdGraphicsOutputDxe
      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