gma bxt: Implement CDClk switching
Again, very similar procedure to the previous generations. The
CDClk is limited to 624MHz (no fuses). Dot clocks can run at the
full CDClk speed.
If all pipes are disabled, we set CDClk to its reference rate.
In this state, the display engine is not operational and neither
are the DP Aux ports. So we have to implement Enable_CDClk() to
allow display probing without any pipe enabled.
Change-Id: I7bccbce0625a9893e2dd5c06fd1475a44987989d
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/35718
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/common/broxton/hw-gfx-gma-power_and_clocks.adb b/common/broxton/hw-gfx-gma-power_and_clocks.adb
index 77f6b35..fe10208 100644
--- a/common/broxton/hw-gfx-gma-power_and_clocks.adb
+++ b/common/broxton/hw-gfx-gma-power_and_clocks.adb
@@ -217,15 +217,26 @@
CDClk_Ref : constant := 19_200_000;
+ function Normalize_CDClk (CDClk : in Int64) return Config.CDClk_Range is
+ (if CDClk <= CDClk_Ref then CDClk_Ref
+ elsif CDClk <= 144_000_000 then 144_000_000
+ elsif CDClk <= 288_000_000 then 288_000_000
+ elsif CDClk <= 384_000_000 then 384_000_000
+ elsif CDClk <= 576_000_000 then 576_000_000
+ else 624_000_000);
+
+ procedure Get_Cur_CDClk (CDClk : out Config.CDClk_Range)
+ is
+ CDCLK_CTL : Word32;
+ begin
+ Registers.Read (Registers.CDCLK_CTL, CDCLK_CTL);
+ CDCLK_CTL := CDCLK_CTL and CDCLK_CTL_CD_FREQ_DECIMAL_MASK;
+ CDClk := Normalize_CDClk (Int64 (CDCLK_CTL) * 500_000 + 1_000_000);
+ end Get_Cur_CDClk;
+
procedure Set_CDClk (Freq_In : Frequency_Type)
is
- Freq : constant Frequency_Type :=
- (if Freq_In = CDClk_Ref then CDClk_Ref
- elsif Freq_In <= 144_000_000 then 144_000_000
- elsif Freq_In <= 288_000_000 then 288_000_000
- elsif Freq_In <= 384_000_000 then 384_000_000
- elsif Freq_In <= 576_000_000 then 576_000_000
- else 624_000_000);
+ Freq : constant Config.CDClk_Range := Normalize_CDClk (Freq_In);
VCO : constant Int64 :=
CDClk_Ref *
(if Freq = CDClk_Ref then
@@ -287,6 +298,8 @@
PCode.Mailbox_Write
(MBox => BXT_PCODE_CDCLK_CONTROL,
Command => Word64 ((Freq + (25_000_000 - 1)) / 25_000_000));
+
+ Config.CDClk := Freq;
end Set_CDClk;
----------------------------------------------------------------------------
@@ -325,6 +338,8 @@
Wait_Set_Mask (FUSE_STATUS, FUSE_STATUS_PG0_DIST_STATUS);
PW_On (PW1);
+ Config.Max_CDClk := 624_000_000;
+ Get_Cur_CDClk (Config.CDClk);
Set_CDClk (Config.Default_CDClk_Freq);
Set_Mask (DBUF_CTL, DBUF_CTL_DBUF_POWER_REQUEST);
@@ -333,4 +348,32 @@
Config.Raw_Clock := Config.Default_RawClk_Freq;
end Initialize;
+ procedure Limit_Dotclocks
+ (Configs : in out Pipe_Configs;
+ CDClk_Switch : out Boolean)
+ is
+ begin
+ Config_Helpers.Limit_Dotclocks (Configs, Config.Max_CDClk);
+ CDClk_Switch :=
+ Config.CDClk /= Normalize_CDClk
+ (Config_Helpers.Highest_Dotclock (Configs));
+ end Limit_Dotclocks;
+
+ procedure Update_CDClk (Configs : in out Pipe_Configs)
+ is
+ New_CDClk : constant Frequency_Type :=
+ Config_Helpers.Highest_Dotclock (Configs);
+ begin
+ Set_CDClk (New_CDClk);
+ Config_Helpers.Limit_Dotclocks (Configs, Config.CDClk);
+ end Update_CDClk;
+
+ procedure Enable_CDClk is
+ begin
+ -- CDClk_Ref means we have CDClk effectively disabled
+ if Config.CDClk = CDClk_Ref then
+ Set_CDClk (Config.Default_CDClk_Freq);
+ end if;
+ end Enable_CDClk;
+
end HW.GFX.GMA.Power_And_Clocks;