blob: 4b84f3c9227ad735b2e2cac05f81ef50a85d6372 [file] [log] [blame]
Tim Wawrzynczak5473d292023-02-06 16:46:33 -07001--
2-- Copyright (C) 2022 Google, LLC
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
6-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
8--
9-- This program is distributed in the hope that it will be useful,
10-- but WITHOUT ANY WARRANTY; without even the implied warranty of
11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-- GNU General Public License for more details.
13--
14
15with HW.GFX.GMA.Config;
16with HW.GFX.GMA.Registers;
17with HW.GFX.DP_Info;
18with HW.GFX.GMA.PCode;
19
20with HW.Debug;
21with GNAT.Source_Info;
22
23use type HW.Word64;
24
25package body HW.GFX.GMA.Connectors.TC is
26
27 function HIP_INDEX_REG (P : USBC_Port) return Registers.Registers_Index
28 is
29 (if P <= DDI_TC4
30 then Registers.HIP_INDEX_REG0
31 else Registers.HIP_INDEX_REG1);
32
33 function HIP_INDEX_VAL (P : USBC_Port; Val : Word32) return Word32 is
34 (Val * 2 ** (8 * ((GPU_Port'Pos (P) - GPU_Port'Pos (DDI_TC1)) mod 4)));
35
36 type Port_Regs_Array is array (USBC_Port) of Registers.Registers_Index;
37 DKL_DP_MODE : constant Port_Regs_Array :=
38 (DDI_TC1 => Registers.DKL_DP_MODE_1,
39 DDI_TC2 => Registers.DKL_DP_MODE_2,
40 DDI_TC3 => Registers.DKL_DP_MODE_3,
41 DDI_TC4 => Registers.DKL_DP_MODE_4,
42 DDI_TC5 => Registers.DKL_DP_MODE_5,
43 DDI_TC6 => Registers.DKL_DP_MODE_6);
44
45 function DP_PIN_ASSIGNMENT_SHIFT (P : USBC_Port) return natural is
46 (case P is
47 when DDI_TC1 => 0,
48 when DDI_TC2 => 4,
49 when DDI_TC3 => 8,
50 when DDI_TC4 => 12,
51 when DDI_TC5 => 16,
52 when DDI_TC6 => 20);
53
54 DP_PIN_ASSIGNMENT_MASK : constant := 16#f#;
55
56 TGL_PCODE_TCCOLD : constant := 16#26#;
57 TCCOLD_BLOCK_REQ : constant := 16#00#;
58 TCCOLD_UNBLOCK_REQ : constant := 16#01#;
59 TCCOLD_BLOCK_RESULT_FAIL : constant := 16#01#;
60
61 type Fia_Regs_Record is record
62 PORT_TX_DFLEXDPMLE1 : Registers.Registers_Index;
63 PORT_TX_DFLEXDPSP : Registers.Registers_Index;
64 PORT_TX_DFLEXDPPMS : Registers.Registers_Index;
65 PORT_TX_DFLEXDPCSSS : Registers.Registers_Index;
66 PORT_TX_DFLEXPA1 : Registers.Registers_Index;
67 end record;
68
69 Fia_Regs : constant array (USBC_Port) of Fia_Regs_Record :=
70 (DDI_TC1 =>
71 (Registers.PORT_TX_DFLEXDPMLE1_FIA1,
72 Registers.PORT_TX_DFLEXDPSP_FIA1,
73 Registers.PORT_TX_DFLEXDPPMS_FIA1,
74 Registers.PORT_TX_DFLEXDPCSSS_FIA1,
75 Registers.PORT_TX_DFLEXPA1_FIA1),
76 DDI_TC2 =>
77 (Registers.PORT_TX_DFLEXDPMLE1_FIA1,
78 Registers.PORT_TX_DFLEXDPSP_FIA1,
79 Registers.PORT_TX_DFLEXDPPMS_FIA1,
80 Registers.PORT_TX_DFLEXDPCSSS_FIA1,
81 Registers.PORT_TX_DFLEXPA1_FIA1),
82 DDI_TC3 =>
83 (Registers.PORT_TX_DFLEXDPMLE1_FIA2,
84 Registers.PORT_TX_DFLEXDPSP_FIA2,
85 Registers.PORT_TX_DFLEXDPPMS_FIA2,
86 Registers.PORT_TX_DFLEXDPCSSS_FIA2,
87 Registers.PORT_TX_DFLEXPA1_FIA2),
88 DDI_TC4 =>
89 (Registers.PORT_TX_DFLEXDPMLE1_FIA2,
90 Registers.PORT_TX_DFLEXDPSP_FIA2,
91 Registers.PORT_TX_DFLEXDPPMS_FIA2,
92 Registers.PORT_TX_DFLEXDPCSSS_FIA2,
93 Registers.PORT_TX_DFLEXPA1_FIA2),
94 DDI_TC5 =>
95 (Registers.PORT_TX_DFLEXDPMLE1_FIA3,
96 Registers.PORT_TX_DFLEXDPSP_FIA3,
97 Registers.PORT_TX_DFLEXDPPMS_FIA3,
98 Registers.PORT_TX_DFLEXDPCSSS_FIA3,
99 Registers.PORT_TX_DFLEXPA1_FIA3),
100 DDI_TC6 =>
101 (Registers.PORT_TX_DFLEXDPMLE1_FIA3,
102 Registers.PORT_TX_DFLEXDPSP_FIA3,
103 Registers.PORT_TX_DFLEXDPPMS_FIA3,
104 Registers.PORT_TX_DFLEXDPCSSS_FIA3,
105 Registers.PORT_TX_DFLEXPA1_FIA3));
106
107 function Fia_Index (Port : USBC_Port) return natural
108 is (case Port is
109 when DDI_TC1 | DDI_TC3 | DDI_TC5 => 0,
110 when DDI_TC2 | DDI_TC4 | DDI_TC6 => 1);
111
112 function DFLEXDPMLE1_DPMLETC_MASK (Port : USBC_Port) return Word32 is
113 (Shift_Left (15, 4 * Fia_Index (Port)));
114 function DFLEXDPMLE1_DPMLETC_ML0 (Port : USBC_Port) return Word32 is
115 (Shift_Left (1, 4 * Fia_Index (Port)));
116 function DFLEXDPMLE1_DPMLETC_ML1_0 (Port : USBC_Port) return Word32 is
117 (Shift_Left (3, 4 * Fia_Index (Port)));
118 function DFLEXDPMLE1_DPMLETC_ML3 (Port : USBC_Port) return Word32 is
119 (Shift_Left (8, 4 * Fia_Index (Port)));
120 function DFLEXDPMLE1_DPMLETC_ML3_2 (Port : USBC_Port) return Word32 is
121 (Shift_Left (12, 4 * Fia_Index (Port)));
122 function DFLEXDPMLE1_DPMLETC_ML3_0 (Port : USBC_Port) return Word32 is
123 (Shift_Left (15, 4 * Fia_Index (Port)));
124 function DP_PHY_MODE_STATUS_COMPLETE (Port : USBC_Port) return Word32 is
125 (Shift_Left (1, Fia_Index (Port)));
126 function DP_PHY_MODE_STATUS_NOT_SAFE (Port : USBC_Port) return Word32 is
127 (Shift_Left (1, Fia_Index (Port)));
128 function TC_LIVE_STATE_TC (Port : USBC_Port) return Word32 is
129 (Shift_Left (1, Fia_Index (Port) * 8 + 5));
130 function DP_LANE_ASSIGNMENT_MASK (Port : USBC_Port) return Word32 is
131 (Shift_Left (16#f#, Fia_Index (Port) * 8));
132 function DP_LANE_ASSIGNMENT_SHIFT (Port : USBC_Port) return natural is
133 (Fia_Index (Port) * 8);
134
135 DDI_BUF_CTL_BUFFER_ENABLE : constant := 1 * 2 ** 31;
136 DDI_BUF_CTL_TRANS_SELECT_MASK : constant := 16#f# * 2 ** 24;
137 DDI_BUF_CTL_PORT_REVERSAL : constant := 1 * 2 ** 16;
138 DDI_BUF_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 1;
139 DDI_BUF_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 1;
140 DDI_BUF_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 1;
141 DDI_BUF_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 1;
142 DDI_BUF_CTL_IDLE_STATUS : constant := 1 * 2 ** 7;
143
144 DDI_BUF_CTL_PORT_WIDTH : constant array (DP_Lane_Count) of Word32 :=
145 (HW.GFX.DP_Lane_Count_1 => DDI_BUF_CTL_PORT_WIDTH_1_LANE,
146 HW.GFX.DP_Lane_Count_2 => DDI_BUF_CTL_PORT_WIDTH_2_LANES,
147 HW.GFX.DP_Lane_Count_4 => DDI_BUF_CTL_PORT_WIDTH_4_LANES);
148 DDI_BUF_CTL : constant Port_Regs_Array :=
149 (DDI_TC1 => Registers.DDI_BUF_CTL_USBC1,
150 DDI_TC2 => Registers.DDI_BUF_CTL_USBC2,
151 DDI_TC3 => Registers.DDI_BUF_CTL_USBC3,
152 DDI_TC4 => Registers.DDI_BUF_CTL_USBC4,
153 DDI_TC5 => Registers.DDI_BUF_CTL_USBC5,
154 DDI_TC6 => Registers.DDI_BUF_CTL_USBC6);
155
156 type Buffer_Trans is record
157 Vswing_Control : Word32;
158 Preshoot_Control : Word32;
159 Deemphasis_Control : Word32;
160 end record;
161
162 type Buffer_Trans_Range is new natural range 0 .. 9;
163 type Buffer_Trans_Array is array (Buffer_Trans_Range) of Buffer_Trans;
164 TGL_Buffer_Trans_DP_HBR2 : constant Buffer_Trans_Array :=
165 ((16#7#, 16#0#, 16#00#),
166 (16#5#, 16#0#, 16#05#),
167 (16#2#, 16#0#, 16#0B#),
168 (16#0#, 16#0#, 16#19#),
169 (16#5#, 16#0#, 16#00#),
170 (16#2#, 16#0#, 16#08#),
171 (16#0#, 16#0#, 16#14#),
172 (16#2#, 16#0#, 16#00#),
173 (16#0#, 16#0#, 16#0B#),
174 (16#0#, 16#0#, 16#00#));
175 TGL_Buffer_Trans_DP_HBR : constant Buffer_Trans_Array :=
176 ((16#7#, 16#0#, 16#00#),
177 (16#5#, 16#0#, 16#05#),
178 (16#2#, 16#0#, 16#0B#),
179 (16#0#, 16#0#, 16#18#),
180 (16#5#, 16#0#, 16#00#),
181 (16#2#, 16#0#, 16#08#),
182 (16#0#, 16#0#, 16#14#),
183 (16#2#, 16#0#, 16#00#),
184 (16#0#, 16#0#, 16#0B#),
185 (16#0#, 16#0#, 16#00#));
186 Buffer_Trans_HDMI : constant Buffer_Trans_Array :=
187 ((16#7#, 16#0#, 16#0#),
188 (16#6#, 16#0#, 16#0#),
189 (16#4#, 16#0#, 16#0#),
190 (16#2#, 16#0#, 16#0#),
191 (16#0#, 16#0#, 16#0#),
192 (16#0#, 16#0#, 16#5#),
193 (16#0#, 16#0#, 16#6#),
194 (16#0#, 16#0#, 16#7#),
195 (16#0#, 16#0#, 16#8#),
196 (16#0#, 16#0#, 16#A#));
197 ADL_Buffer_Trans_DP_HBR2 : constant Buffer_Trans_Array :=
198 ((16#7#, 16#0#, 16#00#),
199 (16#5#, 16#0#, 16#04#),
200 (16#2#, 16#0#, 16#0a#),
201 (16#0#, 16#0#, 16#18#),
202 (16#5#, 16#0#, 16#00#),
203 (16#2#, 16#0#, 16#06#),
204 (16#0#, 16#0#, 16#14#),
205 (16#2#, 16#0#, 16#00#),
206 (16#0#, 16#0#, 16#09#),
207 (16#0#, 16#0#, 16#00#));
208 ADL_Buffer_Trans_DP_HBR : constant Buffer_Trans_Array :=
209 ((16#7#, 16#0#, 16#01#),
210 (16#5#, 16#0#, 16#06#),
211 (16#2#, 16#0#, 16#0b#),
212 (16#0#, 16#0#, 16#17#),
213 (16#5#, 16#0#, 16#00#),
214 (16#2#, 16#0#, 16#08#),
215 (16#0#, 16#0#, 16#14#),
216 (16#2#, 16#0#, 16#00#),
217 (16#0#, 16#0#, 16#0b#),
218 (16#0#, 16#0#, 16#00#));
219
220 type Vswing_Regs_Record is record
221 DKL_TX_PMD_LANE_SUS : Registers.Registers_Index;
222 DKL_TX_DPCNTL0 : Registers.Registers_Index;
223 DKL_TX_DPCNTL1 : Registers.Registers_Index;
224 DKL_TX_DPCNTL2 : Registers.Registers_Index;
225 end record;
226
227 Vswing_Regs : constant array (USBC_Port) of Vswing_Regs_Record :=
228 (DDI_TC1 =>
229 (Registers.DKL_TX_PMD_LANE_SUS_1,
230 Registers.DKL_TX_DPCNTL0_1,
231 Registers.DKL_TX_DPCNTL1_1,
232 Registers.DKL_TX_DPCNTL2_1),
233 DDI_TC2 =>
234 (Registers.DKL_TX_PMD_LANE_SUS_2,
235 Registers.DKL_TX_DPCNTL0_2,
236 Registers.DKL_TX_DPCNTL1_2,
237 Registers.DKL_TX_DPCNTL2_2),
238 DDI_TC3 =>
239 (Registers.DKL_TX_PMD_LANE_SUS_3,
240 Registers.DKL_TX_DPCNTL0_3,
241 Registers.DKL_TX_DPCNTL1_3,
242 Registers.DKL_TX_DPCNTL2_3),
243 DDI_TC4 =>
244 (Registers.DKL_TX_PMD_LANE_SUS_4,
245 Registers.DKL_TX_DPCNTL0_4,
246 Registers.DKL_TX_DPCNTL1_4,
247 Registers.DKL_TX_DPCNTL2_4),
248 DDI_TC5 =>
249 (Registers.DKL_TX_PMD_LANE_SUS_5,
250 Registers.DKL_TX_DPCNTL0_5,
251 Registers.DKL_TX_DPCNTL1_5,
252 Registers.DKL_TX_DPCNTL2_5),
253 DDI_TC6 =>
254 (Registers.DKL_TX_PMD_LANE_SUS_6,
255 Registers.DKL_TX_DPCNTL0_6,
256 Registers.DKL_TX_DPCNTL1_6,
257 Registers.DKL_TX_DPCNTL2_6));
258
259 procedure Set_HIP_For_Port (P : USBC_Port; N : Natural) is
260 begin
261 Registers.Write (HIP_INDEX_REG (P), HIP_INDEX_VAL (P, Word32 (N)));
262 end Set_HIP_For_Port;
263
264 subtype Pin_Assignment_Type is natural range 0 .. 6;
265 procedure Get_Pin_Assignment
266 (P : in USBC_Port;
267 Assignment : out Pin_Assignment_Type)
268 is
269 Tmp : Word32;
270 A : Word32;
271 begin
272 Registers.Read (Fia_Regs (P).PORT_TX_DFLEXPA1, Tmp);
273 A := Shift_Right (Tmp, DP_PIN_ASSIGNMENT_SHIFT (P));
274 A := A and DP_PIN_ASSIGNMENT_MASK;
275
276 if natural (A) in Pin_Assignment_Type then
277 Assignment := Pin_Assignment_Type (A);
278 else
279 Assignment := Pin_Assignment_Type'First;
280 end if;
281 end Get_Pin_Assignment;
282
283 ---------------------------------------------------------------------
284
285 procedure Program_DP_Mode (P : USBC_Port; Lane_Count : Natural)
286 is
287 MG_DP_MODE_CFG_DP_X1_MODE : constant := 1 * 2 ** 6;
288 MG_DP_MODE_CFG_DP_X2_MODE : constant := 1 * 2 ** 7;
289 DP_X_MODE_MASK : constant Word32 :=
290 MG_DP_MODE_CFG_DP_X1_MODE or MG_DP_MODE_CFG_DP_X2_MODE;
291 Assignment : Pin_Assignment_Type;
292 Ln0, Ln1 : Word32;
293 begin
294 Set_HIP_For_Port (P, 0);
295 Registers.Read (DKL_DP_MODE (P), Ln0);
296 Set_HIP_For_Port (P, 1);
297 Registers.Read (DKL_DP_MODE (P), Ln1);
298
299 Ln0 := Ln0 and not DP_X_MODE_MASK;
300 Ln1 := Ln1 and not DP_X_MODE_MASK;
301
302 Get_Pin_Assignment (P, Assignment);
303 case Assignment is
304 when 0 =>
305 if Lane_Count = 1 then
306 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X1_MODE;
307 else
308 Ln0 := Ln0 or MG_DP_MODE_CFG_DP_X2_MODE;
309 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X2_MODE;
310 end if;
311 when 1 =>
312 if Lane_Count = 4 then
313 Ln0 := Ln0 or MG_DP_MODE_CFG_DP_X2_MODE;
314 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X2_MODE;
315 end if;
316 when 2 =>
317 if Lane_Count = 2 then
318 Ln0 := Ln0 or MG_DP_MODE_CFG_DP_X2_MODE;
319 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X2_MODE;
320 end if;
321 when 3 | 4 | 5 | 6 =>
322 if Lane_Count = 1 then
323 Ln0 := Ln0 or MG_DP_MODE_CFG_DP_X1_MODE;
324 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X1_MODE;
325 else
326 Ln0 := Ln0 or MG_DP_MODE_CFG_DP_X2_MODE;
327 Ln1 := Ln1 or MG_DP_MODE_CFG_DP_X2_MODE;
328 end if;
329 end case;
330
331 Set_HIP_For_Port (P, 0);
332 Registers.Unset_And_Set_Mask (DKL_DP_MODE (P), DP_X_MODE_MASK, Ln0);
333 Set_HIP_For_Port (P, 1);
334 Registers.Unset_And_Set_Mask (DKL_DP_MODE (P), DP_X_MODE_MASK, Ln1);
335 end Program_DP_Mode;
336
337 ---------------------------------------------------------------------
338
339 procedure TC_Cold_Request
340 (Request : in TC_Cold_Request_Type;
341 Success : out Boolean)
342 is
343 Result : Word64;
344 begin
345 for Try in 1 .. 3 loop
346 PCode.Mailbox_Read
347 (MBox => TGL_PCODE_TCCOLD,
348 Command => (if Request = Block
349 then TCCOLD_BLOCK_REQ
350 else TCCOLD_UNBLOCK_REQ),
351 Wait_Ready => True,
352 Reply => Result,
353 Success => Success);
354
355 if Success then
356 Success := (Result and TCCOLD_BLOCK_RESULT_FAIL) = 0;
357 end if;
358
359 exit when Success;
360
361 -- Wait 1 millisecond and try again
362 Time.U_Delay (1_000);
363 end loop;
364 end TC_Cold_Request;
365
366 ---------------------------------------------------------------------
367
368 procedure Claim
369 (Port : in USBC_Port;
370 DP_Alt : in Boolean;
371 Success : out Boolean)
372 is
373 begin
374 -- For legacy ports, this is supposed to be
375 -- initialized once during boot, hence wait.
376 Registers.Wait_Set_Mask
377 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPPMS,
378 Mask => DP_PHY_MODE_STATUS_COMPLETE (Port),
379 TOut_MS => (if DP_Alt then 0 else 100),
380 Success => Success);
381 if not Success then
382 pragma Debug (Debug.Put_Line ("DP PHY mode status not complete"));
383 return;
384 end if;
385
386 Registers.Set_Mask
387 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPCSSS,
388 Mask => DP_PHY_MODE_STATUS_NOT_SAFE (Port));
389 end Claim;
390
391 procedure Claimed (Port : USBC_Port; Is_Claimed : out Boolean) is
392 begin
393 if Port not in DDI_TC1 .. Config.Last_TC_Port then
394 Is_Claimed := False;
395 return;
396 end if;
397
398 Registers.Is_Set_Mask
399 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPCSSS,
400 Mask => DP_PHY_MODE_STATUS_NOT_SAFE (Port),
401 Result => Is_Claimed);
402 end Claimed;
403
404 ---------------------------------------------------------------------
405
406 procedure Connect
407 (Port : in USBC_Port;
408 DP_Alt : in Boolean;
409 Lanes : in DP_Lane_Count;
410 Success : out Boolean)
411 is
412 procedure Get_Lane_Assignment_Count (Lanes : out DP_Lane_Count)
413 is
414 Lane_Mask : Word32;
415 Tmp : Word32;
416 begin
417 Registers.Read (Fia_Regs (Port).PORT_TX_DFLEXDPSP, Tmp);
418 Lane_Mask := Shift_Right (Tmp and DP_LANE_ASSIGNMENT_MASK (Port),
419 DP_LANE_ASSIGNMENT_SHIFT (Port));
420 Lanes :=
421 (case Lane_Mask is
422 when 16#1# | 16#2# | 16#4# | 16#8# => DP_Lane_Count_1,
423 when 16#3# | 16#c# => DP_Lane_Count_2,
424 when 16#f# => DP_Lane_Count_4,
425 when others => DP_Lane_Count_1);
426 end Get_Lane_Assignment_Count;
427
428 procedure Set_Lane_Count (Lanes : DP_Lane_Count) is
429 begin
430 Registers.Unset_And_Set_Mask
431 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPMLE1,
432 Mask_Unset => DFLEXDPMLE1_DPMLETC_MASK (Port),
433 Mask_Set =>
434 (case Lanes is
435 -- ML0 is not lane-reversed, ML3 is reverse
436 when DP_Lane_Count_1 => DFLEXDPMLE1_DPMLETC_ML0 (Port),
437 -- ML1_0 is not reversed, ML3_2 is reverse
438 when DP_Lane_Count_2 => DFLEXDPMLE1_DPMLETC_ML1_0 (Port),
439 -- symmetric
440 when DP_Lane_Count_4 => DFLEXDPMLE1_DPMLETC_ML3_0 (Port)));
441 end Set_Lane_Count;
442
443 Assigned_Lanes : DP_Lane_Count;
444 begin
445 Claimed (Port, Success);
446 if not Success then
447 pragma Debug (Debug.Put_Line ("Tried to connect to unclaimed port."));
448 return;
449 end if;
450
451 if DP_Alt then
452 Registers.Is_Set_Mask
453 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPSP,
454 Mask => TC_LIVE_STATE_TC (Port),
455 Result => Success);
456 if not Success then
457 pragma Debug (Debug.Put_Line ("DP-Alt is not connected."));
458 return;
459 end if;
460
461 Get_Lane_Assignment_Count (Assigned_Lanes);
462 Set_Lane_Count (Assigned_Lanes);
463 else
464 Set_Lane_Count (Lanes);
465 end if;
466 end Connect;
467
468 ---------------------------------------------------------------------
469
470 procedure Disconnect (Port : USBC_Port) is
471 begin
472 if Port in DDI_TC1 .. Config.Last_TC_Port then
473 Registers.Unset_Mask
474 (Register => Fia_Regs (Port).PORT_TX_DFLEXDPCSSS,
475 Mask => DP_PHY_MODE_STATUS_NOT_SAFE (Port));
476 end if;
477 end Disconnect;
478
479 ---------------------------------------------------------------------
480
481 procedure Set_Vswing_And_Deemphasis
482 (Port : USBC_Port;
483 Buf_Trans : Buffer_Trans)
484 is
485 -- Preshoot Coeff, Deemphasis Coeff, VSwing Control,
486 DPcnt_Mask : constant Word32 := 16#3_ff07#;
487 DPcnt_Val : constant Word32 :=
488 Buf_Trans.Vswing_Control or
489 Shift_Left (Buf_Trans.Deemphasis_Control, 8) or
490 Shift_Left (Buf_Trans.Preshoot_Control, 13);
491 DKL_TX_DP20BITMODE : constant := 1 * 2 ** 2;
492 begin
493 for Lane in 0 .. 1 loop
494 Set_HIP_For_Port (Port, Lane);
495 Registers.Write (Vswing_Regs (Port).DKL_TX_PMD_LANE_SUS, 0);
496 Registers.Unset_And_Set_Mask
497 (Vswing_Regs (Port).DKL_TX_DPCNTL0, DPcnt_Mask, DPcnt_Val);
498 Registers.Unset_And_Set_Mask
499 (Vswing_Regs (Port).DKL_TX_DPCNTL1, DPcnt_Mask, DPcnt_Val);
500 Registers.Unset_Mask
501 (Vswing_Regs (Port).DKL_TX_DPCNTL2, DKL_TX_DP20BITMODE);
502 end loop;
503
504 end Set_Vswing_And_Deemphasis;
505
506 ---------------------------------------------------------------------
507
508 procedure Set_Signal_Levels
509 (Port : USBC_Port;
510 Link : DP_Link;
511 Train_Set : DP_Info.Train_Set)
512 is
513 function To_Buf_Trans_Index
514 (Set : DP_Info.Train_Set) return Buffer_Trans_Range
515 is
516 begin
517 case Set.Voltage_Swing is
518 when DP_Info.VS_Level_0 =>
519 case Set.Pre_Emph is
520 when DP_Info.Emph_Level_0 => return 0;
521 when DP_Info.Emph_Level_1 => return 1;
522 when DP_Info.Emph_Level_2 => return 2;
523 when DP_Info.Emph_Level_3 => return 3;
524 end case;
525 when DP_Info.VS_Level_1 =>
526 case Set.Pre_Emph is
527 when DP_Info.Emph_Level_0 => return 4;
528 when DP_Info.Emph_Level_1 => return 5;
529 when DP_Info.Emph_Level_2 => return 6;
530 when others => return 0;
531 end case;
532 when DP_Info.VS_Level_2 =>
533 case Set.Pre_Emph is
534 when DP_Info.Emph_Level_0 => return 7;
535 when DP_Info.Emph_Level_1 => return 8;
536 when others => return 0;
537 end case;
538 when DP_Info.VS_Level_3 =>
539 case Set.Pre_Emph is
540 when DP_Info.Emph_Level_0 => return 9;
541 when others => return 0;
542 end case;
543 end case;
544 end To_Buf_Trans_Index;
545
546 Was_Enabled : Boolean;
547 Buf_Trans : Buffer_Trans;
548 Entry_Index : constant Buffer_Trans_Range :=
549 To_Buf_Trans_Index (Train_Set);
550 begin
551 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
552
553 Registers.Is_Set_Mask
554 (Register => DDI_BUF_CTL (Port),
555 Mask => DDI_BUF_CTL_BUFFER_ENABLE,
556 Result => Was_Enabled);
557
558 if Config.Has_TGL_Buffer_Translations then
559 if Link.Bandwidth > DP_Bandwidth_2_7 then
560 Buf_Trans := TGL_Buffer_Trans_DP_HBR2 (Entry_Index);
561 else
562 Buf_Trans := TGL_Buffer_Trans_DP_HBR (Entry_Index);
563 end if;
564 else
565 if Link.Bandwidth > DP_Bandwidth_2_7 then
566 Buf_Trans := ADL_Buffer_Trans_DP_HBR2 (Entry_Index);
567 else
568 Buf_Trans := ADL_Buffer_Trans_DP_HBR (Entry_Index);
569 end if;
570 end if;
571
572 Set_Vswing_And_Deemphasis (Port, Buf_Trans);
573
574 Registers.Unset_And_Set_Mask
575 (Register => DDI_BUF_CTL (Port),
576 Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
577 DDI_BUF_CTL_PORT_REVERSAL or
578 DDI_BUF_CTL_PORT_WIDTH_MASK,
579 Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or
580 DDI_BUF_CTL_PORT_WIDTH (Link.Lane_Count));
581 Registers.Posting_Read (DDI_BUF_CTL (Port));
582
583 if not Was_Enabled then
584 Registers.Wait_Unset_Mask (DDI_BUF_CTL (Port), DDI_BUF_CTL_IDLE_STATUS);
585 end if;
586 end Set_Signal_Levels;
587
588 procedure Enable_HDMI (Port : USBC_Port)
589 is
590 HDMI_Lane_Count : constant := 4;
591 Buf_Trans : constant Buffer_Trans :=
592 Buffer_Trans_HDMI (Buffer_Trans_HDMI'Last);
593 begin
594 Program_DP_Mode (Port, HDMI_Lane_Count);
595 Set_Vswing_And_Deemphasis (Port, Buf_Trans);
596
597 Registers.Unset_And_Set_Mask
598 (Register => DDI_BUF_CTL (Port),
599 Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
600 DDI_BUF_CTL_PORT_REVERSAL or
601 DDI_BUF_CTL_PORT_WIDTH_MASK,
602 Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE);
603
604 Registers.Wait_Unset_Mask
605 (Register => DDI_BUF_CTL (Port),
606 Mask => DDI_BUF_CTL_IDLE_STATUS,
607 TOut_MS => 1);
608 end Enable_HDMI;
609
610end HW.GFX.GMA.Connectors.TC;