blob: 31f0b4c408d2b73d1e8c342cbc6dfe467f0c5674 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2015-2016 secunet Security Networks AG
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
Nico Huber125a29e2016-10-18 00:23:54 +02006-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02008--
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.Time;
16with HW.GFX.DP_Training;
17with HW.GFX.GMA.Config;
18with HW.GFX.GMA.PCH.FDI;
19with HW.GFX.GMA.PCH.Transcoder;
20with HW.GFX.GMA.PCH.VGA;
21with HW.GFX.GMA.DP_Info;
22with HW.GFX.GMA.DP_Aux_Ch;
23with HW.GFX.GMA.SPLL;
24
25with HW.Debug;
26with GNAT.Source_Info;
27
28package body HW.GFX.GMA.Connectors.DDI is
29
30 DDI_BUF_CTL_BUFFER_ENABLE : constant := 1 * 2 ** 31;
31 DDI_BUF_CTL_TRANS_SELECT_MASK : constant := 15 * 2 ** 24;
32 DDI_BUF_CTL_PORT_REVERSAL : constant := 1 * 2 ** 16;
33 DDI_BUF_CTL_IDLE_STATUS : constant := 1 * 2 ** 7;
34 DDI_BUF_CTL_DDI_A_LANE_CAP : constant := 1 * 2 ** 4;
35 DDI_BUF_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 1;
36 DDI_BUF_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 1;
37 DDI_BUF_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 1;
38 DDI_BUF_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 1;
39 DDI_BUF_CTL_INIT_DISPLAY_DETECT : constant := 1 * 2 ** 0;
40
41 subtype DDI_BUF_CTL_TRANS_SELECT_T is Natural range 0 .. 9;
42 function DDI_BUF_CTL_TRANS_SELECT
43 (Sel : DDI_BUF_CTL_TRANS_SELECT_T)
44 return Word32;
45
46 type DDI_BUF_CTL_PORT_WIDTH_T is array (HW.GFX.DP_Lane_Count) of Word32;
47 DDI_BUF_CTL_PORT_WIDTH : constant DDI_BUF_CTL_PORT_WIDTH_T :=
48 DDI_BUF_CTL_PORT_WIDTH_T'
49 (HW.GFX.DP_Lane_Count_1 => DDI_BUF_CTL_PORT_WIDTH_1_LANE,
50 HW.GFX.DP_Lane_Count_2 => DDI_BUF_CTL_PORT_WIDTH_2_LANES,
51 HW.GFX.DP_Lane_Count_4 => DDI_BUF_CTL_PORT_WIDTH_4_LANES);
52
53 DP_TP_CTL_TRANSPORT_ENABLE : constant := 1 * 2 ** 31;
54 DP_TP_CTL_MODE_SST : constant := 0 * 2 ** 27;
55 DP_TP_CTL_MODE_MST : constant := 1 * 2 ** 27;
56 DP_TP_CTL_FORCE_ACT : constant := 1 * 2 ** 25;
57 DP_TP_CTL_ENHANCED_FRAME_ENABLE : constant := 1 * 2 ** 18;
58 DP_TP_CTL_FDI_AUTOTRAIN : constant := 1 * 2 ** 15;
59 DP_TP_CTL_LINK_TRAIN_MASK : constant := 7 * 2 ** 8;
60 DP_TP_CTL_LINK_TRAIN_PAT1 : constant := 0 * 2 ** 8;
61 DP_TP_CTL_LINK_TRAIN_PAT2 : constant := 1 * 2 ** 8;
62 DP_TP_CTL_LINK_TRAIN_PAT3 : constant := 4 * 2 ** 8;
63 DP_TP_CTL_LINK_TRAIN_IDLE : constant := 2 * 2 ** 8;
64 DP_TP_CTL_LINK_TRAIN_NORMAL : constant := 3 * 2 ** 8;
65 DP_TP_CTL_SCRAMBLE_DISABLE : constant := 1 * 2 ** 7;
66 DP_TP_CTL_ALT_SCRAMBLER_RESET : constant := 1 * 2 ** 6;
67
68 type DP_TP_CTL_LINK_TRAIN_Array is
69 array (DP_Info.Training_Pattern) of Word32;
70 DP_TP_CTL_LINK_TRAIN : constant DP_TP_CTL_LINK_TRAIN_Array :=
71 DP_TP_CTL_LINK_TRAIN_Array'
72 (DP_Info.TP_1 => DP_TP_CTL_LINK_TRAIN_PAT1 or DP_TP_CTL_SCRAMBLE_DISABLE,
73 DP_Info.TP_2 => DP_TP_CTL_LINK_TRAIN_PAT2 or DP_TP_CTL_SCRAMBLE_DISABLE,
74 DP_Info.TP_3 => DP_TP_CTL_LINK_TRAIN_PAT3 or DP_TP_CTL_SCRAMBLE_DISABLE,
75 DP_Info.TP_Idle => DP_TP_CTL_LINK_TRAIN_IDLE,
76 DP_Info.TP_None => DP_TP_CTL_LINK_TRAIN_NORMAL);
77
78 DP_TP_STATUS_MIN_IDLES_SENT : constant := 1 * 2 ** 25;
79 DP_TP_STATUS_FDI_AUTO_TRAIN_DONE : constant := 1 * 2 ** 12;
80
81 PORT_CLK_SEL_LCPLL2700 : constant := 0 * 2 ** 29; -- not on ULX
82 PORT_CLK_SEL_LCPLL1350 : constant := 1 * 2 ** 29;
83 PORT_CLK_SEL_LCPLL810 : constant := 2 * 2 ** 29;
84 PORT_CLK_SEL_SPLL : constant := 3 * 2 ** 29;
85 PORT_CLK_SEL_WRPLL1 : constant := 4 * 2 ** 29;
86 PORT_CLK_SEL_WRPLL2 : constant := 5 * 2 ** 29;
87 PORT_CLK_SEL_NONE : constant := 7 * 2 ** 29;
88
89 type PORT_CLK_SEL_LCPLL_T is array (HW.GFX.DP_Bandwidth) of Word32;
90 PORT_CLK_SEL_LCPLL : constant PORT_CLK_SEL_LCPLL_T :=
91 PORT_CLK_SEL_LCPLL_T'
92 (HW.GFX.DP_Bandwidth_1_62 => PORT_CLK_SEL_LCPLL810,
93 HW.GFX.DP_Bandwidth_2_7 => PORT_CLK_SEL_LCPLL1350,
94 HW.GFX.DP_Bandwidth_5_4 => PORT_CLK_SEL_LCPLL2700);
95
96 type DDI_Registers is record
97 BUF_CTL : Registers.Registers_Index;
98 DP_TP_CTL : Registers.Registers_Index;
99 DP_TP_STATUS : Registers.Registers_Invalid_Index;
100 PORT_CLK_SEL : Registers.Registers_Index;
101 end record;
102
103 type DDI_Registers_Array is array (Digital_Port) of DDI_Registers;
104
105 DDI_Regs : constant DDI_Registers_Array := DDI_Registers_Array'
106 (DIGI_A => DDI_Registers'
107 (BUF_CTL => Registers.DDI_BUF_CTL_A,
108 DP_TP_CTL => Registers.DP_TP_CTL_A,
109 DP_TP_STATUS => Registers.Invalid_Register,
110 PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIA),
111 DIGI_B => DDI_Registers'
112 (BUF_CTL => Registers.DDI_BUF_CTL_B,
113 DP_TP_CTL => Registers.DP_TP_CTL_B,
114 DP_TP_STATUS => Registers.DP_TP_STATUS_B,
115 PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIB),
116 DIGI_C => DDI_Registers'
117 (BUF_CTL => Registers.DDI_BUF_CTL_C,
118 DP_TP_CTL => Registers.DP_TP_CTL_C,
119 DP_TP_STATUS => Registers.DP_TP_STATUS_C,
120 PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIC),
121 DIGI_D => DDI_Registers'
122 (BUF_CTL => Registers.DDI_BUF_CTL_D,
123 DP_TP_CTL => Registers.DP_TP_CTL_D,
124 DP_TP_STATUS => Registers.DP_TP_STATUS_D,
125 PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDID),
126 DIGI_E => DDI_Registers'
127 (BUF_CTL => Registers.DDI_BUF_CTL_E,
128 DP_TP_CTL => Registers.DP_TP_CTL_E,
129 DP_TP_STATUS => Registers.DP_TP_STATUS_E,
130 PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIE));
131
132 ----------------------------------------------------------------------------
133
134 type Values is array (Digital_Port) of Word32;
135 type Shifts is array (Digital_Port) of Natural;
136
137 DPLL_CTRL2_DDIx_CLOCK_OFF : constant Values := Values'
138 (DIGI_A => 1 * 2 ** 15,
139 DIGI_B => 1 * 2 ** 16,
140 DIGI_C => 1 * 2 ** 17,
141 DIGI_D => 1 * 2 ** 18,
142 DIGI_E => 1 * 2 ** 19);
143
144 DPLL_CTRL2_DDIx_SELECT_MASK : constant Values := Values'
145 (DIGI_A => 3 * 2 ** 1,
146 DIGI_B => 3 * 2 ** 4,
147 DIGI_C => 3 * 2 ** 7,
148 DIGI_D => 3 * 2 ** 10,
149 DIGI_E => 3 * 2 ** 13);
150 DPLL_CTRL2_DDIx_SELECT_SHIFT : constant Shifts := Shifts'
151 (DIGI_A => 1,
152 DIGI_B => 4,
153 DIGI_C => 7,
154 DIGI_D => 10,
155 DIGI_E => 13);
156
157 DPLL_CTRL2_DDIx_SELECT_OVERRIDE : constant Values := Values'
158 (DIGI_A => 1 * 2 ** 0,
159 DIGI_B => 1 * 2 ** 3,
160 DIGI_C => 1 * 2 ** 6,
161 DIGI_D => 1 * 2 ** 9,
162 DIGI_E => 1 * 2 ** 12);
163
164 ----------------------------------------------------------------------------
165
166 function DDI_BUF_CTL_TRANS_SELECT
167 (Sel : DDI_BUF_CTL_TRANS_SELECT_T)
168 return Word32
169 is
170 begin
171 return Word32 (Sel) * 2 ** 24;
172 end DDI_BUF_CTL_TRANS_SELECT;
173
174 ----------------------------------------------------------------------------
175
176 function Max_V_Swing
177 (Port : Digital_Port)
178 return DP_Info.DP_Voltage_Swing
179 is
180 begin
181 return
182 (if (Config.Has_Low_Voltage_Swing and Config.EDP_Low_Voltage_Swing)
183 and then Port = DIGI_A
184 then
185 DP_Info.VS_Level_3
186 else
187 DP_Info.VS_Level_2);
188 end Max_V_Swing;
189
190 pragma Warnings (GNATprove, Off, "unused variable ""Port""",
191 Reason => "Needed for a common interface");
192 function Max_Pre_Emph
193 (Port : Digital_Port;
194 Train_Set : DP_Info.Train_Set)
195 return DP_Info.DP_Pre_Emph
196 is
197 begin
198 return
199 (case Train_Set.Voltage_Swing is
200 when DP_Info.VS_Level_0 => DP_Info.Emph_Level_3,
201 when DP_Info.VS_Level_1 => DP_Info.Emph_Level_2,
202 when DP_Info.VS_Level_2 => DP_Info.Emph_Level_1,
203 when others => DP_Info.Emph_Level_0);
204 end Max_Pre_Emph;
205 pragma Warnings (GNATprove, On, "unused variable ""Port""");
206
207 ----------------------------------------------------------------------------
208
209 procedure Set_TP_CTL
210 (Port : Digital_Port;
211 Link : DP_Link;
212 Pattern : DP_Info.Training_Pattern)
213 is
214 DP_TP_CTL_Enhanced_Frame : Word32 := 0;
215 begin
216 if Link.Enhanced_Framing then
217 DP_TP_CTL_Enhanced_Frame := DP_TP_CTL_ENHANCED_FRAME_ENABLE;
218 end if;
219
220 Registers.Write
221 (Register => DDI_Regs (Port).DP_TP_CTL,
222 Value => DP_TP_CTL_TRANSPORT_ENABLE or
223 DP_TP_CTL_Enhanced_Frame or
224 DP_TP_CTL_LINK_TRAIN (Pattern));
225 end Set_TP_CTL;
226
227 procedure Set_Training_Pattern
228 (Port : Digital_Port;
229 Link : DP_Link;
230 Pattern : DP_Info.Training_Pattern)
231 is
232 use type DP_Info.Training_Pattern;
233 begin
234 if Pattern < DP_Info.TP_Idle then
235 Set_TP_CTL (Port, Link, Pattern);
236 else
237 -- send at least 5 idle patterns
238 Set_TP_CTL (Port, Link, DP_Info.TP_Idle);
239
240 -- switch to normal frame delivery
241 if Config.End_EDP_Training_Late and then Port = DIGI_A then
242 null; -- do it later in Post_On procedure
243 -- TODO: if there are problems getting the pipe up,
244 -- wait here some time
245 -- Time.U_Delay (100);
246 else
247 if Port /= DIGI_A then
248 Registers.Wait_Set_Mask
249 (Register => DDI_Regs (Port).DP_TP_STATUS,
250 Mask => DP_TP_STATUS_MIN_IDLES_SENT);
251 end if;
252 Set_TP_CTL (Port, Link, DP_Info.TP_None);
253 end if;
254 end if;
255 end Set_Training_Pattern;
256
257 procedure Set_Signal_Levels
258 (Port : Digital_Port;
259 Link : DP_Link;
260 Train_Set : DP_Info.Train_Set)
261 is
262 Was_Enabled : Boolean;
263 Trans_Select : DDI_BUF_CTL_TRANS_SELECT_T;
264 begin
265 case Train_Set.Voltage_Swing is
266 when DP_Info.VS_Level_0 =>
267 case Train_Set.Pre_Emph is
268 when DP_Info.Emph_Level_0 => Trans_Select := 0;
269 when DP_Info.Emph_Level_1 => Trans_Select := 1;
270 when DP_Info.Emph_Level_2 => Trans_Select := 2;
271 when DP_Info.Emph_Level_3 => Trans_Select := 3;
272 end case;
273 when DP_Info.VS_Level_1 =>
274 case Train_Set.Pre_Emph is
275 when DP_Info.Emph_Level_0 => Trans_Select := 4;
276 when DP_Info.Emph_Level_1 => Trans_Select := 5;
277 when DP_Info.Emph_Level_2 => Trans_Select := 6;
278 when others => Trans_Select := 0;
279 end case;
280 when DP_Info.VS_Level_2 =>
281 case Train_Set.Pre_Emph is
282 when DP_Info.Emph_Level_0 => Trans_Select := 7;
283 when DP_Info.Emph_Level_1 => Trans_Select := 8;
284 when others => Trans_Select := 0;
285 end case;
286 when DP_Info.VS_Level_3 =>
287 case Train_Set.Pre_Emph is
288 when DP_Info.Emph_Level_0 => Trans_Select := 9;
289 when others => Trans_Select := 0;
290 end case;
291 end case;
292
293 Registers.Is_Set_Mask
294 (Register => DDI_Regs (Port).BUF_CTL,
295 Mask => DDI_BUF_CTL_BUFFER_ENABLE,
296 Result => Was_Enabled);
297
298 -- enable DDI buffer
299 Registers.Unset_And_Set_Mask
300 (Register => DDI_Regs (Port).BUF_CTL,
301 Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
302 DDI_BUF_CTL_PORT_REVERSAL or
303 DDI_BUF_CTL_PORT_WIDTH_MASK,
304 Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or
305 DDI_BUF_CTL_TRANS_SELECT (Trans_Select) or
306 DDI_BUF_CTL_PORT_WIDTH (Link.Lane_Count));
307 Registers.Posting_Read (DDI_Regs (Port).BUF_CTL);
308
309 if not Was_Enabled then
310 Time.U_Delay (600); -- wait >= 518us (intel spec)
311 end if;
312 end Set_Signal_Levels;
313
314 ----------------------------------------------------------------------------
315
316 procedure Digital_Off (Port : Digital_Port)
317 is
318 Enabled : Boolean;
319 begin
320 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
321
322 Registers.Is_Set_Mask
323 (Register => DDI_Regs (Port).BUF_CTL,
324 Mask => DDI_BUF_CTL_BUFFER_ENABLE,
325 Result => Enabled);
326
327 if Enabled then
328 Registers.Unset_Mask
329 (Register => DDI_Regs (Port).BUF_CTL,
330 Mask => DDI_BUF_CTL_BUFFER_ENABLE);
331 end if;
332
333 Registers.Unset_Mask
334 (Register => DDI_Regs (Port).DP_TP_CTL,
335 Mask => DP_TP_CTL_TRANSPORT_ENABLE);
336
337 if Enabled then
338 Registers.Wait_Set_Mask
339 (Register => DDI_Regs (Port).BUF_CTL,
340 Mask => DDI_BUF_CTL_IDLE_STATUS);
341 end if;
342
343 if Config.Has_Per_DDI_Clock_Sel then
344 Registers.Write
345 (Register => DDI_Regs (Port).PORT_CLK_SEL,
346 Value => PORT_CLK_SEL_NONE);
347 else
348 Registers.Set_Mask
349 (Register => Registers.DPLL_CTRL2,
350 Mask => DPLL_CTRL2_DDIx_CLOCK_OFF (Port));
351 end if;
352 end Digital_Off;
353
354 ----------------------------------------------------------------------------
355
356 procedure Train_FDI
357 (Port_Cfg : in Port_Config;
358 Success : out Boolean)
359 is
360 begin
361 PCH.FDI.Pre_Train (PCH.FDI_A, Port_Cfg);
362
363 -- always use SPLL for FDI
364 SPLL.On;
365 Registers.Write
366 (Register => DDI_Regs (DIGI_E).PORT_CLK_SEL,
367 Value => PORT_CLK_SEL_SPLL);
368
369 -- try each preemph/voltage pair twice
370 for Trans2 in Natural range 0 .. DDI_BUF_CTL_TRANS_SELECT_T'Last * 2 + 1
371 loop
372 Registers.Write
373 (Register => DDI_Regs (DIGI_E).DP_TP_CTL,
374 Value => DP_TP_CTL_TRANSPORT_ENABLE or
375 DP_TP_CTL_ENHANCED_FRAME_ENABLE or
376 DP_TP_CTL_FDI_AUTOTRAIN or
377 DP_TP_CTL_LINK_TRAIN_PAT1);
378
379 Registers.Unset_And_Set_Mask
380 (Register => DDI_Regs (DIGI_E).BUF_CTL,
381 Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
382 DDI_BUF_CTL_PORT_REVERSAL or
383 DDI_BUF_CTL_PORT_WIDTH_MASK,
384 Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or
385 DDI_BUF_CTL_TRANS_SELECT (Trans2 / 2) or
386 DDI_BUF_CTL_PORT_WIDTH (Port_Cfg.FDI.Lane_Count));
387 Registers.Posting_Read (DDI_Regs (DIGI_E).BUF_CTL);
388 Time.U_Delay (600); -- wait >= 518us (intel spec)
389
390 PCH.FDI.Auto_Train (PCH.FDI_A);
391 Registers.Is_Set_Mask
392 (Register => DDI_Regs (DIGI_E).DP_TP_STATUS,
393 Mask => DP_TP_STATUS_FDI_AUTO_TRAIN_DONE,
394 Result => Success);
395 exit when Success;
396
397 Registers.Unset_Mask
398 (Register => DDI_Regs (DIGI_E).BUF_CTL,
399 Mask => DDI_BUF_CTL_BUFFER_ENABLE);
400 Registers.Posting_Read (DDI_Regs (DIGI_E).BUF_CTL);
401
402 Registers.Unset_And_Set_Mask
403 (Register => DDI_Regs (DIGI_E).DP_TP_CTL,
404 Mask_Unset => DP_TP_CTL_TRANSPORT_ENABLE or
405 DP_TP_CTL_LINK_TRAIN_MASK,
406 Mask_Set => DP_TP_CTL_LINK_TRAIN_PAT1);
407 Registers.Posting_Read (DDI_Regs (DIGI_E).DP_TP_CTL);
408
409 Registers.Wait_Set_Mask
410 (Register => DDI_Regs (DIGI_E).BUF_CTL,
411 Mask => DDI_BUF_CTL_IDLE_STATUS);
412
413 PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Lanes_Off);
414 end loop;
415
416 if Success then
417 -- start normal frame delivery
418 Registers.Write
419 (Register => DDI_Regs (DIGI_E).DP_TP_CTL,
420 Value => DP_TP_CTL_TRANSPORT_ENABLE or
421 DP_TP_CTL_ENHANCED_FRAME_ENABLE or
422 DP_TP_CTL_FDI_AUTOTRAIN or
423 DP_TP_CTL_LINK_TRAIN_NORMAL);
424 else
425 Registers.Write
426 (Register => DDI_Regs (DIGI_E).PORT_CLK_SEL,
427 Value => PORT_CLK_SEL_NONE);
428 SPLL.Off;
429
430 PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Clock_Off);
431 end if;
432 end Train_FDI;
433
434 ----------------------------------------------------------------------------
435
436 procedure Pre_On
437 (Port_Cfg : in Port_Config;
438 PLL_Hint : in Word32;
439 Success : out Boolean)
440 is
441 function To_DP (Port : Digital_Port) return DP_Port
442 is
443 begin
444 return
445 (case Port is
446 when DIGI_A => DP_A,
447 when DIGI_B => DP_B,
448 when DIGI_C => DP_C,
449 when DIGI_D => DP_D,
450 when others => DP_Port'First);
451 end To_DP;
452 package Training is new DP_Training
453 (TPS3_Supported => True,
454 T => Digital_Port,
455 Aux_T => DP_Port,
456 Aux_Ch => DP_Aux_Ch,
457 DP_Info => DP_Info,
458 To_Aux => To_DP,
459 Max_V_Swing => Max_V_Swing,
460 Max_Pre_Emph => Max_Pre_Emph,
461 Set_Pattern => Set_Training_Pattern,
462 Set_Signal_Levels => Set_Signal_Levels,
463 Off => Digital_Off);
464 begin
465 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
466
467 if Port_Cfg.Display = VGA then
468 Train_FDI (Port_Cfg, Success);
469 else
470 -- direct configured PLL output to this port
471 if Config.Has_Per_DDI_Clock_Sel then
472 Registers.Write
473 (Register => DDI_Regs (Port_Cfg.Port).PORT_CLK_SEL,
474 Value => PLL_Hint);
475 else
476 Registers.Unset_And_Set_Mask
477 (Register => Registers.DPLL_CTRL2,
478 Mask_Unset => DPLL_CTRL2_DDIx_CLOCK_OFF (Port_Cfg.Port) or
479 DPLL_CTRL2_DDIx_SELECT_MASK (Port_Cfg.Port),
480 Mask_Set => Shift_Left
481 (PLL_Hint,
482 DPLL_CTRL2_DDIx_SELECT_SHIFT (Port_Cfg.Port))
483 or
484 DPLL_CTRL2_DDIx_SELECT_OVERRIDE (Port_Cfg.Port));
485 end if;
486
487 if Port_Cfg.Display = DP then
488 Training.Train_DP
489 (Port => Port_Cfg.Port,
490 Link => Port_Cfg.DP,
491 Success => Success);
492 else
493 Success := True;
494 end if;
495 end if;
496 end Pre_On;
497
498 ----------------------------------------------------------------------------
499
500 procedure Post_On (Port_Cfg : Port_Config)
501 is
502 begin
503 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
504
505 if Port_Cfg.Port = DIGI_A then
506 if Config.End_EDP_Training_Late then
507 Registers.Unset_And_Set_Mask
508 (Register => DDI_Regs (DIGI_A).DP_TP_CTL,
509 Mask_Unset => DP_TP_CTL_LINK_TRAIN_MASK,
510 Mask_Set => DP_TP_CTL_LINK_TRAIN_NORMAL);
511 end if;
512 end if;
513
514 case Port_Cfg.Display is
515 when HDMI =>
516 Registers.Unset_And_Set_Mask
517 (Register => DDI_Regs (Port_Cfg.Port).BUF_CTL,
518 Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
519 DDI_BUF_CTL_PORT_REVERSAL,
520 Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE);
521 Time.U_Delay (600); -- wait >= 518us (intel spec)
522 when VGA =>
523 PCH.VGA.Clock_On (Port_Cfg.Mode);
524 PCH.Transcoder.On (Port_Cfg, PCH.FDI_A, 0);
525 PCH.VGA.On
526 (Port => PCH.FDI_A,
527 Mode => Port_Cfg.Mode);
528 when others =>
529 null;
530 end case;
531 end Post_On;
532
533 ----------------------------------------------------------------------------
534
535 procedure Off (Port : Digital_Port)
536 is
537 begin
538 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
539
540 if Port = DIGI_E then
541 PCH.VGA.Off;
542 PCH.Transcoder.Off (PCH.FDI_A);
543 -- PCH.VGA.Clock_Off; -- Can't tell what Linux does, if anything.
544 PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Rx_Off);
545 end if;
546
547 Digital_Off (Port);
548
549 if Port = DIGI_E then
550 SPLL.Off;
551 PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Clock_Off);
552 end if;
553 end Off;
554
555end HW.GFX.GMA.Connectors.DDI;