gma: Add support for rotated framebuffers
As for the tiling, we enable support for rotated framebuffers on
platforms with Plane_Control. On every path where a rotated frame-
buffer may be expected, we have to exchange width and height in
case of 90 degree rotations. Beside the rotation setting itself,
the hardware needs to know the vertical stride instead of the hori-
zontal and a delicate page mapping in case of 90 degree rotations.
For that we divide the GTT space into two, the lower half contains
the linear mappings, the upper half mappings for a rotated scanout.
Change-Id: I1c901b7abc0fe7764bee87f6fda58ba9fa3f340d
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/22711
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Tested-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index e4ad3b3..d8438ab 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -479,7 +479,7 @@
-- Check basics and that it fits in GTT
function Valid_FB (FB : Framebuffer_Type) return Boolean is
- (Valid_Stride (FB) and FB_Last_Page (FB) <= GTT_Range'Last);
+ (Valid_Stride (FB) and FB_Last_Page (FB) < GTT_Rotation_Offset);
-- Also check that we don't overflow the GTT's 39-bit space
-- (always true with a 32-bit base)
@@ -514,6 +514,30 @@
Valid => True);
Phys_Addr := Phys_Addr + GTT_Page_Size;
end loop;
+
+ if Rotation_90 (FB) and FB.Tiling = Y_Tiled and FB.V_Stride >= 32 then
+ declare
+ V_Pages : constant Natural := Natural (FB.V_Stride) / 32;
+ Bytes_Per_Row : constant GTT_Address_Type :=
+ GTT_Address_Type (Pixel_To_Bytes (32 * FB.Stride, FB));
+ begin
+ Phys_Addr := GTT_Address_Type (Phys_Base) +
+ GTT_Address_Type (FB.Offset) +
+ GTT_Address_Type (FB_Size (FB));
+ for Page in FB_First_Page (FB) .. FB_Last_Page (FB) loop
+ Phys_Addr := Phys_Addr - Bytes_Per_Row;
+ Registers.Write_GTT
+ (GTT_Page => GTT_Rotation_Offset + Page,
+ Device_Address => Phys_Addr,
+ Valid => True);
+
+ if (Page - FB_First_Page (FB) + 1) mod V_Pages = 0 then
+ Phys_Addr := Phys_Addr + GTT_Page_Size +
+ GTT_Address_Type (V_Pages) * Bytes_Per_Row;
+ end if;
+ end loop;
+ end;
+ end if;
end Setup_Default_GTT;
----------------------------------------------------------------------------