blob: 49c403964f7ed3ccc54d91d748cae7bba8125ce7 [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.DP_Info;
18with HW.GFX.GMA.DP_Aux_Ch;
19with HW.GFX.GMA.Registers;
20
21with HW.Debug;
22with GNAT.Source_Info;
23
24package body HW.GFX.GMA.Connectors.EDP
25is
26
27 DP_CTL_DISPLAYPORT_ENABLE : constant := 1 * 2 ** 31;
Nico Huber83693c82016-10-08 22:17:55 +020028 DP_CTL_VSWING_EMPH_SET_MASK : constant := 63 * 2 ** 22;
29 DP_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 19;
30 DP_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 19;
31 DP_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 19;
32 DP_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 19;
33 DP_CTL_ENHANCED_FRAMING_ENABLE : constant := 1 * 2 ** 18;
34 DP_CTL_PLL_FREQUENCY_MASK : constant := 3 * 2 ** 16;
35 DP_CTL_PLL_FREQUENCY_270 : constant := 0 * 2 ** 16;
36 DP_CTL_PLL_FREQUENCY_162 : constant := 1 * 2 ** 16;
37 DP_CTL_PORT_REVERSAL : constant := 1 * 2 ** 15;
38 DP_CTL_PLL_ENABLE : constant := 1 * 2 ** 14;
39 DP_CTL_LINK_TRAIN_MASK : constant := 3 * 2 ** 8;
40 DP_CTL_LINK_TRAIN_PAT1 : constant := 0 * 2 ** 8;
41 DP_CTL_LINK_TRAIN_PAT2 : constant := 1 * 2 ** 8;
42 DP_CTL_LINK_TRAIN_IDLE : constant := 2 * 2 ** 8;
43 DP_CTL_LINK_TRAIN_NORMAL : constant := 3 * 2 ** 8;
44 DP_CTL_ALT_SCRAMBLER_RESET : constant := 1 * 2 ** 6;
45 DP_CTL_VSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 4;
46 DP_CTL_HSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 3;
47 DP_CTL_PORT_DETECT : constant := 1 * 2 ** 2;
48
Nico Huber6e327c92016-12-21 14:45:45 +010049 type Pipe_Value_Array is array (Pipe_Index) of Word32;
50 DP_CTL_PIPE_SELECT : constant Pipe_Value_Array :=
51 (Primary => 0 * 2 ** 29,
52 Secondary => 1 * 2 ** 29,
53 Tertiary => 2 * 2 ** 29);
54
Nico Huber83693c82016-10-08 22:17:55 +020055 -- TODO? Values are for Ivy Bridge only
56 DP_CTL_VSWING_0_EMPH_0 : constant := 1 * 2 ** 27 + 1 * 2 ** 24 + 0 * 2 ** 22;
57 DP_CTL_VSWING_0_EMPH_1 : constant := 1 * 2 ** 27 + 2 * 2 ** 24 + 2 * 2 ** 22;
58 DP_CTL_VSWING_0_EMPH_2 : constant := 1 * 2 ** 27 + 3 * 2 ** 24 + 3 * 2 ** 22;
59 DP_CTL_VSWING_1_EMPH_0 : constant := 1 * 2 ** 27 + 4 * 2 ** 24 + 0 * 2 ** 22;
60 DP_CTL_VSWING_1_EMPH_1 : constant := 1 * 2 ** 27 + 5 * 2 ** 24 + 2 * 2 ** 22;
61 DP_CTL_VSWING_2_EMPH_0 : constant := 1 * 2 ** 27 + 6 * 2 ** 24 + 0 * 2 ** 22;
62 DP_CTL_VSWING_2_EMPH_1 : constant := 1 * 2 ** 27 + 7 * 2 ** 24 + 2 * 2 ** 22;
63
64 type DP_CTL_PORT_WIDTH_T is array (DP_Lane_Count) of Word32;
65 DP_CTL_PORT_WIDTH : constant DP_CTL_PORT_WIDTH_T :=
66 DP_CTL_PORT_WIDTH_T'
67 (DP_Lane_Count_1 => DP_CTL_PORT_WIDTH_1_LANE,
68 DP_Lane_Count_2 => DP_CTL_PORT_WIDTH_2_LANES,
69 DP_Lane_Count_4 => DP_CTL_PORT_WIDTH_4_LANES);
70
71 type DP_CTL_LINK_TRAIN_Array is array (DP_Info.Training_Pattern) of Word32;
72 DP_CTL_LINK_TRAIN : constant DP_CTL_LINK_TRAIN_Array :=
73 DP_CTL_LINK_TRAIN_Array'
74 (DP_Info.TP_1 => DP_CTL_LINK_TRAIN_PAT1,
75 DP_Info.TP_2 => DP_CTL_LINK_TRAIN_PAT2,
76 DP_Info.TP_3 => DP_CTL_LINK_TRAIN_PAT2,
77 DP_Info.TP_Idle => DP_CTL_LINK_TRAIN_IDLE,
78 DP_Info.TP_None => DP_CTL_LINK_TRAIN_NORMAL);
79
80 ----------------------------------------------------------------------------
81
82 procedure Pre_Training is
83 begin
84 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
85
86 Registers.Unset_And_Set_Mask
87 (Register => Registers.DP_CTL_A,
88 Mask_Unset => DP_CTL_LINK_TRAIN_MASK,
89 Mask_Set => DP_CTL_LINK_TRAIN (DP_Info.TP_1) or
90 DP_CTL_DISPLAYPORT_ENABLE);
91 end Pre_Training;
92
93 ----------------------------------------------------------------------------
94
95 pragma Warnings (GNATprove, Off, "unused variable ""Port""",
96 Reason => "Needed for a common interface");
97 function Max_V_Swing
98 (Port : Digital_Port)
99 return DP_Info.DP_Voltage_Swing
100 is
101 begin
102 return DP_Info.VS_Level_2;
103 end Max_V_Swing;
104
105 function Max_Pre_Emph
106 (Port : Digital_Port;
107 Train_Set : DP_Info.Train_Set)
108 return DP_Info.DP_Pre_Emph
109 is
110 begin
111 return
112 (case Train_Set.Voltage_Swing is
113 when DP_Info.VS_Level_0 => DP_Info.Emph_Level_2,
114 when DP_Info.VS_Level_1 |
115 DP_Info.VS_Level_2 => DP_Info.Emph_Level_1,
116 when others => DP_Info.Emph_Level_0);
117 end Max_Pre_Emph;
118
119 ----------------------------------------------------------------------------
120
121 pragma Warnings (GNATprove, Off, "unused variable ""Link""",
122 Reason => "Needed for a common interface");
123 procedure Set_Training_Pattern
124 (Port : Digital_Port;
125 Link : DP_Link;
126 Pattern : DP_Info.Training_Pattern)
127 is
128 use type DP_Info.Training_Pattern;
129 begin
130 if Pattern < DP_Info.TP_Idle then
131 Registers.Unset_And_Set_Mask
132 (Register => Registers.DP_CTL_A,
133 Mask_Unset => DP_CTL_LINK_TRAIN_MASK,
134 Mask_Set => DP_CTL_LINK_TRAIN (Pattern));
135 else
136 -- send at least 5 idle patterns
137 Registers.Unset_And_Set_Mask
138 (Register => Registers.DP_CTL_A,
139 Mask_Unset => DP_CTL_LINK_TRAIN_MASK,
140 Mask_Set => DP_CTL_LINK_TRAIN (DP_Info.TP_Idle));
141
142 -- we switch to normal frame delivery later in Post_On procedure
143 end if;
144 end Set_Training_Pattern;
145
146 procedure Set_Signal_Levels
147 (Port : Digital_Port;
148 Link : DP_Link;
149 Train_Set : DP_Info.Train_Set)
150 is
151 VSwing_Emph : Word32;
152 begin
153 VSwing_Emph :=
154 (case Train_Set.Voltage_Swing is
155 when DP_Info.VS_Level_0 =>
156 (case Train_Set.Pre_Emph is
157 when DP_Info.Emph_Level_0 => DP_CTL_VSWING_0_EMPH_0,
158 when DP_Info.Emph_Level_1 => DP_CTL_VSWING_0_EMPH_1,
159 when DP_Info.Emph_Level_2 => DP_CTL_VSWING_0_EMPH_2,
160 when others => DP_CTL_VSWING_0_EMPH_0),
161 when DP_Info.VS_Level_1 =>
162 (case Train_Set.Pre_Emph is
163 when DP_Info.Emph_Level_0 => DP_CTL_VSWING_1_EMPH_0,
164 when DP_Info.Emph_Level_1 => DP_CTL_VSWING_1_EMPH_1,
165 when others => DP_CTL_VSWING_1_EMPH_0),
166 when DP_Info.VS_Level_2 =>
167 (case Train_Set.Pre_Emph is
168 when DP_Info.Emph_Level_0 => DP_CTL_VSWING_2_EMPH_0,
169 when DP_Info.Emph_Level_1 => DP_CTL_VSWING_2_EMPH_1,
170 when others => DP_CTL_VSWING_2_EMPH_0),
171 when others => DP_CTL_VSWING_0_EMPH_0);
172
173 Registers.Unset_And_Set_Mask
174 (Register => Registers.DP_CTL_A,
175 Mask_Unset => DP_CTL_VSWING_EMPH_SET_MASK,
176 Mask_Set => VSwing_Emph);
177 end Set_Signal_Levels;
178 pragma Warnings (GNATprove, On, "unused variable ""Port""");
179 pragma Warnings (GNATprove, On, "unused variable ""Link""");
180
181 ----------------------------------------------------------------------------
182
Nico Huber6e327c92016-12-21 14:45:45 +0100183 procedure Pre_On (Pipe : Pipe_Index; Port_Cfg : Port_Config)
Nico Huber83693c82016-10-08 22:17:55 +0200184 is
185 DP_CTL_Set : Word32;
186 begin
187 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
188
189 DP_CTL_Set :=
Nico Huber6e327c92016-12-21 14:45:45 +0100190 DP_CTL_PIPE_SELECT (Pipe) or
Nico Huber83693c82016-10-08 22:17:55 +0200191 DP_CTL_PORT_WIDTH (Port_Cfg.DP.Lane_Count);
192
193 if Port_Cfg.DP.Enhanced_Framing then
194 DP_CTL_Set := DP_CTL_Set or DP_CTL_ENHANCED_FRAMING_ENABLE;
195 end if;
196
197 case Port_Cfg.DP.Bandwidth is
198 when DP_Bandwidth_1_62 =>
199 DP_CTL_Set := DP_CTL_Set or DP_CTL_PLL_FREQUENCY_162;
200 when DP_Bandwidth_2_7 =>
201 DP_CTL_Set := DP_CTL_Set or DP_CTL_PLL_FREQUENCY_270;
202 when others =>
203 null;
204 end case;
205
206 if Port_Cfg.Mode.V_Sync_Active_High then
207 DP_CTL_Set := DP_CTL_Set or DP_CTL_VSYNC_ACTIVE_HIGH;
208 end if;
209 if Port_Cfg.Mode.H_Sync_Active_High then
210 DP_CTL_Set := DP_CTL_Set or DP_CTL_HSYNC_ACTIVE_HIGH;
211 end if;
212
213 Registers.Write
214 (Register => Registers.DP_CTL_A,
215 Value => DP_CTL_Set);
216
217 Registers.Write
218 (Register => Registers.DP_CTL_A,
219 Value => DP_CTL_PLL_ENABLE or DP_CTL_Set);
220 Registers.Posting_Read (Registers.DP_CTL_A);
221 Time.U_Delay (20);
222 end Pre_On;
223
224 ----------------------------------------------------------------------------
225
226 procedure Post_On
227 (Link : in DP_Link;
228 Success : out Boolean)
229 is
230 pragma Warnings (GNATprove, Off, "unused variable ""Port""",
231 Reason => "Needed for a common interface");
232 function To_DP (Port : Digital_Port) return DP_Port
233 is
234 begin
235 return DP_A;
236 end To_DP;
237 pragma Warnings (GNATprove, On, "unused variable ""Port""");
238 package Training is new DP_Training
239 (TPS3_Supported => False,
240 T => Digital_Port,
241 Aux_T => DP_Port,
242 Aux_Ch => DP_Aux_Ch,
243 DP_Info => DP_Info,
244 To_Aux => To_DP,
245 Max_V_Swing => Max_V_Swing,
246 Max_Pre_Emph => Max_Pre_Emph,
247 Set_Pattern => Set_Training_Pattern,
248 Set_Signal_Levels => Set_Signal_Levels,
249 Off => Off);
250 begin
251 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
252
253 Training.Train_DP
254 (Port => DIGI_A,
255 Link => Link,
256 Success => Success);
257
258 if Success then
259 Registers.Unset_And_Set_Mask
260 (Register => Registers.DP_CTL_A,
261 Mask_Unset => DP_CTL_LINK_TRAIN_MASK,
262 Mask_Set => DP_CTL_LINK_TRAIN_NORMAL);
263 end if;
264 end Post_On;
265
266 ----------------------------------------------------------------------------
267
268 procedure Off (Port : Digital_Port)
269 is
270 Enabled : Boolean;
271 begin
272 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
273
274 Registers.Unset_And_Set_Mask
275 (Register => Registers.DP_CTL_A,
276 Mask_Unset => DP_CTL_LINK_TRAIN_MASK,
277 Mask_Set => DP_CTL_LINK_TRAIN_IDLE);
278 Registers.Posting_Read (Registers.DP_CTL_A);
279
280 Registers.Unset_Mask
281 (Register => Registers.DP_CTL_A,
282 Mask => DP_CTL_DISPLAYPORT_ENABLE);
283 -- implicit Posting_Read below
284
285 Registers.Is_Set_Mask
286 (Register => Registers.DP_CTL_A,
287 Mask => DP_CTL_PLL_ENABLE,
288 Result => Enabled);
289
290 Registers.Write
291 (Register => Registers.DP_CTL_A,
292 Value => 16#0000_0000#);
293 Registers.Posting_Read (Registers.DP_CTL_A);
294
295 if Enabled then
296 Time.U_Delay (20);
297 end if;
298 end Off;
299
300end HW.GFX.GMA.Connectors.EDP;