blob: 269feec6c08d82fa0465479c2c1fc2ad0a6cbe8b [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber9a4c4c32019-09-16 22:05:11 +02002-- Copyright (C) 2014-2019 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;
Nico Huber312433c2019-09-28 03:15:48 +020024with HW.GFX.GMA.PCode;
Nico Huber83693c82016-10-08 22:17:55 +020025with HW.GFX.GMA.Power_And_Clocks;
26with HW.GFX.GMA.Panel;
27with HW.GFX.GMA.PLLs;
28with HW.GFX.GMA.Port_Detect;
29with HW.GFX.GMA.Connectors;
30with HW.GFX.GMA.Connector_Info;
31with HW.GFX.GMA.Pipe_Setup;
32
Nico Huber83693c82016-10-08 22:17:55 +020033with HW.Debug;
34with GNAT.Source_Info;
35
Nico Huber83693c82016-10-08 22:17:55 +020036use type HW.Int32;
37
38package body HW.GFX.GMA
39 with Refined_State =>
40 (State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020041 (Dev.Address_State,
42 Registers.Address_State,
Nico Huber312433c2019-09-28 03:15:48 +020043 PCode.Mailbox_Ready,
Nico Huber83693c82016-10-08 22:17:55 +020044 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +010045 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +020046 HPD_Delay, Wait_For_HPD,
47 Linear_FB_Base),
Nico Huber83693c82016-10-08 22:17:55 +020048 Init_State => Initialized,
Nico Huber30e84082018-06-10 13:28:05 +020049 Config_State => (Config.Variable),
Nico Huber83693c82016-10-08 22:17:55 +020050 Device_State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020051 (Dev.PCI_State, Registers.Register_State, Registers.GTT_State))
Nico Huber83693c82016-10-08 22:17:55 +020052is
Nico Huber2b6f6992017-07-09 18:11:34 +020053 pragma Disable_Atomic_Synchronization;
Nico Huber83693c82016-10-08 22:17:55 +020054
55 subtype Port_Name is String (1 .. 8);
56 type Port_Name_Array is array (Port_Type) of Port_Name;
57 Port_Names : constant Port_Name_Array :=
58 (Disabled => "Disabled",
59 Internal => "Internal",
60 DP1 => "DP1 ",
61 DP2 => "DP2 ",
62 DP3 => "DP3 ",
Nico Huber0d454cd2016-11-21 13:33:43 +010063 HDMI1 => "HDMI1 ",
64 HDMI2 => "HDMI2 ",
65 HDMI3 => "HDMI3 ",
Nico Huber83693c82016-10-08 22:17:55 +020066 Analog => "Analog ");
67
Nico Huber2b6f6992017-07-09 18:11:34 +020068 package Dev is new HW.PCI.Dev (PCI.Address'(0, 2, 0));
69
Nico Huber83693c82016-10-08 22:17:55 +020070 package Display_Controller renames Pipe_Setup;
71
Nico Huber99f10f32016-11-20 00:34:05 +010072 type PLLs_Type is array (Pipe_Index) of PLLs.T;
Nico Huber83693c82016-10-08 22:17:55 +020073
Nico Huber83693c82016-10-08 22:17:55 +020074 type HPD_Type is array (Port_Type) of Boolean;
Nico Huber3be61d42017-01-09 13:58:18 +010075 type HPD_Delay_Type is array (Active_Port_Type) of Time.T;
Nico Huber83693c82016-10-08 22:17:55 +020076
Nico Huber83693c82016-10-08 22:17:55 +020077 Allocated_PLLs : PLLs_Type;
Nico Huber83693c82016-10-08 22:17:55 +020078 HPD_Delay : HPD_Delay_Type;
79 Wait_For_HPD : HPD_Type;
80 Initialized : Boolean := False;
81
Nico Huberc3f66f62017-07-16 21:39:54 +020082 Linear_FB_Base : Word64;
83
Nico Huber83693c82016-10-08 22:17:55 +020084 ----------------------------------------------------------------------------
85
Nico Huberf54d0962016-10-20 14:17:18 +020086 PCH_RAWCLK_FREQ_MASK : constant := 16#3ff# * 2 ** 0;
87
88 function PCH_RAWCLK_FREQ (Freq : Frequency_Type) return Word32
89 is
90 begin
91 return Word32 (Freq / 1_000_000);
92 end PCH_RAWCLK_FREQ;
93
94 ----------------------------------------------------------------------------
95
Nico Huber43370ba2017-01-09 15:26:19 +010096 procedure Enable_Output
97 (Pipe : in Pipe_Index;
98 Pipe_Cfg : in Pipe_Config;
99 Success : out Boolean)
Nico Huber8a5a3b52018-06-04 14:42:13 +0200100 with
Nico Huber9a4c4c32019-09-16 22:05:11 +0200101 Pre =>
102 Pipe_Cfg.Port in Active_Port_Type and
103 Config_Helpers.Valid_FB (Pipe_Cfg.Framebuffer, Pipe_Cfg.Mode)
Nico Huber43370ba2017-01-09 15:26:19 +0100104 is
105 Port_Cfg : Port_Config;
106 begin
Nico Huber3be61d42017-01-09 13:58:18 +0100107 pragma Debug (Debug.New_Line);
108 pragma Debug (Debug.Put_Line
109 ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
110
Nico Huber43370ba2017-01-09 15:26:19 +0100111 Config_Helpers.Fill_Port_Config
112 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
113
114 if Success then
Nico Huber43370ba2017-01-09 15:26:19 +0100115 Connector_Info.Preferred_Link_Setting (Port_Cfg, Success);
116 end if;
117
118 -- loop over all possible DP-lane configurations
119 -- (non-DP ports use a single fake configuration)
120 while Success loop
121 pragma Loop_Invariant
122 (Pipe_Cfg.Port in Active_Port_Type and
123 Port_Cfg.Mode = Port_Cfg.Mode'Loop_Entry);
124
125 PLLs.Alloc
126 (Port_Cfg => Port_Cfg,
127 PLL => Allocated_PLLs (Pipe),
128 Success => Success);
129
130 if Success then
131 -- try each DP-lane configuration twice
132 for Try in 1 .. 2 loop
133 pragma Loop_Invariant
134 (Pipe_Cfg.Port in Active_Port_Type);
135
Nico Huber4798c662017-01-11 12:44:48 +0100136 -- Clear pending hot-plug events before every try
137 Port_Detect.Clear_Hotplug_Detect (Pipe_Cfg.Port);
138
Nico Huber43370ba2017-01-09 15:26:19 +0100139 Connectors.Pre_On
140 (Pipe => Pipe,
141 Port_Cfg => Port_Cfg,
142 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
143 Success => Success);
144
145 if Success then
146 Display_Controller.On
147 (Pipe => Pipe,
148 Port_Cfg => Port_Cfg,
Nico Huber4dc4c612018-01-10 15:55:09 +0100149 Framebuffer => Pipe_Cfg.Framebuffer,
150 Cursor => Pipe_Cfg.Cursor);
Nico Huber43370ba2017-01-09 15:26:19 +0100151
152 Connectors.Post_On
Arthur Heymans60d0e5f2018-03-28 17:08:27 +0200153 (Pipe => Pipe,
154 Port_Cfg => Port_Cfg,
Nico Huber43370ba2017-01-09 15:26:19 +0100155 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
156 Success => Success);
157
158 if not Success then
159 Display_Controller.Off (Pipe);
160 Connectors.Post_Off (Port_Cfg);
161 end if;
162 end if;
163
164 exit when Success;
165 end loop;
166 exit when Success; -- connection established => stop loop
167
168 -- connection failed
169 PLLs.Free (Allocated_PLLs (Pipe));
170 end if;
171
172 Connector_Info.Next_Link_Setting (Port_Cfg, Success);
173 end loop;
174
175 if Success then
176 pragma Debug (Debug.Put_Line
177 ("Enabled port " & Port_Names (Pipe_Cfg.Port)));
178 else
179 Wait_For_HPD (Pipe_Cfg.Port) := True;
180 if Pipe_Cfg.Port = Internal then
181 Panel.Off;
182 end if;
183 end if;
184 end Enable_Output;
185
Nico Huber3be61d42017-01-09 13:58:18 +0100186 procedure Disable_Output (Pipe : Pipe_Index; Pipe_Cfg : Pipe_Config)
187 is
188 Port_Cfg : Port_Config;
189 Success : Boolean;
190 begin
191 Config_Helpers.Fill_Port_Config
192 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
193 if Success then
194 pragma Debug (Debug.New_Line);
195 pragma Debug (Debug.Put_Line
196 ("Disabling port " & Port_Names (Pipe_Cfg.Port)));
197 pragma Debug (Debug.New_Line);
198
199 Connectors.Pre_Off (Port_Cfg);
200 Display_Controller.Off (Pipe);
201 Connectors.Post_Off (Port_Cfg);
202
203 PLLs.Free (Allocated_PLLs (Pipe));
204 end if;
205 end Disable_Output;
206
Nico Huber99f10f32016-11-20 00:34:05 +0100207 procedure Update_Outputs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200208 is
Nico Huber3be61d42017-01-09 13:58:18 +0100209 procedure Check_HPD (Port : in Active_Port_Type; Detected : out Boolean)
210 is
211 HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
212 begin
213 if HPD_Delay_Over then
214 Port_Detect.Hotplug_Detect (Port, Detected);
215 HPD_Delay (Port) := Time.MS_From_Now (333);
216 else
217 Detected := False;
218 end if;
219 end Check_HPD;
Nico Huberb56b9c52017-01-11 15:12:23 +0100220
Nico Huber9a4c4c32019-09-16 22:05:11 +0200221 Scaler_Reservation : Display_Controller.Scaler_Reservation :=
222 Display_Controller.Null_Scaler_Reservation;
Nico Huber564103f2017-01-11 15:33:07 +0100223
Nico Huber9a4c4c32019-09-16 22:05:11 +0200224 Update_Power : Boolean := False;
225 Old_Configs,
226 New_Configs : Pipe_Configs;
Nico Huber3d06de82018-05-29 01:35:04 +0200227
228 function Full_Update (Cur_Config, New_Config : Pipe_Config) return Boolean
229 is
230 begin
231 return
Nico Huber958c5642018-06-02 16:59:31 +0200232 Cur_Config.Port /= New_Config.Port
233 or else
234 Cur_Config.Mode /= New_Config.Mode
235 or else
Nico Huber3d06de82018-05-29 01:35:04 +0200236 (Config.Use_PDW_For_EDP_Scaling and then
237 (Cur_Config.Port = Internal and
Nico Huber958c5642018-06-02 16:59:31 +0200238 Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config)))
239 or else
240 (Config.Has_GMCH_PFIT_CONTROL and then
241 (Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config) or
242 Scaling_Type (Cur_Config) /= Scaling_Type (New_Config)));
Nico Huber3d06de82018-05-29 01:35:04 +0200243 end Full_Update;
Nico Huber83693c82016-10-08 22:17:55 +0200244 begin
245 Old_Configs := Cur_Configs;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200246 New_Configs := Configs;
247
248 -- validate new configs, filter invalid configs and those waiting for HPD
249 for Pipe in Pipe_Index loop
250 declare
251 Success : Boolean := True;
252 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
253 New_Config : Pipe_Config renames New_Configs (Pipe);
254 begin
255 if New_Config.Port /= Disabled then
256 if Wait_For_HPD (New_Config.Port) then
257 Check_HPD (New_Config.Port, Success);
258 Wait_For_HPD (New_Config.Port) := not Success;
259 end if;
260
261 Success := Success and then
262 Config_Helpers.Validate_Config
263 (New_Config.Framebuffer, New_Config.Mode, Pipe);
264
265 if Success and then Requires_Scaling (New_Config) then
266 Display_Controller.Reserve_Scaler
267 (Success, Scaler_Reservation, Pipe);
268 end if;
269
270 if not Success then
271 New_Config.Port := Disabled;
272 end if;
273 end if;
274 end;
275 pragma Loop_Invariant
276 (for all P in Pipe_Index'First .. Pipe =>
277 New_Configs (P).Port = Disabled or
278 Config_Helpers.Valid_FB
279 (New_Configs (P).Framebuffer, New_Configs (P).Mode));
280 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200281
Nico Huberb56b9c52017-01-11 15:12:23 +0100282 -- disable all pipes that changed or had a hot-plug event
283 for Pipe in Pipe_Index loop
284 declare
285 Unplug_Detected : Boolean;
286 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
Nico Huber9a4c4c32019-09-16 22:05:11 +0200287 New_Config : Pipe_Config renames New_Configs (Pipe);
Nico Huberb56b9c52017-01-11 15:12:23 +0100288 begin
289 if Cur_Config.Port /= Disabled then
290 Check_HPD (Cur_Config.Port, Unplug_Detected);
Nico Huber83693c82016-10-08 22:17:55 +0200291
Nico Huber3d06de82018-05-29 01:35:04 +0200292 if Full_Update (Cur_Config, New_Config) or Unplug_Detected then
Nico Huberb56b9c52017-01-11 15:12:23 +0100293 Disable_Output (Pipe, Cur_Config);
294 Cur_Config.Port := Disabled;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200295 Update_Power := True;
Nico Huberb56b9c52017-01-11 15:12:23 +0100296 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200297 end if;
Nico Huberb56b9c52017-01-11 15:12:23 +0100298 end;
299 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200300
Nico Huberb56b9c52017-01-11 15:12:23 +0100301 -- enable all pipes that changed and should be active
302 for Pipe in Pipe_Index loop
303 declare
304 Success : Boolean;
305 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
Nico Huber9a4c4c32019-09-16 22:05:11 +0200306 New_Config : Pipe_Config renames New_Configs (Pipe);
Nico Huberb56b9c52017-01-11 15:12:23 +0100307 begin
Nico Huber9a4c4c32019-09-16 22:05:11 +0200308 -- full update
Nico Huber3d06de82018-05-29 01:35:04 +0200309 if New_Config.Port /= Disabled and
310 Full_Update (Cur_Config, New_Config)
Nico Huberb56b9c52017-01-11 15:12:23 +0100311 then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200312 Power_And_Clocks.Power_Up (Old_Configs, New_Configs);
313 Update_Power := True;
Nico Huberc7a4fee2016-11-03 18:18:03 +0100314
Nico Huber9a4c4c32019-09-16 22:05:11 +0200315 Enable_Output (Pipe, New_Config, Success);
Nico Huber83693c82016-10-08 22:17:55 +0200316 if Success then
Nico Huberb56b9c52017-01-11 15:12:23 +0100317 Cur_Config := New_Config;
Nico Huber83693c82016-10-08 22:17:55 +0200318 end if;
Nico Huber3be61d42017-01-09 13:58:18 +0100319
Nico Huberb56b9c52017-01-11 15:12:23 +0100320 -- update framebuffer offset only
321 elsif New_Config.Port /= Disabled and
Nico Huberf361ec82018-06-02 18:01:45 +0200322 Cur_Config.Framebuffer /= New_Config.Framebuffer
Nico Huberb56b9c52017-01-11 15:12:23 +0100323 then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200324 Display_Controller.Setup_FB
325 (Pipe, New_Config.Mode, New_Config.Framebuffer);
326 Display_Controller.Update_Cursor
327 (Pipe, New_Config.Framebuffer, New_Config.Cursor);
328 Cur_Config := New_Config;
Nico Huberb56b9c52017-01-11 15:12:23 +0100329 end if;
330 end;
Nico Huber83693c82016-10-08 22:17:55 +0200331 end loop;
332
Nico Huber9a4c4c32019-09-16 22:05:11 +0200333 if Update_Power then
334 Power_And_Clocks.Power_Down (Old_Configs, New_Configs, Cur_Configs);
Nico Huber83693c82016-10-08 22:17:55 +0200335 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200336 end Update_Outputs;
337
338 ----------------------------------------------------------------------------
339
Nico Huber15ffc4f2018-01-11 14:44:43 +0100340 procedure Update_Cursor (Pipe : Pipe_Index; Cursor : Cursor_Type)
341 is
342 begin
343 Cur_Configs (Pipe).Cursor := Cursor;
344 Display_Controller.Update_Cursor
345 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
346 end Update_Cursor;
347
348 procedure Place_Cursor
349 (Pipe : Pipe_Index;
350 X : Cursor_Pos;
351 Y : Cursor_Pos)
352 is
353 begin
354 Cur_Configs (Pipe).Cursor.Center_X := X;
355 Cur_Configs (Pipe).Cursor.Center_Y := Y;
356 Display_Controller.Place_Cursor
357 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
358 end Place_Cursor;
359
360 procedure Move_Cursor
361 (Pipe : Pipe_Index;
362 X : Cursor_Pos;
363 Y : Cursor_Pos)
364 is
365 function Cap_Add (A, B : Cursor_Pos) return Cursor_Pos is
366 (if A + B < 0
367 then Int32'Max (Cursor_Pos'First, A + B)
368 else Int32'Min (Cursor_Pos'Last, A + B));
369 begin
370 Place_Cursor
371 (Pipe => Pipe,
372 X => Cap_Add (Cur_Configs (Pipe).Cursor.Center_X, X),
373 Y => Cap_Add (Cur_Configs (Pipe).Cursor.Center_Y, Y));
374 end Move_Cursor;
375
376 ----------------------------------------------------------------------------
377
Nico Huber83693c82016-10-08 22:17:55 +0200378 procedure Initialize
Nico Huber2b6f6992017-07-09 18:11:34 +0200379 (Write_Delay : in Word64 := 0;
Nico Huber793a8d42016-11-21 18:57:03 +0100380 Clean_State : in Boolean := False;
Nico Huber83693c82016-10-08 22:17:55 +0200381 Success : out Boolean)
382 with
383 Refined_Global =>
Nico Huber27088aa2018-06-10 13:28:05 +0200384 (Input => (Time.State),
385 In_Out => (Dev.PCI_State, Registers.Register_State, Port_IO.State),
Nico Huber83693c82016-10-08 22:17:55 +0200386 Output =>
Nico Huber27088aa2018-06-10 13:28:05 +0200387 (Config.Variable,
388 Dev.Address_State,
Nico Huber2b6f6992017-07-09 18:11:34 +0200389 Registers.Address_State,
Nico Huber312433c2019-09-28 03:15:48 +0200390 PCode.Mailbox_Ready,
Nico Huber83693c82016-10-08 22:17:55 +0200391 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +0100392 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +0200393 HPD_Delay, Wait_For_HPD,
394 Linear_FB_Base, Initialized))
Nico Huber83693c82016-10-08 22:17:55 +0200395 is
396 use type HW.Word64;
397
Nico Huber0b2329a2018-06-09 21:14:27 +0200398 function MMIO_GTT_Offset return Natural is
399 (if Config.Has_64bit_GTT
400 then Registers.MMIO_GTT_64_Offset
401 else Registers.MMIO_GTT_32_Offset);
Nico Huber2b6f6992017-07-09 18:11:34 +0200402 PCI_MMIO_Base, PCI_GTT_Base : Word64;
403
Nico Huber83693c82016-10-08 22:17:55 +0200404 Now : constant Time.T := Time.Now;
405
406 procedure Check_Platform (Success : out Boolean)
407 is
408 Audio_VID_DID : Word32;
409 begin
Nico Huber6621a142018-06-07 23:56:54 +0200410 case Config.Gen is
Arthur Heymans73ea0322018-03-28 17:17:07 +0200411 when G45 =>
412 Registers.Read (Registers.G4X_AUD_VID_DID, Audio_VID_DID);
Nico Huber6621a142018-06-07 23:56:54 +0200413 when Ironlake =>
414 Registers.Read (Registers.PCH_AUD_VID_DID, Audio_VID_DID);
Nico Huber83693c82016-10-08 22:17:55 +0200415 when Haswell .. Skylake =>
416 Registers.Read (Registers.AUD_VID_DID, Audio_VID_DID);
Nico Huber83693c82016-10-08 22:17:55 +0200417 end case;
418 Success :=
Nico Huber998ee2b2018-06-12 23:02:17 +0200419 ((Config.Gen_Broxton and Audio_VID_DID = 16#8086_280a#) or
Nico Huber88badbe2018-09-27 16:36:47 +0200420 (Config.CPU_Kabylake and Audio_VID_DID = 16#8086_280b#) or
421 (Config.CPU_Skylake and Audio_VID_DID = 16#8086_2809#) or
Nico Huber998ee2b2018-06-12 23:02:17 +0200422 (Config.CPU_Broadwell and Audio_VID_DID = 16#8086_2808#) or
423 (Config.CPU_Haswell and Audio_VID_DID = 16#8086_2807#) or
424 ((Config.CPU_Ivybridge or
425 Config.CPU_Sandybridge) and (Audio_VID_DID = 16#8086_2806# or
426 Audio_VID_DID = 16#8086_2805#)) or
427 (Config.CPU_Ironlake and Audio_VID_DID = 16#0000_0000#) or
428 (Config.Gen_G45 and (Audio_VID_DID = 16#8086_2801# or
429 Audio_VID_DID = 16#8086_2802# or
430 Audio_VID_DID = 16#8086_2803#)));
Nico Huber83693c82016-10-08 22:17:55 +0200431 end Check_Platform;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200432
433 procedure Check_Platform_PCI (Success : out Boolean)
434 is
435 use type HW.Word16;
436 Vendor, Device : Word16;
437 begin
438 Dev.Read16 (Vendor, PCI.Vendor_Id);
439 Dev.Read16 (Device, PCI.Device_Id);
440
Nico Huber6a996dc2018-06-17 16:30:33 +0200441 Config.Detect_CPU (Device);
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200442 Success := Vendor = 16#8086# and Config.Compatible_GPU (Device);
443 end Check_Platform_PCI;
Nico Huber83693c82016-10-08 22:17:55 +0200444 begin
Nico Huber83693c82016-10-08 22:17:55 +0200445 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
446
447 pragma Debug (Debug.Set_Register_Write_Delay (Write_Delay));
448
Nico Huberc3f66f62017-07-16 21:39:54 +0200449 Linear_FB_Base := 0;
Nico Huber312433c2019-09-28 03:15:48 +0200450 PCode.Mailbox_Ready := False;
Nico Huber83693c82016-10-08 22:17:55 +0200451 Wait_For_HPD := HPD_Type'(others => False);
452 HPD_Delay := HPD_Delay_Type'(others => Now);
Nico Huber83693c82016-10-08 22:17:55 +0200453 Allocated_PLLs := (others => PLLs.Invalid);
Nico Huber99f10f32016-11-20 00:34:05 +0100454 Cur_Configs := Pipe_Configs'
455 (others => Pipe_Config'
Nico Huber83693c82016-10-08 22:17:55 +0200456 (Port => Disabled,
457 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100458 Cursor => Default_Cursor,
Nico Huber83693c82016-10-08 22:17:55 +0200459 Mode => HW.GFX.Invalid_Mode));
Nico Huber27088aa2018-06-10 13:28:05 +0200460 Config.Variable := Config.Initial_Settings;
Nico Huber6a996dc2018-06-17 16:30:33 +0200461 Registers.Set_Register_Base (Config.Default_MMIO_Base);
Nico Huber83693c82016-10-08 22:17:55 +0200462 PLLs.Initialize;
463
Nico Huber2b6f6992017-07-09 18:11:34 +0200464 Dev.Initialize (Success);
465
466 if Success then
Nico Huber6a996dc2018-06-17 16:30:33 +0200467 Check_Platform_PCI (Success);
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200468 if Success then
Nico Huber6a996dc2018-06-17 16:30:33 +0200469 Dev.Map (PCI_MMIO_Base, PCI.Res0, Length => MMIO_GTT_Offset);
470 Dev.Map (PCI_GTT_Base, PCI.Res0, Offset => MMIO_GTT_Offset);
471 if PCI_MMIO_Base /= 0 and PCI_GTT_Base /= 0 then
472 Registers.Set_Register_Base (PCI_MMIO_Base, PCI_GTT_Base);
473 else
474 pragma Debug (Debug.Put_Line
475 ("ERROR: Couldn't map resoure0."));
476 Success := Config.Default_MMIO_Base_Set;
477 end if;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200478 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200479 else
480 pragma Debug (Debug.Put_Line
481 ("WARNING: Couldn't initialize PCI dev."));
Nico Huber2b6f6992017-07-09 18:11:34 +0200482 Success := Config.Default_MMIO_Base_Set;
Nico Huber2b6f6992017-07-09 18:11:34 +0200483
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200484 if Success then
485 Check_Platform (Success);
486 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200487 end if;
488
Nico Huber83693c82016-10-08 22:17:55 +0200489 if not Success then
490 pragma Debug (Debug.Put_Line ("ERROR: Incompatible CPU or PCH."));
491
492 Panel.Static_Init; -- for flow analysis
493
494 Initialized := False;
495 return;
496 end if;
497
498 Panel.Setup_PP_Sequencer;
499 Port_Detect.Initialize;
Nico Huber0923b792017-06-09 15:28:41 +0200500 Connectors.Initialize;
Nico Huber83693c82016-10-08 22:17:55 +0200501
Nico Huber793a8d42016-11-21 18:57:03 +0100502 if Clean_State then
503 Power_And_Clocks.Pre_All_Off;
504 Connectors.Pre_All_Off;
505 Display_Controller.All_Off;
506 Connectors.Post_All_Off;
507 PLLs.All_Off;
508 Power_And_Clocks.Post_All_Off;
Nico Huber17d64b62017-07-15 20:51:25 +0200509 Registers.Clear_Fences;
Nico Huber33912aa2016-12-06 20:36:23 +0100510 else
511 -- According to PRMs, VGA plane is the only thing
Nico Huber3a0e2a02017-07-19 14:41:46 +0200512 -- that's enabled by default after reset...
Nico Huber33912aa2016-12-06 20:36:23 +0100513 Display_Controller.Legacy_VGA_Off;
Nico Huber3a0e2a02017-07-19 14:41:46 +0200514 -- ... along with some DDI port bits since Skylake.
515 Connectors.Post_Reset_Off;
Nico Huber793a8d42016-11-21 18:57:03 +0100516 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200517
518 -------------------- Now restart from a clean state ---------------------
519 Power_And_Clocks.Initialize;
520
Nico Huber1c3b9282017-02-09 13:57:04 +0100521 if Config.Has_PCH then
522 Registers.Unset_And_Set_Mask
523 (Register => Registers.PCH_RAWCLK_FREQ,
524 Mask_Unset => PCH_RAWCLK_FREQ_MASK,
525 Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
526 end if;
Nico Huberf54d0962016-10-20 14:17:18 +0200527
Nico Huber83693c82016-10-08 22:17:55 +0200528 Initialized := True;
529
530 end Initialize;
531
532 function Is_Initialized return Boolean
533 with
534 Refined_Post => Is_Initialized'Result = Initialized
535 is
536 begin
537 return Initialized;
538 end Is_Initialized;
539
540 ----------------------------------------------------------------------------
541
Nico Hubercf88f3d2018-06-05 13:27:34 +0200542 pragma Warnings
543 (GNATprove, Off, """Registers.Register_State"" * is not modified*",
Nico Huberadfe11f2018-06-10 14:59:04 +0200544 Reason => "Power_Up_VGA is only effective in certain configurations.");
Nico Huber42fb2d02017-09-01 17:01:51 +0200545 procedure Power_Up_VGA
Nico Hubercf88f3d2018-06-05 13:27:34 +0200546 with
547 Refined_Global =>
Nico Huberadfe11f2018-06-10 14:59:04 +0200548 (Input => (Cur_Configs, Config.Variable, Time.State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200549 In_Out => (Registers.Register_State),
550 Proof_In => (Initialized))
Nico Huber42fb2d02017-09-01 17:01:51 +0200551 is
552 Fake_Config : constant Pipe_Configs :=
553 (Primary =>
554 (Port => Analog,
555 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100556 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200557 Mode => HW.GFX.Invalid_Mode),
558 others =>
559 (Port => Disabled,
560 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100561 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200562 Mode => HW.GFX.Invalid_Mode));
563 begin
564 Power_And_Clocks.Power_Up (Cur_Configs, Fake_Config);
565 end Power_Up_VGA;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200566 pragma Warnings
567 (GNATprove, Off, "no check message justified*", Reason => "see below");
568 pragma Annotate
569 (GNATprove, Intentional, "unused global",
Nico Huberadfe11f2018-06-10 14:59:04 +0200570 "Power_Up_VGA is only effective in certain configurations.");
Nico Hubercf88f3d2018-06-05 13:27:34 +0200571 pragma Warnings (GNATprove, On, "no check message justified*");
572 pragma Warnings
573 (GNATprove, On, """Registers.Register_State"" * is not modified*");
Nico Huber42fb2d02017-09-01 17:01:51 +0200574
575 ----------------------------------------------------------------------------
576
Nico Huber5374c3a2017-07-15 21:48:06 +0200577 function FB_First_Page (FB : Framebuffer_Type) return Natural is
Nico Huber34be6542017-12-13 09:26:24 +0100578 (Natural (Phys_Offset (FB) / GTT_Page_Size));
Nico Huber5374c3a2017-07-15 21:48:06 +0200579 function FB_Pages (FB : Framebuffer_Type) return Natural is
580 (Natural (Div_Round_Up (FB_Size (FB), GTT_Page_Size)));
581 function FB_Last_Page (FB : Framebuffer_Type) return Natural is
582 (FB_First_Page (FB) + FB_Pages (FB) - 1);
583
Nico Huber34be6542017-12-13 09:26:24 +0100584 -- Check basics and that it fits in GTT. For 90 degree rotations,
585 -- the Offset should be above GTT_Rotation_Offset. The latter will
586 -- be subtracted for the aperture mapping.
Nico Huber5374c3a2017-07-15 21:48:06 +0200587 function Valid_FB (FB : Framebuffer_Type) return Boolean is
Nico Huber34be6542017-12-13 09:26:24 +0100588 (Valid_Stride (FB) and
589 FB_First_Page (FB) in GTT_Range and
590 FB_Last_Page (FB) in GTT_Range and
591 (not Rotation_90 (FB) or
592 (FB_Last_Page (FB) + GTT_Rotation_Offset in GTT_Range and
593 FB.Offset >= Word32 (GTT_Rotation_Offset) * GTT_Page_Size)));
Nico Huber5374c3a2017-07-15 21:48:06 +0200594
595 -- Also check that we don't overflow the GTT's 39-bit space
596 -- (always true with a 32-bit base)
597 function Valid_Phys_FB (FB : Framebuffer_Type; Phys_Base : Word32)
598 return Boolean is
599 (Valid_FB (FB) and
Nico Huber34be6542017-12-13 09:26:24 +0100600 Int64 (Phys_Base) + Int64 (Phys_Offset (FB)) + Int64 (FB_Size (FB)) <=
Nico Huber5374c3a2017-07-15 21:48:06 +0200601 Int64 (GTT_Address_Type'Last))
602 with
603 Ghost;
604
Nico Huber83693c82016-10-08 22:17:55 +0200605 procedure Write_GTT
606 (GTT_Page : GTT_Range;
607 Device_Address : GTT_Address_Type;
Nico Huber5374c3a2017-07-15 21:48:06 +0200608 Valid : Boolean)
609 is
Nico Huber83693c82016-10-08 22:17:55 +0200610 begin
611 Registers.Write_GTT (GTT_Page, Device_Address, Valid);
612 end Write_GTT;
613
Nico Huberceda17d2018-06-09 22:00:29 +0200614 procedure Read_GTT
615 (Device_Address : out GTT_Address_Type;
616 Valid : out Boolean;
617 GTT_Page : in GTT_Range)
618 is
619 begin
620 Registers.Read_GTT (Device_Address, Valid, GTT_Page);
621 end Read_GTT;
622
Nico Huber194e57e2017-07-15 21:15:46 +0200623 procedure Setup_Default_GTT (FB : Framebuffer_Type; Phys_Base : Word32)
Nico Huber5374c3a2017-07-15 21:48:06 +0200624 with
625 Pre => Is_Initialized and Valid_Phys_FB (FB, Phys_Base)
Nico Huber83693c82016-10-08 22:17:55 +0200626 is
Nico Huber194e57e2017-07-15 21:15:46 +0200627 Phys_Addr : GTT_Address_Type :=
Nico Huber34be6542017-12-13 09:26:24 +0100628 GTT_Address_Type (Phys_Base) + GTT_Address_Type (Phys_Offset (FB));
Nico Huber83693c82016-10-08 22:17:55 +0200629 begin
Nico Huber194e57e2017-07-15 21:15:46 +0200630 for Idx in FB_First_Page (FB) .. FB_Last_Page (FB) loop
Nico Huber83693c82016-10-08 22:17:55 +0200631 Registers.Write_GTT
632 (GTT_Page => Idx,
633 Device_Address => Phys_Addr,
634 Valid => True);
Nico Huber194e57e2017-07-15 21:15:46 +0200635 Phys_Addr := Phys_Addr + GTT_Page_Size;
Nico Huber83693c82016-10-08 22:17:55 +0200636 end loop;
Nico Huber9b479412017-08-27 11:55:56 +0200637
638 if Rotation_90 (FB) and FB.Tiling = Y_Tiled and FB.V_Stride >= 32 then
639 declare
640 V_Pages : constant Natural := Natural (FB.V_Stride) / 32;
641 Bytes_Per_Row : constant GTT_Address_Type :=
642 GTT_Address_Type (Pixel_To_Bytes (32 * FB.Stride, FB));
643 begin
644 Phys_Addr := GTT_Address_Type (Phys_Base) +
Nico Huber34be6542017-12-13 09:26:24 +0100645 GTT_Address_Type (Phys_Offset (FB)) +
Nico Huber9b479412017-08-27 11:55:56 +0200646 GTT_Address_Type (FB_Size (FB));
647 for Page in FB_First_Page (FB) .. FB_Last_Page (FB) loop
648 Phys_Addr := Phys_Addr - Bytes_Per_Row;
649 Registers.Write_GTT
650 (GTT_Page => GTT_Rotation_Offset + Page,
651 Device_Address => Phys_Addr,
652 Valid => True);
653
654 if (Page - FB_First_Page (FB) + 1) mod V_Pages = 0 then
655 Phys_Addr := Phys_Addr + GTT_Page_Size +
656 GTT_Address_Type (V_Pages) * Bytes_Per_Row;
657 end if;
658 end loop;
659 end;
660 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200661 end Setup_Default_GTT;
662
663 ----------------------------------------------------------------------------
664
Nico Hubereedde882017-07-16 02:54:39 +0200665 use type HW.Word16;
666 subtype Stolen_Size_Range is Int64 range 0 .. 2 ** 33;
667
668 function GGMS_Gen4 (GGC : Word16) return Natural is
669 (Natural (Shift_Right (GGC, 8) and 16#07#));
670 function GTT_Size_Gen4 (GGC : Word16) return Natural is
671 (if GGMS_Gen4 (GGC) in 1 .. 3 then
672 (GGMS_Gen4 (GGC) + 1) * 2 ** 19 else 0);
673
674 function GMS_Gen4 (GGC : Word16) return Natural is
675 (Natural (Shift_Right (GGC, 4) and 16#0f#));
676 Valid_Stolen_Size_Gen4 : constant
677 array (Natural range 1 .. 13) of Stolen_Size_Range :=
678 (1, 4, 8, 16, 32, 48, 64, 128, 256, 96, 160, 224, 352);
679 function Stolen_Size_Gen4 (GGC : Word16) return Stolen_Size_Range is
680 (if GMS_Gen4 (GGC) in Valid_Stolen_Size_Gen4'Range then
Arthur Heymans5fd9a312017-09-12 12:45:18 +0200681 Valid_Stolen_Size_Gen4 (GMS_Gen4 (GGC)) * 2 ** 20 else 0);
Nico Hubereedde882017-07-16 02:54:39 +0200682
683 function GTT_Size_Gen6 (GGC : Word16) return Natural is
684 (Natural (Shift_Right (GGC, 8) and 16#03#) * 2 ** 20);
685
686 function Stolen_Size_Gen6 (GGC : Word16) return Stolen_Size_Range is
687 (Stolen_Size_Range (Shift_Right (GGC, 3) and 16#1f#) * 32 * 2 ** 20);
688
689 function GTT_Size_Gen8 (GGC : Word16) return Natural is
690 (Natural (Shift_Right (GGC, 6) and 16#03#) * 2 ** 20);
691
692 function GMS_Gen8 (GGC : Word16) return Stolen_Size_Range is
693 (Stolen_Size_Range (Shift_Right (GGC, 8) and 16#ff#));
694 function Stolen_Size_Gen8 (GGC : Word16) return Stolen_Size_Range is
695 (GMS_Gen8 (GGC) * 32 * 2 ** 20);
696
697 function Stolen_Size_Gen9 (GGC : Word16) return Stolen_Size_Range is
698 (if GMS_Gen8 (GGC) < 16#f0# then
699 Stolen_Size_Gen8 (GGC)
700 else
701 (GMS_Gen8 (GGC) - 16#f0# + 1) * 4 * 2 ** 20);
702
703 procedure Decode_Stolen
704 (GTT_Size : out Natural;
705 Stolen_Size : out Stolen_Size_Range)
706 with
707 Pre => Is_Initialized
708 is
Nico Huber63ec8362018-06-09 17:42:19 +0200709 GGC_Reg : constant PCI.Index :=
Nico Huber998ee2b2018-06-12 23:02:17 +0200710 (if Config.Gen_G45 or Config.CPU_Ironlake then 16#52# else 16#50#);
Nico Hubereedde882017-07-16 02:54:39 +0200711 GGC : Word16;
712 begin
713 Dev.Read16 (GGC, GGC_Reg);
Nico Huber998ee2b2018-06-12 23:02:17 +0200714 if Config.Gen_G45 or Config.CPU_Ironlake then
715 GTT_Size := GTT_Size_Gen4 (GGC);
716 Stolen_Size := Stolen_Size_Gen4 (GGC);
717 elsif Config.CPU_Sandybridge or Config.CPU_Ivybridge or Config.CPU_Haswell
718 then
719 GTT_Size := GTT_Size_Gen6 (GGC);
720 Stolen_Size := Stolen_Size_Gen6 (GGC);
721 elsif Config.CPU_Broadwell then
722 GTT_Size := GTT_Size_Gen8 (GGC);
723 Stolen_Size := Stolen_Size_Gen8 (GGC);
724 else
725 GTT_Size := GTT_Size_Gen8 (GGC);
726 Stolen_Size := Stolen_Size_Gen9 (GGC);
727 end if;
Nico Hubereedde882017-07-16 02:54:39 +0200728 end Decode_Stolen;
729
730 -- Additional runtime validation that FB fits stolen memory and aperture.
731 procedure Validate_FB (FB : Framebuffer_Type; Valid : out Boolean)
732 with
733 Pre => Is_Initialized,
734 Post => (if Valid then Valid_FB (FB))
735 is
736 GTT_Size, Aperture_Size : Natural;
737 Stolen_Size : Stolen_Size_Range;
738 begin
739 Valid := Valid_FB (FB);
740
741 if Valid then
742 Decode_Stolen (GTT_Size, Stolen_Size);
743 Dev.Resource_Size (Aperture_Size, PCI.Res2);
744 Valid :=
745 FB_Last_Page (FB) < GTT_Size / Config.GTT_PTE_Size and
746 FB_Last_Page (FB) < Natural (Stolen_Size / GTT_Page_Size) and
747 FB_Last_Page (FB) < Aperture_Size / GTT_Page_Size;
Nico Huber34be6542017-12-13 09:26:24 +0100748 pragma Debug (not Valid, Debug.Put_Line
Nico Hubereedde882017-07-16 02:54:39 +0200749 ("Stolen memory too small to hold framebuffer."));
750 end if;
751 end Validate_FB;
752
Nico Huber5374c3a2017-07-15 21:48:06 +0200753 procedure Setup_Default_FB
754 (FB : in Framebuffer_Type;
755 Clear : in Boolean := True;
756 Success : out Boolean)
757 is
758 GMA_Phys_Base : constant PCI.Index := 16#5c#;
759 GMA_Phys_Base_Mask : constant := 16#fff0_0000#;
760
761 Phys_Base : Word32;
762 begin
Nico Hubereedde882017-07-16 02:54:39 +0200763 Validate_FB (FB, Success);
Nico Huber5374c3a2017-07-15 21:48:06 +0200764
765 if Success then
766 Dev.Read32 (Phys_Base, GMA_Phys_Base);
767 Phys_Base := Phys_Base and GMA_Phys_Base_Mask;
768 Success := Phys_Base /= GMA_Phys_Base_Mask and Phys_Base /= 0;
769 pragma Debug (not Success, Debug.Put_Line
770 ("Failed to read stolen memory base."));
Nico Huber0164b022017-08-24 15:12:51 +0200771
772 if Success then
773 if FB.Tiling in XY_Tiling then
774 Registers.Add_Fence
775 (First_Page => FB_First_Page (FB),
776 Last_Page => FB_Last_Page (FB),
777 Tiling => FB.Tiling,
778 Pitch => FB_Pitch (FB.Stride, FB),
779 Success => Success);
780 end if;
781 pragma Debug (not Success, Debug.Put_Line
782 ("Tiled framebuffer but no fence regs available."));
783 end if;
784
Nico Huber5374c3a2017-07-15 21:48:06 +0200785 if Success then
786 Setup_Default_GTT (FB, Phys_Base);
787 end if;
788 end if;
789
790 if Success and then Clear then
791 declare
792 use type HW.Word64;
793 Linear_FB : Word64;
794 begin
Nico Huberc3f66f62017-07-16 21:39:54 +0200795 Map_Linear_FB (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200796 if Linear_FB /= 0 then
Nico Huberc3f66f62017-07-16 21:39:54 +0200797 Framebuffer_Filler.Fill (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200798 end if;
Nico Huber5374c3a2017-07-15 21:48:06 +0200799 end;
800 end if;
801 end Setup_Default_FB;
802
Nico Huberc3f66f62017-07-16 21:39:54 +0200803 procedure Map_Linear_FB (Linear_FB : out Word64; FB : in Framebuffer_Type)
804 is
805 use type HW.Word64;
806
807 Valid : Boolean;
808 begin
809 Linear_FB := 0;
810
811 if Linear_FB_Base = 0 then
812 Dev.Map (Linear_FB_Base, PCI.Res2);
813 pragma Debug
814 (Linear_FB_Base = 0, Debug.Put_Line ("Failed to map resource2."));
815 end if;
816
817 if Linear_FB_Base /= 0 then
818 Validate_FB (FB, Valid);
819 if Valid then
Nico Huber34be6542017-12-13 09:26:24 +0100820 Linear_FB := Linear_FB_Base + Word64 (Phys_Offset (FB));
Nico Huberc3f66f62017-07-16 21:39:54 +0200821 end if;
822 end if;
823 end Map_Linear_FB;
824
Nico Huber5374c3a2017-07-15 21:48:06 +0200825 ----------------------------------------------------------------------------
826
Nico Huber99f10f32016-11-20 00:34:05 +0100827 procedure Dump_Configs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200828 is
829 subtype Pipe_Name is String (1 .. 9);
Nico Huber99f10f32016-11-20 00:34:05 +0100830 type Pipe_Name_Array is array (Pipe_Index) of Pipe_Name;
Nico Huber83693c82016-10-08 22:17:55 +0200831 Pipe_Names : constant Pipe_Name_Array :=
832 (Primary => "Primary ",
833 Secondary => "Secondary",
834 Tertiary => "Tertiary ");
Nico Huber5ef4d602017-12-13 13:56:47 +0100835
836 subtype Tiling_Name is String (1 .. 7);
837 type Tiling_Name_Array is array (Tiling_Type) of Tiling_Name;
838 Tilings : constant Tiling_Name_Array :=
839 (Linear => "Linear ",
840 X_Tiled => "X_Tiled",
841 Y_Tiled => "Y_Tiled");
842
843 subtype Rotation_Name is String (1 .. 11);
844 type Rotation_Name_Array is array (Rotation_Type) of Rotation_Name;
845 Rotations : constant Rotation_Name_Array :=
846 (No_Rotation => "No_Rotation",
847 Rotated_90 => "Rotated_90 ",
848 Rotated_180 => "Rotated_180",
849 Rotated_270 => "Rotated_270");
Nico Huber83693c82016-10-08 22:17:55 +0200850 begin
851 Debug.New_Line;
Paul Menzelb83107c2017-05-04 09:02:33 +0200852 Debug.Put_Line ("CONFIG =>");
Nico Huber99f10f32016-11-20 00:34:05 +0100853 for Pipe in Pipe_Index loop
854 if Pipe = Pipe_Index'First then
Nico Huber83693c82016-10-08 22:17:55 +0200855 Debug.Put (" (");
856 else
857 Debug.Put (" ");
858 end if;
859 Debug.Put_Line (Pipe_Names (Pipe) & " =>");
860 Debug.Put_Line
861 (" (Port => " & Port_Names (Configs (Pipe).Port) & ",");
862 Debug.Put_Line (" Framebuffer =>");
Nico Huber5ef4d602017-12-13 13:56:47 +0100863 Debug.Put (" (Width => ");
Nico Huber83693c82016-10-08 22:17:55 +0200864 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Width);
865 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100866 Debug.Put (" Height => ");
Nico Huber83693c82016-10-08 22:17:55 +0200867 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Height);
868 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100869 Debug.Put (" Start_X => ");
870 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_X);
871 Debug.Put_Line (",");
872 Debug.Put (" Start_Y => ");
873 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_Y);
874 Debug.Put_Line (",");
875 Debug.Put (" Stride => ");
Nico Huber83693c82016-10-08 22:17:55 +0200876 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Stride);
877 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100878 Debug.Put (" V_Stride => ");
879 Debug.Put_Int32 (Configs (Pipe).Framebuffer.V_Stride);
880 Debug.Put_Line (",");
881 Debug.Put (" Tiling => ");
882 Debug.Put_Line (Tilings (Configs (Pipe).Framebuffer.Tiling) & ",");
883 Debug.Put (" Rotation => ");
884 Debug.Put_Line (Rotations (Configs (Pipe).Framebuffer.Rotation) & ",");
Nico Huber83693c82016-10-08 22:17:55 +0200885 Debug.Put (" Offset => ");
886 Debug.Put_Word32 (Configs (Pipe).Framebuffer.Offset);
887 Debug.Put_Line (",");
888 Debug.Put (" BPC => ");
889 Debug.Put_Int64 (Configs (Pipe).Framebuffer.BPC);
890 Debug.Put_Line ("),");
891 Debug.Put_Line (" Mode =>");
892 Debug.Put (" (Dotclock => ");
893 Debug.Put_Int64 (Configs (Pipe).Mode.Dotclock);
894 Debug.Put_Line (",");
895 Debug.Put (" H_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200896 Debug.Put_Int32 (Configs (Pipe).Mode.H_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200897 Debug.Put_Line (",");
898 Debug.Put (" H_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200899 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200900 Debug.Put_Line (",");
901 Debug.Put (" H_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200902 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200903 Debug.Put_Line (",");
904 Debug.Put (" H_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200905 Debug.Put_Int32 (Configs (Pipe).Mode.H_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200906 Debug.Put_Line (",");
907 Debug.Put (" V_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200908 Debug.Put_Int32 (Configs (Pipe).Mode.V_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200909 Debug.Put_Line (",");
910 Debug.Put (" V_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200911 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200912 Debug.Put_Line (",");
913 Debug.Put (" V_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200914 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200915 Debug.Put_Line (",");
916 Debug.Put (" V_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200917 Debug.Put_Int32 (Configs (Pipe).Mode.V_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200918 Debug.Put_Line (",");
919 Debug.Put_Line (" H_Sync_Active_High => " &
920 (if Configs (Pipe).Mode.H_Sync_Active_High
921 then "True,"
922 else "False,"));
923 Debug.Put_Line (" V_Sync_Active_High => " &
924 (if Configs (Pipe).Mode.V_Sync_Active_High
925 then "True,"
926 else "False,"));
927 Debug.Put (" BPC => ");
928 Debug.Put_Int64 (Configs (Pipe).Mode.BPC);
Nico Huber99f10f32016-11-20 00:34:05 +0100929 if Pipe /= Pipe_Index'Last then
Nico Huber83693c82016-10-08 22:17:55 +0200930 Debug.Put_Line (")),");
931 else
932 Debug.Put_Line (")));");
933 end if;
934 end loop;
935 end Dump_Configs;
936
937end HW.GFX.GMA;