gma pipe: Fix source size and scaler limits for Tiger Lake
Some more changes came with Tiger Lake:
* The source size of the display pipeline must have an even width.
* The scaler setup changed: There is no "Scaler Mode" anymore, and
the scaling limits have been lifted.
Change-Id: If6916c43ce986bad4fc652649539de2adbb934ea
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/477
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index 3b21351..93e7ca4 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -212,6 +212,8 @@
Has_Pipeconf_Misc : <hswbool> := Broadwell_On;
Has_Pipeconf_BPC : <hswbool> := not CPU_Haswell;
Has_Plane_Control : <genbool> := Broxton_On;
+ Needs_Even_Source_Width : <genbool> := Tigerlake_On;
+ Has_Skylake_Scaler_Limits : <genbool> := Gen_Broxton or Gen_Skylake;
Has_DSP_Linoff : <genbool> := Up_To_Ironlake;
Has_DSPSURF : <genbool> := G45_On;
Has_PF_Pipe_Select : <ilkhswbool> := CPU_Ivybridge or CPU_Haswell;
diff --git a/common/hw-gfx-gma-pipe_setup.adb b/common/hw-gfx-gma-pipe_setup.adb
index 941a5e7..cb5369e 100644
--- a/common/hw-gfx-gma-pipe_setup.adb
+++ b/common/hw-gfx-gma-pipe_setup.adb
@@ -160,10 +160,20 @@
---------------------------------------------------------------------------
- function Encode (LSW, MSW : Pos32) return Word32 is
- begin
- return Shift_Left (Word32 (MSW) - 1, 16) or (Word32 (LSW) - 1);
- end Encode;
+ function Encode_Size (LSW, MSW : Word32) return Word32
+ is
+ (Shift_Left (MSW - 1, 16) or (LSW - 1));
+
+ function Prepare_Source_Width (Framebuffer : Framebuffer_Type) return Word32
+ is
+ (if Config.Needs_Even_Source_Width then
+ Word32 (Rotated_Width (Framebuffer)) and not 1
+ else
+ Word32 (Rotated_Width (Framebuffer)));
+
+ function Prepare_Source_Height (Framebuffer : Framebuffer_Type) return Word32
+ is
+ (Word32 (Rotated_Height (Framebuffer)));
----------------------------------------------------------------------------
@@ -218,6 +228,9 @@
with
Pre => FB.Height + FB.Start_Y <= FB.V_Stride
is
+ Width : constant Word32 := Prepare_Source_Width (FB);
+ Height : constant Word32 := Prepare_Source_Height (FB);
+
-- FIXME: setup correct format, based on framebuffer RGB format
Format : constant Word32 := 6 * 2 ** 26;
PRI : Word32 := Format;
@@ -227,8 +240,6 @@
if Config.Has_Plane_Control then
declare
Stride, Offset : Word32;
- Width : constant Width_Type := Rotated_Width (FB);
- Height : constant Width_Type := Rotated_Height (FB);
function PLANE_CTL_ARB_SLOTS (N : Word32) return Word32 is
(if Config.Need_Pipe_Arb_Slots then Shift_Left (N, 28) else 0);
@@ -264,7 +275,7 @@
Registers.Write (Controller.PLANE_AUX_DIST, 0);
Registers.Write (Controller.PLANE_CTL, Plane_Ctl);
Registers.Write (Controller.PLANE_OFFSET, Offset);
- Registers.Write (Controller.PLANE_SIZE, Encode (Width, Height));
+ Registers.Write (Controller.PLANE_SIZE, Encode_Size (Width, Height));
Registers.Write (Controller.PLANE_STRIDE, Stride);
Registers.Write (Controller.PLANE_POS, 16#0000_0000#);
Registers.Write (Controller.PLANE_SURF, FB.Offset and 16#ffff_f000#);
@@ -294,9 +305,7 @@
-- Gen3 (i945): program DSPSIZE and DSPPOS before the surface
-- address write that arms the double-buffered plane registers.
if Config.Gen_I945 then
- Registers.Write
- (Controller.DSPSIZE,
- Encode (Rotated_Width (FB), Rotated_Height (FB)));
+ Registers.Write (Controller.DSPSIZE, Encode_Size (Width, Height));
Registers.Write (Controller.DSPPOS, 16#0000_0000#);
end if;
@@ -412,6 +421,9 @@
-- using DSC, or using PSR2.
-- i915 always disables underrun recovery for gen 13+.
UNDERRUN_RECOVERY_DISABLE : constant := 1 * 2 ** 30;
+
+ Width : constant Word32 := Prepare_Source_Width (Framebuffer);
+ Height : constant Word32 := Prepare_Source_Height (Framebuffer);
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
@@ -462,8 +474,7 @@
Registers.Write
(Register => Controller.PIPESRC,
- Value => Encode
- (Rotated_Height (Framebuffer), Rotated_Width (Framebuffer)));
+ Value => Encode_Size (Height, Width));
if Config.Has_Pipeconf_Misc then
Registers.Write
@@ -555,6 +566,58 @@
end case;
end Scale_Keep_Aspect;
+ type Pipe_Scaler_Limit_Config is record
+ Control : Word32;
+ Horizontal : Pos32;
+ Vertical : Pos32;
+ end record;
+
+ function Skylake_Scaler_Limits
+ (Controller : Controller_Type;
+ Width : Width_Type;
+ Height : Height_Type)
+ return Pipe_Scaler_Limit_Config
+ with
+ Post => Skylake_Scaler_Limits'Result.Horizontal >= Width
+ and Skylake_Scaler_Limits'Result.Vertical >= Height
+ is
+ use type Registers.Registers_Invalid_Index;
+
+ -- Enable 7x5 extended mode where possible:
+ Scaler_Mode : constant Word32 :=
+ (if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
+ PS_CTRL_SCALER_MODE_7X5_EXTENDED else 0);
+
+ -- We can scale up to 2.99x horizontally:
+ Horizontal_Limit : constant Pos32 := (Width * 299) / 100;
+ -- The third scaler is limited to 1.99x
+ -- vertical scaling for source widths > 2048:
+ Vertical_Limit : constant Pos32 :=
+ (Height *
+ (if Controller.PS_CTRL_2 = Registers.Invalid_Register and
+ Width > 2048
+ then
+ 199
+ else
+ 299)) / 100;
+ begin
+ return (Scaler_Mode, Horizontal_Limit, Vertical_Limit);
+ end Skylake_Scaler_Limits;
+
+ function Tigerlake_Scaler_Limits
+ (Width : Width_Type;
+ Height : Height_Type)
+ return Pipe_Scaler_Limit_Config
+ with
+ Post => Tigerlake_Scaler_Limits'Result.Horizontal >= Width
+ and Tigerlake_Scaler_Limits'Result.Vertical >= Height
+ is
+ Scaling : constant := 32_000; -- PRM says: Scaling * 2**15 >= 1.0
+ -- so virtually unlimited
+ begin
+ return (Control => 0, Horizontal => Width * Scaling, Vertical => Height * Scaling);
+ end Tigerlake_Scaler_Limits;
+
procedure Setup_Skylake_Pipe_Scaler
(Controller : in Controller_Type;
Mode : in HW.GFX.Mode_Type;
@@ -564,28 +627,13 @@
Rotated_Width (Framebuffer) <= Mode.H_Visible and
Rotated_Height (Framebuffer) <= Mode.V_Visible
is
- use type Registers.Registers_Invalid_Index;
-
- -- Enable 7x5 extended mode where possible:
- Scaler_Mode : constant Word32 :=
- (if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
- PS_CTRL_SCALER_MODE_7X5_EXTENDED else 0);
-
Width_In : constant Width_Type := Rotated_Width (Framebuffer);
Height_In : constant Height_Type := Rotated_Height (Framebuffer);
-
- -- We can scale up to 2.99x horizontally:
- Horizontal_Limit : constant Pos32 := (Width_In * 299) / 100;
- -- The third scaler is limited to 1.99x
- -- vertical scaling for source widths > 2048:
- Vertical_Limit : constant Pos32 :=
- (Height_In *
- (if Controller.PS_CTRL_2 = Registers.Invalid_Register and
- Width_In > 2048
- then
- 199
- else
- 299)) / 100;
+ Limits : constant Pipe_Scaler_Limit_Config :=
+ (if Config.Has_Skylake_Scaler_Limits then
+ Skylake_Scaler_Limits (Controller, Width_In, Height_In)
+ else
+ Tigerlake_Scaler_Limits (Width_In, Height_In));
Width : Width_Type;
Height : Height_Type;
@@ -595,13 +643,13 @@
Scale_Keep_Aspect
(Width => Width,
Height => Height,
- Max_Width => Pos32'Min (Horizontal_Limit, Mode.H_Visible),
- Max_Height => Pos32'Min (Vertical_Limit, Mode.V_Visible),
+ Max_Width => Pos32'Min (Limits.Horizontal, Mode.H_Visible),
+ Max_Height => Pos32'Min (Limits.Vertical, Mode.V_Visible),
Framebuffer => Framebuffer);
Registers.Write
(Register => Controller.PS_CTRL_1,
- Value => PS_CTRL_ENABLE_SCALER or Scaler_Mode);
+ Value => PS_CTRL_ENABLE_SCALER or Limits.Control);
Registers.Write
(Register => Controller.PS_WIN_POS_1,
Value =>