greg@unrelenting.technology has uploaded this change for review. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
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. (And higher rate is required because the panel is high res.)
Change-Id: I52b4d8ad94564904854b502f300b812c41a9751a Signed-off-by: Greg V greg@unrelenting.technology --- M common/hw-gfx-dp_info.adb M common/hw-gfx-dp_info.ads M common/hw-gfx-gma-connector_info.adb 3 files changed, 86 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/69/35869/1
diff --git a/common/hw-gfx-dp_info.adb b/common/hw-gfx-dp_info.adb index d45826d..8d66dd3 100644 --- a/common/hw-gfx-dp_info.adb +++ b/common/hw-gfx-dp_info.adb @@ -86,6 +86,82 @@ end if; end Read_Caps;
+ function Read_LE16 + (Raw_Payload : DP_Defs.Aux_Payload; + Offset : DP_Defs.Aux_Payload_Index) + return Word32 + is + begin + return Shift_Left (Word32 (Raw_Payload (Offset + 1)), 8) or + Word32 (Raw_Payload (Offset)); + end Read_LE16; + + procedure Read_eDP_Rates + (Link : in out DP_Link; + Port : in T; + Success : out Boolean) + is + Data : DP_Defs.Aux_Payload; + Length : DP_Defs.Aux_Payload_Length; + Max_Rate : Word32; + + Caps_Size : constant := 3; + Rates_Size : constant := 8; + 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 Length = Caps_Size and Data (0) >= 16#03# then + 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 Length = Rates_Size then + Max_Rate := Read_LE16 (Data, 0); + if Read_LE16 (Data, 2) > Max_Rate then + Max_Rate := Read_LE16 (Data, 2); + end if; + if Read_LE16 (Data, 4) > Max_Rate then + Max_Rate := Read_LE16 (Data, 4); + end if; + if Read_LE16 (Data, 6) > Max_Rate then + Max_Rate := Read_LE16 (Data, 6); + end if; + -- convert to KHz + Max_Rate := Max_Rate * 20; + + if Max_Rate >= 540000 then + Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_5_4; + elsif Max_Rate >= 270000 then + Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7; + elsif Max_Rate >= 162000 then + Link.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_1_62; + end if; + + pragma Debug (Debug.New_Line); + pragma Debug (Debug.Put_Line ("DPCD eDP 1.4+ link rates:")); + pragma Debug (Debug.Put_Reg32 (" 0: ", Read_LE16 (Data, 0))); + pragma Debug (Debug.Put_Reg32 (" 1: ", Read_LE16 (Data, 2))); + pragma Debug (Debug.Put_Reg32 (" 2: ", Read_LE16 (Data, 4))); + pragma Debug (Debug.Put_Reg32 (" 3: ", Read_LE16 (Data, 6))); + pragma Debug (Debug.New_Line); + end if; + 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..501099f 100644 --- a/common/hw-gfx-dp_info.ads +++ b/common/hw-gfx-dp_info.ads @@ -81,6 +81,11 @@ Port : in T; Success : out Boolean);
+ procedure Read_eDP_Rates + (Link : in out DP_Link; + Port : in T; + Success : out Boolean); + 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..a014edd 100644 --- a/common/hw-gfx-gma-connector_info.adb +++ b/common/hw-gfx-gma-connector_info.adb @@ -51,6 +51,11 @@ Port => DP_Port, Success => Success); if Success then + DP_Info.Read_eDP_Rates + (Link => Port_Cfg.DP, + Port => DP_Port, + Success => Success); + DP_Info.Preferred_Link_Setting (Link => Port_Cfg.DP, Mode => Port_Cfg.Mode,
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 1:
(12 comments)
Hi Greg, thanks for your patch. I wasn't sure if I should expect any :D
As you might have noticed, libgfxinit is written in SPARK, which requires a tool (GNATprove) to be run over the source to check for certain errors. If you mind, I can do that for you and report back any problem. But that might be the slow road. If you want to try for yourself, you can follow the README.md instructions for a standalone build of libgfxinit. Alas, I haven't documented these further steps: o Install GNATprove (or download the prebuilt package from libre.adacore.com, e.g. spark-discovery-gpl-2017-x86_64-linux-bin.tar.gz) Haven't tried anything newish lately, because it was borked in 2018 :-/ o Run it for one config, e.g. make cnf=configs/skylake full or all of them make -j proof-allconfigs
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG@12 PS1, Line 12: (And higher rate is required because the panel is high res.) The high resolution is actually unrelated. libgfxinit could as well bail out on the 0x00.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 102: Success : out Boolean) What's the intended meaning of `Success` here? The result seems to be ignored later...
As the whole part is optional, I think we could live without it. Or, at least, only report a failure if we could read the eDP revision, it is >= 1.4, and then failed to read the rates. i.e. `Success = failed_to_read_0x700 or < 3 or succeeded to read 0x10`
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 106: Max_Rate : Word32; An Integer type, e.g. `Natural`, would be preferred. GNATprove could check that we don't overflow any calculation.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 109: Rates_Size : constant := 8; Linux's i915 reads up to 8 rates, thus 16 bytes.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 120: Success := Success and Length = Caps_Size; I guess I understand now how you interpret `Success`. You think it's kind the summed up result of all steps?
However, as `Success` is usually an `out` parameter, the next call to Aux_Read() will overwrite any previous value, i.e. if reading 0x700 fails, but reading at 0x10 works, `Success` would be true.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 122: 16#03# We might want to give this a name, e.g. `eDP_Rev_1_4 : constant := 3;`, it's not obvious that it's the eDP revision that is checked.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 122: Length = Caps_Size Better check `Success` here instead of repeating `Length = Caps_Size`.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 132: Length = Rates_Size Same here, better check `Success`.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 142: end if; I would prefer a loop, especially considering the 8 rates.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 146: 540000 Nit, numbers could be written as `540_000` etc., makes it easier to review :)
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 152: end if; Please leave a comment here, that this actually needs support for individual (instead of a maximum) rates in libgfxinit. Just using the maximum should cover 99% of the use cases, so I'm ok with the current solution.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-gma-connect... File common/hw-gfx-gma-connector_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-gma-connect... PS1, Line 57: Success => Success); Could we make the call part of Read_Caps() instead?
greg@unrelenting.technology has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 1:
(4 comments)
o Install GNATprove (or download the prebuilt package from libre.adacore.com, e.g. spark-discovery-gpl-2017-x86_64-linux-bin.tar.gz)
Yeah, I should eventually try to package gnatprove in FreeBSD, but really don't have the energy for this right now. Thanks for pointing to the Linux binaries, I'll try that, that seems easy.
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG@12 PS1, Line 12: (And higher rate is required because the panel is high res.)
The high resolution is actually unrelated. libgfxinit could as well […]
But it didn't, it read this as the minimum speed..
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 109: Rates_Size : constant := 8;
Linux's i915 reads up to 8 rates, thus 16 bytes.
oh.. I misread the Linux code, sorry.
So you did find where it's handled there :)
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 120: Success := Success and Length = Caps_Size;
I guess I understand now how you interpret `Success`. You think it's kind the […]
Yeah, I thought it's `in out`, I was looking at the wrong parameter (and didn't know how out parameters really work in Ada)
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 142: end if;
I would prefer a loop, especially considering the 8 rates.
I couldn't find a good way to step by 2 in loops.. Would looping over an array of constant indexes (0, 2, 4, …) be okay?
(+ from experience with ACSL, assumed that loops might need more effort for verification — though a 'foreach' type thing should be fine)
I don't really know anything about Ada, so feel free to suggest better code or rewrite anything.
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 1:
(1 comment)
It looks rather well for being written by somebody not familiar with Ada :)
I might have time to look more into it on the weekend (unless you beat me to it). I left an idea for the loop. Apart from that, I guess all that's left is to turn it into SPARK code.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 142: end if;
I couldn't find a good way to step by 2 in loops.. […]
Something like this might do:
Max_Rate := Word32'First; for I in 0 .. 7 loop declare Rate : constant Word32 := Read_LE16 (Data, I * 2); begin exit when Rate = 0; -- prematurely exit the loop if Rate > Max_Rate then Max_Rate = Rate; end if; end; end loop;
Hello Nico Huber,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/libgfxinit/+/35869
to look at the new patch set (#2).
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
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 --- M common/hw-gfx-dp_info.adb M common/hw-gfx-dp_info.ads M common/hw-gfx-gma-connector_info.adb 3 files changed, 95 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/69/35869/2
greg@unrelenting.technology has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 2:
(9 comments)
Now using early returns with the success thing.
As for SPARK, the 'full' make target with spark-discovery-gpl-2017 spews a ton of warnings from all around the project. For new code, it says
hw-gfx-dp_info.adb:147:58: medium: range check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:147:58: medium: overflow check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:163:28: medium: range check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:163:28: medium: overflow check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19
which seems silly, it can't prove that the constants from the 0..7 range multiplied by 2 fit into the Aux_Payload_Index.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 106: Max_Rate : Word32;
An Integer type, e.g. `Natural`, would be preferred. GNATprove could check […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 109: Rates_Size : constant := 8;
oh.. I misread the Linux code, sorry. […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 120: Success := Success and Length = Caps_Size;
Yeah, I thought it's `in out`, I was looking at the wrong parameter (and didn't know how out paramet […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 122: 16#03#
We might want to give this a name, e.g. `eDP_Rev_1_4 : constant := 3;`, it's […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 122: Length = Caps_Size
Better check `Success` here instead of repeating `Length = Caps_Size`.
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 132: Length = Rates_Size
Same here, better check `Success`.
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 142: end if;
Something like this might do: […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 146: 540000
Nit, numbers could be written as `540_000` etc. […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 152: end if;
Please leave a comment here, that this actually needs support for individual […]
Done
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 2:
(6 comments)
Now using early returns with the success thing.
Thanks for the update :)
As for SPARK, the 'full' make target with spark-discovery-gpl-2017 spews a ton of warnings from all around the project. For new code, it says
hw-gfx-dp_info.adb:147:58: medium: range check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:147:58: medium: overflow check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:163:28: medium: range check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19 hw-gfx-dp_info.adb:163:28: medium: overflow check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19
which seems silly, it can't prove that the constants from the 0..7 range multiplied by 2 fit into the Aux_Payload_Index.
That's silly indeed. I assume the other ton of warnings is too, there shouldn't be any. Maybe GNATprove has trouble finding the theorem prover. We currently have `z3` hardcoded. Maybe it can't find it or something is wrong with its installation *shrug*
I left comments on the three lines it spat out for me. That's quite impressive btw. only 3 for nearly 100 new lines \o/
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/libgfxinit/+/35869/1//COMMIT_MSG@12 PS1, Line 12: (And higher rate is required because the panel is high res.)
But it didn't, it read this as the minimum speed..
Yes, well, that it tries the lower rate at all is libgfxinit specific. Reading the above just made me wonder: max link rate is 0x00 and it needs something higher? ofc, it needs something higher than 0.
Anyway, it just made me stumble a little, when I read it.
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 102: Success : out Boolean)
What's the intended meaning of `Success` here? The result seems to be ignored later... […]
Thinking about this again. I would just make it a local variable. Return early on errors, but don't propagate the error.
Also, currently we have:
hw-gfx-gma-connector_info.adb:57:28: warning: unused assignment to "Success"
Because we ignore the result anyway.
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 93: return Word16 We should add a precondition here for `Offset`. As we read 2 bytes, we'll need some margin at the end:
with Pre => Offset < DP_Defs.Aux_Payload_Index'Last
Without this, we get for the `Offset + 1` below:
hw-gfx-dp_info.adb:96:54: medium: array index check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 134: Success := Success and Length = Rates_Size; Alternatively, we can use the resulting `Length` to limit the loop below...
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 145: for I in 0 .. 7 loop e.g.
for I in 0 .. Length / 2 - 1 loop
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 158: end; You were correct that loops are a little special. GNATprove doesn't track all available information across the iterations. But we need to know that `Max_Rate` doesn't get to big:
pragma Loop_Invariant (Max_Rate <= Natural (Word16'Last));
Otherwise, we can't prove that the `Max_Rate * 20` below doesn't overflow:
hw-gfx-dp_info.adb:163:28: medium: overflow check might fail, in instantiation at hw-gfx-gma-dp_info.ads:19
Hello Nico Huber,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/libgfxinit/+/35869
to look at the new patch set (#3).
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
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 --- M common/hw-gfx-dp_info.adb M common/hw-gfx-dp_info.ads M common/hw-gfx-gma-connector_info.adb 3 files changed, 96 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/69/35869/3
Matt DeVillier has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 3:
(1 comment)
https://review.coreboot.org/c/libgfxinit/+/35869/3//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/libgfxinit/+/35869/3//COMMIT_MSG@9 PS3, Line 9: 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. probably google/nocturne as well; wish I still had the one to test
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
Patch Set 3: Verified+1 Code-Review+2
(3 comments)
Thanks!
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/1/common/hw-gfx-dp_info.adb... PS1, Line 102: Success : out Boolean)
Thinking about this again. I would just make it a local variable. […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb File common/hw-gfx-dp_info.adb:
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 93: return Word16
We should add a precondition here for `Offset`. As we read 2 bytes, we'll […]
Done
https://review.coreboot.org/c/libgfxinit/+/35869/2/common/hw-gfx-dp_info.adb... PS2, Line 158: end;
You were correct that loops are a little special. GNATprove doesn't track […]
Done
Nico Huber has submitted this change. ( https://review.coreboot.org/c/libgfxinit/+/35869 )
Change subject: dp_info: read eDP 1.4+ DPCD link rates ......................................................................
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 --- M common/hw-gfx-dp_info.adb M common/hw-gfx-dp_info.ads M common/hw-gfx-gma-connector_info.adb 3 files changed, 96 insertions(+), 0 deletions(-)
Approvals: Nico Huber: Verified; Looks good to me, approved
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,