blob: 0fe360d5c2435d6881a526045d70bec08db210ba [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 Hubere317e9c2019-09-29 03:03:18 +020041 (Config.Variable,
42 PCI_Usable,
Nico Huberc5c66ec2019-09-28 23:59:45 +020043 Dev.Address_State,
Nico Huber2b6f6992017-07-09 18:11:34 +020044 Registers.Address_State,
Nico Huber312433c2019-09-28 03:15:48 +020045 PCode.Mailbox_Ready,
Nico Huber83693c82016-10-08 22:17:55 +020046 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +010047 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +020048 HPD_Delay, Wait_For_HPD,
49 Linear_FB_Base),
Nico Huber83693c82016-10-08 22:17:55 +020050 Init_State => Initialized,
Nico Huber83693c82016-10-08 22:17:55 +020051 Device_State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020052 (Dev.PCI_State, Registers.Register_State, Registers.GTT_State))
Nico Huber83693c82016-10-08 22:17:55 +020053is
Nico Huber2b6f6992017-07-09 18:11:34 +020054 pragma Disable_Atomic_Synchronization;
Nico Huber83693c82016-10-08 22:17:55 +020055
56 subtype Port_Name is String (1 .. 8);
57 type Port_Name_Array is array (Port_Type) of Port_Name;
58 Port_Names : constant Port_Name_Array :=
59 (Disabled => "Disabled",
60 Internal => "Internal",
61 DP1 => "DP1 ",
62 DP2 => "DP2 ",
63 DP3 => "DP3 ",
Nico Huber0d454cd2016-11-21 13:33:43 +010064 HDMI1 => "HDMI1 ",
65 HDMI2 => "HDMI2 ",
66 HDMI3 => "HDMI3 ",
Nico Huber83693c82016-10-08 22:17:55 +020067 Analog => "Analog ");
68
Nico Huber2b6f6992017-07-09 18:11:34 +020069 package Dev is new HW.PCI.Dev (PCI.Address'(0, 2, 0));
70
Nico Huber83693c82016-10-08 22:17:55 +020071 package Display_Controller renames Pipe_Setup;
72
Nico Huber99f10f32016-11-20 00:34:05 +010073 type PLLs_Type is array (Pipe_Index) of PLLs.T;
Nico Huber83693c82016-10-08 22:17:55 +020074
Nico Huber83693c82016-10-08 22:17:55 +020075 type HPD_Type is array (Port_Type) of Boolean;
Nico Huber3be61d42017-01-09 13:58:18 +010076 type HPD_Delay_Type is array (Active_Port_Type) of Time.T;
Nico Huber83693c82016-10-08 22:17:55 +020077
Nico Huber83693c82016-10-08 22:17:55 +020078 Allocated_PLLs : PLLs_Type;
Nico Huber83693c82016-10-08 22:17:55 +020079 HPD_Delay : HPD_Delay_Type;
80 Wait_For_HPD : HPD_Type;
81 Initialized : Boolean := False;
82
Nico Huberc3f66f62017-07-16 21:39:54 +020083 Linear_FB_Base : Word64;
84
Nico Huber83693c82016-10-08 22:17:55 +020085 ----------------------------------------------------------------------------
86
Nico Huberf54d0962016-10-20 14:17:18 +020087 PCH_RAWCLK_FREQ_MASK : constant := 16#3ff# * 2 ** 0;
88
89 function PCH_RAWCLK_FREQ (Freq : Frequency_Type) return Word32
90 is
91 begin
92 return Word32 (Freq / 1_000_000);
93 end PCH_RAWCLK_FREQ;
94
95 ----------------------------------------------------------------------------
96
Nico Huber43370ba2017-01-09 15:26:19 +010097 procedure Enable_Output
98 (Pipe : in Pipe_Index;
99 Pipe_Cfg : in Pipe_Config;
100 Success : out Boolean)
Nico Huber8a5a3b52018-06-04 14:42:13 +0200101 with
Nico Huber9a4c4c32019-09-16 22:05:11 +0200102 Pre =>
103 Pipe_Cfg.Port in Active_Port_Type and
104 Config_Helpers.Valid_FB (Pipe_Cfg.Framebuffer, Pipe_Cfg.Mode)
Nico Huber43370ba2017-01-09 15:26:19 +0100105 is
106 Port_Cfg : Port_Config;
107 begin
Nico Huber3be61d42017-01-09 13:58:18 +0100108 pragma Debug (Debug.New_Line);
109 pragma Debug (Debug.Put_Line
110 ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
111
Nico Huber43370ba2017-01-09 15:26:19 +0100112 Config_Helpers.Fill_Port_Config
113 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
114
115 if Success then
Nico Huber43370ba2017-01-09 15:26:19 +0100116 Connector_Info.Preferred_Link_Setting (Port_Cfg, Success);
117 end if;
118
119 -- loop over all possible DP-lane configurations
120 -- (non-DP ports use a single fake configuration)
121 while Success loop
122 pragma Loop_Invariant
123 (Pipe_Cfg.Port in Active_Port_Type and
124 Port_Cfg.Mode = Port_Cfg.Mode'Loop_Entry);
125
126 PLLs.Alloc
127 (Port_Cfg => Port_Cfg,
128 PLL => Allocated_PLLs (Pipe),
129 Success => Success);
130
131 if Success then
132 -- try each DP-lane configuration twice
133 for Try in 1 .. 2 loop
134 pragma Loop_Invariant
135 (Pipe_Cfg.Port in Active_Port_Type);
136
Nico Huber4798c662017-01-11 12:44:48 +0100137 -- Clear pending hot-plug events before every try
138 Port_Detect.Clear_Hotplug_Detect (Pipe_Cfg.Port);
139
Nico Huber43370ba2017-01-09 15:26:19 +0100140 Connectors.Pre_On
141 (Pipe => Pipe,
142 Port_Cfg => Port_Cfg,
143 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
144 Success => Success);
145
146 if Success then
147 Display_Controller.On
148 (Pipe => Pipe,
149 Port_Cfg => Port_Cfg,
Nico Huber4dc4c612018-01-10 15:55:09 +0100150 Framebuffer => Pipe_Cfg.Framebuffer,
151 Cursor => Pipe_Cfg.Cursor);
Nico Huber43370ba2017-01-09 15:26:19 +0100152
153 Connectors.Post_On
Arthur Heymans60d0e5f2018-03-28 17:08:27 +0200154 (Pipe => Pipe,
155 Port_Cfg => Port_Cfg,
Nico Huber43370ba2017-01-09 15:26:19 +0100156 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
157 Success => Success);
158
159 if not Success then
160 Display_Controller.Off (Pipe);
161 Connectors.Post_Off (Port_Cfg);
162 end if;
163 end if;
164
165 exit when Success;
166 end loop;
167 exit when Success; -- connection established => stop loop
168
169 -- connection failed
170 PLLs.Free (Allocated_PLLs (Pipe));
171 end if;
172
173 Connector_Info.Next_Link_Setting (Port_Cfg, Success);
174 end loop;
175
176 if Success then
177 pragma Debug (Debug.Put_Line
178 ("Enabled port " & Port_Names (Pipe_Cfg.Port)));
179 else
180 Wait_For_HPD (Pipe_Cfg.Port) := True;
181 if Pipe_Cfg.Port = Internal then
182 Panel.Off;
183 end if;
184 end if;
185 end Enable_Output;
186
Nico Huber3be61d42017-01-09 13:58:18 +0100187 procedure Disable_Output (Pipe : Pipe_Index; Pipe_Cfg : Pipe_Config)
188 is
189 Port_Cfg : Port_Config;
190 Success : Boolean;
191 begin
192 Config_Helpers.Fill_Port_Config
193 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
194 if Success then
195 pragma Debug (Debug.New_Line);
196 pragma Debug (Debug.Put_Line
197 ("Disabling port " & Port_Names (Pipe_Cfg.Port)));
198 pragma Debug (Debug.New_Line);
199
200 Connectors.Pre_Off (Port_Cfg);
201 Display_Controller.Off (Pipe);
202 Connectors.Post_Off (Port_Cfg);
203
204 PLLs.Free (Allocated_PLLs (Pipe));
205 end if;
206 end Disable_Output;
207
Nico Huber99f10f32016-11-20 00:34:05 +0100208 procedure Update_Outputs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200209 is
Nico Huber3be61d42017-01-09 13:58:18 +0100210 procedure Check_HPD (Port : in Active_Port_Type; Detected : out Boolean)
211 is
212 HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
213 begin
214 if HPD_Delay_Over then
215 Port_Detect.Hotplug_Detect (Port, Detected);
216 HPD_Delay (Port) := Time.MS_From_Now (333);
217 else
218 Detected := False;
219 end if;
220 end Check_HPD;
Nico Huberb56b9c52017-01-11 15:12:23 +0100221
Nico Huber9a4c4c32019-09-16 22:05:11 +0200222 Scaler_Reservation : Display_Controller.Scaler_Reservation :=
223 Display_Controller.Null_Scaler_Reservation;
Nico Huber564103f2017-01-11 15:33:07 +0100224
Nico Huber9a4c4c32019-09-16 22:05:11 +0200225 Update_Power : Boolean := False;
Nico Huberb0bbdbc2019-09-27 22:32:21 +0200226 Update_CDClk : Boolean;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200227 Old_Configs,
228 New_Configs : Pipe_Configs;
Nico Huber3d06de82018-05-29 01:35:04 +0200229
230 function Full_Update (Cur_Config, New_Config : Pipe_Config) return Boolean
231 is
232 begin
233 return
Nico Huber958c5642018-06-02 16:59:31 +0200234 Cur_Config.Port /= New_Config.Port
235 or else
236 Cur_Config.Mode /= New_Config.Mode
237 or else
Nico Huber3d06de82018-05-29 01:35:04 +0200238 (Config.Use_PDW_For_EDP_Scaling and then
239 (Cur_Config.Port = Internal and
Nico Huber958c5642018-06-02 16:59:31 +0200240 Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config)))
241 or else
242 (Config.Has_GMCH_PFIT_CONTROL and then
243 (Requires_Scaling (Cur_Config) /= Requires_Scaling (New_Config) or
244 Scaling_Type (Cur_Config) /= Scaling_Type (New_Config)));
Nico Huber3d06de82018-05-29 01:35:04 +0200245 end Full_Update;
Nico Huber83693c82016-10-08 22:17:55 +0200246 begin
247 Old_Configs := Cur_Configs;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200248 New_Configs := Configs;
249
250 -- validate new configs, filter invalid configs and those waiting for HPD
251 for Pipe in Pipe_Index loop
252 declare
253 Success : Boolean := True;
254 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
255 New_Config : Pipe_Config renames New_Configs (Pipe);
256 begin
257 if New_Config.Port /= Disabled then
258 if Wait_For_HPD (New_Config.Port) then
259 Check_HPD (New_Config.Port, Success);
260 Wait_For_HPD (New_Config.Port) := not Success;
261 end if;
262
263 Success := Success and then
264 Config_Helpers.Validate_Config
265 (New_Config.Framebuffer, New_Config.Mode, Pipe);
266
267 if Success and then Requires_Scaling (New_Config) then
268 Display_Controller.Reserve_Scaler
269 (Success, Scaler_Reservation, Pipe);
270 end if;
271
272 if not Success then
273 New_Config.Port := Disabled;
274 end if;
275 end if;
276 end;
277 pragma Loop_Invariant
278 (for all P in Pipe_Index'First .. Pipe =>
279 New_Configs (P).Port = Disabled or
280 Config_Helpers.Valid_FB
281 (New_Configs (P).Framebuffer, New_Configs (P).Mode));
282 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200283
Nico Huberb0bbdbc2019-09-27 22:32:21 +0200284 -- limit dotclocks to maximum CDClk, if we are about
285 -- to switch CDClk, all pipes have to be disabled
286 Power_And_Clocks.Limit_Dotclocks (New_Configs, Update_CDClk);
287
Nico Huberb56b9c52017-01-11 15:12:23 +0100288 -- disable all pipes that changed or had a hot-plug event
289 for Pipe in Pipe_Index loop
290 declare
291 Unplug_Detected : Boolean;
292 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
Nico Huber9a4c4c32019-09-16 22:05:11 +0200293 New_Config : Pipe_Config renames New_Configs (Pipe);
Nico Huberb56b9c52017-01-11 15:12:23 +0100294 begin
295 if Cur_Config.Port /= Disabled then
296 Check_HPD (Cur_Config.Port, Unplug_Detected);
Nico Huber83693c82016-10-08 22:17:55 +0200297
Nico Huberb0bbdbc2019-09-27 22:32:21 +0200298 if Update_CDClk or
299 Unplug_Detected or
300 Full_Update (Cur_Config, New_Config)
301 then
Nico Huberb56b9c52017-01-11 15:12:23 +0100302 Disable_Output (Pipe, Cur_Config);
303 Cur_Config.Port := Disabled;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200304 Update_Power := True;
Nico Huberb56b9c52017-01-11 15:12:23 +0100305 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200306 end if;
Nico Huberb56b9c52017-01-11 15:12:23 +0100307 end;
308 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200309
Nico Huberb0bbdbc2019-09-27 22:32:21 +0200310 -- switch CDClk if necessary and possible, limit dotclocks accordingly
311 if Update_CDClk then
312 Power_And_Clocks.Update_CDClk (New_Configs);
313 end if;
314
Nico Huberb56b9c52017-01-11 15:12:23 +0100315 -- enable all pipes that changed and should be active
316 for Pipe in Pipe_Index loop
317 declare
318 Success : Boolean;
319 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
Nico Huber9a4c4c32019-09-16 22:05:11 +0200320 New_Config : Pipe_Config renames New_Configs (Pipe);
Nico Huberb56b9c52017-01-11 15:12:23 +0100321 begin
Nico Huber9a4c4c32019-09-16 22:05:11 +0200322 -- full update
Nico Huber3d06de82018-05-29 01:35:04 +0200323 if New_Config.Port /= Disabled and
324 Full_Update (Cur_Config, New_Config)
Nico Huberb56b9c52017-01-11 15:12:23 +0100325 then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200326 Power_And_Clocks.Power_Up (Old_Configs, New_Configs);
327 Update_Power := True;
Nico Huberc7a4fee2016-11-03 18:18:03 +0100328
Nico Huber9a4c4c32019-09-16 22:05:11 +0200329 Enable_Output (Pipe, New_Config, Success);
Nico Huber83693c82016-10-08 22:17:55 +0200330 if Success then
Nico Huberb56b9c52017-01-11 15:12:23 +0100331 Cur_Config := New_Config;
Nico Huber83693c82016-10-08 22:17:55 +0200332 end if;
Nico Huber3be61d42017-01-09 13:58:18 +0100333
Nico Huberb56b9c52017-01-11 15:12:23 +0100334 -- update framebuffer offset only
335 elsif New_Config.Port /= Disabled and
Nico Huberf361ec82018-06-02 18:01:45 +0200336 Cur_Config.Framebuffer /= New_Config.Framebuffer
Nico Huberb56b9c52017-01-11 15:12:23 +0100337 then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200338 Display_Controller.Setup_FB
339 (Pipe, New_Config.Mode, New_Config.Framebuffer);
340 Display_Controller.Update_Cursor
341 (Pipe, New_Config.Framebuffer, New_Config.Cursor);
342 Cur_Config := New_Config;
Nico Huberb56b9c52017-01-11 15:12:23 +0100343 end if;
344 end;
Nico Huber83693c82016-10-08 22:17:55 +0200345 end loop;
346
Nico Huber9a4c4c32019-09-16 22:05:11 +0200347 if Update_Power then
348 Power_And_Clocks.Power_Down (Old_Configs, New_Configs, Cur_Configs);
Nico Huber83693c82016-10-08 22:17:55 +0200349 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200350 end Update_Outputs;
351
352 ----------------------------------------------------------------------------
353
Nico Huber15ffc4f2018-01-11 14:44:43 +0100354 procedure Update_Cursor (Pipe : Pipe_Index; Cursor : Cursor_Type)
355 is
356 begin
357 Cur_Configs (Pipe).Cursor := Cursor;
358 Display_Controller.Update_Cursor
359 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
360 end Update_Cursor;
361
362 procedure Place_Cursor
363 (Pipe : Pipe_Index;
364 X : Cursor_Pos;
365 Y : Cursor_Pos)
366 is
367 begin
368 Cur_Configs (Pipe).Cursor.Center_X := X;
369 Cur_Configs (Pipe).Cursor.Center_Y := Y;
370 Display_Controller.Place_Cursor
371 (Pipe, Cur_Configs (Pipe).Framebuffer, Cur_Configs (Pipe).Cursor);
372 end Place_Cursor;
373
374 procedure Move_Cursor
375 (Pipe : Pipe_Index;
376 X : Cursor_Pos;
377 Y : Cursor_Pos)
378 is
379 function Cap_Add (A, B : Cursor_Pos) return Cursor_Pos is
380 (if A + B < 0
381 then Int32'Max (Cursor_Pos'First, A + B)
382 else Int32'Min (Cursor_Pos'Last, A + B));
383 begin
384 Place_Cursor
385 (Pipe => Pipe,
386 X => Cap_Add (Cur_Configs (Pipe).Cursor.Center_X, X),
387 Y => Cap_Add (Cur_Configs (Pipe).Cursor.Center_Y, Y));
388 end Move_Cursor;
389
390 ----------------------------------------------------------------------------
391
Nico Huber83693c82016-10-08 22:17:55 +0200392 procedure Initialize
Nico Huber2b6f6992017-07-09 18:11:34 +0200393 (Write_Delay : in Word64 := 0;
Nico Huber793a8d42016-11-21 18:57:03 +0100394 Clean_State : in Boolean := False;
Nico Huber83693c82016-10-08 22:17:55 +0200395 Success : out Boolean)
396 with
397 Refined_Global =>
Nico Huber27088aa2018-06-10 13:28:05 +0200398 (Input => (Time.State),
399 In_Out => (Dev.PCI_State, Registers.Register_State, Port_IO.State),
Nico Huber83693c82016-10-08 22:17:55 +0200400 Output =>
Nico Huberc5c66ec2019-09-28 23:59:45 +0200401 (PCI_Usable,
402 Config.Variable,
Nico Huber27088aa2018-06-10 13:28:05 +0200403 Dev.Address_State,
Nico Huber2b6f6992017-07-09 18:11:34 +0200404 Registers.Address_State,
Nico Huber312433c2019-09-28 03:15:48 +0200405 PCode.Mailbox_Ready,
Nico Huber83693c82016-10-08 22:17:55 +0200406 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +0100407 Cur_Configs, Allocated_PLLs,
Nico Huberc3f66f62017-07-16 21:39:54 +0200408 HPD_Delay, Wait_For_HPD,
409 Linear_FB_Base, Initialized))
Nico Huber83693c82016-10-08 22:17:55 +0200410 is
411 use type HW.Word64;
412
Nico Huber0b2329a2018-06-09 21:14:27 +0200413 function MMIO_GTT_Offset return Natural is
414 (if Config.Has_64bit_GTT
415 then Registers.MMIO_GTT_64_Offset
416 else Registers.MMIO_GTT_32_Offset);
Nico Huber2b6f6992017-07-09 18:11:34 +0200417 PCI_MMIO_Base, PCI_GTT_Base : Word64;
418
Nico Huber83693c82016-10-08 22:17:55 +0200419 Now : constant Time.T := Time.Now;
420
421 procedure Check_Platform (Success : out Boolean)
422 is
423 Audio_VID_DID : Word32;
424 begin
Nico Huber6621a142018-06-07 23:56:54 +0200425 case Config.Gen is
Arthur Heymans73ea0322018-03-28 17:17:07 +0200426 when G45 =>
427 Registers.Read (Registers.G4X_AUD_VID_DID, Audio_VID_DID);
Nico Huber6621a142018-06-07 23:56:54 +0200428 when Ironlake =>
429 Registers.Read (Registers.PCH_AUD_VID_DID, Audio_VID_DID);
Nico Huber83693c82016-10-08 22:17:55 +0200430 when Haswell .. Skylake =>
431 Registers.Read (Registers.AUD_VID_DID, Audio_VID_DID);
Nico Huber83693c82016-10-08 22:17:55 +0200432 end case;
433 Success :=
Nico Huber998ee2b2018-06-12 23:02:17 +0200434 ((Config.Gen_Broxton and Audio_VID_DID = 16#8086_280a#) or
Nico Huber88badbe2018-09-27 16:36:47 +0200435 (Config.CPU_Kabylake and Audio_VID_DID = 16#8086_280b#) or
436 (Config.CPU_Skylake and Audio_VID_DID = 16#8086_2809#) or
Nico Huber998ee2b2018-06-12 23:02:17 +0200437 (Config.CPU_Broadwell and Audio_VID_DID = 16#8086_2808#) or
438 (Config.CPU_Haswell and Audio_VID_DID = 16#8086_2807#) or
439 ((Config.CPU_Ivybridge or
440 Config.CPU_Sandybridge) and (Audio_VID_DID = 16#8086_2806# or
441 Audio_VID_DID = 16#8086_2805#)) or
442 (Config.CPU_Ironlake and Audio_VID_DID = 16#0000_0000#) or
443 (Config.Gen_G45 and (Audio_VID_DID = 16#8086_2801# or
444 Audio_VID_DID = 16#8086_2802# or
445 Audio_VID_DID = 16#8086_2803#)));
Nico Huber83693c82016-10-08 22:17:55 +0200446 end Check_Platform;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200447
448 procedure Check_Platform_PCI (Success : out Boolean)
449 is
450 use type HW.Word16;
451 Vendor, Device : Word16;
452 begin
453 Dev.Read16 (Vendor, PCI.Vendor_Id);
454 Dev.Read16 (Device, PCI.Device_Id);
455
Nico Huber6a996dc2018-06-17 16:30:33 +0200456 Config.Detect_CPU (Device);
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200457 Success := Vendor = 16#8086# and Config.Compatible_GPU (Device);
458 end Check_Platform_PCI;
Nico Huber83693c82016-10-08 22:17:55 +0200459 begin
Nico Huber83693c82016-10-08 22:17:55 +0200460 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
461
462 pragma Debug (Debug.Set_Register_Write_Delay (Write_Delay));
463
Nico Huberc5c66ec2019-09-28 23:59:45 +0200464 PCI_Usable := False;
Nico Huberc3f66f62017-07-16 21:39:54 +0200465 Linear_FB_Base := 0;
Nico Huber312433c2019-09-28 03:15:48 +0200466 PCode.Mailbox_Ready := False;
Nico Huber83693c82016-10-08 22:17:55 +0200467 Wait_For_HPD := HPD_Type'(others => False);
468 HPD_Delay := HPD_Delay_Type'(others => Now);
Nico Huber83693c82016-10-08 22:17:55 +0200469 Allocated_PLLs := (others => PLLs.Invalid);
Nico Huber99f10f32016-11-20 00:34:05 +0100470 Cur_Configs := Pipe_Configs'
471 (others => Pipe_Config'
Nico Huber83693c82016-10-08 22:17:55 +0200472 (Port => Disabled,
473 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100474 Cursor => Default_Cursor,
Nico Huber83693c82016-10-08 22:17:55 +0200475 Mode => HW.GFX.Invalid_Mode));
Nico Huber27088aa2018-06-10 13:28:05 +0200476 Config.Variable := Config.Initial_Settings;
Nico Huber6a996dc2018-06-17 16:30:33 +0200477 Registers.Set_Register_Base (Config.Default_MMIO_Base);
Nico Huber83693c82016-10-08 22:17:55 +0200478 PLLs.Initialize;
479
Nico Huber2b6f6992017-07-09 18:11:34 +0200480 Dev.Initialize (Success);
481
482 if Success then
Nico Huber6a996dc2018-06-17 16:30:33 +0200483 Check_Platform_PCI (Success);
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200484 if Success then
Nico Huber6a996dc2018-06-17 16:30:33 +0200485 Dev.Map (PCI_MMIO_Base, PCI.Res0, Length => MMIO_GTT_Offset);
486 Dev.Map (PCI_GTT_Base, PCI.Res0, Offset => MMIO_GTT_Offset);
487 if PCI_MMIO_Base /= 0 and PCI_GTT_Base /= 0 then
488 Registers.Set_Register_Base (PCI_MMIO_Base, PCI_GTT_Base);
Nico Huberc5c66ec2019-09-28 23:59:45 +0200489 PCI_Usable := True;
Nico Huber6a996dc2018-06-17 16:30:33 +0200490 else
491 pragma Debug (Debug.Put_Line
492 ("ERROR: Couldn't map resoure0."));
493 Success := Config.Default_MMIO_Base_Set;
494 end if;
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200495 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200496 else
497 pragma Debug (Debug.Put_Line
498 ("WARNING: Couldn't initialize PCI dev."));
Nico Huber2b6f6992017-07-09 18:11:34 +0200499 Success := Config.Default_MMIO_Base_Set;
Nico Huber2b6f6992017-07-09 18:11:34 +0200500
Nico Hubere7ac6eb2017-09-04 23:54:13 +0200501 if Success then
502 Check_Platform (Success);
503 end if;
Nico Huber2b6f6992017-07-09 18:11:34 +0200504 end if;
505
Nico Huber83693c82016-10-08 22:17:55 +0200506 if not Success then
507 pragma Debug (Debug.Put_Line ("ERROR: Incompatible CPU or PCH."));
508
509 Panel.Static_Init; -- for flow analysis
510
511 Initialized := False;
512 return;
513 end if;
514
515 Panel.Setup_PP_Sequencer;
516 Port_Detect.Initialize;
Nico Huber0923b792017-06-09 15:28:41 +0200517 Connectors.Initialize;
Nico Huber83693c82016-10-08 22:17:55 +0200518
Nico Huber793a8d42016-11-21 18:57:03 +0100519 if Clean_State then
520 Power_And_Clocks.Pre_All_Off;
521 Connectors.Pre_All_Off;
522 Display_Controller.All_Off;
523 Connectors.Post_All_Off;
524 PLLs.All_Off;
525 Power_And_Clocks.Post_All_Off;
Nico Huber17d64b62017-07-15 20:51:25 +0200526 Registers.Clear_Fences;
Nico Huber33912aa2016-12-06 20:36:23 +0100527 else
528 -- According to PRMs, VGA plane is the only thing
Nico Huber3a0e2a02017-07-19 14:41:46 +0200529 -- that's enabled by default after reset...
Nico Huber33912aa2016-12-06 20:36:23 +0100530 Display_Controller.Legacy_VGA_Off;
Nico Huber3a0e2a02017-07-19 14:41:46 +0200531 -- ... along with some DDI port bits since Skylake.
532 Connectors.Post_Reset_Off;
Nico Huber793a8d42016-11-21 18:57:03 +0100533 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200534
535 -------------------- Now restart from a clean state ---------------------
536 Power_And_Clocks.Initialize;
537
Nico Huber1c3b9282017-02-09 13:57:04 +0100538 if Config.Has_PCH then
539 Registers.Unset_And_Set_Mask
540 (Register => Registers.PCH_RAWCLK_FREQ,
541 Mask_Unset => PCH_RAWCLK_FREQ_MASK,
542 Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
543 end if;
Nico Huberf54d0962016-10-20 14:17:18 +0200544
Nico Huber83693c82016-10-08 22:17:55 +0200545 Initialized := True;
546
547 end Initialize;
548
549 function Is_Initialized return Boolean
550 with
551 Refined_Post => Is_Initialized'Result = Initialized
552 is
553 begin
554 return Initialized;
555 end Is_Initialized;
556
557 ----------------------------------------------------------------------------
558
Nico Hubercf88f3d2018-06-05 13:27:34 +0200559 pragma Warnings
560 (GNATprove, Off, """Registers.Register_State"" * is not modified*",
Nico Huberadfe11f2018-06-10 14:59:04 +0200561 Reason => "Power_Up_VGA is only effective in certain configurations.");
Nico Huber42fb2d02017-09-01 17:01:51 +0200562 procedure Power_Up_VGA
Nico Hubercf88f3d2018-06-05 13:27:34 +0200563 with
564 Refined_Global =>
Nico Huberadfe11f2018-06-10 14:59:04 +0200565 (Input => (Cur_Configs, Config.Variable, Time.State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200566 In_Out => (Registers.Register_State),
567 Proof_In => (Initialized))
Nico Huber42fb2d02017-09-01 17:01:51 +0200568 is
569 Fake_Config : constant Pipe_Configs :=
570 (Primary =>
571 (Port => Analog,
572 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100573 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200574 Mode => HW.GFX.Invalid_Mode),
575 others =>
576 (Port => Disabled,
577 Framebuffer => HW.GFX.Default_FB,
Nico Hubera02b2c62018-01-09 15:58:34 +0100578 Cursor => Default_Cursor,
Nico Huber42fb2d02017-09-01 17:01:51 +0200579 Mode => HW.GFX.Invalid_Mode));
580 begin
581 Power_And_Clocks.Power_Up (Cur_Configs, Fake_Config);
582 end Power_Up_VGA;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200583 pragma Warnings
584 (GNATprove, Off, "no check message justified*", Reason => "see below");
585 pragma Annotate
586 (GNATprove, Intentional, "unused global",
Nico Huberadfe11f2018-06-10 14:59:04 +0200587 "Power_Up_VGA is only effective in certain configurations.");
Nico Hubercf88f3d2018-06-05 13:27:34 +0200588 pragma Warnings (GNATprove, On, "no check message justified*");
589 pragma Warnings
590 (GNATprove, On, """Registers.Register_State"" * is not modified*");
Nico Huber42fb2d02017-09-01 17:01:51 +0200591
592 ----------------------------------------------------------------------------
593
Nico Huber5374c3a2017-07-15 21:48:06 +0200594 function FB_First_Page (FB : Framebuffer_Type) return Natural is
Nico Huber34be6542017-12-13 09:26:24 +0100595 (Natural (Phys_Offset (FB) / GTT_Page_Size));
Nico Huber5374c3a2017-07-15 21:48:06 +0200596 function FB_Pages (FB : Framebuffer_Type) return Natural is
597 (Natural (Div_Round_Up (FB_Size (FB), GTT_Page_Size)));
598 function FB_Last_Page (FB : Framebuffer_Type) return Natural is
599 (FB_First_Page (FB) + FB_Pages (FB) - 1);
600
Nico Huber34be6542017-12-13 09:26:24 +0100601 -- Check basics and that it fits in GTT. For 90 degree rotations,
602 -- the Offset should be above GTT_Rotation_Offset. The latter will
603 -- be subtracted for the aperture mapping.
Nico Huber5374c3a2017-07-15 21:48:06 +0200604 function Valid_FB (FB : Framebuffer_Type) return Boolean is
Nico Huber34be6542017-12-13 09:26:24 +0100605 (Valid_Stride (FB) and
606 FB_First_Page (FB) in GTT_Range and
607 FB_Last_Page (FB) in GTT_Range and
608 (not Rotation_90 (FB) or
609 (FB_Last_Page (FB) + GTT_Rotation_Offset in GTT_Range and
610 FB.Offset >= Word32 (GTT_Rotation_Offset) * GTT_Page_Size)));
Nico Huber5374c3a2017-07-15 21:48:06 +0200611
612 -- Also check that we don't overflow the GTT's 39-bit space
613 -- (always true with a 32-bit base)
614 function Valid_Phys_FB (FB : Framebuffer_Type; Phys_Base : Word32)
615 return Boolean is
616 (Valid_FB (FB) and
Nico Huber34be6542017-12-13 09:26:24 +0100617 Int64 (Phys_Base) + Int64 (Phys_Offset (FB)) + Int64 (FB_Size (FB)) <=
Nico Huber5374c3a2017-07-15 21:48:06 +0200618 Int64 (GTT_Address_Type'Last))
619 with
620 Ghost;
621
Nico Huber83693c82016-10-08 22:17:55 +0200622 procedure Write_GTT
623 (GTT_Page : GTT_Range;
624 Device_Address : GTT_Address_Type;
Nico Huber5374c3a2017-07-15 21:48:06 +0200625 Valid : Boolean)
626 is
Nico Huber83693c82016-10-08 22:17:55 +0200627 begin
628 Registers.Write_GTT (GTT_Page, Device_Address, Valid);
629 end Write_GTT;
630
Nico Huberceda17d2018-06-09 22:00:29 +0200631 procedure Read_GTT
632 (Device_Address : out GTT_Address_Type;
633 Valid : out Boolean;
634 GTT_Page : in GTT_Range)
635 is
636 begin
637 Registers.Read_GTT (Device_Address, Valid, GTT_Page);
638 end Read_GTT;
639
Nico Huber194e57e2017-07-15 21:15:46 +0200640 procedure Setup_Default_GTT (FB : Framebuffer_Type; Phys_Base : Word32)
Nico Huber5374c3a2017-07-15 21:48:06 +0200641 with
642 Pre => Is_Initialized and Valid_Phys_FB (FB, Phys_Base)
Nico Huber83693c82016-10-08 22:17:55 +0200643 is
Nico Huber194e57e2017-07-15 21:15:46 +0200644 Phys_Addr : GTT_Address_Type :=
Nico Huber34be6542017-12-13 09:26:24 +0100645 GTT_Address_Type (Phys_Base) + GTT_Address_Type (Phys_Offset (FB));
Nico Huber83693c82016-10-08 22:17:55 +0200646 begin
Nico Huber194e57e2017-07-15 21:15:46 +0200647 for Idx in FB_First_Page (FB) .. FB_Last_Page (FB) loop
Nico Huber83693c82016-10-08 22:17:55 +0200648 Registers.Write_GTT
649 (GTT_Page => Idx,
650 Device_Address => Phys_Addr,
651 Valid => True);
Nico Huber194e57e2017-07-15 21:15:46 +0200652 Phys_Addr := Phys_Addr + GTT_Page_Size;
Nico Huber83693c82016-10-08 22:17:55 +0200653 end loop;
Nico Huber9b479412017-08-27 11:55:56 +0200654
655 if Rotation_90 (FB) and FB.Tiling = Y_Tiled and FB.V_Stride >= 32 then
656 declare
657 V_Pages : constant Natural := Natural (FB.V_Stride) / 32;
658 Bytes_Per_Row : constant GTT_Address_Type :=
659 GTT_Address_Type (Pixel_To_Bytes (32 * FB.Stride, FB));
660 begin
661 Phys_Addr := GTT_Address_Type (Phys_Base) +
Nico Huber34be6542017-12-13 09:26:24 +0100662 GTT_Address_Type (Phys_Offset (FB)) +
Nico Huber9b479412017-08-27 11:55:56 +0200663 GTT_Address_Type (FB_Size (FB));
664 for Page in FB_First_Page (FB) .. FB_Last_Page (FB) loop
665 Phys_Addr := Phys_Addr - Bytes_Per_Row;
666 Registers.Write_GTT
667 (GTT_Page => GTT_Rotation_Offset + Page,
668 Device_Address => Phys_Addr,
669 Valid => True);
670
671 if (Page - FB_First_Page (FB) + 1) mod V_Pages = 0 then
672 Phys_Addr := Phys_Addr + GTT_Page_Size +
673 GTT_Address_Type (V_Pages) * Bytes_Per_Row;
674 end if;
675 end loop;
676 end;
677 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200678 end Setup_Default_GTT;
679
680 ----------------------------------------------------------------------------
681
Nico Hubereedde882017-07-16 02:54:39 +0200682 use type HW.Word16;
683 subtype Stolen_Size_Range is Int64 range 0 .. 2 ** 33;
684
685 function GGMS_Gen4 (GGC : Word16) return Natural is
686 (Natural (Shift_Right (GGC, 8) and 16#07#));
687 function GTT_Size_Gen4 (GGC : Word16) return Natural is
688 (if GGMS_Gen4 (GGC) in 1 .. 3 then
689 (GGMS_Gen4 (GGC) + 1) * 2 ** 19 else 0);
690
691 function GMS_Gen4 (GGC : Word16) return Natural is
692 (Natural (Shift_Right (GGC, 4) and 16#0f#));
693 Valid_Stolen_Size_Gen4 : constant
694 array (Natural range 1 .. 13) of Stolen_Size_Range :=
695 (1, 4, 8, 16, 32, 48, 64, 128, 256, 96, 160, 224, 352);
696 function Stolen_Size_Gen4 (GGC : Word16) return Stolen_Size_Range is
697 (if GMS_Gen4 (GGC) in Valid_Stolen_Size_Gen4'Range then
Arthur Heymans5fd9a312017-09-12 12:45:18 +0200698 Valid_Stolen_Size_Gen4 (GMS_Gen4 (GGC)) * 2 ** 20 else 0);
Nico Hubereedde882017-07-16 02:54:39 +0200699
700 function GTT_Size_Gen6 (GGC : Word16) return Natural is
701 (Natural (Shift_Right (GGC, 8) and 16#03#) * 2 ** 20);
702
703 function Stolen_Size_Gen6 (GGC : Word16) return Stolen_Size_Range is
704 (Stolen_Size_Range (Shift_Right (GGC, 3) and 16#1f#) * 32 * 2 ** 20);
705
Nico Huberfe7985f2019-10-12 22:19:24 +0200706 function GGMS_Gen8 (GGC : Word16) return Natural is
707 (Natural (Shift_Right (GGC, 6) and 16#03#));
Nico Hubereedde882017-07-16 02:54:39 +0200708 function GTT_Size_Gen8 (GGC : Word16) return Natural is
Nico Huberfe7985f2019-10-12 22:19:24 +0200709 (if GGMS_Gen8 (GGC) /= 0 then
710 Natural (Shift_Left (Word32'(1), 20 + GGMS_Gen8 (GGC))) else 0);
Nico Hubereedde882017-07-16 02:54:39 +0200711
712 function GMS_Gen8 (GGC : Word16) return Stolen_Size_Range is
713 (Stolen_Size_Range (Shift_Right (GGC, 8) and 16#ff#));
714 function Stolen_Size_Gen8 (GGC : Word16) return Stolen_Size_Range is
715 (GMS_Gen8 (GGC) * 32 * 2 ** 20);
716
717 function Stolen_Size_Gen9 (GGC : Word16) return Stolen_Size_Range is
718 (if GMS_Gen8 (GGC) < 16#f0# then
719 Stolen_Size_Gen8 (GGC)
720 else
721 (GMS_Gen8 (GGC) - 16#f0# + 1) * 4 * 2 ** 20);
722
723 procedure Decode_Stolen
724 (GTT_Size : out Natural;
725 Stolen_Size : out Stolen_Size_Range)
726 with
727 Pre => Is_Initialized
728 is
Nico Huber63ec8362018-06-09 17:42:19 +0200729 GGC_Reg : constant PCI.Index :=
Nico Huber998ee2b2018-06-12 23:02:17 +0200730 (if Config.Gen_G45 or Config.CPU_Ironlake then 16#52# else 16#50#);
Nico Hubereedde882017-07-16 02:54:39 +0200731 GGC : Word16;
732 begin
733 Dev.Read16 (GGC, GGC_Reg);
Nico Huber998ee2b2018-06-12 23:02:17 +0200734 if Config.Gen_G45 or Config.CPU_Ironlake then
735 GTT_Size := GTT_Size_Gen4 (GGC);
736 Stolen_Size := Stolen_Size_Gen4 (GGC);
737 elsif Config.CPU_Sandybridge or Config.CPU_Ivybridge or Config.CPU_Haswell
738 then
739 GTT_Size := GTT_Size_Gen6 (GGC);
740 Stolen_Size := Stolen_Size_Gen6 (GGC);
741 elsif Config.CPU_Broadwell then
742 GTT_Size := GTT_Size_Gen8 (GGC);
743 Stolen_Size := Stolen_Size_Gen8 (GGC);
744 else
745 GTT_Size := GTT_Size_Gen8 (GGC);
746 Stolen_Size := Stolen_Size_Gen9 (GGC);
747 end if;
Nico Hubereedde882017-07-16 02:54:39 +0200748 end Decode_Stolen;
749
750 -- Additional runtime validation that FB fits stolen memory and aperture.
751 procedure Validate_FB (FB : Framebuffer_Type; Valid : out Boolean)
752 with
753 Pre => Is_Initialized,
754 Post => (if Valid then Valid_FB (FB))
755 is
756 GTT_Size, Aperture_Size : Natural;
757 Stolen_Size : Stolen_Size_Range;
758 begin
759 Valid := Valid_FB (FB);
760
761 if Valid then
762 Decode_Stolen (GTT_Size, Stolen_Size);
763 Dev.Resource_Size (Aperture_Size, PCI.Res2);
764 Valid :=
765 FB_Last_Page (FB) < GTT_Size / Config.GTT_PTE_Size and
766 FB_Last_Page (FB) < Natural (Stolen_Size / GTT_Page_Size) and
767 FB_Last_Page (FB) < Aperture_Size / GTT_Page_Size;
Nico Huber34be6542017-12-13 09:26:24 +0100768 pragma Debug (not Valid, Debug.Put_Line
Nico Hubereedde882017-07-16 02:54:39 +0200769 ("Stolen memory too small to hold framebuffer."));
770 end if;
771 end Validate_FB;
772
Nico Huber5374c3a2017-07-15 21:48:06 +0200773 procedure Setup_Default_FB
774 (FB : in Framebuffer_Type;
775 Clear : in Boolean := True;
776 Success : out Boolean)
777 is
778 GMA_Phys_Base : constant PCI.Index := 16#5c#;
779 GMA_Phys_Base_Mask : constant := 16#fff0_0000#;
780
781 Phys_Base : Word32;
782 begin
Nico Hubereedde882017-07-16 02:54:39 +0200783 Validate_FB (FB, Success);
Nico Huber5374c3a2017-07-15 21:48:06 +0200784
785 if Success then
786 Dev.Read32 (Phys_Base, GMA_Phys_Base);
787 Phys_Base := Phys_Base and GMA_Phys_Base_Mask;
788 Success := Phys_Base /= GMA_Phys_Base_Mask and Phys_Base /= 0;
789 pragma Debug (not Success, Debug.Put_Line
790 ("Failed to read stolen memory base."));
Nico Huber0164b022017-08-24 15:12:51 +0200791
792 if Success then
793 if FB.Tiling in XY_Tiling then
794 Registers.Add_Fence
795 (First_Page => FB_First_Page (FB),
796 Last_Page => FB_Last_Page (FB),
797 Tiling => FB.Tiling,
798 Pitch => FB_Pitch (FB.Stride, FB),
799 Success => Success);
800 end if;
801 pragma Debug (not Success, Debug.Put_Line
802 ("Tiled framebuffer but no fence regs available."));
803 end if;
804
Nico Huber5374c3a2017-07-15 21:48:06 +0200805 if Success then
806 Setup_Default_GTT (FB, Phys_Base);
807 end if;
808 end if;
809
810 if Success and then Clear then
811 declare
812 use type HW.Word64;
813 Linear_FB : Word64;
814 begin
Nico Huberc3f66f62017-07-16 21:39:54 +0200815 Map_Linear_FB (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200816 if Linear_FB /= 0 then
Nico Huberc3f66f62017-07-16 21:39:54 +0200817 Framebuffer_Filler.Fill (Linear_FB, FB);
Nico Huber5374c3a2017-07-15 21:48:06 +0200818 end if;
Nico Huber5374c3a2017-07-15 21:48:06 +0200819 end;
820 end if;
821 end Setup_Default_FB;
822
Nico Huberc3f66f62017-07-16 21:39:54 +0200823 procedure Map_Linear_FB (Linear_FB : out Word64; FB : in Framebuffer_Type)
824 is
825 use type HW.Word64;
826
827 Valid : Boolean;
828 begin
829 Linear_FB := 0;
830
831 if Linear_FB_Base = 0 then
832 Dev.Map (Linear_FB_Base, PCI.Res2);
833 pragma Debug
834 (Linear_FB_Base = 0, Debug.Put_Line ("Failed to map resource2."));
835 end if;
836
837 if Linear_FB_Base /= 0 then
838 Validate_FB (FB, Valid);
839 if Valid then
Nico Huber34be6542017-12-13 09:26:24 +0100840 Linear_FB := Linear_FB_Base + Word64 (Phys_Offset (FB));
Nico Huberc3f66f62017-07-16 21:39:54 +0200841 end if;
842 end if;
843 end Map_Linear_FB;
844
Nico Huber5374c3a2017-07-15 21:48:06 +0200845 ----------------------------------------------------------------------------
846
Nico Huber99f10f32016-11-20 00:34:05 +0100847 procedure Dump_Configs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200848 is
849 subtype Pipe_Name is String (1 .. 9);
Nico Huber99f10f32016-11-20 00:34:05 +0100850 type Pipe_Name_Array is array (Pipe_Index) of Pipe_Name;
Nico Huber83693c82016-10-08 22:17:55 +0200851 Pipe_Names : constant Pipe_Name_Array :=
852 (Primary => "Primary ",
853 Secondary => "Secondary",
854 Tertiary => "Tertiary ");
Nico Huber5ef4d602017-12-13 13:56:47 +0100855
856 subtype Tiling_Name is String (1 .. 7);
857 type Tiling_Name_Array is array (Tiling_Type) of Tiling_Name;
858 Tilings : constant Tiling_Name_Array :=
859 (Linear => "Linear ",
860 X_Tiled => "X_Tiled",
861 Y_Tiled => "Y_Tiled");
862
863 subtype Rotation_Name is String (1 .. 11);
864 type Rotation_Name_Array is array (Rotation_Type) of Rotation_Name;
865 Rotations : constant Rotation_Name_Array :=
866 (No_Rotation => "No_Rotation",
867 Rotated_90 => "Rotated_90 ",
868 Rotated_180 => "Rotated_180",
869 Rotated_270 => "Rotated_270");
Nico Huber83693c82016-10-08 22:17:55 +0200870 begin
871 Debug.New_Line;
Paul Menzelb83107c2017-05-04 09:02:33 +0200872 Debug.Put_Line ("CONFIG =>");
Nico Huber99f10f32016-11-20 00:34:05 +0100873 for Pipe in Pipe_Index loop
874 if Pipe = Pipe_Index'First then
Nico Huber83693c82016-10-08 22:17:55 +0200875 Debug.Put (" (");
876 else
877 Debug.Put (" ");
878 end if;
879 Debug.Put_Line (Pipe_Names (Pipe) & " =>");
880 Debug.Put_Line
881 (" (Port => " & Port_Names (Configs (Pipe).Port) & ",");
882 Debug.Put_Line (" Framebuffer =>");
Nico Huber5ef4d602017-12-13 13:56:47 +0100883 Debug.Put (" (Width => ");
Nico Huber83693c82016-10-08 22:17:55 +0200884 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Width);
885 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100886 Debug.Put (" Height => ");
Nico Huber83693c82016-10-08 22:17:55 +0200887 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Height);
888 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100889 Debug.Put (" Start_X => ");
890 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_X);
891 Debug.Put_Line (",");
892 Debug.Put (" Start_Y => ");
893 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Start_Y);
894 Debug.Put_Line (",");
895 Debug.Put (" Stride => ");
Nico Huber83693c82016-10-08 22:17:55 +0200896 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Stride);
897 Debug.Put_Line (",");
Nico Huber5ef4d602017-12-13 13:56:47 +0100898 Debug.Put (" V_Stride => ");
899 Debug.Put_Int32 (Configs (Pipe).Framebuffer.V_Stride);
900 Debug.Put_Line (",");
901 Debug.Put (" Tiling => ");
902 Debug.Put_Line (Tilings (Configs (Pipe).Framebuffer.Tiling) & ",");
903 Debug.Put (" Rotation => ");
904 Debug.Put_Line (Rotations (Configs (Pipe).Framebuffer.Rotation) & ",");
Nico Huber83693c82016-10-08 22:17:55 +0200905 Debug.Put (" Offset => ");
906 Debug.Put_Word32 (Configs (Pipe).Framebuffer.Offset);
907 Debug.Put_Line (",");
908 Debug.Put (" BPC => ");
909 Debug.Put_Int64 (Configs (Pipe).Framebuffer.BPC);
910 Debug.Put_Line ("),");
911 Debug.Put_Line (" Mode =>");
912 Debug.Put (" (Dotclock => ");
913 Debug.Put_Int64 (Configs (Pipe).Mode.Dotclock);
914 Debug.Put_Line (",");
915 Debug.Put (" H_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200916 Debug.Put_Int32 (Configs (Pipe).Mode.H_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200917 Debug.Put_Line (",");
918 Debug.Put (" H_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200919 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200920 Debug.Put_Line (",");
921 Debug.Put (" H_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200922 Debug.Put_Int32 (Configs (Pipe).Mode.H_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200923 Debug.Put_Line (",");
924 Debug.Put (" H_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200925 Debug.Put_Int32 (Configs (Pipe).Mode.H_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200926 Debug.Put_Line (",");
927 Debug.Put (" V_Visible => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200928 Debug.Put_Int32 (Configs (Pipe).Mode.V_Visible);
Nico Huber83693c82016-10-08 22:17:55 +0200929 Debug.Put_Line (",");
930 Debug.Put (" V_Sync_Begin => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200931 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_Begin);
Nico Huber83693c82016-10-08 22:17:55 +0200932 Debug.Put_Line (",");
933 Debug.Put (" V_Sync_End => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200934 Debug.Put_Int32 (Configs (Pipe).Mode.V_Sync_End);
Nico Huber83693c82016-10-08 22:17:55 +0200935 Debug.Put_Line (",");
936 Debug.Put (" V_Total => ");
Nico Huberc5c767a2018-06-03 01:09:04 +0200937 Debug.Put_Int32 (Configs (Pipe).Mode.V_Total);
Nico Huber83693c82016-10-08 22:17:55 +0200938 Debug.Put_Line (",");
939 Debug.Put_Line (" H_Sync_Active_High => " &
940 (if Configs (Pipe).Mode.H_Sync_Active_High
941 then "True,"
942 else "False,"));
943 Debug.Put_Line (" V_Sync_Active_High => " &
944 (if Configs (Pipe).Mode.V_Sync_Active_High
945 then "True,"
946 else "False,"));
947 Debug.Put (" BPC => ");
948 Debug.Put_Int64 (Configs (Pipe).Mode.BPC);
Nico Huber99f10f32016-11-20 00:34:05 +0100949 if Pipe /= Pipe_Index'Last then
Nico Huber83693c82016-10-08 22:17:55 +0200950 Debug.Put_Line (")),");
951 else
952 Debug.Put_Line (")));");
953 end if;
954 end loop;
955 end Dump_Configs;
956
Nico Huberc5c66ec2019-09-28 23:59:45 +0200957 ----------------------------------------------------------------------------
958
959 procedure PCI_Read16 (Value : out Word16; Offset : HW.PCI.Index) is
960 begin
961 Dev.Read16 (Value, Offset);
962 end PCI_Read16;
963
Nico Huber83693c82016-10-08 22:17:55 +0200964end HW.GFX.GMA;