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