blob: de30c4e2f17af57d065e00b5c7307859bf679102 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2014-2016 secunet Security Networks AG
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
6-- the Free Software Foundation; version 2 of the License.
7--
8-- This program is distributed in the hope that it will be useful,
9-- but WITHOUT ANY WARRANTY; without even the implied warranty of
10-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11-- GNU General Public License for more details.
12--
13
14with HW.GFX.EDID;
15with HW.GFX.GMA.Config;
16with HW.GFX.GMA.DP_Info;
17with HW.GFX.GMA.Registers;
18with HW.GFX.GMA.Power_And_Clocks;
19with HW.GFX.GMA.Panel;
20with HW.GFX.GMA.PLLs;
21with HW.GFX.GMA.Port_Detect;
22with HW.GFX.GMA.Connectors;
23with HW.GFX.GMA.Connector_Info;
24with HW.GFX.GMA.Pipe_Setup;
25
26with System;
27
28with HW.Debug;
29with GNAT.Source_Info;
30
31use type HW.Word8;
32use type HW.Int32;
33
34package body HW.GFX.GMA
35 with Refined_State =>
36 (State =>
37 (Registers.Address_State,
38 PLLs.State, Panel.Panel_State,
39 Cur_Configs, Allocated_PLLs, DP_Links,
40 HPD_Delay, Wait_For_HPD),
41 Init_State => Initialized,
42 Config_State => Config.Valid_Port_GPU,
43 Device_State =>
44 (Registers.Register_State, Registers.GTT_State))
45is
46
47 subtype Port_Name is String (1 .. 8);
48 type Port_Name_Array is array (Port_Type) of Port_Name;
49 Port_Names : constant Port_Name_Array :=
50 (Disabled => "Disabled",
51 Internal => "Internal",
52 DP1 => "DP1 ",
53 DP2 => "DP2 ",
54 DP3 => "DP3 ",
55 Digital1 => "Digital1",
56 Digital2 => "Digital2",
57 Digital3 => "Digital3",
58 Analog => "Analog ");
59
60 package Display_Controller renames Pipe_Setup;
61
62 type PLLs_Type is array (Config_Index) of PLLs.T;
63
64 type Links_Type is array (Config_Index) of DP_Link;
65
66 type HPD_Type is array (Port_Type) of Boolean;
67 type HPD_Delay_Type is array (Port_Type) of Time.T;
68
69 Cur_Configs : Configs_Type;
70 Allocated_PLLs : PLLs_Type;
71 DP_Links : Links_Type;
72 HPD_Delay : HPD_Delay_Type;
73 Wait_For_HPD : HPD_Type;
74 Initialized : Boolean := False;
75
76 subtype Active_Port_Type is Port_Type range Port_Type'Succ (Disabled) .. Port_Type'Last;
77
78 ----------------------------------------------------------------------------
79
80 function To_GPU_Port
81 (Configs : Configs_Type;
82 Idx : Config_Index)
83 return GPU_Port
84 is
85 begin
86 return
87 (case Config.CPU is
88 when Ironlake .. Ivybridge => -- everything but eDP through FDI/PCH
89 (if Config.Internal_Is_EDP and then Configs (Idx).Port = Internal
90 then
91 DIGI_A
92 else
93 (case Idx is
94 -- FDIs are fixed to the CPU pipe
95 when Primary => DIGI_B,
96 when Secondary => DIGI_C,
97 when Tertiary => DIGI_D)),
98 when Haswell .. Skylake => -- everything but VGA directly on CPU
99 (case Configs (Idx).Port is
100 when Disabled => GPU_Port'First,
101 when Internal => DIGI_A, -- LVDS not available
102 when Digital1 | DP1 => DIGI_B,
103 when Digital2 | DP2 => DIGI_C,
104 when Digital3 | DP3 => DIGI_D,
105 when Analog => DIGI_E));
106 end To_GPU_Port;
107
108 function To_PCH_Port (Port : Active_Port_Type) return PCH_Port
109 is
110 begin
111 return
112 (case Port is
113 when Internal => PCH_LVDS, -- will be ignored if Internal is DP
114 when Analog => PCH_DAC,
115 when Digital1 => PCH_HDMI_B,
116 when Digital2 => PCH_HDMI_C,
117 when Digital3 => PCH_HDMI_D,
118 when DP1 => PCH_DP_B,
119 when DP2 => PCH_DP_C,
120 when DP3 => PCH_DP_D);
121 end To_PCH_Port;
122
123 function To_Display_Type (Port : Active_Port_Type) return Display_Type
124 with Pre => True
125 is
126 begin
127 return
128 (case Port is
129 when Internal => Config.Internal_Display,
130 when Analog => VGA,
131 when Digital1 |
132 Digital2 |
133 Digital3 => HDMI,
134 when DP1 |
135 DP2 |
136 DP3 => DP);
137 end To_Display_Type;
138
139 procedure Configure_FDI_Link
140 (Port_Cfg : in out Port_Config;
141 Success : out Boolean)
142 with Pre => True
143 is
144 procedure Limit_Lane_Count
145 is
146 FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
147 Enabled : Boolean;
148 begin
149 -- if DIGI_D enabled: (FDI names are off by one)
150 Registers.Is_Set_Mask
151 (Register => Registers.FDI_TX_CTL_C,
152 Mask => FDI_TX_CTL_FDI_TX_ENABLE,
153 Result => Enabled);
154 if Enabled then
155 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
156 end if;
157 end Limit_Lane_Count;
158 begin
159 Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
160 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count :=
161 Config.FDI_Lane_Count (Port_Cfg.Port);
162 Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
163 if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
164 Limit_Lane_Count;
165 end if;
166 DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
167 end Configure_FDI_Link;
168
169 procedure Fill_Port_Config
170 (Port_Cfg : out Port_Config;
171 Configs : in Configs_Type;
172 Idx : in Config_Index;
173 Success : out Boolean)
174 with Pre => True
175 is
176 begin
177 Success :=
178 Config.Supported_Pipe (Idx) and then
179 Config.Valid_Port (Configs (Idx).Port) and then
180 Configs (Idx).Port /= Disabled;
181
182 if Success then
183 declare
184 Port : constant Port_Type := Configs (Idx).Port;
185 Mode : constant Mode_Type := Configs (Idx).Mode;
186 Link : constant DP_Link := DP_Links (Idx);
187 begin
188 Port_Cfg := Port_Config'
189 (Port => To_GPU_Port (Configs, Idx),
190 PCH_Port => To_PCH_Port (Port),
191 Display => To_Display_Type (Port),
192 Mode => Mode,
193 Is_FDI => Config.FDI_Port (To_GPU_Port (Configs, Idx)),
194 FDI => Default_DP,
195 DP => Link);
196 if Port_Cfg.Mode.BPC = Auto_BPC then
197 Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
198 end if;
199 end;
200 else
201 Port_Cfg := Port_Config'
202 (Port => GPU_Port'First,
203 PCH_Port => PCH_Port'First,
204 Display => Display_Type'First,
205 Mode => Invalid_Mode,
206 Is_FDI => False,
207 FDI => Default_DP,
208 DP => Default_DP);
209 end if;
210 end Fill_Port_Config;
211
212 ----------------------------------------------------------------------------
213
214 function To_Controller
215 (Dsp_Config : Config_Index) return Display_Controller.Controller_Type
216 is
217 Result : Display_Controller.Controller_Type;
218 begin
219 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
220
221 case Dsp_Config is
222 when Primary =>
223 Result := Display_Controller.Controllers (Display_Controller.A);
224 when Secondary =>
225 Result := Display_Controller.Controllers (Display_Controller.B);
226 when Tertiary =>
227 Result := Display_Controller.Controllers (Display_Controller.C);
228 end case;
229 return Result;
230 end To_Controller;
231
232 ----------------------------------------------------------------------------
233
234 function To_Head
235 (N_Config : Config_Index;
236 Port : Active_Port_Type)
237 return Display_Controller.Head_Type
238 is
239 Result : Display_Controller.Head_Type;
240 begin
241 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
242
243 if Config.Has_EDP_Pipe and then Port = Internal then
244 Result := Display_Controller.Heads (Display_Controller.Head_EDP);
245 else
246 case N_Config is
247 when Primary =>
248 Result := Display_Controller.Heads (Display_Controller.Head_A);
249 when Secondary =>
250 Result := Display_Controller.Heads (Display_Controller.Head_B);
251 when Tertiary =>
252 Result := Display_Controller.Heads (Display_Controller.Head_C);
253 end case;
254 end if;
255 return Result;
256 end To_Head;
257
258 ----------------------------------------------------------------------------
259
260 procedure Legacy_VGA_Off
261 is
262 Reg8 : Word8;
263 begin
264 -- disable legacy VGA plane, taking over control now
265 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
266 Port_IO.InB (Reg8, VGA_SR_DATA);
267 Port_IO.OutB (VGA_SR_DATA, Reg8 or 1 * 2 ** 5);
268 Time.U_Delay (100); -- PRM says 100us, Linux does 300
269 Registers.Set_Mask (Registers.VGACNTRL, 1 * 2 ** 31);
270 end Legacy_VGA_Off;
271
272 ----------------------------------------------------------------------------
273
274 function Port_Configured
275 (Configs : Configs_Type;
276 Port : Port_Type)
277 return Boolean
278 with
279 Global => null
280 is
281 begin
282 return Configs (Primary).Port = Port or
283 Configs (Secondary).Port = Port or
284 Configs (Tertiary).Port = Port;
285 end Port_Configured;
286
287 procedure Scan_Ports
288 (Configs : out Configs_Type;
289 Ports : in Port_List)
290 is
291 Raw_EDID : EDID.Raw_EDID_Data := (others => 16#00#);
292 Port_Idx : Port_List_Range := Port_List_Range'First;
293 Port_Cfg : Port_Config;
294 Success : Boolean := False;
295 begin
296 Configs := (Config_Index =>
297 (Port => Disabled,
298 Mode => Invalid_Mode,
299 Framebuffer => Default_FB));
300
301 for Config_Idx in Config_Index loop
302 while Ports (Port_Idx) /= Disabled loop
303 if not Port_Configured (Configs, Ports (Port_Idx)) then
304 Configs (Config_Idx).Port := Ports (Port_Idx);
305 Fill_Port_Config (Port_Cfg, Configs, Config_Idx, Success);
306
307 if Success then
308 -- May need power to probe port
309 if Port_Cfg.Display = DP then
310 Power_And_Clocks.Power_Up (Cur_Configs, Configs);
311 end if;
312 if Ports (Port_Idx) = Internal then
313 Panel.On;
314 end if;
315
316 Connector_Info.Read_EDID (Raw_EDID, Port_Cfg, Success);
317 end if;
318
319 if Success and then EDID.Has_Preferred_Mode (Raw_EDID) then
320 Configs (Config_Idx).Mode := EDID.Preferred_Mode (Raw_EDID);
321 else
322 Configs (Config_Idx).Port := Disabled;
323
324 if Ports (Port_Idx) = Internal and
325 not Port_Configured (Cur_Configs, Internal)
326 then
327 Panel.Off;
328 end if;
329 end if;
330 end if;
331
332 exit when Port_Idx = Port_List_Range'Last;
333 Port_Idx := Port_List_Range'Succ (Port_Idx);
334
335 exit when Success;
336 end loop;
337 end loop;
338
339 Power_And_Clocks.Power_Set_To (Cur_Configs);
340 end Scan_Ports;
341
342 procedure Auto_Configure
343 (Configs : in out Configs_Type;
344 Keep_Power : in Boolean := False)
345 is
346 Raw_EDID : EDID.Raw_EDID_Data := (others => 16#00#);
347 Success : Boolean;
348
349 Config_Idx : Config_Index;
350 Port_Cfg : Port_Config;
351
352 function Free_Config return Boolean
353 with
354 Pre => True
355 is
356 begin
357 return Port_Configured (Configs, Disabled);
358 end Free_Config;
359
360 function First_Free_Config return Config_Index
361 with
362 Pre => Free_Config
363 is
364 begin
365 return (if Configs (Primary).Port = Disabled then Primary else
366 (if Configs (Secondary).Port = Disabled then Secondary
367 else Tertiary));
368 end First_Free_Config;
369 begin
370 -- TODO: Only check ports with hot-plug event?
371
372 if Config.Has_Internal_Display and then
373 not Keep_Power and then
374 not Port_Configured (Cur_Configs, Internal)
375 then
376 Panel.On (Wait => False);
377 end if;
378
379 -- Check if displays are still connected
380 for I in Config_Index loop
381 if Configs (I).Port /= Disabled then
382 Fill_Port_Config (Port_Cfg, Configs, I, Success);
383 if Success then
384 Connector_Info.Read_EDID
385 (Raw_EDID => Raw_EDID,
386 Port_Cfg => Port_Cfg,
387 Success => Success);
388 end if;
389 if not Success or else
390 not EDID.Has_Preferred_Mode (Raw_EDID) or else
391 Configs (I).Mode /= EDID.Preferred_Mode (Raw_EDID)
392 then
393 Configs (I).Port := Disabled;
394 end if;
395 end if;
396 end loop;
397
398 -- Add new displays as long as there is a free pipe config
399 for Port in Active_Port_Type loop
400 if Free_Config and then not Port_Configured (Configs, Port) then
401 Config_Idx := First_Free_Config;
402 Configs (Config_Idx).Port := Port;
403 Fill_Port_Config (Port_Cfg, Configs, Config_Idx, Success);
404
405 if Success then
406 -- Need power to probe port
407 if not Keep_Power and then To_Display_Type (Port) = DP then
408 Power_And_Clocks.Power_Up (Cur_Configs, Configs);
409 end if;
410 if not Keep_Power and then Port = Internal then
411 Panel.Wait_On;
412 end if;
413
414 Connector_Info.Read_EDID
415 (Raw_EDID => Raw_EDID,
416 Port_Cfg => Port_Cfg,
417 Success => Success);
418 end if;
419
420 if Success and then EDID.Has_Preferred_Mode (Raw_EDID) then
421 Configs (Config_Idx) := Config_Type'
422 (Port => Port,
423 Framebuffer => Configs (Config_Idx).Framebuffer,
424 Mode => EDID.Preferred_Mode (Raw_EDID));
425 else
426 Configs (Config_Idx).Port := Disabled;
427 end if;
428 end if;
429 end loop;
430
431 if not Keep_Power then
432 Power_And_Clocks.Power_Set_To (Cur_Configs);
433
434 if Config.Has_Internal_Display and then
435 not Port_Configured (Cur_Configs, Internal)
436 then
437 Panel.Off;
438 end if;
439 end if;
440 end Auto_Configure;
441
442 ----------------------------------------------------------------------------
443
444 procedure Update_Outputs (Configs : Configs_Type)
445 is
446 Did_Power_Up : Boolean := False;
447
448 HPD, HPD_Delay_Over, Success : Boolean;
449 Old_Config, New_Config : Config_Type;
450 Old_Configs : Configs_Type;
451 Port_Cfg : Port_Config;
452
453 procedure Check_HPD
454 (Port_Cfg : in Port_Config;
455 Port : in Port_Type;
456 Detected : out Boolean)
457 is
458 begin
459 HPD_Delay_Over := Time.Timed_Out (HPD_Delay (Port));
460 if HPD_Delay_Over then
461 Port_Detect.Hotplug_Detect (Port_Cfg, Detected);
462 HPD_Delay (Port) := Time.MS_From_Now (333);
463 else
464 Detected := False;
465 end if;
466 end Check_HPD;
467 begin
468 Old_Configs := Cur_Configs;
469
470 for I in Config_Index loop
471 HPD := False;
472
473 Old_Config := Cur_Configs (I);
474 New_Config := Configs (I);
475
476 Fill_Port_Config (Port_Cfg, Old_Configs, I, Success);
477 if Success then
478 Check_HPD (Port_Cfg, Old_Config.Port, HPD);
479 end if;
480
481 -- Connector changed?
482 if (Success and then HPD) or
483 Old_Config.Port /= New_Config.Port or
484 Old_Config.Mode /= New_Config.Mode
485 then
486 if Old_Config.Port /= Disabled then
487 if Success then
488 pragma Debug (Debug.New_Line);
489 pragma Debug (Debug.Put_Line
490 ("Disabling port " & Port_Names (Old_Config.Port)));
491
492 Connectors.Pre_Off (Port_Cfg);
493
494 Display_Controller.Off
495 (To_Controller (I), To_Head (I, Old_Config.Port));
496
497 Connectors.Post_Off (Port_Cfg);
498 end if;
499
500 -- Free PLL
501 PLLs.Free (Allocated_PLLs (I));
502
503 Cur_Configs (I).Port := Disabled;
504 end if;
505
506 if New_Config.Port /= Disabled then
507 Fill_Port_Config (Port_Cfg, Configs, I, Success);
508
509 if Success and then Wait_For_HPD (New_Config.Port) then
510 Check_HPD (Port_Cfg, New_Config.Port, Success);
511 Wait_For_HPD (New_Config.Port) := not Success;
512 end if;
513
514 if Success then
515 pragma Debug (Debug.New_Line);
516 pragma Debug (Debug.Put_Line
517 ("Trying to enable port " & Port_Names (New_Config.Port)));
518
519 if not Did_Power_Up then
520 Power_And_Clocks.Power_Up (Old_Configs, Configs);
521 Did_Power_Up := True;
522 end if;
523
524 if Port_Cfg.Is_FDI then
525 Configure_FDI_Link (Port_Cfg, Success);
526 end if;
527 end if;
528
529 if Success then
530 Connector_Info.Preferred_Link_Setting
531 (Port_Cfg => Port_Cfg,
532 Success => Success);
533 end if;
534
535 while Success loop
536 pragma Loop_Invariant (New_Config.Port in Active_Port_Type);
537
538 PLLs.Alloc
539 (Port_Cfg => Port_Cfg,
540 PLL => Allocated_PLLs (I),
541 Success => Success);
542
543 if Success then
544 for Try in 1 .. 2 loop
545 pragma Loop_Invariant
546 (New_Config.Port in Active_Port_Type);
547
548 Connectors.Pre_On
549 (Port_Cfg => Port_Cfg,
550 PLL_Hint => PLLs.Register_Value
551 (Allocated_PLLs (I)),
552 Pipe_Hint => Display_Controller.Get_Pipe_Hint
553 (To_Head (I, New_Config.Port)),
554 Success => Success);
555
556 if Success then
557 Display_Controller.On
558 (Controller => To_Controller (I),
559 Head => To_Head (I, New_Config.Port),
560 Port_Cfg => Port_Cfg,
561 Framebuffer => New_Config.Framebuffer);
562
563 Connectors.Post_On
564 (Port_Cfg => Port_Cfg,
565 PLL_Hint => PLLs.Register_Value
566 (Allocated_PLLs (I)),
567 Success => Success);
568
569 if not Success then
570 Display_Controller.Off
571 (To_Controller (I),
572 To_Head (I, New_Config.Port));
573 Connectors.Post_Off (Port_Cfg);
574 end if;
575 end if;
576
577 exit when Success;
578 end loop;
579 exit when Success; -- connection established => stop loop
580
581 -- connection failed
582 PLLs.Free (Allocated_PLLs (I));
583 end if;
584
585 Connector_Info.Next_Link_Setting
586 (Port_Cfg => Port_Cfg,
587 Success => Success);
588 end loop;
589
590 if Success then
591 pragma Debug (Debug.Put_Line
592 ("Enabled port " & Port_Names (New_Config.Port)));
593 Cur_Configs (I) := New_Config;
594 DP_Links (I) := Port_Cfg.DP;
595 else
596 Wait_For_HPD (New_Config.Port) := True;
597 if New_Config.Port = Internal then
598 Panel.Off;
599 end if;
600 end if;
601 else
602 Cur_Configs (I) := New_Config;
603 end if;
604 elsif Old_Config.Framebuffer /= New_Config.Framebuffer and
605 Old_Config.Port /= Disabled
606 then
607 Display_Controller.Update_Offset
608 (Controller => To_Controller (I),
609 Framebuffer => New_Config.Framebuffer);
610 Cur_Configs (I) := New_Config;
611 end if;
612 end loop;
613
614 if Did_Power_Up then
615 Power_And_Clocks.Power_Down (Old_Configs, Configs, Cur_Configs);
616 end if;
617
618 end Update_Outputs;
619
620 ----------------------------------------------------------------------------
621
622 procedure Initialize
623 (MMIO_Base : in Word64 := 0;
624 Write_Delay : in Word64 := 0;
625 Success : out Boolean)
626 with
627 Refined_Global =>
628 (In_Out =>
629 (Config.Valid_Port_GPU,
630 Registers.Register_State, Port_IO.State),
631 Input =>
632 (Time.State),
633 Output =>
634 (Registers.Address_State,
635 PLLs.State, Panel.Panel_State,
636 Cur_Configs, Allocated_PLLs, DP_Links,
637 HPD_Delay, Wait_For_HPD, Initialized))
638 is
639 use type HW.Word64;
640
641 Now : constant Time.T := Time.Now;
642
643 procedure Check_Platform (Success : out Boolean)
644 is
645 Audio_VID_DID : Word32;
646 begin
647 case Config.CPU is
648 when Haswell .. Skylake =>
649 Registers.Read (Registers.AUD_VID_DID, Audio_VID_DID);
650 when Ironlake .. Ivybridge =>
651 Registers.Read (Registers.PCH_AUD_VID_DID, Audio_VID_DID);
652 end case;
653 Success :=
654 (case Config.CPU is
655 when Skylake => Audio_VID_DID = 16#8086_2809#,
656 when Broadwell => Audio_VID_DID = 16#8086_2808#,
657 when Haswell => Audio_VID_DID = 16#8086_2807#,
658 when Ivybridge |
659 Sandybridge => Audio_VID_DID = 16#8086_2806# or
660 Audio_VID_DID = 16#8086_2805#,
Nico Hubereeb5a392016-10-09 19:28:30 +0200661 when Ironlake => Audio_VID_DID = 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200662 end Check_Platform;
663 begin
664 pragma Warnings (GNATprove, Off, "unused variable ""Write_Delay""",
665 Reason => "Write_Delay is used for debugging only");
666
667 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
668
669 pragma Debug (Debug.Set_Register_Write_Delay (Write_Delay));
670
671 Wait_For_HPD := HPD_Type'(others => False);
672 HPD_Delay := HPD_Delay_Type'(others => Now);
673 DP_Links := Links_Type'(others => HW.GFX.Default_DP);
674 Allocated_PLLs := (others => PLLs.Invalid);
675 Cur_Configs := Configs_Type'
676 (others => Config_Type'
677 (Port => Disabled,
678 Framebuffer => HW.GFX.Default_FB,
679 Mode => HW.GFX.Invalid_Mode));
680 Registers.Set_Register_Base
681 (if MMIO_Base /= 0 then
682 MMIO_Base
683 else
684 Config.Default_MMIO_Base);
685 PLLs.Initialize;
686
687 Check_Platform (Success);
688 if not Success then
689 pragma Debug (Debug.Put_Line ("ERROR: Incompatible CPU or PCH."));
690
691 Panel.Static_Init; -- for flow analysis
692
693 Initialized := False;
694 return;
695 end if;
696
697 Panel.Setup_PP_Sequencer;
698 Port_Detect.Initialize;
699
700 Power_And_Clocks.Pre_All_Off;
701
702 Legacy_VGA_Off;
703
704 Connectors.Pre_All_Off;
705 Display_Controller.All_Off;
706 Connectors.Post_All_Off;
707 PLLs.All_Off;
708
709 Power_And_Clocks.Post_All_Off;
710
711 -------------------- Now restart from a clean state ---------------------
712 Power_And_Clocks.Initialize;
713
714 Initialized := True;
715
716 end Initialize;
717
718 function Is_Initialized return Boolean
719 with
720 Refined_Post => Is_Initialized'Result = Initialized
721 is
722 begin
723 return Initialized;
724 end Is_Initialized;
725
726 ----------------------------------------------------------------------------
727
728 procedure Write_GTT
729 (GTT_Page : GTT_Range;
730 Device_Address : GTT_Address_Type;
731 Valid : Boolean) is
732 begin
733 Registers.Write_GTT (GTT_Page, Device_Address, Valid);
734 end Write_GTT;
735
736 procedure Setup_Default_GTT (FB : Framebuffer_Type; Phys_FB : Word32)
737 is
738 FB_Size : constant Pos32 :=
739 FB.Stride * FB.Height * Pos32 (((FB.BPC * 4) / 8));
740 Phys_Addr : GTT_Address_Type := GTT_Address_Type (Phys_FB);
741 begin
742 for Idx in GTT_Range range 0 .. GTT_Range (((FB_Size + 4095) / 4096) - 1)
743 loop
744 Registers.Write_GTT
745 (GTT_Page => Idx,
746 Device_Address => Phys_Addr,
747 Valid => True);
748 Phys_Addr := Phys_Addr + 4096;
749 end loop;
750 end Setup_Default_GTT;
751
752 ----------------------------------------------------------------------------
753
754 procedure Dump_Configs (Configs : Configs_Type)
755 is
756 subtype Pipe_Name is String (1 .. 9);
757 type Pipe_Name_Array is array (Config_Index) of Pipe_Name;
758 Pipe_Names : constant Pipe_Name_Array :=
759 (Primary => "Primary ",
760 Secondary => "Secondary",
761 Tertiary => "Tertiary ");
762 begin
763 Debug.New_Line;
764 Debug.Put_Line ("CONFIG => ");
765 for Pipe in Config_Index loop
766 if Pipe = Config_Index'First then
767 Debug.Put (" (");
768 else
769 Debug.Put (" ");
770 end if;
771 Debug.Put_Line (Pipe_Names (Pipe) & " =>");
772 Debug.Put_Line
773 (" (Port => " & Port_Names (Configs (Pipe).Port) & ",");
774 Debug.Put_Line (" Framebuffer =>");
775 Debug.Put (" (Width => ");
776 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Width);
777 Debug.Put_Line (",");
778 Debug.Put (" Height => ");
779 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Height);
780 Debug.Put_Line (",");
781 Debug.Put (" Stride => ");
782 Debug.Put_Int32 (Configs (Pipe).Framebuffer.Stride);
783 Debug.Put_Line (",");
784 Debug.Put (" Offset => ");
785 Debug.Put_Word32 (Configs (Pipe).Framebuffer.Offset);
786 Debug.Put_Line (",");
787 Debug.Put (" BPC => ");
788 Debug.Put_Int64 (Configs (Pipe).Framebuffer.BPC);
789 Debug.Put_Line ("),");
790 Debug.Put_Line (" Mode =>");
791 Debug.Put (" (Dotclock => ");
792 Debug.Put_Int64 (Configs (Pipe).Mode.Dotclock);
793 Debug.Put_Line (",");
794 Debug.Put (" H_Visible => ");
795 Debug.Put_Int16 (Configs (Pipe).Mode.H_Visible);
796 Debug.Put_Line (",");
797 Debug.Put (" H_Sync_Begin => ");
798 Debug.Put_Int16 (Configs (Pipe).Mode.H_Sync_Begin);
799 Debug.Put_Line (",");
800 Debug.Put (" H_Sync_End => ");
801 Debug.Put_Int16 (Configs (Pipe).Mode.H_Sync_End);
802 Debug.Put_Line (",");
803 Debug.Put (" H_Total => ");
804 Debug.Put_Int16 (Configs (Pipe).Mode.H_Total);
805 Debug.Put_Line (",");
806 Debug.Put (" V_Visible => ");
807 Debug.Put_Int16 (Configs (Pipe).Mode.V_Visible);
808 Debug.Put_Line (",");
809 Debug.Put (" V_Sync_Begin => ");
810 Debug.Put_Int16 (Configs (Pipe).Mode.V_Sync_Begin);
811 Debug.Put_Line (",");
812 Debug.Put (" V_Sync_End => ");
813 Debug.Put_Int16 (Configs (Pipe).Mode.V_Sync_End);
814 Debug.Put_Line (",");
815 Debug.Put (" V_Total => ");
816 Debug.Put_Int16 (Configs (Pipe).Mode.V_Total);
817 Debug.Put_Line (",");
818 Debug.Put_Line (" H_Sync_Active_High => " &
819 (if Configs (Pipe).Mode.H_Sync_Active_High
820 then "True,"
821 else "False,"));
822 Debug.Put_Line (" V_Sync_Active_High => " &
823 (if Configs (Pipe).Mode.V_Sync_Active_High
824 then "True,"
825 else "False,"));
826 Debug.Put (" BPC => ");
827 Debug.Put_Int64 (Configs (Pipe).Mode.BPC);
828 if Pipe /= Config_Index'Last then
829 Debug.Put_Line (")),");
830 else
831 Debug.Put_Line (")));");
832 end if;
833 end loop;
834 end Dump_Configs;
835
836end HW.GFX.GMA;