ArmPlatformPkg: Add support for PL111 Lcd driver

This driver implements the interface for the PL111 Lcd controller.
The LcdPlatformLib allows to set the platform specific requirements
needed by the platform for setting the LCD (oscillators, etc).

ArmPlatformPkg/ArmVExpressPkg: Implement LcdPlatformLib

This library exports the supported resolutions. It also allocates the
memory for the framebuffer and send the correct settings to the VExpress
motherboard microcontroller.



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11786 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin
2011-06-11 11:12:38 +00:00
parent 7b80d1a3b6
commit 7d0f2f23d2
13 changed files with 2341 additions and 9 deletions

View File

@@ -0,0 +1,885 @@
/** @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 <PiDxe.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Guid/GlobalVariable.h>
#include <ArmPlatform.h>
#include "LcdGraphicsOutputDxe.h"
extern BOOLEAN mDisplayInitialized;
//
// Function Definitions
//
STATIC
EFI_STATUS
VideoCopyNoHorizontalOverlap (
IN UINTN BitsPerPixel,
IN volatile VOID *FrameBufferBase,
IN UINT32 HorizontalResolution,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height
)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN SourceLine;
UINTN DestinationLine;
UINTN WidthInBytes;
UINTN LineCount;
INTN Step;
VOID *SourceAddr;
VOID *DestinationAddr;
if( DestinationY <= SourceY ) {
// scrolling up (or horizontally but without overlap)
SourceLine = SourceY;
DestinationLine = DestinationY;
Step = 1;
} else {
// scrolling down
SourceLine = SourceY + Height;
DestinationLine = DestinationY + Height;
Step = -1;
}
switch (BitsPerPixel) {
case LCD_BITS_PER_PIXEL_24:
WidthInBytes = Width * 4;
for( LineCount = 0; LineCount < Height; LineCount++ ) {
// Update the start addresses of source & destination using 32bit pointer arithmetic
SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
// Copy the entire line Y from video ram to the temp buffer
CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
// Update the line numbers
SourceLine += Step;
DestinationLine += Step;
}
break;
case LCD_BITS_PER_PIXEL_16_555:
case LCD_BITS_PER_PIXEL_16_565:
case LCD_BITS_PER_PIXEL_12_444:
WidthInBytes = Width * 2;
for( LineCount = 0; LineCount < Height; LineCount++ ) {
// Update the start addresses of source & destination using 16bit pointer arithmetic
SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
// Copy the entire line Y from video ram to the temp buffer
CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
// Update the line numbers
SourceLine += Step;
DestinationLine += Step;
}
break;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
default:
// Can't handle this case
DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
// break;
}
EXIT:
return Status;
}
STATIC
EFI_STATUS
VideoCopyHorizontalOverlap (
IN UINTN BitsPerPixel,
IN volatile VOID *FrameBufferBase,
UINT32 HorizontalResolution,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height
)
{
EFI_STATUS Status = EFI_SUCCESS;
UINT32 *PixelBuffer32bit;
UINT32 *SourcePixel32bit;
UINT32 *DestinationPixel32bit;
UINT16 *PixelBuffer16bit;
UINT16 *SourcePixel16bit;
UINT16 *DestinationPixel16bit;
UINT32 SourcePixelY;
UINT32 DestinationPixelY;
UINTN SizeIn32Bits;
UINTN SizeIn16Bits;
switch (BitsPerPixel) {
case LCD_BITS_PER_PIXEL_24:
// Allocate a temporary buffer
PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
if (PixelBuffer32bit == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
SizeIn32Bits = Width * 4;
// Copy from the video ram (source region) to a temp buffer
for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
SourcePixelY < SourceY + Height;
SourcePixelY++, DestinationPixel32bit += Width)
{
// Update the start address of line Y (source)
SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
// Copy the entire line Y from video ram to the temp buffer
CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
}
// Copy from the temp buffer to the video ram (destination region)
for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
DestinationPixelY < DestinationY + Height;
DestinationPixelY++, SourcePixel32bit += Width)
{
// Update the start address of line Y (target)
DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
// Copy the entire line Y from the temp buffer to video ram
CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
}
// Free up the allocated memory
FreePool((VOID *) PixelBuffer32bit);
break;
case LCD_BITS_PER_PIXEL_16_555:
case LCD_BITS_PER_PIXEL_16_565:
case LCD_BITS_PER_PIXEL_12_444:
// Allocate a temporary buffer
PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
if (PixelBuffer16bit == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
// Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
SizeIn16Bits = Width * 2;
for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
SourcePixelY < SourceY + Height;
SourcePixelY++, DestinationPixel16bit += Width)
{
// Calculate the source address:
SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
// Copy the entire line Y from Video to the temp buffer
CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
}
// Copy from the temp buffer into the destination area of the Video Memory
for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
DestinationPixelY < DestinationY + Height;
DestinationPixelY++, SourcePixel16bit += Width)
{
// Calculate the target address:
DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
// Copy the entire line Y from the temp buffer to Video
CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
}
// Free the allocated memory
FreePool((VOID *) PixelBuffer16bit);
break;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
default:
// Can't handle this case
DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
// break;
}
EXIT:
return Status;
}
STATIC
EFI_STATUS
BltVideoFill (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
)
{
EFI_PIXEL_BITMASK* PixelInformation;
EFI_STATUS Status;
UINT32 HorizontalResolution;
LCD_BPP BitsPerPixel;
VOID *FrameBufferBase;
VOID *DestinationAddr;
UINT16 *DestinationPixel16bit;
UINT16 Pixel16bit;
UINT32 DestinationPixelX;
UINT32 DestinationLine;
UINTN WidthInBytes;
Status = EFI_SUCCESS;
PixelInformation = &This->Mode->Info->PixelInformation;
FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
HorizontalResolution = This->Mode->Info->HorizontalResolution;
LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
switch (BitsPerPixel) {
case LCD_BITS_PER_PIXEL_24:
WidthInBytes = Width * 4;
// Copy the SourcePixel into every pixel inside the target rectangle
for (DestinationLine = DestinationY;
DestinationLine < DestinationY + Height;
DestinationLine++)
{
// Calculate the target address using 32bit pointer arithmetic:
DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
// Fill the entire line
SetMemN( DestinationAddr, WidthInBytes, *((UINTN *)EfiSourcePixel));
}
break;
case LCD_BITS_PER_PIXEL_16_555:
// Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
Pixel16bit = (UINT16) (
( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
// | ( 0 & PixelInformation->ReservedMask )
);
// Copy the SourcePixel into every pixel inside the target rectangle
for (DestinationLine = DestinationY;
DestinationLine < DestinationY + Height;
DestinationLine++)
{
for (DestinationPixelX = DestinationX;
DestinationPixelX < DestinationX + Width;
DestinationPixelX++)
{
// Calculate the target address:
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
*DestinationPixel16bit = Pixel16bit;
}
}
break;
case LCD_BITS_PER_PIXEL_16_565:
// Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
Pixel16bit = (UINT16) (
( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
);
// Copy the SourcePixel into every pixel inside the target rectangle
for (DestinationLine = DestinationY;
DestinationLine < DestinationY + Height;
DestinationLine++)
{
for (DestinationPixelX = DestinationX;
DestinationPixelX < DestinationX + Width;
DestinationPixelX++)
{
// Calculate the target address:
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
*DestinationPixel16bit = Pixel16bit;
}
}
break;
case LCD_BITS_PER_PIXEL_12_444:
// Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
Pixel16bit = (UINT16) (
( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask )
);
// Copy the SourcePixel into every pixel inside the target rectangle
for (DestinationLine = DestinationY;
DestinationLine < DestinationY + Height;
DestinationLine++)
{
for (DestinationPixelX = DestinationX;
DestinationPixelX < DestinationX + Width;
DestinationPixelX++)
{
// Calculate the target address:
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
*DestinationPixel16bit = Pixel16bit;
}
}
break;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
default:
// Can't handle this case
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
Status = EFI_INVALID_PARAMETER;
break;
}
return Status;
}
STATIC
EFI_STATUS
BltVideoToBltBuffer (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
LCD_BPP BitsPerPixel;
EFI_PIXEL_BITMASK *PixelInformation;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
VOID *FrameBufferBase;
VOID *SourceAddr;
VOID *DestinationAddr;
UINT16 *SourcePixel16bit;
UINT16 Pixel16bit;
UINT32 SourcePixelX;
UINT32 SourceLine;
UINT32 DestinationPixelX;
UINT32 DestinationLine;
UINT32 BltBufferHorizontalResolution;
UINTN WidthInBytes;
Status = EFI_SUCCESS;
PixelInformation = &This->Mode->Info->PixelInformation;
HorizontalResolution = This->Mode->Info->HorizontalResolution;
FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
// Delta is not zero and it is different from the width.
// Divide it by the size of a pixel to find out the buffer's horizontal resolution.
BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
} else {
BltBufferHorizontalResolution = Width;
}
LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
switch (BitsPerPixel) {
case LCD_BITS_PER_PIXEL_24:
WidthInBytes = Width * 4;
// Access each line inside the Video Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++)
{
// Calculate the source and target addresses using 32bit pointer arithmetic:
SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
DestinationAddr = (VOID *)((UINT32 *)BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationX);
// Copy the entire line
CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
}
break;
case LCD_BITS_PER_PIXEL_16_555:
// Access each pixel inside the Video Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++)
{
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
// Snapshot the pixel from the video buffer once, to speed up the operation.
// If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
Pixel16bit = *SourcePixel16bit;
// Copy the pixel into the new target
EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 );
EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2);
EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
// EfiDestinationPixel->Reserved = (UINT8) 0;
}
}
break;
case LCD_BITS_PER_PIXEL_16_565:
// Access each pixel inside the Video Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++)
{
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
// Snapshot the pixel from the video buffer once, to speed up the operation.
// If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
Pixel16bit = *SourcePixel16bit;
// Copy the pixel into the new target
// There is no info for the Reserved byte, so we set it to zero
EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 );
EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3);
EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
// EfiDestinationPixel->Reserved = (UINT8) 0;
}
}
break;
case LCD_BITS_PER_PIXEL_12_444:
// Access each pixel inside the Video Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++)
{
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
// Snapshot the pixel from the video buffer once, to speed up the operation.
// If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
Pixel16bit = *SourcePixel16bit;
// Copy the pixel into the new target
EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 );
EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) );
EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 );
// EfiDestinationPixel->Reserved = (UINT8) 0;
}
}
break;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
default:
// Can't handle this case
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
Status = EFI_INVALID_PARAMETER;
break;
}
return Status;
}
STATIC
EFI_STATUS
BltBufferToVideo (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
LCD_BPP BitsPerPixel;
EFI_PIXEL_BITMASK *PixelInformation;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
VOID *FrameBufferBase;
VOID *SourceAddr;
VOID *DestinationAddr;
UINT16 *DestinationPixel16bit;
UINT32 SourcePixelX;
UINT32 SourceLine;
UINT32 DestinationPixelX;
UINT32 DestinationLine;
UINT32 BltBufferHorizontalResolution;
UINTN WidthInBytes;
Status = EFI_SUCCESS;
PixelInformation = &This->Mode->Info->PixelInformation;
HorizontalResolution = This->Mode->Info->HorizontalResolution;
FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
// Delta is not zero and it is different from the width.
// Divide it by the size of a pixel to find out the buffer's horizontal resolution.
BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
} else {
BltBufferHorizontalResolution = Width;
}
LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
switch (BitsPerPixel) {
case LCD_BITS_PER_PIXEL_24:
WidthInBytes = Width * 4;
// Access each pixel inside the BltBuffer Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++)
{
// Calculate the source and target addresses using 32bit pointer arithmetic:
SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX );
DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
// Copy the entire row Y
CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
}
break;
case LCD_BITS_PER_PIXEL_16_555:
// Access each pixel inside the BltBuffer Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++) {
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
// Only the most significant bits will be copied across:
// To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
*DestinationPixel16bit = (UINT16) (
( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
// | ( 0 & PixelInformation->ReservedMask )
);
}
}
break;
case LCD_BITS_PER_PIXEL_16_565:
// Access each pixel inside the BltBuffer Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++) {
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
// Only the most significant bits will be copied across:
// To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits
// There is no room for the Reserved byte so we ignore that completely
*DestinationPixel16bit = (UINT16) (
( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
);
}
}
break;
case LCD_BITS_PER_PIXEL_12_444:
// Access each pixel inside the BltBuffer Memory
for (SourceLine = SourceY, DestinationLine = DestinationY;
SourceLine < SourceY + Height;
SourceLine++, DestinationLine++) {
for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
SourcePixelX < SourceX + Width;
SourcePixelX++, DestinationPixelX++)
{
// Calculate the source and target addresses:
EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
// Copy the pixel into the new target
// Only the most significant bits will be copied across:
// To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
*DestinationPixel16bit = (UINT16) (
( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask )
| ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
| ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask )
// | ( 0 & PixelInformation->ReservedMask )
);
}
}
break;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
default:
// Can't handle this case
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
Status = EFI_INVALID_PARAMETER;
break;
}
return Status;
}
STATIC
EFI_STATUS
BltVideoToVideo (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
LCD_BPP BitsPerPixel;
VOID *FrameBufferBase;
HorizontalResolution = This->Mode->Info->HorizontalResolution;
FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
//
// BltVideo to BltVideo:
//
// Source is the Video Memory,
// Destination is the Video Memory
LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
// The UEFI spec currently states:
// "There is no limitation on the overlapping of the source and destination rectangles"
// Therefore, we must be careful to avoid overwriting the source data
if( SourceY == DestinationY ) {
// Copying within the same height, e.g. horizontal shift
if( SourceX == DestinationX ) {
// Nothing to do
Status = EFI_SUCCESS;
} else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
// There is overlap
Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
} else {
// No overlap
Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
}
} else {
// Copying from different heights
Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
}
return Status;
}
/***************************************
* GraphicsOutput Protocol function, mapping to
* EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
*
* PRESUMES: 1 pixel = 4 bytes (32bits)
* ***************************************/
EFI_STATUS
EFIAPI
LcdGraphicsBlt (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
LCD_INSTANCE* Instance;
Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
// Setup the hardware if not already done
if (!mDisplayInitialized) {
Status = InitializeDisplay (Instance);
if (EFI_ERROR(Status)) {
goto EXIT;
}
}
HorizontalResolution = This->Mode->Info->HorizontalResolution;
VerticalResolution = This->Mode->Info->VerticalResolution;
DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
// Check we have reasonable parameters
if (Width == 0 || Height == 0) {
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}
if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
ASSERT( BltBuffer != NULL);
}
/*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}*/
// If we are reading data out of the video buffer, check that the source area is within the display limits
if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}
}
// If we are writing data into the video buffer, that the destination area is within the display limits
if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}
}
//
// Perform the Block Transfer Operation
//
switch (BltOperation) {
case EfiBltVideoFill:
Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
break;
case EfiBltVideoToBltBuffer:
Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
break;
case EfiBltBufferToVideo:
Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
break;
case EfiBltVideoToVideo:
Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
break;
case EfiGraphicsOutputBltOperationMax:
default:
DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
Status = EFI_INVALID_PARAMETER;
break;
}
EXIT:
return Status;
}

View File

@@ -0,0 +1,379 @@
/** @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 <PiDxe.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Guid/GlobalVariable.h>
#include <ArmPlatform.h>
#include "LcdGraphicsOutputDxe.h"
/**********************************************************************
*
* This file implements the Graphics Output protocol on ArmVersatileExpress
* using the Lcd controller
*
**********************************************************************/
//
// Global variables
//
BOOLEAN mDisplayInitialized = FALSE;
LCD_INSTANCE mLcdTemplate = {
LCD_INSTANCE_SIGNATURE,
NULL, // Handle
{ // ModeInfo
0, // Version
0, // HorizontalResolution
0, // VerticalResolution
PixelBltOnly, // PixelFormat
0, // PixelInformation
0, // PixelsPerScanLine
},
{
0, // 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_EVENT) NULL // ExitBootServicesEvent
};
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->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
Instance->Mode.Info = &Instance->ModeInfo;
*NewInstance = Instance;
return EFI_SUCCESS;
}
//
// Function Definitions
//
EFI_STATUS
InitializeDisplay (
IN LCD_INSTANCE* Instance
)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_PHYSICAL_ADDRESS VramBaseAddress;
UINTN VramSize;
Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
if (EFI_ERROR(Status)) {
return Status;
}
// Setup the LCD
Status = LcdInitialize (VramBaseAddress);
if (EFI_ERROR(Status)) {
goto EXIT_ERROR_LCD_SHUTDOWN;
}
Status = LcdPlatformInitializeDisplay ();
if (EFI_ERROR(Status)) {
goto EXIT_ERROR_LCD_SHUTDOWN;
}
// Setup all the relevant mode information
Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
Instance->Gop.Mode->FrameBufferSize = VramSize;
// Set the flag before changing the mode, to avoid infinite loops
mDisplayInitialized = TRUE;
// All is ok, so don't deal with any errors
goto EXIT;
EXIT_ERROR_LCD_SHUTDOWN:
DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
LcdShutdown ();
EXIT:
return Status;
}
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;
}
/***************************************
* This function should be called
* on Event: ExitBootServices
* to free up memory, stop the driver
* and uninstall the protocols
***************************************/
VOID
LcdGraphicsExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//TODO: Implement me
}
/***************************************
* GraphicsOutput Protocol function, mapping to
* EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
***************************************/
EFI_STATUS
EFIAPI
LcdGraphicsQueryMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber,
OUT UINTN *SizeOfInfo,
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
)
{
EFI_STATUS Status = EFI_SUCCESS;
LCD_INSTANCE *Instance;
Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
// Setup the hardware if not already done
if( !mDisplayInitialized ) {
Status = InitializeDisplay(Instance);
if (EFI_ERROR(Status)) {
goto EXIT;
}
}
// 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 ));
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}
*Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
if (*Info == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
*SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
Status = LcdPlatformQueryMode (ModeNumber,*Info);
if (EFI_ERROR(Status)) {
FreePool(*Info);
}
EXIT:
return Status;
}
/***************************************
* GraphicsOutput Protocol function, mapping to
* EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
***************************************/
EFI_STATUS
EFIAPI
LcdGraphicsSetMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber
)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;
LCD_INSTANCE* Instance;
Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
// Setup the hardware if not already done
if(!mDisplayInitialized) {
Status = InitializeDisplay (Instance);
if (EFI_ERROR(Status)) {
goto EXIT;
}
}
// Check if this mode is supported
if( ModeNumber >= This->Mode->MaxMode ) {
DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
Status = EFI_UNSUPPORTED;
goto EXIT;
}
// Set the oscillator frequency to support the new mode
Status = LcdPlatformSetMode (ModeNumber);
if (EFI_ERROR(Status)) {
Status = EFI_DEVICE_ERROR;
goto EXIT;
}
// Update the UEFI mode information
This->Mode->Mode = ModeNumber;
LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
// Set the hardware to the new mode
Status = LcdSetMode (ModeNumber);
if (EFI_ERROR(Status)) {
Status = EFI_DEVICE_ERROR;
goto EXIT;
}
// The UEFI spec requires that we now clear the visible portions of the output display to black.
// Set the fill colour to black
SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
// Fill the entire visible area with the same colour.
Status = This->Blt (
This,
&FillColour,
EfiBltVideoFill,
0,
0,
0,
0,
This->Mode->Info->HorizontalResolution,
This->Mode->Info->VerticalResolution,
0);
EXIT:
return Status;
}
UINTN
GetBytesPerPixel (
IN LCD_BPP Bpp
)
{
switch(Bpp) {
case LCD_BITS_PER_PIXEL_24:
return 4;
case LCD_BITS_PER_PIXEL_16_565:
case LCD_BITS_PER_PIXEL_16_555:
case LCD_BITS_PER_PIXEL_12_444:
return 2;
case LCD_BITS_PER_PIXEL_8:
case LCD_BITS_PER_PIXEL_4:
case LCD_BITS_PER_PIXEL_2:
case LCD_BITS_PER_PIXEL_1:
return 1;
default:
return 0;
}
}

View File

@@ -0,0 +1,124 @@
/** @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.
**/
#ifndef __ARM_VE_GRAPHICS_DXE_H__
#define __ARM_VE_GRAPHICS_DXE_H__
#include <Base.h>
#include <Library/UefiLib.h>
#include <Protocol/DevicePath.h>
#include <Library/LcdPlatformLib.h>
//
// Device structures
//
typedef struct {
VENDOR_DEVICE_PATH Guid;
EFI_DEVICE_PATH_PROTOCOL End;
} LCD_GRAPHICS_DEVICE_PATH;
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE Mode;
EFI_GRAPHICS_OUTPUT_PROTOCOL Gop;
LCD_GRAPHICS_DEVICE_PATH DevicePath;
EFI_EVENT ExitBootServicesEvent;
} LCD_INSTANCE;
#define LCD_INSTANCE_SIGNATURE SIGNATURE_32('l', 'c', 'd', '0')
#define LCD_INSTANCE_FROM_GOP_THIS(a) CR (a, LCD_INSTANCE, Gop, LCD_INSTANCE_SIGNATURE)
//
// Function Prototypes
//
VOID
LcdGraphicsExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
);
EFI_STATUS
EFIAPI
LcdGraphicsQueryMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber,
OUT UINTN *SizeOfInfo,
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
);
EFI_STATUS
EFIAPI
LcdGraphicsSetMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber
);
EFI_STATUS
EFIAPI
LcdGraphicsBlt (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL
);
UINTN
GetBytesPerPixel (
IN LCD_BPP Bpp
);
EFI_STATUS
EFIAPI
GraphicsOutputDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
InitializeDisplay (
IN LCD_INSTANCE* Instance
);
EFI_STATUS
LcdIndentify (
VOID
);
EFI_STATUS
LcdInitialize (
EFI_PHYSICAL_ADDRESS VramBaseAddress
);
EFI_STATUS
LcdSetMode (
IN UINT32 ModeNumber
);
VOID
LcdShutdown (
VOID
);
#endif /* __ARM_VE_GRAPHICS_DXE_H__ */

View File

@@ -0,0 +1,140 @@
/** @file PL111Lcd.c
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 <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/LcdPlatformLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Drivers/PL111Lcd.h>
#include "LcdGraphicsOutputDxe.h"
/**********************************************************************
*
* This file contains all the bits of the PL111 that are
* platform independent.
*
**********************************************************************/
EFI_STATUS
PL111Indentify (
VOID
)
{
// Check if this is a PrimeCell Peripheral
if ( ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_0 ) != 0x0D )
|| ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_1 ) != 0xF0 )
|| ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_2 ) != 0x05 )
|| ( MmioRead8( PL111_REG_CLCD_P_CELL_ID_3 ) != 0xB1 ) ) {
return EFI_NOT_FOUND;
}
// Check if this PrimeCell Peripheral is the PL111 LCD
if ( ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_0 ) != 0x11 )
|| ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_1 ) != 0x11 )
|| ( (MmioRead8( PL111_REG_CLCD_PERIPH_ID_2 ) & 0xF) != 0x04 )
|| ( MmioRead8( PL111_REG_CLCD_PERIPH_ID_3 ) != 0x00 ) ) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
EFI_STATUS
LcdInitialize (
IN EFI_PHYSICAL_ADDRESS VramBaseAddress
)
{
EFI_STATUS Status = EFI_SUCCESS;
// Check if the PL111 is fitted on this motherboard
Status = PL111Indentify();
if (EFI_ERROR( Status )) {
return EFI_DEVICE_ERROR;
}
// Define start of the VRAM. This never changes for any graphics mode
MmioWrite32(PL111_REG_LCD_UP_BASE, (UINT32) VramBaseAddress);
MmioWrite32(PL111_REG_LCD_LP_BASE, 0); // We are not using a double buffer
// Disable all interrupts from the PL111
MmioWrite32(PL111_REG_LCD_IMSC, 0);
return EFI_SUCCESS;
}
EFI_STATUS
LcdSetMode (
IN UINT32 ModeNumber
)
{
EFI_STATUS Status;
UINT32 HRes;
UINT32 HSync;
UINT32 HBackPorch;
UINT32 HFrontPorch;
UINT32 VRes;
UINT32 VSync;
UINT32 VBackPorch;
UINT32 VFrontPorch;
UINT32 LcdControl;
LCD_BPP LcdBpp;
// Set the video mode timings and other relevant information
Status = LcdPlatformGetTimings (ModeNumber,
&HRes,&HSync,&HBackPorch,&HFrontPorch,
&VRes,&VSync,&VBackPorch,&VFrontPorch);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR( Status )) {
return EFI_DEVICE_ERROR;
}
Status = LcdPlatformGetBpp (ModeNumber,&LcdBpp);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR( Status )) {
return EFI_DEVICE_ERROR;
}
// Disable the CLCD_LcdEn bit
LcdControl = MmioRead32( PL111_REG_LCD_CONTROL);
MmioWrite32(PL111_REG_LCD_CONTROL, LcdControl & ~1);
// Set Timings
MmioWrite32 (PL111_REG_LCD_TIMING_0, HOR_AXIS_PANEL(HBackPorch, HFrontPorch, HSync, HRes));
MmioWrite32 (PL111_REG_LCD_TIMING_1, VER_AXIS_PANEL(VBackPorch, VFrontPorch, VSync, VRes));
MmioWrite32 (PL111_REG_LCD_TIMING_2, CLK_SIG_POLARITY(HRes));
MmioWrite32 (PL111_REG_LCD_TIMING_3, 0);
// PL111_REG_LCD_CONTROL
LcdControl = PL111_CTRL_LCD_EN | PL111_CTRL_LCD_BPP(LcdBpp) | PL111_CTRL_LCD_TFT | PL111_CTRL_BGR;
MmioWrite32(PL111_REG_LCD_CONTROL, LcdControl);
// Turn on power to the LCD Panel
LcdControl |= PL111_CTRL_LCD_PWR;
MmioWrite32(PL111_REG_LCD_CONTROL, LcdControl);
return EFI_SUCCESS;
}
VOID
LcdShutdown (
VOID
)
{
// Nothing to do in terms of hardware.
// We could switch off the monitor display if required
//TODO: ImplementMe
}

View File

@@ -0,0 +1,60 @@
#/** @file
#
# Component discription file for ArmVeGraphicsDxe module
#
# 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PL111LcdGraphicsDxe
FILE_GUID = 407B4008-BF5B-11DF-9547-CF16E0D72085
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = LcdGraphicsOutputDxeInitialize
[Sources.common]
LcdGraphicsOutputDxe.c
LcdGraphicsOutputBlt.c
PL111Lcd.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
[LibraryClasses]
ArmLib
UefiLib
BaseLib
DebugLib
TimerLib
UefiDriverEntryPoint
UefiBootServicesTableLib
IoLib
BaseMemoryLib
LcdPlatformLib
[Guids]
[Protocols]
gEfiDevicePathProtocolGuid
gEfiGraphicsOutputProtocolGuid
[FixedPcd.common]
[Pcd.common]
[Depex]
gEfiCpuArchProtocolGuid