gma: Automatically update CDClk and dot clocks

Dot clocks should be limited, depending on CDClk. This comes with a
caveat: if a display only works at a specific refresh rate, we will
likely fail without knowing. It seems to be better, though, to try
at least. We can implement a config switch controlling this beha-
viour, later, if needed.

If we can raise / lower CDClk with a given set of dot clocks, we
have to disable all pipes first, then switch CDClk, and finally
enable all pipes with their new configuration.

Calling Update_Outputs() with all pipe configs disabled may disable
the CDClk. So we have to ensure it is enabled when trying to probe
for displays.

Change-Id: I375f2bd37c921cd5ed4b0094247df5a34a087188
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/35719
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index 3221e3e..8d58841 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -223,6 +223,7 @@
          Display_Controller.Null_Scaler_Reservation;
 
       Update_Power   : Boolean := False;
+      Update_CDClk : Boolean;
       Old_Configs,
       New_Configs    : Pipe_Configs;
 
@@ -280,6 +281,10 @@
                  (New_Configs (P).Framebuffer, New_Configs (P).Mode));
       end loop;
 
+      -- limit dotclocks to maximum CDClk, if we are about
+      -- to switch CDClk, all pipes have to be disabled
+      Power_And_Clocks.Limit_Dotclocks (New_Configs, Update_CDClk);
+
       -- disable all pipes that changed or had a hot-plug event
       for Pipe in Pipe_Index loop
          declare
@@ -290,7 +295,10 @@
             if Cur_Config.Port /= Disabled then
                Check_HPD (Cur_Config.Port, Unplug_Detected);
 
-               if Full_Update (Cur_Config, New_Config) or Unplug_Detected then
+               if Update_CDClk or
+                  Unplug_Detected or
+                  Full_Update (Cur_Config, New_Config)
+               then
                   Disable_Output (Pipe, Cur_Config);
                   Cur_Config.Port := Disabled;
                   Update_Power := True;
@@ -299,6 +307,11 @@
          end;
       end loop;
 
+      -- switch CDClk if necessary and possible, limit dotclocks accordingly
+      if Update_CDClk then
+         Power_And_Clocks.Update_CDClk (New_Configs);
+      end if;
+
       -- enable all pipes that changed and should be active
       for Pipe in Pipe_Index loop
          declare