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