Home | History | Annotate | Download | only in CirrusLogic5430Dxe
      1 /** @file
      2   This file produces the graphics abstration of UGA Draw. It is called by
      3   CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
      4   This file just does graphics.
      5 
      6   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "CirrusLogic5430.h"
     18 
     19 //
     20 // UGA Draw Protocol Member Functions
     21 //
     22 EFI_STATUS
     23 EFIAPI
     24 CirrusLogic5430UgaDrawGetMode (
     25   IN  EFI_UGA_DRAW_PROTOCOL *This,
     26   OUT UINT32                *HorizontalResolution,
     27   OUT UINT32                *VerticalResolution,
     28   OUT UINT32                *ColorDepth,
     29   OUT UINT32                *RefreshRate
     30   )
     31 {
     32   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
     33 
     34   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
     35 
     36   if (Private->HardwareNeedsStarting) {
     37     return EFI_NOT_STARTED;
     38   }
     39 
     40   if ((HorizontalResolution == NULL) ||
     41       (VerticalResolution == NULL)   ||
     42       (ColorDepth == NULL)           ||
     43       (RefreshRate == NULL)) {
     44     return EFI_INVALID_PARAMETER;
     45   }
     46 
     47   *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
     48   *VerticalResolution   = Private->ModeData[Private->CurrentMode].VerticalResolution;
     49   *ColorDepth           = Private->ModeData[Private->CurrentMode].ColorDepth;
     50   *RefreshRate          = Private->ModeData[Private->CurrentMode].RefreshRate;
     51 
     52   return EFI_SUCCESS;
     53 }
     54 
     55 EFI_STATUS
     56 EFIAPI
     57 CirrusLogic5430UgaDrawSetMode (
     58   IN  EFI_UGA_DRAW_PROTOCOL *This,
     59   IN  UINT32                HorizontalResolution,
     60   IN  UINT32                VerticalResolution,
     61   IN  UINT32                ColorDepth,
     62   IN  UINT32                RefreshRate
     63   )
     64 {
     65   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
     66   UINTN                           Index;
     67 
     68   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
     69 
     70   for (Index = 0; Index < Private->MaxMode; Index++) {
     71 
     72     if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
     73       continue;
     74     }
     75 
     76     if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
     77       continue;
     78     }
     79 
     80     if (ColorDepth != Private->ModeData[Index].ColorDepth) {
     81       continue;
     82     }
     83 
     84     if (RefreshRate != Private->ModeData[Index].RefreshRate) {
     85       continue;
     86     }
     87 
     88     if (Private->LineBuffer) {
     89       gBS->FreePool (Private->LineBuffer);
     90     }
     91 
     92     Private->LineBuffer = NULL;
     93     Private->LineBuffer = AllocatePool (HorizontalResolution);
     94     if (Private->LineBuffer == NULL) {
     95       return EFI_OUT_OF_RESOURCES;
     96     }
     97 
     98     InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[Private->ModeData[Index].ModeNumber]);
     99 
    100     Private->CurrentMode            = Index;
    101 
    102     Private->HardwareNeedsStarting  = FALSE;
    103 
    104     return EFI_SUCCESS;
    105   }
    106 
    107   return EFI_NOT_FOUND;
    108 }
    109 
    110 EFI_STATUS
    111 EFIAPI
    112 CirrusLogic5430UgaDrawBlt (
    113   IN  EFI_UGA_DRAW_PROTOCOL     *This,
    114   IN  EFI_UGA_PIXEL             *BltBuffer, OPTIONAL
    115   IN  EFI_UGA_BLT_OPERATION     BltOperation,
    116   IN  UINTN                     SourceX,
    117   IN  UINTN                     SourceY,
    118   IN  UINTN                     DestinationX,
    119   IN  UINTN                     DestinationY,
    120   IN  UINTN                     Width,
    121   IN  UINTN                     Height,
    122   IN  UINTN                     Delta
    123   )
    124 {
    125   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
    126   EFI_TPL                         OriginalTPL;
    127   UINTN                           DstY;
    128   UINTN                           SrcY;
    129   EFI_UGA_PIXEL                   *Blt;
    130   UINTN                           X;
    131   UINT8                           Pixel;
    132   UINT32                          WidePixel;
    133   UINTN                           ScreenWidth;
    134   UINTN                           Offset;
    135   UINTN                           SourceOffset;
    136 
    137   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
    138 
    139   if ((UINT32)BltOperation >= EfiUgaBltMax) {
    140     return EFI_INVALID_PARAMETER;
    141   }
    142 
    143   if (Width == 0 || Height == 0) {
    144     return EFI_INVALID_PARAMETER;
    145   }
    146 
    147   //
    148   // If Delta is zero, then the entire BltBuffer is being used, so Delta
    149   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
    150   // the number of bytes in each row can be computed.
    151   //
    152   if (Delta == 0) {
    153     Delta = Width * sizeof (EFI_UGA_PIXEL);
    154   }
    155 
    156   //
    157   // We need to fill the Virtual Screen buffer with the blt data.
    158   // The virtual screen is upside down, as the first row is the bootom row of
    159   // the image.
    160   //
    161 
    162   //
    163   // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
    164   // are valid for the operation and the current screen geometry.
    165   //
    166   if (BltOperation == EfiUgaVideoToBltBuffer) {
    167     //
    168     // Video to BltBuffer: Source is Video, destination is BltBuffer
    169     //
    170     if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
    171       return EFI_INVALID_PARAMETER;
    172     }
    173 
    174     if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
    175       return EFI_INVALID_PARAMETER;
    176     }
    177   } else {
    178     //
    179     // BltBuffer to Video: Source is BltBuffer, destination is Video
    180     //
    181     if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
    182       return EFI_INVALID_PARAMETER;
    183     }
    184 
    185     if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
    186       return EFI_INVALID_PARAMETER;
    187     }
    188   }
    189   //
    190   // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
    191   // We would not want a timer based event (Cursor, ...) to come in while we are
    192   // doing this operation.
    193   //
    194   OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
    195 
    196   switch (BltOperation) {
    197   case EfiUgaVideoToBltBuffer:
    198     //
    199     // Video to BltBuffer: Source is Video, destination is BltBuffer
    200     //
    201     for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
    202 
    203       Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX;
    204       if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
    205         Private->PciIo->Mem.Read (
    206                               Private->PciIo,
    207                               EfiPciIoWidthUint32,
    208                               0,
    209                               Offset,
    210                               Width >> 2,
    211                               Private->LineBuffer
    212                               );
    213       } else {
    214         Private->PciIo->Mem.Read (
    215                               Private->PciIo,
    216                               EfiPciIoWidthUint8,
    217                               0,
    218                               Offset,
    219                               Width,
    220                               Private->LineBuffer
    221                               );
    222       }
    223 
    224       for (X = 0; X < Width; X++) {
    225         Blt         = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_UGA_PIXEL));
    226 
    227         Blt->Red    = (UINT8) (Private->LineBuffer[X] & 0xe0);
    228         Blt->Green  = (UINT8) ((Private->LineBuffer[X] & 0x1c) << 3);
    229         Blt->Blue   = (UINT8) ((Private->LineBuffer[X] & 0x03) << 6);
    230       }
    231     }
    232     break;
    233 
    234   case EfiUgaVideoToVideo:
    235     //
    236     // Perform hardware acceleration for Video to Video operations
    237     //
    238     ScreenWidth   = Private->ModeData[Private->CurrentMode].HorizontalResolution;
    239     SourceOffset  = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX);
    240     Offset        = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX);
    241 
    242     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000);
    243     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010);
    244     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012);
    245     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014);
    246 
    247     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001);
    248     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011);
    249     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013);
    250     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015);
    251 
    252     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20));
    253     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21));
    254     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22));
    255     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23));
    256     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24));
    257     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25));
    258     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26));
    259     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27));
    260     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28));
    261     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29));
    262     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a));
    263     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c));
    264     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d));
    265     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e));
    266     outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f);
    267     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030);
    268     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32);
    269     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033);
    270     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034);
    271     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035);
    272 
    273     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
    274 
    275     outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
    276     while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
    277       ;
    278     break;
    279 
    280   case EfiUgaVideoFill:
    281     Blt       = BltBuffer;
    282     Pixel     = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
    283     WidePixel = (Pixel << 8) | Pixel;
    284     WidePixel = (WidePixel << 16) | WidePixel;
    285 
    286     if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) {
    287       Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution;
    288       if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) {
    289         Private->PciIo->Mem.Write (
    290                               Private->PciIo,
    291                               EfiPciIoWidthFillUint32,
    292                               0,
    293                               Offset,
    294                               (Width * Height) >> 2,
    295                               &WidePixel
    296                               );
    297       } else {
    298         Private->PciIo->Mem.Write (
    299                               Private->PciIo,
    300                               EfiPciIoWidthFillUint8,
    301                               0,
    302                               Offset,
    303                               Width * Height,
    304                               &Pixel
    305                               );
    306       }
    307     } else {
    308       for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
    309         Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
    310         if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
    311           Private->PciIo->Mem.Write (
    312                                 Private->PciIo,
    313                                 EfiPciIoWidthFillUint32,
    314                                 0,
    315                                 Offset,
    316                                 Width >> 2,
    317                                 &WidePixel
    318                                 );
    319         } else {
    320           Private->PciIo->Mem.Write (
    321                                 Private->PciIo,
    322                                 EfiPciIoWidthFillUint8,
    323                                 0,
    324                                 Offset,
    325                                 Width,
    326                                 &Pixel
    327                                 );
    328         }
    329       }
    330     }
    331     break;
    332 
    333   case EfiUgaBltBufferToVideo:
    334     for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
    335 
    336       for (X = 0; X < Width; X++) {
    337         Blt                     = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + (SourceX + X) * sizeof (EFI_UGA_PIXEL));
    338         Private->LineBuffer[X]  = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
    339       }
    340 
    341       Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
    342 
    343       if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
    344         Private->PciIo->Mem.Write (
    345                               Private->PciIo,
    346                               EfiPciIoWidthUint32,
    347                               0,
    348                               Offset,
    349                               Width >> 2,
    350                               Private->LineBuffer
    351                               );
    352       } else {
    353         Private->PciIo->Mem.Write (
    354                               Private->PciIo,
    355                               EfiPciIoWidthUint8,
    356                               0,
    357                               Offset,
    358                               Width,
    359                               Private->LineBuffer
    360                               );
    361       }
    362     }
    363     break;
    364 
    365   default:
    366     break;
    367   }
    368 
    369   gBS->RestoreTPL (OriginalTPL);
    370 
    371   return EFI_SUCCESS;
    372 }
    373 
    374 //
    375 // Construction and Destruction functions
    376 //
    377 EFI_STATUS
    378 CirrusLogic5430UgaDrawConstructor (
    379   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
    380   )
    381 {
    382   EFI_UGA_DRAW_PROTOCOL *UgaDraw;
    383 
    384   //
    385   // Fill in Private->UgaDraw protocol
    386   //
    387   UgaDraw           = &Private->UgaDraw;
    388 
    389   UgaDraw->GetMode  = CirrusLogic5430UgaDrawGetMode;
    390   UgaDraw->SetMode  = CirrusLogic5430UgaDrawSetMode;
    391   UgaDraw->Blt      = CirrusLogic5430UgaDrawBlt;
    392 
    393   //
    394   // Initialize the private data
    395   //
    396   Private->CurrentMode            = 0;
    397   Private->HardwareNeedsStarting  = TRUE;
    398   Private->LineBuffer             = NULL;
    399 
    400   //
    401   // Initialize the hardware
    402   //
    403   UgaDraw->SetMode (
    404             UgaDraw,
    405             Private->ModeData[Private->CurrentMode].HorizontalResolution,
    406             Private->ModeData[Private->CurrentMode].VerticalResolution,
    407             Private->ModeData[Private->CurrentMode].ColorDepth,
    408             Private->ModeData[Private->CurrentMode].RefreshRate
    409             );
    410   DrawLogo (
    411     Private,
    412     Private->ModeData[Private->CurrentMode].HorizontalResolution,
    413     Private->ModeData[Private->CurrentMode].VerticalResolution
    414     );
    415 
    416   return EFI_SUCCESS;
    417 }
    418 
    419