diff --git a/edk2-rockchip/Platform/FydeInnovations/FydetabDuo/FydetabDuo.dsc b/edk2-rockchip/Platform/FydeInnovations/FydetabDuo/FydetabDuo.dsc index 7875625f..b7e93c74 100644 --- a/edk2-rockchip/Platform/FydeInnovations/FydetabDuo/FydetabDuo.dsc +++ b/edk2-rockchip/Platform/FydeInnovations/FydetabDuo/FydetabDuo.dsc @@ -92,6 +92,11 @@ gRK3588TokenSpaceGuid.PcdUsbDpPhy0Supported|TRUE gRK3588TokenSpaceGuid.PcdDp0LaneMux|{ 0x2, 0x3 } + # + # Landscape graphics output + # + gRockchipTokenSpaceGuid.PcdLcdRotateToLandscape|TRUE + # # I2S # diff --git a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c index a92f5f86..5f7d711a 100644 --- a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c +++ b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c @@ -830,6 +830,290 @@ BltVideoToVideo ( return Status; } +STATIC +EFI_STATUS +BltVideoFill90 ( + 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_STATUS Status; + UINT32 FrameBufferHeight; + VOID *FrameBufferBase; + VOID *DestinationAddr; + + Status = EFI_SUCCESS; + FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); + FrameBufferHeight = This->Mode->Info->VerticalResolution; + + for (UINTN y = 0; y < Height; ++y) { + for (UINTN x = 0; x < Width; ++x) { + DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + (DestinationX + x) * FrameBufferHeight + (FrameBufferHeight - 1 - (DestinationY + y))); + + *(UINT32 *)DestinationAddr = *((UINT32 *)EfiSourcePixel); + } + } + + return Status; +} + +STATIC +EFI_STATUS +BltVideoToBltBuffer90 ( + 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 FrameBufferHeight; + VOID *FrameBufferBase; + VOID *SourceAddr; + VOID *DestinationAddr; + UINT32 BltBufferHorizontalResolution; + + Status = EFI_SUCCESS; + FrameBufferHeight = This->Mode->Info->VerticalResolution; + 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; + } + + for (UINTN y = 0; y < Height; ++y) { + for (UINTN x = 0; x < Width; ++x) { + SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + (SourceX + x) * FrameBufferHeight + (FrameBufferHeight - 1 - (SourceY + y))); + DestinationAddr = (VOID *)((UINT32 *)BltBuffer + (DestinationY + y) * BltBufferHorizontalResolution + (DestinationX + x)); + + *(UINT32 *)DestinationAddr = *(UINT32 *)SourceAddr; + } + } + + return Status; +} + +STATIC +EFI_STATUS +BltBufferToVideo90 ( + 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 FrameBufferHeight; + VOID *FrameBufferBase; + VOID *SourceAddr; + VOID *DestinationAddr; + UINT32 BltBufferHorizontalResolution; + + Status = EFI_SUCCESS; + FrameBufferHeight = This->Mode->Info->VerticalResolution; + 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; + } + + for (UINTN y = 0; y < Height; ++y) { + for (UINTN x = 0; x < Width; ++x) { + SourceAddr = (VOID *)((UINT32 *)BltBuffer + (SourceY + y) * BltBufferHorizontalResolution + (SourceX + x)); + DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + (DestinationX + x) * FrameBufferHeight + (FrameBufferHeight - 1 - (DestinationY + y))); + + *(UINT32 *)DestinationAddr = *(UINT32 *)SourceAddr; + } + } + + return Status; +} + +STATIC +EFI_STATUS +VideoCopyNoHorizontalOverlap90 ( + IN UINTN BitsPerPixel, + IN volatile VOID *FrameBufferBase, + IN UINT32 VerticalResolution, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height +) +{ + EFI_STATUS Status; + UINTN SourceLine; + UINTN DestinationLine; + UINTN LineCount; + INTN Step; + VOID *SourceAddr; + VOID *DestinationAddr; + + Status = EFI_SUCCESS; + + 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; + } + + for (LineCount = 0; LineCount < Height; LineCount++) { + for (UINTN x = 0; x < Width; ++x) { + SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + (SourceX + x) * VerticalResolution + (VerticalResolution - 1 - SourceLine)); + DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + (DestinationX + x) * VerticalResolution + (VerticalResolution - 1 - DestinationLine)); + + *(UINT32 *)DestinationAddr = *(UINT32 *)SourceAddr; + } + + SourceLine += Step; + DestinationLine += Step; + } + + return Status; +} + +STATIC +EFI_STATUS +VideoCopyHorizontalOverlap90 ( + IN UINTN BitsPerPixel, + IN volatile VOID *FrameBufferBase, + IN UINT32 VerticalResolution, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height +) +{ + EFI_STATUS Status; + + UINT32 *PixelBuffer32bit; + UINT32 *SourcePixel32bit; + UINT32 *DestinationPixel32bit; + + Status = EFI_SUCCESS; + + // Allocate a temporary buffer + PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32)); + + if (PixelBuffer32bit == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + // Copy from the video ram (source region) to a temp buffer + for (UINTN y = 0; y < Height; ++y) { + for (UINTN x = 0; x < Width; ++x) { + SourcePixel32bit = (UINT32 *)FrameBufferBase + (SourceX + x) * VerticalResolution + (VerticalResolution - 1 - (SourceY + y)); + + PixelBuffer32bit[y * Width + x] = *SourcePixel32bit; + } + } + + // Copy from the temp buffer to the video ram (destination region) + for (UINTN y = 0; y < Height; ++y) { + for (UINTN x = 0; x < Width; ++x) { + DestinationPixel32bit = (UINT32 *)FrameBufferBase + (DestinationX + x) * VerticalResolution + (VerticalResolution - 1 - (DestinationY + y)); + + *DestinationPixel32bit = PixelBuffer32bit[y * Width + x]; + } + } + + // Free up the allocated memory + FreePool((VOID *) PixelBuffer32bit); + +EXIT: + return Status; +} + +STATIC +EFI_STATUS +BltVideoToVideo90 ( + 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 VerticalResolution; + LCD_BPP BitsPerPixel; + VOID *FrameBufferBase; + + VerticalResolution = This->Mode->Info->VerticalResolution; + FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); + + // + // BltVideo to BltVideo: + // + // Source is the Video Memory, + // Destination is the Video Memory + + LcdGraphicsGetBpp (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 = VideoCopyHorizontalOverlap90 (BitsPerPixel, FrameBufferBase, VerticalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); + } else { + // No overlap + Status = VideoCopyNoHorizontalOverlap90 (BitsPerPixel, FrameBufferBase, VerticalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); + } + } else { + // Copying from different heights + Status = VideoCopyNoHorizontalOverlap90 (BitsPerPixel, FrameBufferBase, VerticalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); + } + + return Status; +} + /*************************************** * GraphicsOutput Protocol function, mapping to * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt @@ -907,21 +1191,39 @@ LcdGraphicsBlt ( // Perform the Block Transfer Operation // + BOOLEAN LandscapeMode = FixedPcdGetBool (PcdLcdRotateToLandscape); + switch (BltOperation) { case EfiBltVideoFill: - Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + if (LandscapeMode) { + Status = BltVideoFill90 (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + } else { + 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); + if (LandscapeMode) { + Status = BltVideoToBltBuffer90 (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + } else { + 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); + if (LandscapeMode) { + Status = BltBufferToVideo90 (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + } else { + 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); + if (LandscapeMode) { + Status = BltVideoToVideo90 (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + } else { + Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); + } break; case EfiGraphicsOutputBltOperationMax: diff --git a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c index 88822401..84f58694 100644 --- a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c +++ b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c @@ -503,8 +503,15 @@ LcdGraphicsQueryMode ( *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); (*Info)->Version = 0; - (*Info)->HorizontalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; - (*Info)->VerticalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + + if (FixedPcdGetBool (PcdLcdRotateToLandscape)) { + (*Info)->HorizontalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + (*Info)->VerticalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; + } else { + (*Info)->HorizontalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; + (*Info)->VerticalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + } + (*Info)->PixelsPerScanLine = mDisplayModes[ModeNumber].Horizontal.Resolution; (*Info)->PixelFormat = FixedPcdGet32 (PcdLcdPixelFormat); @@ -597,8 +604,15 @@ LcdGraphicsSetMode ( This->Mode->Mode = ModeNumber; Instance->ModeInfo.Version = 0; - Instance->ModeInfo.HorizontalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; - Instance->ModeInfo.VerticalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + + if (FixedPcdGetBool (PcdLcdRotateToLandscape)) { + Instance->ModeInfo.HorizontalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + Instance->ModeInfo.VerticalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; + } else { + Instance->ModeInfo.HorizontalResolution = mDisplayModes[ModeNumber].Horizontal.Resolution; + Instance->ModeInfo.VerticalResolution = mDisplayModes[ModeNumber].Vertical.Resolution; + } + Instance->ModeInfo.PixelsPerScanLine = mDisplayModes[ModeNumber].Horizontal.Resolution; Instance->ModeInfo.PixelFormat = FixedPcdGet32 (PcdLcdPixelFormat); Instance->Mode.SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); diff --git a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf index bd2eb1ff..6fe90fd7 100644 --- a/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf +++ b/edk2-rockchip/Silicon/Rockchip/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf @@ -54,6 +54,7 @@ [Pcd] gRockchipTokenSpaceGuid.PcdLcdPixelFormat + gRockchipTokenSpaceGuid.PcdLcdRotateToLandscape [FeaturePcd] gArmPlatformTokenSpaceGuid.PcdGopDisableOnExitBootServices diff --git a/edk2-rockchip/Silicon/Rockchip/RockchipPkg.dec b/edk2-rockchip/Silicon/Rockchip/RockchipPkg.dec index a893b4ed..26f65a20 100644 --- a/edk2-rockchip/Silicon/Rockchip/RockchipPkg.dec +++ b/edk2-rockchip/Silicon/Rockchip/RockchipPkg.dec @@ -90,6 +90,7 @@ gRockchipTokenSpaceGuid.PcdNvStoragePreferSpiFlash|FALSE|BOOLEAN|0x21200009 gRockchipTokenSpaceGuid.PcdLcdPixelFormat|0|UINT32|0x32000001 + gRockchipTokenSpaceGuid.PcdLcdRotateToLandscape|FALSE|BOOLEAN|0x32000002 gRockchipTokenSpaceGuid.PcdEdpId|0|UINT32|0x32000003 gRockchipTokenSpaceGuid.PcdHdmiId|0|UINT32|0x32000004 gRockchipTokenSpaceGuid.PcdHdmiDDCI2CPinMux|0|UINT32|0x32000005