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