gma: Refactor Update_Outputs()

In Update_Outputs(), we used to have two steps, iterating over
all available pipes: We disabled all pipes whose mode changed
or that would be disabled otherwise. Then, we enabled all pipes
with new modes.

As checks for validity of the configurations were only done on
demand in the second step, that left us with no knowledge about
what configs would actually be tried. To make this information
available for future work, we add a validation step before the
existing two. That gives us:

 1. Validate all new configs
 2. Disable pipes
    - whose mode changed
    - that were disconnected
    - whose config didn't validate
 3. Enable/update pipes with new configs

This way, we can make global decisions ahead of 2. and 3. based
on the remaining, _valid_ configurations.

We had to turn Pipe_Setup.Scaler_Available() into a Reserve_Scaler()
so we can keep track which new configuration gets to use a scaler.
G45 is still the only case where we have less scalers than pipes
available. To keep that transparent to Update_Outputs() we add the
opaque type `Scaler_Reservation`.

The `Loop_Invariant` of 1. allows us to keep the validation
in mind, to satisfy pre-conditions of the various steps ahead.
To not lose the validation, Fill_Port_Config() needs a post
condition and a little restructuring to prove it.

Change-Id: I079ae8f85c821a272b5d095c1ef437ee804aa9ac
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/35528
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/common/hw-gfx-gma-config_helpers.adb b/common/hw-gfx-gma-config_helpers.adb
index 162c9c6..ede140c 100644
--- a/common/hw-gfx-gma-config_helpers.adb
+++ b/common/hw-gfx-gma-config_helpers.adb
@@ -113,13 +113,20 @@
    procedure Configure_FDI_Link
      (Port_Cfg : in out Port_Config;
       Success  :    out Boolean)
-   with Pre => True
+   with
+      Post =>
+         Port_Cfg.Mode.H_Visible = Port_Cfg'Old.Mode.H_Visible and
+         Port_Cfg.Mode.V_Visible = Port_Cfg'Old.Mode.V_Visible
    is
-      procedure Limit_Lane_Count
-      is
-         FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
-         Enabled : Boolean;
-      begin
+      FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
+      Enabled : Boolean;
+   begin
+      Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate    := DP_Bandwidth_2_7;
+      Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count   :=
+         Config.FDI_Lane_Count (Port_Cfg.Port);
+      Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
+
+      if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
          -- if DIGI_D enabled: (FDI names are off by one)
          Registers.Is_Set_Mask
            (Register => Registers.FDI_TX_CTL_C,
@@ -128,15 +135,8 @@
          if Enabled then
             Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
          end if;
-      end Limit_Lane_Count;
-   begin
-      Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate    := DP_Bandwidth_2_7;
-      Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count   :=
-         Config.FDI_Lane_Count (Port_Cfg.Port);
-      Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
-      if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
-         Limit_Lane_Count;
       end if;
+
       DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
    end Configure_FDI_Link;
 
@@ -216,8 +216,7 @@
    function Validate_Config
      (FB                : Framebuffer_Type;
       Mode              : Mode_Type;
-      Pipe              : Pipe_Index;
-      Scaler_Available  : Boolean)
+      Pipe              : Pipe_Index)
       return Boolean
    is
    begin
@@ -233,8 +232,7 @@
       return
          ((Rotated_Width (FB) = Mode.H_Visible and
            Rotated_Height (FB) = Mode.V_Visible) or
-          (Scaler_Available and
-           Rotated_Width (FB) <= Config.Maximum_Scalable_Width (Pipe) and
+          (Rotated_Width (FB) <= Config.Maximum_Scalable_Width (Pipe) and
            Rotated_Width (FB) <= Mode.H_Visible and
            Rotated_Height (FB) <= Mode.V_Visible)) and
          (FB.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary) and