blob: f9cbb10fe861f1db511d782bb54be0b01d52470a [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber3be61d42017-01-09 13:58:18 +01002-- Copyright (C) 2014-2017 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 Huber5374c3a2017-07-15 21:48:06 +020021with HW.GFX.Framebuffer_Filler;
22
Nico Huber83693c82016-10-08 22:17:55 +020023with HW.GFX.GMA.Config;
Nico Huber8c45bcf2016-11-20 17:30:57 +010024with HW.GFX.GMA.Config_Helpers;
Nico Huber83693c82016-10-08 22:17:55 +020025with HW.GFX.GMA.Registers;
26with HW.GFX.GMA.Power_And_Clocks;
27with HW.GFX.GMA.Panel;
28with HW.GFX.GMA.PLLs;
29with HW.GFX.GMA.Port_Detect;
30with HW.GFX.GMA.Connectors;
31with HW.GFX.GMA.Connector_Info;
32with HW.GFX.GMA.Pipe_Setup;
33
Nico Huber83693c82016-10-08 22:17:55 +020034with HW.Debug;
35with GNAT.Source_Info;
36
Nico Huber83693c82016-10-08 22:17:55 +020037use type HW.Int32;
38
39package body HW.GFX.GMA
40 with Refined_State =>
41 (State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020042 (Dev.Address_State,
43 Registers.Address_State,
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 Huber83693c82016-10-08 22:17:55 +020046 HPD_Delay, Wait_For_HPD),
47 Init_State => Initialized,
48 Config_State => Config.Valid_Port_GPU,
49 Device_State =>
Nico Huber2b6f6992017-07-09 18:11:34 +020050 (Dev.PCI_State, Registers.Register_State, Registers.GTT_State))
Nico Huber83693c82016-10-08 22:17:55 +020051is
Nico Huber2b6f6992017-07-09 18:11:34 +020052 pragma Disable_Atomic_Synchronization;
Nico Huber83693c82016-10-08 22:17:55 +020053
54 subtype Port_Name is String (1 .. 8);
55 type Port_Name_Array is array (Port_Type) of Port_Name;
56 Port_Names : constant Port_Name_Array :=
57 (Disabled => "Disabled",
58 Internal => "Internal",
59 DP1 => "DP1 ",
60 DP2 => "DP2 ",
61 DP3 => "DP3 ",
Nico Huber0d454cd2016-11-21 13:33:43 +010062 HDMI1 => "HDMI1 ",
63 HDMI2 => "HDMI2 ",
64 HDMI3 => "HDMI3 ",
Nico Huber83693c82016-10-08 22:17:55 +020065 Analog => "Analog ");
66
Nico Huber2b6f6992017-07-09 18:11:34 +020067 package Dev is new HW.PCI.Dev (PCI.Address'(0, 2, 0));
68
Nico Huber83693c82016-10-08 22:17:55 +020069 package Display_Controller renames Pipe_Setup;
70
Nico Huber99f10f32016-11-20 00:34:05 +010071 type PLLs_Type is array (Pipe_Index) of PLLs.T;
Nico Huber83693c82016-10-08 22:17:55 +020072
Nico Huber83693c82016-10-08 22:17:55 +020073 type HPD_Type is array (Port_Type) of Boolean;
Nico Huber3be61d42017-01-09 13:58:18 +010074 type HPD_Delay_Type is array (Active_Port_Type) of Time.T;
Nico Huber83693c82016-10-08 22:17:55 +020075
Nico Huber83693c82016-10-08 22:17:55 +020076 Allocated_PLLs : PLLs_Type;
Nico Huber83693c82016-10-08 22:17:55 +020077 HPD_Delay : HPD_Delay_Type;
78 Wait_For_HPD : HPD_Type;
79 Initialized : Boolean := False;
80
Nico Huber83693c82016-10-08 22:17:55 +020081 ----------------------------------------------------------------------------
82
Nico Huberf54d0962016-10-20 14:17:18 +020083 PCH_RAWCLK_FREQ_MASK : constant := 16#3ff# * 2 ** 0;
84
85 function PCH_RAWCLK_FREQ (Freq : Frequency_Type) return Word32
86 is
87 begin
88 return Word32 (Freq / 1_000_000);
89 end PCH_RAWCLK_FREQ;
90
91 ----------------------------------------------------------------------------
92
Nico Huber43370ba2017-01-09 15:26:19 +010093 procedure Enable_Output
94 (Pipe : in Pipe_Index;
95 Pipe_Cfg : in Pipe_Config;
96 Success : out Boolean)
97 is
98 Port_Cfg : Port_Config;
99 begin
Nico Huber3be61d42017-01-09 13:58:18 +0100100 pragma Debug (Debug.New_Line);
101 pragma Debug (Debug.Put_Line
102 ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
103
Nico Huber43370ba2017-01-09 15:26:19 +0100104 Config_Helpers.Fill_Port_Config
105 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
106
107 if Success then
108 Success := Config_Helpers.Validate_Config
109 (Pipe_Cfg.Framebuffer, Port_Cfg, Pipe);
110 end if;
111
Nico Huber43370ba2017-01-09 15:26:19 +0100112 if Success then
Nico Huber43370ba2017-01-09 15:26:19 +0100113 Connector_Info.Preferred_Link_Setting (Port_Cfg, Success);
114 end if;
115
116 -- loop over all possible DP-lane configurations
117 -- (non-DP ports use a single fake configuration)
118 while Success loop
119 pragma Loop_Invariant
120 (Pipe_Cfg.Port in Active_Port_Type and
121 Port_Cfg.Mode = Port_Cfg.Mode'Loop_Entry);
122
123 PLLs.Alloc
124 (Port_Cfg => Port_Cfg,
125 PLL => Allocated_PLLs (Pipe),
126 Success => Success);
127
128 if Success then
129 -- try each DP-lane configuration twice
130 for Try in 1 .. 2 loop
131 pragma Loop_Invariant
132 (Pipe_Cfg.Port in Active_Port_Type);
133
Nico Huber4798c662017-01-11 12:44:48 +0100134 -- Clear pending hot-plug events before every try
135 Port_Detect.Clear_Hotplug_Detect (Pipe_Cfg.Port);
136
Nico Huber43370ba2017-01-09 15:26:19 +0100137 Connectors.Pre_On
138 (Pipe => Pipe,
139 Port_Cfg => Port_Cfg,
140 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
141 Success => Success);
142
143 if Success then
144 Display_Controller.On
145 (Pipe => Pipe,
146 Port_Cfg => Port_Cfg,
147 Framebuffer => Pipe_Cfg.Framebuffer);
148
149 Connectors.Post_On
150 (Port_Cfg => Port_Cfg,
151 PLL_Hint => PLLs.Register_Value (Allocated_PLLs (Pipe)),
152 Success => Success);
153
154 if not Success then
155 Display_Controller.Off (Pipe);
156 Connectors.Post_Off (Port_Cfg);
157 end if;
158 end if;
159
160 exit when Success;
161 end loop;
162 exit when Success; -- connection established => stop loop
163
164 -- connection failed
165 PLLs.Free (Allocated_PLLs (Pipe));
166 end if;
167
168 Connector_Info.Next_Link_Setting (Port_Cfg, Success);
169 end loop;
170
171 if Success then
172 pragma Debug (Debug.Put_Line
173 ("Enabled port " & Port_Names (Pipe_Cfg.Port)));
174 else
175 Wait_For_HPD (Pipe_Cfg.Port) := True;
176 if Pipe_Cfg.Port = Internal then
177 Panel.Off;
178 end if;
179 end if;
180 end Enable_Output;
181
Nico Huber3be61d42017-01-09 13:58:18 +0100182 procedure Disable_Output (Pipe : Pipe_Index; Pipe_Cfg : Pipe_Config)
183 is
184 Port_Cfg : Port_Config;
185 Success : Boolean;
186 begin
187 Config_Helpers.Fill_Port_Config
188 (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
189 if Success then
190 pragma Debug (Debug.New_Line);
191 pragma Debug (Debug.Put_Line
192 ("Disabling port " & Port_Names (Pipe_Cfg.Port)));
193 pragma Debug (Debug.New_Line);
194
195 Connectors.Pre_Off (Port_Cfg);
196 Display_Controller.Off (Pipe);
197 Connectors.Post_Off (Port_Cfg);
198
199 PLLs.Free (Allocated_PLLs (Pipe));
200 end if;
201 end Disable_Output;
202
Nico Huber99f10f32016-11-20 00:34:05 +0100203 procedure Update_Outputs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200204 is
Nico Huber3be61d42017-01-09 13:58:18 +0100205 procedure Check_HPD (Port : in Active_Port_Type; Detected : out Boolean)
206 is
207 HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
208 begin
209 if HPD_Delay_Over then
210 Port_Detect.Hotplug_Detect (Port, Detected);
211 HPD_Delay (Port) := Time.MS_From_Now (333);
212 else
213 Detected := False;
214 end if;
215 end Check_HPD;
Nico Huberb56b9c52017-01-11 15:12:23 +0100216
Nico Huber564103f2017-01-11 15:33:07 +0100217 Power_Changed : Boolean := False;
Nico Huberb56b9c52017-01-11 15:12:23 +0100218 Old_Configs : Pipe_Configs;
Nico Huber564103f2017-01-11 15:33:07 +0100219
220 -- Only called when we actually tried to change something
221 -- so we don't congest the log with unnecessary messages.
222 procedure Update_Power
223 is
224 begin
225 if not Power_Changed then
226 Power_And_Clocks.Power_Up (Old_Configs, Configs);
227 Power_Changed := True;
228 end if;
229 end Update_Power;
Nico Huber83693c82016-10-08 22:17:55 +0200230 begin
231 Old_Configs := Cur_Configs;
232
Nico Huberb56b9c52017-01-11 15:12:23 +0100233 -- disable all pipes that changed or had a hot-plug event
234 for Pipe in Pipe_Index loop
235 declare
236 Unplug_Detected : Boolean;
237 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
238 New_Config : Pipe_Config renames Configs (Pipe);
239 begin
240 if Cur_Config.Port /= Disabled then
241 Check_HPD (Cur_Config.Port, Unplug_Detected);
Nico Huber83693c82016-10-08 22:17:55 +0200242
Nico Huberb56b9c52017-01-11 15:12:23 +0100243 if Cur_Config.Port /= New_Config.Port or
244 Cur_Config.Mode /= New_Config.Mode or
245 Unplug_Detected
246 then
247 Disable_Output (Pipe, Cur_Config);
248 Cur_Config.Port := Disabled;
Nico Huber564103f2017-01-11 15:33:07 +0100249 Update_Power;
Nico Huberb56b9c52017-01-11 15:12:23 +0100250 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200251 end if;
Nico Huberb56b9c52017-01-11 15:12:23 +0100252 end;
253 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200254
Nico Huberb56b9c52017-01-11 15:12:23 +0100255 -- enable all pipes that changed and should be active
256 for Pipe in Pipe_Index loop
257 declare
258 Success : Boolean;
259 Cur_Config : Pipe_Config renames Cur_Configs (Pipe);
260 New_Config : Pipe_Config renames Configs (Pipe);
261 begin
262 if New_Config.Port /= Disabled and then
263 (Cur_Config.Port /= New_Config.Port or
264 Cur_Config.Mode /= New_Config.Mode)
265 then
Nico Huber3be61d42017-01-09 13:58:18 +0100266 if Wait_For_HPD (New_Config.Port) then
267 Check_HPD (New_Config.Port, Success);
268 Wait_For_HPD (New_Config.Port) := not Success;
269 else
270 Success := True;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100271 end if;
Nico Huberc7a4fee2016-11-03 18:18:03 +0100272
Nico Huber3be61d42017-01-09 13:58:18 +0100273 if Success then
Nico Huber564103f2017-01-11 15:33:07 +0100274 Update_Power;
Nico Huberb56b9c52017-01-11 15:12:23 +0100275 Enable_Output (Pipe, New_Config, Success);
Nico Huber3be61d42017-01-09 13:58:18 +0100276 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200277
278 if Success then
Nico Huberb56b9c52017-01-11 15:12:23 +0100279 Cur_Config := New_Config;
Nico Huber83693c82016-10-08 22:17:55 +0200280 end if;
Nico Huber3be61d42017-01-09 13:58:18 +0100281
Nico Huberb56b9c52017-01-11 15:12:23 +0100282 -- update framebuffer offset only
283 elsif New_Config.Port /= Disabled and
284 Cur_Config.Framebuffer /= New_Config.Framebuffer
285 then
286 Display_Controller.Update_Offset (Pipe, New_Config.Framebuffer);
287 Cur_Config := New_Config;
288 end if;
289 end;
Nico Huber83693c82016-10-08 22:17:55 +0200290 end loop;
291
Nico Huber564103f2017-01-11 15:33:07 +0100292 if Power_Changed then
Nico Huber83693c82016-10-08 22:17:55 +0200293 Power_And_Clocks.Power_Down (Old_Configs, Configs, Cur_Configs);
294 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200295 end Update_Outputs;
296
297 ----------------------------------------------------------------------------
298
299 procedure Initialize
Nico Huber2b6f6992017-07-09 18:11:34 +0200300 (Write_Delay : in Word64 := 0;
Nico Huber793a8d42016-11-21 18:57:03 +0100301 Clean_State : in Boolean := False;
Nico Huber83693c82016-10-08 22:17:55 +0200302 Success : out Boolean)
303 with
304 Refined_Global =>
305 (In_Out =>
Nico Hubere015e822017-08-25 20:12:09 +0200306 (Config.Valid_Port_GPU, Dev.PCI_State,
Nico Huber83693c82016-10-08 22:17:55 +0200307 Registers.Register_State, Port_IO.State),
308 Input =>
309 (Time.State),
310 Output =>
Nico Huber2b6f6992017-07-09 18:11:34 +0200311 (Dev.Address_State,
312 Registers.Address_State,
Nico Huber83693c82016-10-08 22:17:55 +0200313 PLLs.State, Panel.Panel_State,
Nico Huber1a712d32017-01-09 15:11:04 +0100314 Cur_Configs, Allocated_PLLs,
Nico Huber83693c82016-10-08 22:17:55 +0200315 HPD_Delay, Wait_For_HPD, Initialized))
316 is
317 use type HW.Word64;
318
Nico Huber2b6f6992017-07-09 18:11:34 +0200319 PCI_MMIO_Base, PCI_GTT_Base : Word64;
320
Nico Huber83693c82016-10-08 22:17:55 +0200321 Now : constant Time.T := Time.Now;
322
323 procedure Check_Platform (Success : out Boolean)
324 is
325 Audio_VID_DID : Word32;
326 begin
327 case Config.CPU is
328 when Haswell .. Skylake =>
329 Registers.Read (Registers.AUD_VID_DID, Audio_VID_DID);
330 when Ironlake .. Ivybridge =>
331 Registers.Read (Registers.PCH_AUD_VID_DID, Audio_VID_DID);
332 end case;
333 Success :=
334 (case Config.CPU is
Nico Huber21da5742017-01-20 14:00:53 +0100335 when Broxton => Audio_VID_DID = 16#8086_280a#,
Nico Huber83693c82016-10-08 22:17:55 +0200336 when Skylake => Audio_VID_DID = 16#8086_2809#,
337 when Broadwell => Audio_VID_DID = 16#8086_2808#,
338 when Haswell => Audio_VID_DID = 16#8086_2807#,
339 when Ivybridge |
340 Sandybridge => Audio_VID_DID = 16#8086_2806# or
341 Audio_VID_DID = 16#8086_2805#,
Nico Hubereeb5a392016-10-09 19:28:30 +0200342 when Ironlake => Audio_VID_DID = 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200343 end Check_Platform;
344 begin
Nico Huber83693c82016-10-08 22:17:55 +0200345 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
346
347 pragma Debug (Debug.Set_Register_Write_Delay (Write_Delay));
348
349 Wait_For_HPD := HPD_Type'(others => False);
350 HPD_Delay := HPD_Delay_Type'(others => Now);
Nico Huber83693c82016-10-08 22:17:55 +0200351 Allocated_PLLs := (others => PLLs.Invalid);
Nico Huber99f10f32016-11-20 00:34:05 +0100352 Cur_Configs := Pipe_Configs'
353 (others => Pipe_Config'
Nico Huber83693c82016-10-08 22:17:55 +0200354 (Port => Disabled,
355 Framebuffer => HW.GFX.Default_FB,
356 Mode => HW.GFX.Invalid_Mode));
Nico Huber83693c82016-10-08 22:17:55 +0200357 PLLs.Initialize;
358
Nico Huber2b6f6992017-07-09 18:11:34 +0200359 Dev.Initialize (Success);
360
361 if Success then
362 Dev.Map (PCI_MMIO_Base, PCI.Res0, Length => Config.GTT_Offset);
363 Dev.Map (PCI_GTT_Base, PCI.Res0, Offset => Config.GTT_Offset);
364 if PCI_MMIO_Base /= 0 and PCI_GTT_Base /= 0 then
365 Registers.Set_Register_Base (PCI_MMIO_Base, PCI_GTT_Base);
366 else
367 pragma Debug (Debug.Put_Line
368 ("ERROR: Couldn't map resoure0."));
369 Registers.Set_Register_Base (Config.Default_MMIO_Base);
370 Success := Config.Default_MMIO_Base_Set;
371 end if;
372 else
373 pragma Debug (Debug.Put_Line
374 ("WARNING: Couldn't initialize PCI dev."));
375 Registers.Set_Register_Base (Config.Default_MMIO_Base);
376 Success := Config.Default_MMIO_Base_Set;
377 end if;
378
379 if Success then
380 Check_Platform (Success);
381 end if;
382
Nico Huber83693c82016-10-08 22:17:55 +0200383 if not Success then
384 pragma Debug (Debug.Put_Line ("ERROR: Incompatible CPU or PCH."));
385
386 Panel.Static_Init; -- for flow analysis
387
388 Initialized := False;
389 return;
390 end if;
391
392 Panel.Setup_PP_Sequencer;
393 Port_Detect.Initialize;
Nico Huber0923b792017-06-09 15:28:41 +0200394 Connectors.Initialize;
Nico Huber83693c82016-10-08 22:17:55 +0200395
Nico Huber793a8d42016-11-21 18:57:03 +0100396 if Clean_State then
397 Power_And_Clocks.Pre_All_Off;
398 Connectors.Pre_All_Off;
399 Display_Controller.All_Off;
400 Connectors.Post_All_Off;
401 PLLs.All_Off;
402 Power_And_Clocks.Post_All_Off;
Nico Huber17d64b62017-07-15 20:51:25 +0200403 Registers.Clear_Fences;
Nico Huber33912aa2016-12-06 20:36:23 +0100404 else
405 -- According to PRMs, VGA plane is the only thing
406 -- that's enabled by default after reset.
407 Display_Controller.Legacy_VGA_Off;
Nico Huber793a8d42016-11-21 18:57:03 +0100408 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200409
410 -------------------- Now restart from a clean state ---------------------
411 Power_And_Clocks.Initialize;
412
Nico Huber1c3b9282017-02-09 13:57:04 +0100413 if Config.Has_PCH then
414 Registers.Unset_And_Set_Mask
415 (Register => Registers.PCH_RAWCLK_FREQ,
416 Mask_Unset => PCH_RAWCLK_FREQ_MASK,
417 Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
418 end if;
Nico Huberf54d0962016-10-20 14:17:18 +0200419
Nico Huber83693c82016-10-08 22:17:55 +0200420 Initialized := True;
421
422 end Initialize;
423
424 function Is_Initialized return Boolean
425 with
426 Refined_Post => Is_Initialized'Result = Initialized
427 is
428 begin
429 return Initialized;
430 end Is_Initialized;
431
432 ----------------------------------------------------------------------------
433
Nico Huber5374c3a2017-07-15 21:48:06 +0200434 function FB_First_Page (FB : Framebuffer_Type) return Natural is
435 (Natural (FB.Offset / GTT_Page_Size));
436 function FB_Pages (FB : Framebuffer_Type) return Natural is
437 (Natural (Div_Round_Up (FB_Size (FB), GTT_Page_Size)));
438 function FB_Last_Page (FB : Framebuffer_Type) return Natural is
439 (FB_First_Page (FB) + FB_Pages (FB) - 1);
440
441 -- Check basics and that it fits in GTT
442 function Valid_FB (FB : Framebuffer_Type) return Boolean is
443 (FB.Width <= FB.Stride and FB_Last_Page (FB) <= GTT_Range'Last);
444
445 -- Also check that we don't overflow the GTT's 39-bit space
446 -- (always true with a 32-bit base)
447 function Valid_Phys_FB (FB : Framebuffer_Type; Phys_Base : Word32)
448 return Boolean is
449 (Valid_FB (FB) and
450 Int64 (Phys_Base) + Int64 (FB.Offset) + Int64 (FB_Size (FB)) <=
451 Int64 (GTT_Address_Type'Last))
452 with
453 Ghost;
454
Nico Huber83693c82016-10-08 22:17:55 +0200455 procedure Write_GTT
456 (GTT_Page : GTT_Range;
457 Device_Address : GTT_Address_Type;
Nico Huber5374c3a2017-07-15 21:48:06 +0200458 Valid : Boolean)
459 is
Nico Huber83693c82016-10-08 22:17:55 +0200460 begin
461 Registers.Write_GTT (GTT_Page, Device_Address, Valid);
462 end Write_GTT;
463
Nico Huber194e57e2017-07-15 21:15:46 +0200464 procedure Setup_Default_GTT (FB : Framebuffer_Type; Phys_Base : Word32)
Nico Huber5374c3a2017-07-15 21:48:06 +0200465 with
466 Pre => Is_Initialized and Valid_Phys_FB (FB, Phys_Base)
Nico Huber83693c82016-10-08 22:17:55 +0200467 is
Nico Huber194e57e2017-07-15 21:15:46 +0200468 Phys_Addr : GTT_Address_Type :=
469 GTT_Address_Type (Phys_Base) + GTT_Address_Type (FB.Offset);
Nico Huber83693c82016-10-08 22:17:55 +0200470 begin
Nico Huber194e57e2017-07-15 21:15:46 +0200471 for Idx in FB_First_Page (FB) .. FB_Last_Page (FB) loop
Nico Huber83693c82016-10-08 22:17:55 +0200472 Registers.Write_GTT
473 (GTT_Page => Idx,
474 Device_Address => Phys_Addr,
475 Valid => True);
Nico Huber194e57e2017-07-15 21:15:46 +0200476 Phys_Addr := Phys_Addr + GTT_Page_Size;
Nico Huber83693c82016-10-08 22:17:55 +0200477 end loop;
478 end Setup_Default_GTT;
479
480 ----------------------------------------------------------------------------
481
Nico Huber5374c3a2017-07-15 21:48:06 +0200482 procedure Setup_Default_FB
483 (FB : in Framebuffer_Type;
484 Clear : in Boolean := True;
485 Success : out Boolean)
486 is
487 GMA_Phys_Base : constant PCI.Index := 16#5c#;
488 GMA_Phys_Base_Mask : constant := 16#fff0_0000#;
489
490 Phys_Base : Word32;
491 begin
492 Success := Valid_FB (FB);
493
494 if Success then
495 Dev.Read32 (Phys_Base, GMA_Phys_Base);
496 Phys_Base := Phys_Base and GMA_Phys_Base_Mask;
497 Success := Phys_Base /= GMA_Phys_Base_Mask and Phys_Base /= 0;
498 pragma Debug (not Success, Debug.Put_Line
499 ("Failed to read stolen memory base."));
500 if Success then
501 Setup_Default_GTT (FB, Phys_Base);
502 end if;
503 end if;
504
505 if Success and then Clear then
506 declare
507 use type HW.Word64;
508 Linear_FB : Word64;
509 begin
510 Dev.Map (Linear_FB, PCI.Res2);
511 if Linear_FB /= 0 then
512 Framebuffer_Filler.Fill (Linear_FB + Word64 (FB.Offset), FB);
513 end if;
514 pragma Debug
515 (Linear_FB = 0, Debug.Put_Line ("Failed to map resource2."));
516 end;
517 end if;
518 end Setup_Default_FB;
519
520 ----------------------------------------------------------------------------
521
Nico Huber99f10f32016-11-20 00:34:05 +0100522 procedure Dump_Configs (Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200523 is
524 subtype Pipe_Name is String (1 .. 9);
Nico Huber99f10f32016-11-20 00:34:05 +0100525 type Pipe_Name_Array is array (Pipe_Index) of Pipe_Name;
Nico Huber83693c82016-10-08 22:17:55 +0200526 Pipe_Names : constant Pipe_Name_Array :=
527 (Primary => "Primary ",
528 Secondary => "Secondary",
529 Tertiary => "Tertiary ");
530 begin
531 Debug.New_Line;
Paul Menzelb83107c2017-05-04 09:02:33 +0200532 Debug.Put_Line ("CONFIG =>");
Nico Huber99f10f32016-11-20 00:34:05 +0100533 for Pipe in Pipe_Index loop
534 if Pipe = Pipe_Index'First then
Nico Huber83693c82016-10-08 22:17:55 +0200535 Debug.Put (" (");
536 else
537 Debug.Put (" ");
538 end if;
539 Debug.Put_Line (Pipe_Names (Pipe) & " =>");
540 Debug.Put_Line
541 (" (Port => " & Port_Names (Configs (Pipe).Port) & ",");
542 Debug.Put_Line (" Framebuffer =>");
543 Debug.Put (" (Width => ");
544 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Width);
545 Debug.Put_Line (",");
546 Debug.Put (" Height => ");
547 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Height);
548 Debug.Put_Line (",");
549 Debug.Put (" Stride => ");
550 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Stride);
551 Debug.Put_Line (",");
552 Debug.Put (" Offset => ");
553 Debug.Put_Word32 (Configs (Pipe).Framebuffer.Offset);
554 Debug.Put_Line (",");
555 Debug.Put (" BPC => ");
556 Debug.Put_Int64 (Configs (Pipe).Framebuffer.BPC);
557 Debug.Put_Line ("),");
558 Debug.Put_Line (" Mode =>");
559 Debug.Put (" (Dotclock => ");
560 Debug.Put_Int64 (Configs (Pipe).Mode.Dotclock);
561 Debug.Put_Line (",");
562 Debug.Put (" H_Visible => ");
563 Debug.Put_Int16 (Configs (Pipe).Mode.H_Visible);
564 Debug.Put_Line (",");
565 Debug.Put (" H_Sync_Begin => ");
566 Debug.Put_Int16 (Configs (Pipe).Mode.H_Sync_Begin);
567 Debug.Put_Line (",");
568 Debug.Put (" H_Sync_End => ");
569 Debug.Put_Int16 (Configs (Pipe).Mode.H_Sync_End);
570 Debug.Put_Line (",");
571 Debug.Put (" H_Total => ");
572 Debug.Put_Int16 (Configs (Pipe).Mode.H_Total);
573 Debug.Put_Line (",");
574 Debug.Put (" V_Visible => ");
575 Debug.Put_Int16 (Configs (Pipe).Mode.V_Visible);
576 Debug.Put_Line (",");
577 Debug.Put (" V_Sync_Begin => ");
578 Debug.Put_Int16 (Configs (Pipe).Mode.V_Sync_Begin);
579 Debug.Put_Line (",");
580 Debug.Put (" V_Sync_End => ");
581 Debug.Put_Int16 (Configs (Pipe).Mode.V_Sync_End);
582 Debug.Put_Line (",");
583 Debug.Put (" V_Total => ");
584 Debug.Put_Int16 (Configs (Pipe).Mode.V_Total);
585 Debug.Put_Line (",");
586 Debug.Put_Line (" H_Sync_Active_High => " &
587 (if Configs (Pipe).Mode.H_Sync_Active_High
588 then "True,"
589 else "False,"));
590 Debug.Put_Line (" V_Sync_Active_High => " &
591 (if Configs (Pipe).Mode.V_Sync_Active_High
592 then "True,"
593 else "False,"));
594 Debug.Put (" BPC => ");
595 Debug.Put_Int64 (Configs (Pipe).Mode.BPC);
Nico Huber99f10f32016-11-20 00:34:05 +0100596 if Pipe /= Pipe_Index'Last then
Nico Huber83693c82016-10-08 22:17:55 +0200597 Debug.Put_Line (")),");
598 else
599 Debug.Put_Line (")));");
600 end if;
601 end loop;
602 end Dump_Configs;
603
604end HW.GFX.GMA;