blob: baa7e6c185a0e0ddd6794cf4e35cecde38cc88a9 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber3d06de82018-05-29 01:35:04 +02002-- Copyright (C) 2014-2018 secunet Security Networks AG
Nico Huber2b6f6992017-07-09 18:11:34 +02003-- Copyright (C) 2017 Nico Huber <nico.h@gmx.de>
Nico Huber83693c82016-10-08 22:17:55 +02004--
5-- This program is free software; you can redistribute it and/or modify
6-- it under the terms of the GNU General Public License as published by
Nico Huber125a29e2016-10-18 00:23:54 +02007-- the Free Software Foundation; either version 2 of the License, or
8-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02009--
10-- This program is distributed in the hope that it will be useful,
11-- but WITHOUT ANY WARRANTY; without even the implied warranty of
12-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13-- GNU General Public License for more details.
14--
15
Nico Huber2b6f6992017-07-09 18:11:34 +020016with HW.MMIO_Range;
17pragma Elaborate_All (HW.MMIO_Range);
18with HW.PCI.Dev;
19pragma Elaborate_All (HW.PCI.Dev);
20
Nico Huber83693c82016-10-08 22:17:55 +020021with HW.GFX.GMA.Config;
Nico Huber8c45bcf2016-11-20 17:30:57 +010022with HW.GFX.GMA.Config_Helpers;
Nico Huber83693c82016-10-08 22:17:55 +020023with HW.GFX.GMA.Registers;
24with HW.GFX.GMA.Power_And_Clocks;
25with HW.GFX.GMA.Panel;
26with HW.GFX.GMA.PLLs;
27with HW.GFX.GMA.Port_Detect;
28with HW.GFX.GMA.Connectors;
29with HW.GFX.GMA.Connector_Info;
30with HW.GFX.GMA.Pipe_Setup;
31
Nico Huber83693c82016-10-08 22:17:55 +020032with HW.Debug;
33with GNAT.Source_Info;
34
Nico Huber83693c82016-10-08 22:17:55 +020035use type HW.Int32;
36
37package body HW.GFX.GMA
38 with Refined_State =>
39 (State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020040 (Dev.Address_State,
41 Registers.Address_State,
Nico Huber83693c82016-10-08 22:17:55 +020042 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +010043 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +020044 HPD_Delay, Wait_For_HPD,
45 Linear_FB_Base),
Nico Huber83693c82016-10-08 22:17:55 +020046 Init_State => Initialized,
Nico Huber318bca12018-06-09 19:22:52 +020047 Config_State => (Config.Valid_Port, Config.Raw_Clock),
Nico Huber83693c82016-10-08 22:17:55 +020048 Device_State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020049 (Dev.PCI_State, Registers.Register_State, Registers.GTT_State))
Nico Huber83693c82016-10-08 22:17:55 +020050is
Nico Huber2b6f6992017-07-09 18:11:34 +020051 pragma Disable_Atomic_Synchronization;
Nico Huber83693c82016-10-08 22:17:55 +020052
53 subtype Port_Name is String (1 .. 8);
54 type Port_Name_Array is array (Port_Type) of Port_Name;
55 Port_Names : constant Port_Name_Array :=
56 (Disabled => "Disabled",
57 Internal => "Internal",
58 DP1 => "DP1 ",
59 DP2 => "DP2 ",
60 DP3 => "DP3 ",
Nico Huber0d454cd2016-11-21 13:33:43 +010061 HDMI1 => "HDMI1 ",
62 HDMI2 => "HDMI2 ",
63 HDMI3 => "HDMI3 ",
Nico Huber83693c82016-10-08 22:17:55 +020064 Analog => "Analog ");
65
Nico Huber2b6f6992017-07-09 18:11:34 +020066 package Dev is new HW.PCI.Dev (PCI.Address'(0, 2, 0));
67
Nico Huber83693c82016-10-08 22:17:55 +020068 package Display_Controller renames Pipe_Setup;
69
Nico Huber99f10f32016-11-20 00:34:05 +010070 type PLLs_Type is array (Pipe_Index) of PLLs.T;
Nico Huber83693c82016-10-08 22:17:55 +020071
Nico Huber83693c82016-10-08 22:17:55 +020072 type HPD_Type is array (Port_Type) of Boolean;
Nico Huber3be61d42017-01-09 13:58:18 +010073 type HPD_Delay_Type is array (Active_Port_Type) of Time.T;
Nico Huber83693c82016-10-08 22:17:55 +020074
Nico Huber83693c82016-10-08 22:17:55 +020075 Allocated_PLLs : PLLs_Type;
Nico Huber83693c82016-10-08 22:17:55 +020076 HPD_Delay : HPD_Delay_Type;
77 Wait_For_HPD : HPD_Type;
78 Initialized : Boolean := False;
79
Nico Huberc3f66f62017-07-16 21:39:54 +020080 Linear_FB_Base : Word64;
81
Nico Huber83693c82016-10-08 22:17:55 +020082 ----------------------------------------------------------------------------
83
Nico Huberf54d0962016-10-20 14:17:18 +020084 PCH_RAWCLK_FREQ_MASK : constant := 16#3ff# * 2 ** 0;
85
86 function PCH_RAWCLK_FREQ (Freq : Frequency_Type) return Word32
87 is
88 begin
89 return Word32 (Freq / 1_000_000);
90 end PCH_RAWCLK_FREQ;
91
92 ----------------------------------------------------------------------------
93
Nico Huber43370ba2017-01-09 15:26:19 +010094 procedure Enable_Output
95 (Pipe : in Pipe_Index;
96 Pipe_Cfg : in Pipe_Config;
97 Success : out Boolean)
Nico Huber8a5a3b52018-06-04 14:42:13 +020098 with
99 Pre => Pipe_Cfg.Port in Active_Port_Type
Nico Huber43370ba2017-01-09 15:26:19 +0100100 is
101 Port_Cfg : Port_Config;
Nico Huberf361ec82018-06-02 18:01:45 +0200102 Scaler_Available : Boolean;
Nico Huber43370ba2017-01-09 15:26:19 +0100103 begin
Nico Huber3be61d42017-01-09 13:58:18 +0100104 pragma Debug (Debug.New_Line);
105 pragma Debug (Debug.Put_Line
106 ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
107
Nico Huber43370ba2017-01-09 15:26:19 +0100108 Config_Helpers.Fill_Port_Config
109 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
110
111 if Success then
Nico Huberf361ec82018-06-02 18:01:45 +0200112 Display_Controller.Scaler_Available (Scaler_Available, Pipe);
Nico Huber43370ba2017-01-09 15:26:19 +0100113 Success := Config_Helpers.Validate_Config
Nico Huberf361ec82018-06-02 18:01:45 +0200114 (Pipe_Cfg.Framebuffer, Port_Cfg.Mode, Pipe, Scaler_Available);
Nico Huber43370ba2017-01-09 15:26:19 +0100115 end if;
116
Nico Huber43370ba2017-01-09 15:26:19 +0100117 if Success then
Nico Huber43370ba2017-01-09 15:26:19 +0100118 Connector_Info.Preferred_Link_Setting (Port_Cfg, Success);
119 end if;
120
121 -- loop over all possible DP-lane configurations
122 -- (non-DP ports use a single fake configuration)
123 while Success loop
124 pragma Loop_Invariant
125 (Pipe_Cfg.Port in Active_Port_Type and
126 Port_Cfg.Mode = Port_Cfg.Mode'Loop_Entry);
127
128 PLLs.Alloc
129 (Port_Cfg => Port_Cfg,
130 PLL => Allocated_PLLs (Pipe),
131 Success => Success);
132
133 if Success then
134 -- try each DP-lane configuration twice
135 for Try in 1 .. 2 loop
136 pragma Loop_Invariant
137 (Pipe_Cfg.Port in Active_Port_Type);
138
Nico Huber4798c662017-01-11 12:44:48 +0100139 -- Clear pending hot-plug events before every try
140 Port_Detect.Clear_Hotplug_Detect (Pipe_Cfg.Port);
141
Nico Huber43370ba2017-01-09 15:26:19 +0100142 Connectors.Pre_On
143 (Pipe => Pipe,
144 Port_Cfg => Port_Cfg,
145 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
146 Success => Success);
147
148 if Success then
149 Display_Controller.On
150 (Pipe => Pipe,
151 Port_Cfg => Port_Cfg,
Nico Huber4dc4c612018-01-10 15:55:09 +0100152 Framebuffer => Pipe_Cfg.Framebuffer,
153 Cursor => Pipe_Cfg.Cursor);
Nico Huber43370ba2017-01-09 15:26:19 +0100154
155 Connectors.Post_On
Arthur Heymans60d0e5f2018-03-28 17:08:27 +0200156 (Pipe => Pipe,
157 Port_Cfg => Port_Cfg,
Nico Huber43370ba2017-01-09 15:26:19 +0100158 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
159 Success => Success);
160
161 if not Success then
162 Display_Controller.Off (Pipe);
163 Connectors.Post_Off (Port_Cfg);
164 end if;
165 end if;
166
167 exit when Success;
168 end loop;
169 exit when Success; -- connection established => stop loop
170
171 -- connection failed
172 PLLs.Free (Allocated_PLLs (Pipe));
173 end if;
174
175 Connector_Info.Next_Link_Setting (Port_Cfg, Success);
176 end loop;
177
178 if Success then
179 pragma Debug (Debug.Put_Line
180 ("Enabled port " & Port_Names (Pipe_Cfg.Port)));
181 else
182 Wait_For_HPD (Pipe_Cfg.Port) := True;
183 if Pipe_Cfg.Port = Internal then
184 Panel.Off;
185 end if;
186 end if;
187 end Enable_Output;
188
Nico Huber3be61d42017-01-09 13:58:18 +0100189 procedure Disable_Output (Pipe : Pipe_Index; Pipe_Cfg : Pipe_Config)
190 is
191 Port_Cfg : Port_Config;
192 Success : Boolean;
193 begin
194 Config_Helpers.Fill_Port_Config
195 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
196 if Success then
197 pragma Debug (Debug.New_Line);
198 pragma Debug (Debug.Put_Line
199 ("Disabling port " & Port_Names (Pipe_Cfg.Port)));
200 pragma Debug (Debug.New_Line);
201
202 Connectors.Pre_Off (Port_Cfg);
203 Display_Controller.Off (Pipe);
204 Connectors.Post_Off (Port_Cfg);
205
206 PLLs.Free (Allocated_PLLs (Pipe));
207 end if;
208 end Disable_Output;
209
Nico Huber99f10f32016-11-20 00:34:05 +0100210 procedure Update_Outputs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200211 is
Nico Huber3be61d42017-01-09 13:58:18 +0100212 procedure Check_HPD (Port : in Active_Port_Type; Detected : out Boolean)
213 is
214 HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
215 begin
216 if HPD_Delay_Over then
217 Port_Detect.Hotplug_Detect (Port, Detected);
218 HPD_Delay (Port) := Time.MS_From_Now (333);
219 else
220 Detected := False;
221 end if;
222 end Check_HPD;
Nico Huberb56b9c52017-01-11 15:12:23 +0100223
Nico Huber564103f2017-01-11 15:33:07 +0100224 Power_Changed : Boolean := False;
Nico Huberb56b9c52017-01-11 15:12:23 +0100225 Old_Configs : Pipe_Configs;
Nico Huber564103f2017-01-11 15:33:07 +0100226
227 -- Only called when we actually tried to change something
228 -- so we don't congest the log with unnecessary messages.
229 procedure Update_Power
230 is
231 begin
232 if not Power_Changed then
233 Power_And_Clocks.Power_Up (Old_Configs, Configs);
234 Power_Changed := True;
235 end if;
236 end Update_Power;
Nico Huber3d06de82018-05-29 01:35:04 +0200237
238 function Full_Update (Cur_Config, New_Config : Pipe_Config) return Boolean
239 is
240 begin
241 return
Nico Huber958c5642018-06-02 16:59:31 +0200242 Cur_Config.Port /= New_Config.Port
243 or else
244 Cur_Config.Mode /= New_Config.Mode
245 or else
Nico Huber3d06de82018-05-29 01:35:04 +0200246 (Config.Use_PDW_For_EDP_Scaling and then
247 (Cur_Config.Port = Internal and
Nico Huber958c5642018-06-02 16:59:31 +0200248 Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config)))
249 or else
250 (Config.Has_GMCH_PFIT_CONTROL and then
251 (Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config) or
252 Scaling_Type (Cur_Config) /= Scaling_Type (New_Config)));
Nico Huber3d06de82018-05-29 01:35:04 +0200253 end Full_Update;
Nico Huber83693c82016-10-08 22:17:55 +0200254 begin
255 Old_Configs := Cur_Configs;
256
Nico Huberb56b9c52017-01-11 15:12:23 +0100257 -- disable all pipes that changed or had a hot-plug event
258 for Pipe in Pipe_Index loop
259 declare
260 Unplug_Detected : Boolean;
261 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
262 New_Config : Pipe_Config renames Configs (Pipe);
263 begin
264 if Cur_Config.Port /= Disabled then
265 Check_HPD (Cur_Config.Port, Unplug_Detected);
Nico Huber83693c82016-10-08 22:17:55 +0200266
Nico Huber3d06de82018-05-29 01:35:04 +0200267 if Full_Update (Cur_Config, New_Config) or Unplug_Detected then
Nico Huberb56b9c52017-01-11 15:12:23 +0100268 Disable_Output (Pipe, Cur_Config);
269 Cur_Config.Port := Disabled;
Nico Huber564103f2017-01-11 15:33:07 +0100270 Update_Power;
Nico Huberb56b9c52017-01-11 15:12:23 +0100271 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200272 end if;
Nico Huberb56b9c52017-01-11 15:12:23 +0100273 end;
274 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200275
Nico Huberb56b9c52017-01-11 15:12:23 +0100276 -- enable all pipes that changed and should be active
277 for Pipe in Pipe_Index loop
278 declare
279 Success : Boolean;
Nico Huberf361ec82018-06-02 18:01:45 +0200280 Scaler_Available : Boolean;
Nico Huberb56b9c52017-01-11 15:12:23 +0100281 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
282 New_Config : Pipe_Config renames Configs (Pipe);
283 begin
Nico Huber3d06de82018-05-29 01:35:04 +0200284 if New_Config.Port /= Disabled and
285 Full_Update (Cur_Config, New_Config)
Nico Huberb56b9c52017-01-11 15:12:23 +0100286 then
Nico Huber3be61d42017-01-09 13:58:18 +0100287 if Wait_For_HPD (New_Config.Port) then
288 Check_HPD (New_Config.Port, Success);
289 Wait_For_HPD (New_Config.Port) := not Success;
290 else
291 Success := True;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100292 end if;
Nico Huberc7a4fee2016-11-03 18:18:03 +0100293
Nico Huber3be61d42017-01-09 13:58:18 +0100294 if Success then
Nico Huber564103f2017-01-11 15:33:07 +0100295 Update_Power;
Nico Huberb56b9c52017-01-11 15:12:23 +0100296 Enable_Output (Pipe, New_Config, Success);
Nico Huber3be61d42017-01-09 13:58:18 +0100297 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200298
299 if Success then
Nico Huberb56b9c52017-01-11 15:12:23 +0100300 Cur_Config := New_Config;
Nico Huber83693c82016-10-08 22:17:55 +0200301 end if;
Nico Huber3be61d42017-01-09 13:58:18 +0100302
Nico Huberb56b9c52017-01-11 15:12:23 +0100303 -- update framebuffer offset only
304 elsif New_Config.Port /= Disabled and
Nico Huberf361ec82018-06-02 18:01:45 +0200305 Cur_Config.Framebuffer /= New_Config.Framebuffer
Nico Huberb56b9c52017-01-11 15:12:23 +0100306 then
Nico Huberf361ec82018-06-02 18:01:45 +0200307 Display_Controller.Scaler_Available (Scaler_Available, Pipe);
308 if Config_Helpers.Validate_Config
309 (New_Config.Framebuffer, New_Config.Mode,
310 Pipe, Scaler_Available)
311 then
312 Display_Controller.Setup_FB
313 (Pipe, New_Config.Mode, New_Config.Framebuffer);
314 Display_Controller.Update_Cursor
315 (Pipe, New_Config.Framebuffer, New_Config.Cursor);
316 Cur_Config := New_Config;
317 end if;
Nico Huberb56b9c52017-01-11 15:12:23 +0100318 end if;
319 end;
Nico Huber83693c82016-10-08 22:17:55 +0200320 end loop;
321
Nico Huber564103f2017-01-11 15:33:07 +0100322 if Power_Changed then
Nico Huber83693c82016-10-08 22:17:55 +0200323 Power_And_Clocks.Power_Down (Old_Configs, Configs, Cur_Configs);
324 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200325 end Update_Outputs;
326
327 ----------------------------------------------------------------------------
328
Nico Huber15ffc4f2018-01-11 14:44:43 +0100329 procedure Update_Cursor (Pipe : Pipe_Index; Cursor : Cursor_Type)
330 is
331 begin
332 Cur_Configs (Pipe).Cursor := Cursor;
333 Display_Controller.Update_Cursor
334 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
335 end Update_Cursor;
336
337 procedure Place_Cursor
338 (Pipe : Pipe_Index;
339 X : Cursor_Pos;
340 Y : Cursor_Pos)
341 is
342 begin
343 Cur_Configs (Pipe).Cursor.Center_X := X;
344 Cur_Configs (Pipe).Cursor.Center_Y := Y;
345 Display_Controller.Place_Cursor
346 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
347 end Place_Cursor;
348
349 procedure Move_Cursor
350 (Pipe : Pipe_Index;
351 X : Cursor_Pos;
352 Y : Cursor_Pos)
353 is
354 function Cap_Add (A, B : Cursor_Pos) return Cursor_Pos is
355 (if A + B < 0
356 then Int32'Max (Cursor_Pos'First, A + B)
357 else Int32'Min (Cursor_Pos'Last, A + B));
358 begin
359 Place_Cursor
360 (Pipe => Pipe,
361 X => Cap_Add (Cur_Configs (Pipe).Cursor.Center_X, X),
362 Y => Cap_Add (Cur_Configs (Pipe).Cursor.Center_Y, Y));
363 end Move_Cursor;
364
365 ----------------------------------------------------------------------------
366
Nico Huber83693c82016-10-08 22:17:55 +0200367 procedure Initialize
Nico Huber2b6f6992017-07-09 18:11:34 +0200368 (Write_Delay : in Word64 := 0;
Nico Huber793a8d42016-11-21 18:57:03 +0100369 Clean_State : in Boolean := False;
Nico Huber83693c82016-10-08 22:17:55 +0200370 Success : out Boolean)
371 with
372 Refined_Global =>
373 (In_Out =>
Nico Huber318bca12018-06-09 19:22:52 +0200374 (Config.Valid_Port, Dev.PCI_State,
Arthur Heymansd1988d12018-03-28 16:27:57 +0200375 Registers.Register_State, Port_IO.State,
376 Config.Raw_Clock),
Nico Huber83693c82016-10-08 22:17:55 +0200377 Input =>
378 (Time.State),
379 Output =>
Nico Huber2b6f6992017-07-09 18:11:34 +0200380 (Dev.Address_State,
381 Registers.Address_State,
Nico Huber83693c82016-10-08 22:17:55 +0200382 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +0100383 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +0200384 HPD_Delay, Wait_For_HPD,
385 Linear_FB_Base, Initialized))
Nico Huber83693c82016-10-08 22:17:55 +0200386 is
387 use type HW.Word64;
388
Nico Huber0b2329a2018-06-09 21:14:27 +0200389 function MMIO_GTT_Offset return Natural is
390 (if Config.Has_64bit_GTT
391 then Registers.MMIO_GTT_64_Offset
392 else Registers.MMIO_GTT_32_Offset);
Nico Huber2b6f6992017-07-09 18:11:34 +0200393 PCI_MMIO_Base, PCI_GTT_Base : Word64;
394
Nico Huber83693c82016-10-08 22:17:55 +0200395 Now : constant Time.T := Time.Now;
396
397 procedure Check_Platform (Success : out Boolean)
398 is
399 Audio_VID_DID : Word32;
400 begin
401 case Config.CPU is
Arthur Heymans73ea0322018-03-28 17:17:07 +0200402 when G45 =>
403 Registers.Read (Registers.G4X_AUD_VID_DID, Audio_VID_DID);
Nico Huber83693c82016-10-08 22:17:55 +0200404 when Haswell .. Skylake =>
405 Registers.Read (Registers.AUD_VID_DID, Audio_VID_DID);
406 when Ironlake .. Ivybridge =>
407 Registers.Read (Registers.PCH_AUD_VID_DID, Audio_VID_DID);
408 end case;
409 Success :=
410 (case Config.CPU is
Nico Huber21da5742017-01-20 14:00:53 +0100411 when Broxton => Audio_VID_DID = 16#8086_280a#,
Nico Huber83693c82016-10-08 22:17:55 +0200412 when Skylake => Audio_VID_DID = 16#8086_2809#,
413 when Broadwell => Audio_VID_DID = 16#8086_2808#,
414 when Haswell => Audio_VID_DID = 16#8086_2807#,
415 when Ivybridge |
416 Sandybridge => Audio_VID_DID = 16#8086_2806# or
417 Audio_VID_DID = 16#8086_2805#,
Arthur Heymans73ea0322018-03-28 17:17:07 +0200418 when Ironlake => Audio_VID_DID = 16#0000_0000#,
419 when G45 => Audio_VID_DID = 16#8086_2801# or
420 Audio_VID_DID = 16#8086_2802# or
421 Audio_VID_DID = 16#8086_2803#);
Nico Huber83693c82016-10-08 22:17:55 +0200422 end Check_Platform;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200423
424 procedure Check_Platform_PCI (Success : out Boolean)
425 is
426 use type HW.Word16;
427 Vendor, Device : Word16;
428 begin
429 Dev.Read16 (Vendor, PCI.Vendor_Id);
430 Dev.Read16 (Device, PCI.Device_Id);
431
432 Success := Vendor = 16#8086# and Config.Compatible_GPU (Device);
433 end Check_Platform_PCI;
Nico Huber83693c82016-10-08 22:17:55 +0200434 begin
Nico Huber83693c82016-10-08 22:17:55 +0200435 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
436
437 pragma Debug (Debug.Set_Register_Write_Delay (Write_Delay));
438
Nico Huberc3f66f62017-07-16 21:39:54 +0200439 Linear_FB_Base := 0;
Nico Huber83693c82016-10-08 22:17:55 +0200440 Wait_For_HPD := HPD_Type'(others => False);
441 HPD_Delay := HPD_Delay_Type'(others => Now);
Nico Huber83693c82016-10-08 22:17:55 +0200442 Allocated_PLLs := (others => PLLs.Invalid);
Nico Huber99f10f32016-11-20 00:34:05 +0100443 Cur_Configs := Pipe_Configs'
444 (others => Pipe_Config'
Nico Huber83693c82016-10-08 22:17:55 +0200445 (Port => Disabled,
446 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100447 Cursor => Default_Cursor,
Nico Huber83693c82016-10-08 22:17:55 +0200448 Mode => HW.GFX.Invalid_Mode));
Nico Huber83693c82016-10-08 22:17:55 +0200449 PLLs.Initialize;
450
Nico Huber2b6f6992017-07-09 18:11:34 +0200451 Dev.Initialize (Success);
452
453 if Success then
Nico Huber0b2329a2018-06-09 21:14:27 +0200454 Dev.Map (PCI_MMIO_Base, PCI.Res0, Length => MMIO_GTT_Offset);
455 Dev.Map (PCI_GTT_Base, PCI.Res0, Offset => MMIO_GTT_Offset);
Nico Huber2b6f6992017-07-09 18:11:34 +0200456 if PCI_MMIO_Base /= 0 and PCI_GTT_Base /= 0 then
457 Registers.Set_Register_Base (PCI_MMIO_Base, PCI_GTT_Base);
458 else
459 pragma Debug (Debug.Put_Line
460 ("ERROR: Couldn't map resoure0."));
461 Registers.Set_Register_Base (Config.Default_MMIO_Base);
462 Success := Config.Default_MMIO_Base_Set;
463 end if;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200464
465 if Success then
466 Check_Platform_PCI (Success);
467 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200468 else
469 pragma Debug (Debug.Put_Line
470 ("WARNING: Couldn't initialize PCI dev."));
471 Registers.Set_Register_Base (Config.Default_MMIO_Base);
472 Success := Config.Default_MMIO_Base_Set;
Nico Huber2b6f6992017-07-09 18:11:34 +0200473
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200474 if Success then
475 Check_Platform (Success);
476 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200477 end if;
478
Nico Huber83693c82016-10-08 22:17:55 +0200479 if not Success then
480 pragma Debug (Debug.Put_Line ("ERROR: Incompatible CPU or PCH."));
481
482 Panel.Static_Init; -- for flow analysis
483
484 Initialized := False;
485 return;
486 end if;
487
488 Panel.Setup_PP_Sequencer;
489 Port_Detect.Initialize;
Nico Huber0923b792017-06-09 15:28:41 +0200490 Connectors.Initialize;
Nico Huber83693c82016-10-08 22:17:55 +0200491
Nico Huber793a8d42016-11-21 18:57:03 +0100492 if Clean_State then
493 Power_And_Clocks.Pre_All_Off;
494 Connectors.Pre_All_Off;
495 Display_Controller.All_Off;
496 Connectors.Post_All_Off;
497 PLLs.All_Off;
498 Power_And_Clocks.Post_All_Off;
Nico Huber17d64b62017-07-15 20:51:25 +0200499 Registers.Clear_Fences;
Nico Huber33912aa2016-12-06 20:36:23 +0100500 else
501 -- According to PRMs, VGA plane is the only thing
Nico Huber3a0e2a02017-07-19 14:41:46 +0200502 -- that's enabled by default after reset...
Nico Huber33912aa2016-12-06 20:36:23 +0100503 Display_Controller.Legacy_VGA_Off;
Nico Huber3a0e2a02017-07-19 14:41:46 +0200504 -- ... along with some DDI port bits since Skylake.
505 Connectors.Post_Reset_Off;
Nico Huber793a8d42016-11-21 18:57:03 +0100506 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200507
508 -------------------- Now restart from a clean state ---------------------
509 Power_And_Clocks.Initialize;
510
Nico Huber1c3b9282017-02-09 13:57:04 +0100511 if Config.Has_PCH then
512 Registers.Unset_And_Set_Mask
513 (Register => Registers.PCH_RAWCLK_FREQ,
514 Mask_Unset => PCH_RAWCLK_FREQ_MASK,
515 Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
516 end if;
Nico Huberf54d0962016-10-20 14:17:18 +0200517
Nico Huber83693c82016-10-08 22:17:55 +0200518 Initialized := True;
519
520 end Initialize;
521
522 function Is_Initialized return Boolean
523 with
524 Refined_Post => Is_Initialized'Result = Initialized
525 is
526 begin
527 return Initialized;
528 end Is_Initialized;
529
530 ----------------------------------------------------------------------------
531
Nico Hubercf88f3d2018-06-05 13:27:34 +0200532 pragma Warnings
533 (GNATprove, Off, """Registers.Register_State"" * is not modified*",
534 Reason => "Power_Up_VGA is only effective on certain generations.");
Nico Huber42fb2d02017-09-01 17:01:51 +0200535 procedure Power_Up_VGA
Nico Hubercf88f3d2018-06-05 13:27:34 +0200536 with
537 Refined_Global =>
538 (Input => (Cur_Configs, Time.State),
539 In_Out => (Registers.Register_State),
540 Proof_In => (Initialized))
Nico Huber42fb2d02017-09-01 17:01:51 +0200541 is
542 Fake_Config : constant Pipe_Configs :=
543 (Primary =>
544 (Port => Analog,
545 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100546 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200547 Mode => HW.GFX.Invalid_Mode),
548 others =>
549 (Port => Disabled,
550 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100551 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200552 Mode => HW.GFX.Invalid_Mode));
553 begin
554 Power_And_Clocks.Power_Up (Cur_Configs, Fake_Config);
555 end Power_Up_VGA;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200556 pragma Warnings
557 (GNATprove, Off, "no check message justified*", Reason => "see below");
558 pragma Annotate
559 (GNATprove, Intentional, "unused global",
560 "Power_Up_VGA is only effective on certain generations.");
561 pragma Warnings (GNATprove, On, "no check message justified*");
562 pragma Warnings
563 (GNATprove, On, """Registers.Register_State"" * is not modified*");
Nico Huber42fb2d02017-09-01 17:01:51 +0200564
565 ----------------------------------------------------------------------------
566
Nico Huber5374c3a2017-07-15 21:48:06 +0200567 function FB_First_Page (FB : Framebuffer_Type) return Natural is
Nico Huber34be6542017-12-13 09:26:24 +0100568 (Natural (Phys_Offset (FB) / GTT_Page_Size));
Nico Huber5374c3a2017-07-15 21:48:06 +0200569 function FB_Pages (FB : Framebuffer_Type) return Natural is
570 (Natural (Div_Round_Up (FB_Size (FB), GTT_Page_Size)));
571 function FB_Last_Page (FB : Framebuffer_Type) return Natural is
572 (FB_First_Page (FB) + FB_Pages (FB) - 1);
573
Nico Huber34be6542017-12-13 09:26:24 +0100574 -- Check basics and that it fits in GTT. For 90 degree rotations,
575 -- the Offset should be above GTT_Rotation_Offset. The latter will
576 -- be subtracted for the aperture mapping.
Nico Huber5374c3a2017-07-15 21:48:06 +0200577 function Valid_FB (FB : Framebuffer_Type) return Boolean is
Nico Huber34be6542017-12-13 09:26:24 +0100578 (Valid_Stride (FB) and
579 FB_First_Page (FB) in GTT_Range and
580 FB_Last_Page (FB) in GTT_Range and
581 (not Rotation_90 (FB) or
582 (FB_Last_Page (FB) + GTT_Rotation_Offset in GTT_Range and
583 FB.Offset >= Word32 (GTT_Rotation_Offset) * GTT_Page_Size)));
Nico Huber5374c3a2017-07-15 21:48:06 +0200584
585 -- Also check that we don't overflow the GTT's 39-bit space
586 -- (always true with a 32-bit base)
587 function Valid_Phys_FB (FB : Framebuffer_Type; Phys_Base : Word32)
588 return Boolean is
589 (Valid_FB (FB) and
Nico Huber34be6542017-12-13 09:26:24 +0100590 Int64 (Phys_Base) + Int64 (Phys_Offset (FB)) + Int64 (FB_Size (FB)) <=
Nico Huber5374c3a2017-07-15 21:48:06 +0200591 Int64 (GTT_Address_Type'Last))
592 with
593 Ghost;
594
Nico Huber83693c82016-10-08 22:17:55 +0200595 procedure Write_GTT
596 (GTT_Page : GTT_Range;
597 Device_Address : GTT_Address_Type;
Nico Huber5374c3a2017-07-15 21:48:06 +0200598 Valid : Boolean)
599 is
Nico Huber83693c82016-10-08 22:17:55 +0200600 begin
601 Registers.Write_GTT (GTT_Page, Device_Address, Valid);
602 end Write_GTT;
603
Nico Huber194e57e2017-07-15 21:15:46 +0200604 procedure Setup_Default_GTT (FB : Framebuffer_Type; Phys_Base : Word32)
Nico Huber5374c3a2017-07-15 21:48:06 +0200605 with
606 Pre => Is_Initialized and Valid_Phys_FB (FB, Phys_Base)
Nico Huber83693c82016-10-08 22:17:55 +0200607 is
Nico Huber194e57e2017-07-15 21:15:46 +0200608 Phys_Addr : GTT_Address_Type :=
Nico Huber34be6542017-12-13 09:26:24 +0100609 GTT_Address_Type (Phys_Base) + GTT_Address_Type (Phys_Offset (FB));
Nico Huber83693c82016-10-08 22:17:55 +0200610 begin
Nico Huber194e57e2017-07-15 21:15:46 +0200611 for Idx in FB_First_Page (FB) .. FB_Last_Page (FB) loop
Nico Huber83693c82016-10-08 22:17:55 +0200612 Registers.Write_GTT
613 (GTT_Page => Idx,
614 Device_Address => Phys_Addr,
615 Valid => True);
Nico Huber194e57e2017-07-15 21:15:46 +0200616 Phys_Addr := Phys_Addr + GTT_Page_Size;
Nico Huber83693c82016-10-08 22:17:55 +0200617 end loop;
Nico Huber9b479412017-08-27 11:55:56 +0200618
619 if Rotation_90 (FB) and FB.Tiling = Y_Tiled and FB.V_Stride >= 32 then
620 declare
621 V_Pages : constant Natural := Natural (FB.V_Stride) / 32;
622 Bytes_Per_Row : constant GTT_Address_Type :=
623 GTT_Address_Type (Pixel_To_Bytes (32 * FB.Stride, FB));
624 begin
625 Phys_Addr := GTT_Address_Type (Phys_Base) +
Nico Huber34be6542017-12-13 09:26:24 +0100626 GTT_Address_Type (Phys_Offset (FB)) +
Nico Huber9b479412017-08-27 11:55:56 +0200627 GTT_Address_Type (FB_Size (FB));
628 for Page in FB_First_Page (FB) .. FB_Last_Page (FB) loop
629 Phys_Addr := Phys_Addr - Bytes_Per_Row;
630 Registers.Write_GTT
631 (GTT_Page => GTT_Rotation_Offset + Page,
632 Device_Address => Phys_Addr,
633 Valid => True);
634
635 if (Page - FB_First_Page (FB) + 1) mod V_Pages = 0 then
636 Phys_Addr := Phys_Addr + GTT_Page_Size +
637 GTT_Address_Type (V_Pages) * Bytes_Per_Row;
638 end if;
639 end loop;
640 end;
641 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200642 end Setup_Default_GTT;
643
644 ----------------------------------------------------------------------------
645
Nico Hubereedde882017-07-16 02:54:39 +0200646 use type HW.Word16;
647 subtype Stolen_Size_Range is Int64 range 0 .. 2 ** 33;
648
649 function GGMS_Gen4 (GGC : Word16) return Natural is
650 (Natural (Shift_Right (GGC, 8) and 16#07#));
651 function GTT_Size_Gen4 (GGC : Word16) return Natural is
652 (if GGMS_Gen4 (GGC) in 1 .. 3 then
653 (GGMS_Gen4 (GGC) + 1) * 2 ** 19 else 0);
654
655 function GMS_Gen4 (GGC : Word16) return Natural is
656 (Natural (Shift_Right (GGC, 4) and 16#0f#));
657 Valid_Stolen_Size_Gen4 : constant
658 array (Natural range 1 .. 13) of Stolen_Size_Range :=
659 (1, 4, 8, 16, 32, 48, 64, 128, 256, 96, 160, 224, 352);
660 function Stolen_Size_Gen4 (GGC : Word16) return Stolen_Size_Range is
661 (if GMS_Gen4 (GGC) in Valid_Stolen_Size_Gen4'Range then
Arthur Heymans5fd9a312017-09-12 12:45:18 +0200662 Valid_Stolen_Size_Gen4 (GMS_Gen4 (GGC)) * 2 ** 20 else 0);
Nico Hubereedde882017-07-16 02:54:39 +0200663
664 function GTT_Size_Gen6 (GGC : Word16) return Natural is
665 (Natural (Shift_Right (GGC, 8) and 16#03#) * 2 ** 20);
666
667 function Stolen_Size_Gen6 (GGC : Word16) return Stolen_Size_Range is
668 (Stolen_Size_Range (Shift_Right (GGC, 3) and 16#1f#) * 32 * 2 ** 20);
669
670 function GTT_Size_Gen8 (GGC : Word16) return Natural is
671 (Natural (Shift_Right (GGC, 6) and 16#03#) * 2 ** 20);
672
673 function GMS_Gen8 (GGC : Word16) return Stolen_Size_Range is
674 (Stolen_Size_Range (Shift_Right (GGC, 8) and 16#ff#));
675 function Stolen_Size_Gen8 (GGC : Word16) return Stolen_Size_Range is
676 (GMS_Gen8 (GGC) * 32 * 2 ** 20);
677
678 function Stolen_Size_Gen9 (GGC : Word16) return Stolen_Size_Range is
679 (if GMS_Gen8 (GGC) < 16#f0# then
680 Stolen_Size_Gen8 (GGC)
681 else
682 (GMS_Gen8 (GGC) - 16#f0# + 1) * 4 * 2 ** 20);
683
684 procedure Decode_Stolen
685 (GTT_Size : out Natural;
686 Stolen_Size : out Stolen_Size_Range)
687 with
688 Pre => Is_Initialized
689 is
690 GGC_Reg : constant :=
691 (case Config.CPU is
Arthur Heymans73ea0322018-03-28 17:17:07 +0200692 when G45 | Ironlake => 16#52#,
Nico Hubereedde882017-07-16 02:54:39 +0200693 when Sandybridge .. Skylake => 16#50#);
694 GGC : Word16;
695 begin
696 Dev.Read16 (GGC, GGC_Reg);
697 case Config.CPU is
Arthur Heymans73ea0322018-03-28 17:17:07 +0200698 when G45 | Ironlake =>
Nico Hubereedde882017-07-16 02:54:39 +0200699 GTT_Size := GTT_Size_Gen4 (GGC);
700 Stolen_Size := Stolen_Size_Gen4 (GGC);
701 when Sandybridge .. Haswell =>
702 GTT_Size := GTT_Size_Gen6 (GGC);
703 Stolen_Size := Stolen_Size_Gen6 (GGC);
704 when Broadwell =>
705 GTT_Size := GTT_Size_Gen8 (GGC);
706 Stolen_Size := Stolen_Size_Gen8 (GGC);
707 when Broxton .. Skylake =>
708 GTT_Size := GTT_Size_Gen8 (GGC);
709 Stolen_Size := Stolen_Size_Gen9 (GGC);
710 end case;
711 end Decode_Stolen;
712
713 -- Additional runtime validation that FB fits stolen memory and aperture.
714 procedure Validate_FB (FB : Framebuffer_Type; Valid : out Boolean)
715 with
716 Pre => Is_Initialized,
717 Post => (if Valid then Valid_FB (FB))
718 is
719 GTT_Size, Aperture_Size : Natural;
720 Stolen_Size : Stolen_Size_Range;
721 begin
722 Valid := Valid_FB (FB);
723
724 if Valid then
725 Decode_Stolen (GTT_Size, Stolen_Size);
726 Dev.Resource_Size (Aperture_Size, PCI.Res2);
727 Valid :=
728 FB_Last_Page (FB) < GTT_Size / Config.GTT_PTE_Size and
729 FB_Last_Page (FB) < Natural (Stolen_Size / GTT_Page_Size) and
730 FB_Last_Page (FB) < Aperture_Size / GTT_Page_Size;
Nico Huber34be6542017-12-13 09:26:24 +0100731 pragma Debug (not Valid, Debug.Put_Line
Nico Hubereedde882017-07-16 02:54:39 +0200732 ("Stolen memory too small to hold framebuffer."));
733 end if;
734 end Validate_FB;
735
Nico Huber5374c3a2017-07-15 21:48:06 +0200736 procedure Setup_Default_FB
737 (FB : in Framebuffer_Type;
738 Clear : in Boolean := True;
739 Success : out Boolean)
740 is
741 GMA_Phys_Base : constant PCI.Index := 16#5c#;
742 GMA_Phys_Base_Mask : constant := 16#fff0_0000#;
743
744 Phys_Base : Word32;
745 begin
Nico Hubereedde882017-07-16 02:54:39 +0200746 Validate_FB (FB, Success);
Nico Huber5374c3a2017-07-15 21:48:06 +0200747
748 if Success then
749 Dev.Read32 (Phys_Base, GMA_Phys_Base);
750 Phys_Base := Phys_Base and GMA_Phys_Base_Mask;
751 Success := Phys_Base /= GMA_Phys_Base_Mask and Phys_Base /= 0;
752 pragma Debug (not Success, Debug.Put_Line
753 ("Failed to read stolen memory base."));
Nico Huber0164b022017-08-24 15:12:51 +0200754
755 if Success then
756 if FB.Tiling in XY_Tiling then
757 Registers.Add_Fence
758 (First_Page => FB_First_Page (FB),
759 Last_Page => FB_Last_Page (FB),
760 Tiling => FB.Tiling,
761 Pitch => FB_Pitch (FB.Stride, FB),
762 Success => Success);
763 end if;
764 pragma Debug (not Success, Debug.Put_Line
765 ("Tiled framebuffer but no fence regs available."));
766 end if;
767
Nico Huber5374c3a2017-07-15 21:48:06 +0200768 if Success then
769 Setup_Default_GTT (FB, Phys_Base);
770 end if;
771 end if;
772
773 if Success and then Clear then
774 declare
775 use type HW.Word64;
776 Linear_FB : Word64;
777 begin
Nico Huberc3f66f62017-07-16 21:39:54 +0200778 Map_Linear_FB (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200779 if Linear_FB /= 0 then
Nico Huberc3f66f62017-07-16 21:39:54 +0200780 Framebuffer_Filler.Fill (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200781 end if;
Nico Huber5374c3a2017-07-15 21:48:06 +0200782 end;
783 end if;
784 end Setup_Default_FB;
785
Nico Huberc3f66f62017-07-16 21:39:54 +0200786 procedure Map_Linear_FB (Linear_FB : out Word64; FB : in Framebuffer_Type)
787 is
788 use type HW.Word64;
789
790 Valid : Boolean;
791 begin
792 Linear_FB := 0;
793
794 if Linear_FB_Base = 0 then
795 Dev.Map (Linear_FB_Base, PCI.Res2);
796 pragma Debug
797 (Linear_FB_Base = 0, Debug.Put_Line ("Failed to map resource2."));
798 end if;
799
800 if Linear_FB_Base /= 0 then
801 Validate_FB (FB, Valid);
802 if Valid then
Nico Huber34be6542017-12-13 09:26:24 +0100803 Linear_FB := Linear_FB_Base + Word64 (Phys_Offset (FB));
Nico Huberc3f66f62017-07-16 21:39:54 +0200804 end if;
805 end if;
806 end Map_Linear_FB;
807
Nico Huber5374c3a2017-07-15 21:48:06 +0200808 ----------------------------------------------------------------------------
809
Nico Huber99f10f32016-11-20 00:34:05 +0100810 procedure Dump_Configs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200811 is
812 subtype Pipe_Name is String (1 .. 9);
Nico Huber99f10f32016-11-20 00:34:05 +0100813 type Pipe_Name_Array is array (Pipe_Index) of Pipe_Name;
Nico Huber83693c82016-10-08 22:17:55 +0200814 Pipe_Names : constant Pipe_Name_Array :=
815 (Primary => "Primary ",
816 Secondary => "Secondary",
817 Tertiary => "Tertiary ");
Nico Huber5ef4d602017-12-13 13:56:47 +0100818
819 subtype Tiling_Name is String (1 .. 7);
820 type Tiling_Name_Array is array (Tiling_Type) of Tiling_Name;
821 Tilings : constant Tiling_Name_Array :=
822 (Linear => "Linear ",
823 X_Tiled => "X_Tiled",
824 Y_Tiled => "Y_Tiled");
825
826 subtype Rotation_Name is String (1 .. 11);
827 type Rotation_Name_Array is array (Rotation_Type) of Rotation_Name;
828 Rotations : constant Rotation_Name_Array :=
829 (No_Rotation => "No_Rotation",
830 Rotated_90 => "Rotated_90 ",
831 Rotated_180 => "Rotated_180",
832 Rotated_270 => "Rotated_270");
Nico Huber83693c82016-10-08 22:17:55 +0200833 begin
834 Debug.New_Line;
Paul Menzelb83107c2017-05-04 09:02:33 +0200835 Debug.Put_Line ("CONFIG =>");
Nico Huber99f10f32016-11-20 00:34:05 +0100836 for Pipe in Pipe_Index loop
837 if Pipe = Pipe_Index'First then
Nico Huber83693c82016-10-08 22:17:55 +0200838 Debug.Put (" (");
839 else
840 Debug.Put (" ");
841 end if;
842 Debug.Put_Line (Pipe_Names (Pipe) & " =>");
843 Debug.Put_Line
844 (" (Port => " & Port_Names (Configs (Pipe).Port) & ",");
845 Debug.Put_Line (" Framebuffer =>");
Nico Huber5ef4d602017-12-13 13:56:47 +0100846 Debug.Put (" (Width => ");
Nico Huber83693c82016-10-08 22:17:55 +0200847 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Width);
848 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100849 Debug.Put (" Height => ");
Nico Huber83693c82016-10-08 22:17:55 +0200850 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Height);
851 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100852 Debug.Put (" Start_X => ");
853 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_X);
854 Debug.Put_Line (",");
855 Debug.Put (" Start_Y => ");
856 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_Y);
857 Debug.Put_Line (",");
858 Debug.Put (" Stride => ");
Nico Huber83693c82016-10-08 22:17:55 +0200859 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Stride);
860 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100861 Debug.Put (" V_Stride => ");
862 Debug.Put_Int32 (Configs (Pipe).Framebuffer.V_Stride);
863 Debug.Put_Line (",");
864 Debug.Put (" Tiling => ");
865 Debug.Put_Line (Tilings (Configs (Pipe).Framebuffer.Tiling) & ",");
866 Debug.Put (" Rotation => ");
867 Debug.Put_Line (Rotations (Configs (Pipe).Framebuffer.Rotation) & ",");
Nico Huber83693c82016-10-08 22:17:55 +0200868 Debug.Put (" Offset => ");
869 Debug.Put_Word32 (Configs (Pipe).Framebuffer.Offset);
870 Debug.Put_Line (",");
871 Debug.Put (" BPC => ");
872 Debug.Put_Int64 (Configs (Pipe).Framebuffer.BPC);
873 Debug.Put_Line ("),");
874 Debug.Put_Line (" Mode =>");
875 Debug.Put (" (Dotclock => ");
876 Debug.Put_Int64 (Configs (Pipe).Mode.Dotclock);
877 Debug.Put_Line (",");
878 Debug.Put (" H_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200879 Debug.Put_Int32 (Configs (Pipe).Mode.H_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200880 Debug.Put_Line (",");
881 Debug.Put (" H_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200882 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200883 Debug.Put_Line (",");
884 Debug.Put (" H_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200885 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200886 Debug.Put_Line (",");
887 Debug.Put (" H_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200888 Debug.Put_Int32 (Configs (Pipe).Mode.H_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200889 Debug.Put_Line (",");
890 Debug.Put (" V_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200891 Debug.Put_Int32 (Configs (Pipe).Mode.V_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200892 Debug.Put_Line (",");
893 Debug.Put (" V_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200894 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200895 Debug.Put_Line (",");
896 Debug.Put (" V_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200897 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200898 Debug.Put_Line (",");
899 Debug.Put (" V_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200900 Debug.Put_Int32 (Configs (Pipe).Mode.V_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200901 Debug.Put_Line (",");
902 Debug.Put_Line (" H_Sync_Active_High => " &
903 (if Configs (Pipe).Mode.H_Sync_Active_High
904 then "True,"
905 else "False,"));
906 Debug.Put_Line (" V_Sync_Active_High => " &
907 (if Configs (Pipe).Mode.V_Sync_Active_High
908 then "True,"
909 else "False,"));
910 Debug.Put (" BPC => ");
911 Debug.Put_Int64 (Configs (Pipe).Mode.BPC);
Nico Huber99f10f32016-11-20 00:34:05 +0100912 if Pipe /= Pipe_Index'Last then
Nico Huber83693c82016-10-08 22:17:55 +0200913 Debug.Put_Line (")),");
914 else
915 Debug.Put_Line (")));");
916 end if;
917 end loop;
918 end Dump_Configs;
919
920end HW.GFX.GMA;