dp training: Write correct training data when switching patterns
Apparently this was wrong all the time. When switching the training
pattern, i.e. writes to DPCD+0x102, we also have to write the current
signal levels to subsequent offsets. We always wrote 0s in this case,
even if we already negotiated higher values during the clock-recovery
phase. Obviously, this results in havoc if the sink takes the 0s
serious.
TEST=Run a few hundred training rounds with a Terra 2462W display.
This display almost always requested an increase of the voltage
swing to level 1. Trainings where it recovered the clock with
level 0 always succeeded, while trainings with level 1 almost
always lost synchronization at the start of channel equalization.
With the patch applied, all trainings succeeded.
Change-Id: I6ae2f9aaec0b042e8dee6e8b0099ea62c82f611b
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/32732
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/common/hw-gfx-dp_training.adb b/common/hw-gfx-dp_training.adb
index 079d49c..d613d85 100644
--- a/common/hw-gfx-dp_training.adb
+++ b/common/hw-gfx-dp_training.adb
@@ -113,9 +113,10 @@
end Sink_Init;
procedure Sink_Set_Training_Pattern
- (DP : in Aux_T;
+ (Port : in T;
Link : in DP_Link;
Pattern : in DP_Info.Training_Pattern;
+ Train_Set : in DP_Info.Train_Set;
Success : out Boolean)
is
use type DP_Info.Training_Pattern;
@@ -124,21 +125,21 @@
TP : constant TP_Array := TP_Array'
(DP_Info.TP_1 => 16#21#, DP_Info.TP_2 => 16#22#, DP_Info.TP_3 => 16#23#,
DP_Info.TP_Idle => 16#00#, DP_Info.TP_None => 16#00#);
+ T_Set : constant Word8 := Training_Set (Port, Train_Set);
Data : DP_Defs.Aux_Payload;
Length : Positive := 1;
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
- Data :=
- (0 => TP (Pattern),
- others => 0); -- Don't care
-
+ Data := (TP (Pattern), others => 0);
if Pattern < DP_Info.TP_Idle then
Length := Length + Lane_Count (Link);
+ Data (1 .. Lane_Count (Link)) := (others => T_Set);
end if;
+
Aux_Ch.Aux_Write
- (Port => DP,
+ (Port => To_Aux (Port),
Address => 16#00102#, -- TRAINING_PATTERN_SET
Length => Length,
Data => Data,
@@ -332,7 +333,8 @@
pragma Warnings
(GNATprove, On, """Success"" modified by call, but value overwritten*");
if Success then
- Sink_Set_Training_Pattern (DP, Link, DP_Info.TP_1, Success);
+ Sink_Set_Training_Pattern
+ (Port, Link, DP_Info.TP_1, Train_Set, Success);
end if;
if Success then
@@ -365,7 +367,7 @@
if Success then
Set_Pattern (Port, Link, EQ_Pattern);
- Sink_Set_Training_Pattern (DP, Link, EQ_Pattern, Success);
+ Sink_Set_Training_Pattern (Port, Link, EQ_Pattern, Train_Set, Success);
end if;
if Success then
@@ -385,7 +387,7 @@
-- Set_Pattern (TP_None) includes sending the Idle Pattern,
-- so tell sink first.
Sink_Set_Training_Pattern
- (DP, Link, DP_Info.TP_None, Success);
+ (Port, Link, DP_Info.TP_None, Train_Set, Success);
Set_Pattern (Port, Link, DP_Info.TP_None);
Success := Success and then EQ_Done;