Nico Huber has uploaded this change for review. ( https://review.coreboot.org/22708
Change subject: gma registers: Add procedures to set fence registers ......................................................................
gma registers: Add procedures to set fence registers
Through fence registers, we can tell the hardware which parts of the aperture cover tiled framebuffers. Only legacy X and Y tiling is sup- ported. According to `i915_reg.h` there are 16 fence registers from G4x on and 32 from Ivy Bridge on (this only partially matches docu- mentation: Haswell has 16 regs documented and the fence registers were not documented at all before).
Change-Id: I02edc99b315e24dc175c6f93aff627e59cb1ff0b Signed-off-by: Nico Huber nico.huber@secunet.com --- M common/hw-gfx-gma-config.ads.template M common/hw-gfx-gma-registers.adb M common/hw-gfx-gma-registers.ads M common/hw-gfx.ads 4 files changed, 90 insertions(+), 7 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/08/22708/1
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template index e82b133..252b023 100644 --- a/common/hw-gfx-gma-config.ads.template +++ b/common/hw-gfx-gma-config.ads.template @@ -287,4 +287,12 @@ when Ironlake .. Haswell => 4, when Broadwell .. Skylake => 8);
+ Fence_Base : constant := (case CPU is + when Ironlake => 16#0000_3000#, + when Sandybridge .. Skylake => 16#0010_0000#); + + Fence_Count : constant := (case CPU is + when Ironlake .. Sandybridge => 16, + when Ivybridge .. Skylake => 32); + end HW.GFX.GMA.Config; diff --git a/common/hw-gfx-gma-registers.adb b/common/hw-gfx-gma-registers.adb index 4a22564..94965d5 100644 --- a/common/hw-gfx-gma-registers.adb +++ b/common/hw-gfx-gma-registers.adb @@ -61,19 +61,84 @@
----------------------------------------------------------------------------
+ subtype Fence_Range is Registers_Range range 0 .. Config.Fence_Count - 1; + + FENCE_PAGE_SHIFT : constant := 12; + FENCE_PAGE_MASK : constant := 16#ffff_f000#; + FENCE_TILE_WALK_YMAJOR : constant := 1 * 2 ** 1; + FENCE_VALID : constant := 1 * 2 ** 0; + + function Fence_Lower_Idx (Fence : Fence_Range) return Registers_Range is + (Config.Fence_Base / Register_Width + 2 * Fence); + function Fence_Upper_Idx (Fence : Fence_Range) return Registers_Range is + (Fence_Lower_Idx (Fence) + 1); + procedure Clear_Fences is - Fence_Regs_Base : constant := - (case Config.CPU is - when Ironlake => 16#00_3000#, - when Sandybridge .. Skylake => 16#10_0000#); - subtype Fence_Range is Registers_Range range 0 .. 63; begin - for Idx in Fence_Range loop - Regs.Write (Fence_Regs_Base / Register_Width + Idx, 0); + for Fence in Fence_Range loop + Regs.Write (Fence_Lower_Idx (Fence), 0); end loop; end Clear_Fences;
+ procedure Add_Fence + (First_Page : in GTT_Range; + Last_Page : in GTT_Range; + Tiling : in XY_Tiling; + Pitch : in Natural; + Success : out Boolean) + is + Y_Tiles : constant Boolean := Tiling = Y_Tiled; + Reg32 : Word32; + begin + pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": ")); + pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (First_Page), 12))); + pragma Debug (Debug.Put (":")); + pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (Last_Page), 12))); + pragma Debug (not Y_Tiles, Debug.Put (" X tiled in ")); + pragma Debug ( Y_Tiles, Debug.Put (" Y tiled in ")); + pragma Debug (Debug.Put_Int32 (Int32 (Pitch))); + pragma Debug (Debug.Put_Line (" tiles per row.")); + + Success := False; + for Fence in Fence_Range loop + Regs.Read (Reg32, Fence_Lower_Idx (Fence)); + if (Reg32 and FENCE_VALID) = 0 then + Regs.Write + (Index => Fence_Lower_Idx (Fence), + Value => Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT) or + (if Y_Tiles then FENCE_TILE_WALK_YMAJOR else 0) or + FENCE_VALID); + Regs.Write + (Index => Fence_Upper_Idx (Fence), + Value => Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT) or + Word32 (Pitch) * (if Y_Tiles then 1 else 4) - 1); + Success := True; + exit; + end if; + end loop; + end Add_Fence; + + procedure Remove_Fence (First_Page, Last_Page : GTT_Range) + is + Page_Lower : constant Word32 := + Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT); + Page_Upper : constant Word32 := + Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT); + Fence_Upper, Fence_Lower : Word32; + begin + for Fence in Fence_Range loop + Regs.Read (Fence_Lower, Fence_Lower_Idx (Fence)); + Regs.Read (Fence_Upper, Fence_Upper_Idx (Fence)); + if (Fence_Lower and FENCE_PAGE_MASK) = Page_Lower and + (Fence_Upper and FENCE_PAGE_MASK) = Page_Upper + then + Regs.Write (Fence_Lower_Idx (Fence), 0); + exit; + end if; + end loop; + end Remove_Fence; + ----------------------------------------------------------------------------
procedure Write_GTT diff --git a/common/hw-gfx-gma-registers.ads b/common/hw-gfx-gma-registers.ads index 2a01aab..87c8069 100644 --- a/common/hw-gfx-gma-registers.ads +++ b/common/hw-gfx-gma-registers.ads @@ -1531,6 +1531,15 @@
procedure Clear_Fences;
+ procedure Add_Fence + (First_Page : in GTT_Range; + Last_Page : in GTT_Range; + Tiling : in XY_Tiling; + Pitch : in Natural; + Success : out Boolean); + + procedure Remove_Fence (First_Page, Last_Page : GTT_Range); + pragma Warnings (Off, "declaration of ""Write_GTT"" hides one at *"); procedure Write_GTT (GTT_Page : GTT_Range; diff --git a/common/hw-gfx.ads b/common/hw-gfx.ads index ae19235..c5d9631 100644 --- a/common/hw-gfx.ads +++ b/common/hw-gfx.ads @@ -28,6 +28,7 @@ subtype BPC_Type is Int64 range Auto_BPC .. 16;
type Tiling_Type is (Linear, X_Tiled, Y_Tiled); + subtype XY_Tiling is Tiling_Type range X_Tiled .. Y_Tiled;
type Framebuffer_Type is record