dp_info: read eDP 1.4+ DPCD link rates
This is required for google/eve (Pixelbook), where only this new
method of reporting the link rate is supported, and the
Max_Link_Rate in the regular DPCD struct is 0x00.
Change-Id: I52b4d8ad94564904854b502f300b812c41a9751a
Signed-off-by: Greg V <greg@unrelenting.technology>
Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/35869
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/common/hw-gfx-dp_info.adb b/common/hw-gfx-dp_info.adb
index d45826d..bf09933 100644
--- a/common/hw-gfx-dp_info.adb
+++ b/common/hw-gfx-dp_info.adb
@@ -20,6 +20,7 @@
with HW.GFX.DP_Defs;
use type HW.Word8;
+use type HW.Word16;
package body HW.GFX.DP_Info is
@@ -86,6 +87,93 @@
end if;
end Read_Caps;
+ function Read_LE16
+ (Raw_Payload : DP_Defs.Aux_Payload;
+ Offset : DP_Defs.Aux_Payload_Index)
+ return Word16
+ with
+ Pre => Offset < DP_Defs.Aux_Payload_Index'Last
+ is
+ begin
+ return Shift_Left (Word16 (Raw_Payload (Offset + 1)), 8) or
+ Word16 (Raw_Payload (Offset));
+ end Read_LE16;
+
+ procedure Read_eDP_Rates
+ (Link : in out DP_Link;
+ Port : in T)
+ is
+ Data : DP_Defs.Aux_Payload;
+ Length : DP_Defs.Aux_Payload_Length;
+ Max_Rate : Natural;
+ Success : Boolean;
+
+ Caps_Size : constant := 3;
+ Rates_Size : constant := 16;
+ eDP_Rev_1_4 : constant := 3;
+ begin
+ pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+ Length := Caps_Size;
+ Aux_Ch.Aux_Read
+ (Port => Port,
+ Address => 16#00700#,
+ Length => Length,
+ Data => Data,
+ Success => Success);
+ Success := Success and Length = Caps_Size;
+ if not Success or Data (0) < eDP_Rev_1_4 then
+ return;
+ end if;
+
+ Length := Rates_Size;
+ Aux_Ch.Aux_Read
+ (Port => Port,
+ Address => 16#00010#,
+ Length => Length,
+ Data => Data,
+ Success => Success);
+ Success := Success and Length = Rates_Size;
+ if not Success then
+ return;
+ end if;
+
+ pragma Debug (Debug.New_Line);
+ pragma Debug (Debug.Put_Line ("DPCD eDP 1.4+ link rates:"));
+
+ -- TODO: support individual link rates (storing them all)
+
+ Max_Rate := Natural'First;
+ for I in 0 .. Length / 2 - 1 loop
+ pragma Loop_Invariant (Max_Rate <= Natural (Word16'Last));
+ declare
+ Rate : constant Word16 := Read_LE16 (Data, I * 2);
+ begin
+ exit when Rate = 0; -- prematurely exit the loop
+ pragma Debug (Debug.Put (" - "));
+ pragma Debug (Debug.Put_Int8 (Int8 (I)));
+ pragma Debug (Debug.Put (": "));
+ pragma Debug (Debug.Put_Word16 (Rate));
+ pragma Debug (Debug.New_Line);
+ if Natural (Rate) > Max_Rate then
+ Max_Rate := Natural (Rate);
+ end if;
+ end;
+ end loop;
+ pragma Debug (Debug.New_Line);
+
+ -- convert to KHz
+ Max_Rate := Max_Rate * 20;
+
+ if Max_Rate >= 540_000 then
+ Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_5_4;
+ elsif Max_Rate >= 270_000 then
+ Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
+ elsif Max_Rate >= 162_000 then
+ Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_1_62;
+ end if;
+ end Read_eDP_Rates;
+
procedure Minimum_Lane_Count
(Link : in out DP_Link;
Mode : in Mode_Type;
diff --git a/common/hw-gfx-dp_info.ads b/common/hw-gfx-dp_info.ads
index aa10c4c..6d22bcc 100644
--- a/common/hw-gfx-dp_info.ads
+++ b/common/hw-gfx-dp_info.ads
@@ -81,6 +81,10 @@
Port : in T;
Success : out Boolean);
+ procedure Read_eDP_Rates
+ (Link : in out DP_Link;
+ Port : in T);
+
procedure Preferred_Link_Setting
(Link : in out DP_Link;
Mode : in Mode_Type;
diff --git a/common/hw-gfx-gma-connector_info.adb b/common/hw-gfx-gma-connector_info.adb
index e8357be..3ce807e 100644
--- a/common/hw-gfx-gma-connector_info.adb
+++ b/common/hw-gfx-gma-connector_info.adb
@@ -51,6 +51,10 @@
Port => DP_Port,
Success => Success);
if Success then
+ DP_Info.Read_eDP_Rates
+ (Link => Port_Cfg.DP,
+ Port => DP_Port);
+
DP_Info.Preferred_Link_Setting
(Link => Port_Cfg.DP,
Mode => Port_Cfg.Mode,