blob: 3da0054beb2d1826806a9c0575b2e0d06a4ce148 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2015-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.GMA.PLLs.DPLL_0;
16with HW.GFX.GMA.PLLs.DPLL;
17
18with HW.Debug;
19with GNAT.Source_Info;
20
21package body HW.GFX.GMA.PLLs
22with
23 Refined_State => (State => PLLs)
24is
25
26 type Count_Range is new Natural range 0 .. 2;
27
28 type PLL_State is record
29 Use_Count : Count_Range;
30 Used_For_DP : Boolean;
31 Link_Rate : DP_Bandwidth;
32 Mode : Mode_Type;
33 end record;
34
35 type PLL_State_Array is array (Configurable_DPLLs) of PLL_State;
36
37 PLLs : PLL_State_Array;
38
39 procedure Initialize
40 is
41 begin
42 PLLs :=
43 (Configurable_DPLLs =>
44 (Use_Count => 0,
45 Used_For_DP => False,
46 Link_Rate => DP_Bandwidth'First,
47 Mode => Invalid_Mode));
48 end Initialize;
49
50 procedure Alloc_Configurable
51 (Port_Cfg : in Port_Config;
52 PLL : out T;
53 Success : out Boolean)
54 with
55 Pre => True
56 is
57 function Config_Matches (PE : PLL_State) return Boolean
58 is
59 begin
60 return
61 PE.Used_For_DP = (Port_Cfg.Display = DP) and
62 ((PE.Used_For_DP and PE.Link_Rate = Port_Cfg.DP.Bandwidth) or
63 (not PE.Used_For_DP and PE.Mode = Port_Cfg.Mode));
64 end Config_Matches;
65 begin
66 -- try to find shareable PLL
67 for P in Configurable_DPLLs loop
68 Success := PLLs (P).Use_Count /= 0 and
69 PLLs (P).Use_Count /= Count_Range'Last and
70 Config_Matches (PLLs (P));
71 if Success then
72 PLL := P;
73 PLLs (PLL).Use_Count := PLLs (PLL).Use_Count + 1;
74 return;
75 end if;
76 end loop;
77
78 -- try to find free PLL
79 for P in Configurable_DPLLs loop
80 if PLLs (P).Use_Count = 0 then
81 PLL := P;
82 DPLL.On (PLL, Port_Cfg, Success);
83 if Success then
84 PLLs (PLL) :=
85 (Use_Count => 1,
86 Used_For_DP => Port_Cfg.Display = DP,
87 Link_Rate => Port_Cfg.DP.Bandwidth,
88 Mode => Port_Cfg.Mode);
89 end if;
90 return;
91 end if;
92 end loop;
93
94 PLL := Invalid;
95 end Alloc_Configurable;
96
97 procedure Alloc
98 (Port_Cfg : in Port_Config;
99 PLL : out T;
100 Success : out Boolean)
101 is
102 begin
103 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
104
105 if Port_Cfg.Port = DIGI_A then
106 DPLL_0.Check_Link_Rate (Port_Cfg.DP.Bandwidth, Success);
107 else
108 Success := False;
109 end if;
110
111 if Success then
112 PLL := DPLL0;
113 else
114 Alloc_Configurable (Port_Cfg, PLL, Success);
115 end if;
116 end Alloc;
117
118 procedure Free (PLL : T)
119 is
120 begin
121 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
122
123 if PLL in Configurable_DPLLs then
124 if PLLs (PLL).Use_Count /= 0 then
125 PLLs (PLL).Use_Count := PLLs (PLL).Use_Count - 1;
126 if PLLs (PLL).Use_Count = 0 then
127 DPLL.Off (PLL);
128 end if;
129 end if;
130 end if;
131 end Free;
132
133 procedure All_Off
134 is
135 begin
136 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
137
138 for PLL in Configurable_DPLLs loop
139 DPLL.Off (PLL);
140 end loop;
141 end All_Off;
142
143 function Register_Value (PLL : T) return Word32
144 is
145 begin
146 return
147 (if PLL = DPLL0 then DPLL_0.Register_Value
148 elsif PLL in Configurable_DPLLs then DPLL.Register_Value (PLL)
149 else 0);
150 end Register_Value;
151
152end HW.GFX.GMA.PLLs;