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