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