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