gma: Limit HDMI pixel rate

Given that current Intel chips only support 4K@30Hz over HDMI, it's
actually no surprise that older chips had even lower limits. For a
24bpp mode, it's 225MHz for Nehalem, Sandy and Ivy Bridge and 300MHz
for everything newer.

To keep the code most simple we keep the display's native resolution
and just limit the clock if we encouter an unsupported mode.

TEST=Booted T420 with a DELL U3415W attached over DP-to-HDMI and
     DVI-to-HDMI adapters. The display came up with 3440x1440@42Hz
     (instead of a garbled picture at 1720x1440@60Hz).

Change-Id: I5386386c648db267a49ed1f62750d2a5fdb2d934
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/17499
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index ccc5c1a..357b93f 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -248,4 +248,9 @@
             Secondary   => 4096,
             Tertiary    => 4096));
 
+   ----------------------------------------------------------------------------
+
+   HDMI_Max_Clock_24bpp : constant Frequency_Type :=
+     (if CPU >= Haswell then 300_000_000 else 225_000_000);
+
 end HW.GFX.GMA.Config;
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index c50d943..d156494 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -237,6 +237,23 @@
             if Port_Cfg.Mode.BPC = Auto_BPC then
                Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
             end if;
+            if Port_Cfg.Display = HDMI then
+               declare
+                  pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
+                                 / Port_Cfg.Mode.BPC >= Frequency_Type'First);
+                  Max_Dotclock : constant Frequency_Type :=
+                     Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
+               begin
+                  if Port_Cfg.Mode.Dotclock > Max_Dotclock then
+                     pragma Debug (Debug.Put ("Dotclock "));
+                     pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
+                     pragma Debug (Debug.Put (" too high, limiting to "));
+                     pragma Debug (Debug.Put_Int64 (Max_Dotclock));
+                     pragma Debug (Debug.Put_Line ("."));
+                     Port_Cfg.Mode.Dotclock := Max_Dotclock;
+                  end if;
+               end;
+            end if;
          end;
       else
          Port_Cfg := Port_Config'