blob: ec7135904166f09de906097e1d1233ba2c4855b1 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber6b4678d2019-09-22 21:31:52 +02002-- Copyright (C) 2014-2016, 2019 secunet Security Networks AG
Nico Huber83693c82016-10-08 22:17:55 +02003--
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 GNAT.Source_Info;
16
17with HW.Time;
18with HW.Debug;
19with HW.GFX.GMA.Config;
20with HW.GFX.GMA.Registers;
Nico Huber312433c2019-09-28 03:15:48 +020021with HW.GFX.GMA.PCode;
Angel Pons3f86b0b2020-07-18 00:22:32 +020022with HW.GFX.GMA.Transcoder;
Nico Huber83693c82016-10-08 22:17:55 +020023
24use type HW.Word64;
25
Angel Pons3318bf22020-07-19 18:38:32 +020026package body HW.GFX.GMA.Power_And_Clocks is
Nico Huber83693c82016-10-08 22:17:55 +020027
28 type Power_Domain is (MISC_IO, PW1, PW2, DDI_AE, DDI_B, DDI_C, DDI_D);
29 subtype Power_Well is Power_Domain range PW1 .. PW2;
30 subtype Dynamic_Domain is Power_Domain range PW2 .. DDI_D;
31
32 NDE_RSTWRN_OPT_RST_PCH_Handshake_En : constant := 1 * 2 ** 4;
33
34 FUSE_STATUS_DOWNLOAD_STATUS : constant := 1 * 2 ** 31;
35 FUSE_STATUS_PG0_DIST_STATUS : constant := 1 * 2 ** 27;
36
Nico Huber6b4678d2019-09-22 21:31:52 +020037 DFSM_DISPLAY_CDCLK_LIMIT_675MHZ : constant := 0 * 2 ** 23;
38 DFSM_DISPLAY_CDCLK_LIMIT_540MHZ : constant := 1 * 2 ** 23;
39 DFSM_DISPLAY_CDCLK_LIMIT_450MHZ : constant := 2 * 2 ** 23;
40 DFSM_DISPLAY_CDCLK_LIMIT_337_5MHZ : constant := 3 * 2 ** 23;
41 DFSM_DISPLAY_CDCLK_LIMIT_MASK : constant := 3 * 2 ** 23;
42
Nico Huberdde06302020-12-20 02:18:30 +010043 SFUSE_STRAP_RAW_FREQUENCY : constant := 1 * 2 ** 8;
44
Nico Huber83693c82016-10-08 22:17:55 +020045 type Power_Domain_Values is array (Power_Domain) of Word32;
46 PWR_WELL_CTL_POWER_REQUEST : constant Power_Domain_Values :=
47 (MISC_IO => 1 * 2 ** 1,
48 DDI_AE => 1 * 2 ** 3,
49 DDI_B => 1 * 2 ** 5,
50 DDI_C => 1 * 2 ** 7,
51 DDI_D => 1 * 2 ** 9,
52 PW1 => 1 * 2 ** 29,
53 PW2 => 1 * 2 ** 31);
54 PWR_WELL_CTL_POWER_STATE : constant Power_Domain_Values :=
55 (MISC_IO => 1 * 2 ** 0,
56 DDI_AE => 1 * 2 ** 2,
57 DDI_B => 1 * 2 ** 4,
58 DDI_C => 1 * 2 ** 6,
59 DDI_D => 1 * 2 ** 8,
60 PW1 => 1 * 2 ** 28,
61 PW2 => 1 * 2 ** 30);
62
63 type Power_Well_Values is array (Power_Well) of Word32;
64 FUSE_STATUS_PGx_DIST_STATUS : constant Power_Well_Values :=
65 (PW1 => 1 * 2 ** 26,
66 PW2 => 1 * 2 ** 25);
67
68 DBUF_CTL_DBUF_POWER_REQUEST : constant := 1 * 2 ** 31;
69 DBUF_CTL_DBUF_POWER_STATE : constant := 1 * 2 ** 30;
70
71 ----------------------------------------------------------------------------
72
73 DPLL_CTRL1_DPLL0_LINK_RATE_MASK : constant := 7 * 2 ** 1;
74 DPLL_CTRL1_DPLL0_LINK_RATE_2700MHZ : constant := 0 * 2 ** 1;
75 DPLL_CTRL1_DPLL0_LINK_RATE_1350MHZ : constant := 1 * 2 ** 1;
76 DPLL_CTRL1_DPLL0_LINK_RATE_810MHZ : constant := 2 * 2 ** 1;
77 DPLL_CTRL1_DPLL0_LINK_RATE_1620MHZ : constant := 3 * 2 ** 1;
78 DPLL_CTRL1_DPLL0_LINK_RATE_1080MHZ : constant := 4 * 2 ** 1;
79 DPLL_CTRL1_DPLL0_LINK_RATE_2160MHZ : constant := 5 * 2 ** 1;
80 DPLL_CTRL1_DPLL0_OVERRIDE : constant := 1 * 2 ** 0;
81
82 LCPLL1_CTL_PLL_ENABLE : constant := 1 * 2 ** 31;
83 LCPLL1_CTL_PLL_LOCK : constant := 1 * 2 ** 30;
84
Angel Ponsae186bd2020-10-21 21:37:34 +020085 DISP_FBC_MEMORY_WAKE : constant := 1 * 2 ** 31;
86
Nico Huber83693c82016-10-08 22:17:55 +020087 ----------------------------------------------------------------------------
88
89 CDCLK_CTL_CD_FREQ_SELECT_MASK : constant := 3 * 2 ** 26;
90 CDCLK_CTL_CD_FREQ_SELECT_450MHZ : constant := 0 * 2 ** 26;
91 CDCLK_CTL_CD_FREQ_SELECT_540MHZ : constant := 1 * 2 ** 26;
92 CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ : constant := 2 * 2 ** 26;
93 CDCLK_CTL_CD_FREQ_SELECT_675MHZ : constant := 3 * 2 ** 26;
94 CDCLK_CTL_CD_FREQ_DECIMAL_MASK : constant := 16#7ff#;
95
96 SKL_PCODE_CDCLK_CONTROL : constant := 7;
97 SKL_CDCLK_PREPARE_FOR_CHANGE : constant := 3;
98 SKL_CDCLK_READY_FOR_CHANGE : constant := 1;
99
Nico Huber6b4678d2019-09-22 21:31:52 +0200100 function CDCLK_CTL_CD_FREQ_DECIMAL (CDClk : Frequency_Type) return Word32 is
Nico Huber83693c82016-10-08 22:17:55 +0200101 begin
Nico Huber6b4678d2019-09-22 21:31:52 +0200102 -- Weirdest representation: CDClk - 1MHz in 10.1 (10 + 1 fractional bit)
103 return Word32 ((CDClk - 1_000_000) / 500_000);
Nico Huber83693c82016-10-08 22:17:55 +0200104 end CDCLK_CTL_CD_FREQ_DECIMAL;
105
106 ----------------------------------------------------------------------------
107
Nico Huber83693c82016-10-08 22:17:55 +0200108 procedure PD_Off (PD : Power_Domain)
109 is
110 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
111 begin
112 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
113
114 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
115 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
116 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
117 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
118 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
119 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
120
121 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
122 PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0
123 then
124 Registers.Wait_Set_Mask
125 (Register => Registers.PWR_WELL_CTL_DRIVER,
126 Mask => PWR_WELL_CTL_POWER_STATE (PD));
127 end if;
128
129 if (Ctl1 and PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0 then
130 Registers.Unset_Mask
131 (Register => Registers.PWR_WELL_CTL_BIOS,
132 Mask => PWR_WELL_CTL_POWER_REQUEST (PD));
133 end if;
134
135 if (Ctl2 and PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0 then
136 Registers.Unset_Mask
137 (Register => Registers.PWR_WELL_CTL_DRIVER,
138 Mask => PWR_WELL_CTL_POWER_REQUEST (PD));
139 end if;
140 end PD_Off;
141
142 procedure PD_On (PD : Power_Domain)
143 with
144 Pre => True
145 is
146 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
147 begin
148 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
149
150 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
151 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
152 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
153 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
154 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
155 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
156
157 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
158 PWR_WELL_CTL_POWER_REQUEST (PD)) = 0
159 then
160 Registers.Wait_Unset_Mask
161 (Register => Registers.PWR_WELL_CTL_DRIVER,
162 Mask => PWR_WELL_CTL_POWER_STATE (PD));
163 end if;
164
165 if (Ctl2 and PWR_WELL_CTL_POWER_REQUEST (PD)) = 0 then
166 Registers.Set_Mask
167 (Register => Registers.PWR_WELL_CTL_DRIVER,
168 Mask => PWR_WELL_CTL_POWER_REQUEST (PD));
169 Registers.Wait_Set_Mask
170 (Register => Registers.PWR_WELL_CTL_DRIVER,
171 Mask => PWR_WELL_CTL_POWER_STATE (PD));
172
173 if PD in Power_Well then
174 Registers.Wait_Set_Mask
175 (Register => Registers.FUSE_STATUS,
176 Mask => FUSE_STATUS_PGx_DIST_STATUS (PD));
177 end if;
178 end if;
179 end PD_On;
180
Nico Huber99f10f32016-11-20 00:34:05 +0100181 function Need_PD (PD : Dynamic_Domain; Configs : Pipe_Configs) return Boolean
Nico Huber83693c82016-10-08 22:17:55 +0200182 is
183 begin
184 return (case PD is
Nico Huber8beafd72020-01-07 14:59:44 +0100185 when DDI_AE => Configs (Primary).Port = eDP or
186 Configs (Secondary).Port = eDP or
187 Configs (Tertiary).Port = eDP,
Nico Huber0d454cd2016-11-21 13:33:43 +0100188 when DDI_B => Configs (Primary).Port = HDMI1 or
Nico Huber83693c82016-10-08 22:17:55 +0200189 Configs (Primary).Port = DP1 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100190 Configs (Secondary).Port = HDMI1 or
Nico Huber83693c82016-10-08 22:17:55 +0200191 Configs (Secondary).Port = DP1 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100192 Configs (Tertiary).Port = HDMI1 or
Nico Huber83693c82016-10-08 22:17:55 +0200193 Configs (Tertiary).Port = DP1,
Nico Huber0d454cd2016-11-21 13:33:43 +0100194 when DDI_C => Configs (Primary).Port = HDMI2 or
Nico Huber83693c82016-10-08 22:17:55 +0200195 Configs (Primary).Port = DP2 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100196 Configs (Secondary).Port = HDMI2 or
Nico Huber83693c82016-10-08 22:17:55 +0200197 Configs (Secondary).Port = DP2 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100198 Configs (Tertiary).Port = HDMI2 or
Nico Huber83693c82016-10-08 22:17:55 +0200199 Configs (Tertiary).Port = DP2,
Nico Huber0d454cd2016-11-21 13:33:43 +0100200 when DDI_D => Configs (Primary).Port = HDMI3 or
Nico Huber83693c82016-10-08 22:17:55 +0200201 Configs (Primary).Port = DP3 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100202 Configs (Secondary).Port = HDMI3 or
Nico Huber83693c82016-10-08 22:17:55 +0200203 Configs (Secondary).Port = DP3 or
Nico Huber0d454cd2016-11-21 13:33:43 +0100204 Configs (Tertiary).Port = HDMI3 or
Nico Huber83693c82016-10-08 22:17:55 +0200205 Configs (Tertiary).Port = DP3,
206 when PW2 => (Configs (Primary).Port /= Disabled and
Nico Huber8beafd72020-01-07 14:59:44 +0100207 Configs (Primary).Port /= eDP) or
Nico Huber83693c82016-10-08 22:17:55 +0200208 Configs (Secondary).Port /= Disabled or
209 Configs (Tertiary).Port /= Disabled);
210 end Need_PD;
211
212 ----------------------------------------------------------------------------
213
214 procedure Pre_All_Off is
215 begin
Angel Pons3f86b0b2020-07-18 00:22:32 +0200216 Transcoder.PSR_Off;
Nico Huber83693c82016-10-08 22:17:55 +0200217 end Pre_All_Off;
218
219 procedure Post_All_Off is
220 begin
221 for PD in reverse Dynamic_Domain loop
222 PD_Off (PD);
223 end loop;
224
225 Registers.Unset_Mask
226 (Register => Registers.DBUF_CTL,
227 Mask => DBUF_CTL_DBUF_POWER_REQUEST);
228 Registers.Wait_Unset_Mask
229 (Register => Registers.DBUF_CTL,
230 Mask => DBUF_CTL_DBUF_POWER_STATE);
231
232 Registers.Unset_Mask
233 (Register => Registers.LCPLL1_CTL,
234 Mask => LCPLL1_CTL_PLL_ENABLE);
235 Registers.Wait_Unset_Mask
236 (Register => Registers.LCPLL1_CTL,
237 Mask => LCPLL1_CTL_PLL_LOCK);
238
239 PD_Off (MISC_IO);
240 PD_Off (PW1);
241 end Post_All_Off;
242
Nico Huber6b4678d2019-09-22 21:31:52 +0200243 function Normalize_CDClk (CDClk : in Int64) return Config.CDClk_Range is
244 ( if CDClk <= 337_500_000 then 337_500_000
245 elsif CDClk <= 450_000_000 then 450_000_000
246 elsif CDClk <= 540_000_000 then 540_000_000
247 else 675_000_000);
248
249 procedure Get_Cur_CDClk (CDClk : out Config.CDClk_Range)
Nico Huber83693c82016-10-08 22:17:55 +0200250 is
Nico Huber6b4678d2019-09-22 21:31:52 +0200251 CDCLK_CTL : Word32;
252 begin
253 Registers.Read (Registers.CDCLK_CTL, CDCLK_CTL);
254 CDCLK_CTL := CDCLK_CTL and CDCLK_CTL_CD_FREQ_DECIMAL_MASK;
255 CDClk := Normalize_CDClk (Int64 (CDCLK_CTL) * 500_000 + 1_000_000);
256 end Get_Cur_CDClk;
257
258 procedure Get_Max_CDClk (CDClk : out Config.CDClk_Range)
259 is
260 DFSM : Word32;
261 begin
262 Registers.Read (Registers.DFSM, DFSM);
263 CDClk :=
264 (case DFSM and DFSM_DISPLAY_CDCLK_LIMIT_MASK is
265 when DFSM_DISPLAY_CDCLK_LIMIT_675MHZ => 675_000_000,
266 when DFSM_DISPLAY_CDCLK_LIMIT_540MHZ => 540_000_000,
267 when DFSM_DISPLAY_CDCLK_LIMIT_450MHZ => 450_000_000,
268 when others => 337_500_000);
269 end Get_Max_CDClk;
270
271 procedure Set_CDClk (CDClk_In : Frequency_Type)
272 is
273 CDClk : constant Config.CDClk_Range :=
274 Normalize_CDClk (Frequency_Type'Min (CDClk_In, Config.Max_CDClk));
Nico Huber312433c2019-09-28 03:15:48 +0200275 Success : Boolean;
Nico Huber83693c82016-10-08 22:17:55 +0200276 begin
Nico Huber6b4678d2019-09-22 21:31:52 +0200277 PCode.Mailbox_Request
278 (MBox => SKL_PCODE_CDCLK_CONTROL,
279 Command => SKL_CDCLK_PREPARE_FOR_CHANGE,
280 Reply_Mask => SKL_CDCLK_READY_FOR_CHANGE,
281 Wait_Ready => True,
282 Success => Success);
283
284 if not Success then
285 pragma Debug (Debug.Put_Line
286 ("ERROR: PCODE not ready for frequency change."));
287 return;
288 end if;
289
290 Registers.Write
291 (Register => Registers.CDCLK_CTL,
292 Value => (case CDClk is
293 when 675_000_000 => CDCLK_CTL_CD_FREQ_SELECT_675MHZ,
294 when 540_000_000 => CDCLK_CTL_CD_FREQ_SELECT_540MHZ,
295 when 450_000_000 => CDCLK_CTL_CD_FREQ_SELECT_450MHZ,
296 when others => CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ)
297 or CDCLK_CTL_CD_FREQ_DECIMAL (CDClk));
298
299 PCode.Mailbox_Write
300 (MBox => SKL_PCODE_CDCLK_CONTROL,
301 Command => (case CDClk is
302 when 675_000_000 => 3,
303 when 540_000_000 => 2,
304 when 450_000_000 => 1,
305 when others => 0));
306 Registers.Set_Mask
307 (Register => Registers.DBUF_CTL,
308 Mask => DBUF_CTL_DBUF_POWER_REQUEST);
309 Registers.Wait_Set_Mask
310 (Register => Registers.DBUF_CTL,
311 Mask => DBUF_CTL_DBUF_POWER_STATE);
312
313 Config.CDClk := CDClk;
314 end Set_CDClk;
315
Nico Huberdde06302020-12-20 02:18:30 +0100316 procedure Get_Raw_Clock (Raw_Clock : out Frequency_Type)
317 is
318 Freq_24MHz : Boolean;
319 begin
320 Raw_Clock := Config.Default_RawClk_Freq;
321 if Config.Has_Fractional_RawClk then
322 Registers.Is_Set_Mask
323 (Register => Registers.SFUSE_STRAP,
324 Mask => SFUSE_STRAP_RAW_FREQUENCY,
325 Result => Freq_24MHz);
326 if not Freq_24MHz then
327 Raw_Clock := 19_200_000;
328 end if;
329 end if;
330 end Get_Raw_Clock;
331
Nico Huber6b4678d2019-09-22 21:31:52 +0200332 procedure Initialize is
333 begin
Nico Huber83693c82016-10-08 22:17:55 +0200334 Registers.Set_Mask
335 (Register => Registers.NDE_RSTWRN_OPT,
336 Mask => NDE_RSTWRN_OPT_RST_PCH_Handshake_En);
337
338 Registers.Wait_Set_Mask
339 (Register => Registers.FUSE_STATUS,
340 Mask => FUSE_STATUS_PG0_DIST_STATUS);
341 PD_On (PW1);
342 PD_On (MISC_IO);
343
Nico Huber83693c82016-10-08 22:17:55 +0200344 -- TODO: Set to preferred eDP rate:
345 -- Registers.Unset_And_Set_Mask
346 -- (Register => Registers.DPLL_CTRL1,
347 -- Unset_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_MASK,
348 -- Set_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_...);
349 Registers.Set_Mask
350 (Register => Registers.LCPLL1_CTL,
351 Mask => LCPLL1_CTL_PLL_ENABLE);
352 Registers.Wait_Set_Mask
353 (Register => Registers.LCPLL1_CTL,
354 Mask => LCPLL1_CTL_PLL_LOCK);
355
Angel Ponsae186bd2020-10-21 21:37:34 +0200356 -- WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl
357 Registers.Set_Mask
358 (Register => Registers.GEN8_CHICKEN_DCPR_1,
359 Mask => 1 * 2 ** 13);
360
361 -- Display WA #0859 WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl
362 Registers.Set_Mask
363 (Register => Registers.ARB_CTL,
364 Mask => DISP_FBC_MEMORY_WAKE);
365
Nico Huber6b4678d2019-09-22 21:31:52 +0200366 Get_Cur_CDClk (Config.CDClk);
367 Get_Max_CDClk (Config.Max_CDClk);
368 Set_CDClk (Config.Default_CDClk_Freq);
Arthur Heymansd1988d12018-03-28 16:27:57 +0200369
Nico Huberdde06302020-12-20 02:18:30 +0100370 Get_Raw_Clock (Config.Raw_Clock);
Nico Huber83693c82016-10-08 22:17:55 +0200371 end Initialize;
372
Nico Huber6b4678d2019-09-22 21:31:52 +0200373 procedure Limit_Dotclocks
374 (Configs : in out Pipe_Configs;
375 CDClk_Switch : out Boolean)
376 is
377 begin
378 Config_Helpers.Limit_Dotclocks (Configs, Config.Max_CDClk);
379 CDClk_Switch :=
380 Config.CDClk /= Normalize_CDClk
381 (Config_Helpers.Highest_Dotclock (Configs));
382 end Limit_Dotclocks;
383
384 procedure Update_CDClk (Configs : in out Pipe_Configs)
385 is
386 New_CDClk : constant Frequency_Type :=
387 Config_Helpers.Highest_Dotclock (Configs);
388 begin
389 Set_CDClk (New_CDClk);
390 Config_Helpers.Limit_Dotclocks (Configs, Config.CDClk);
391 end Update_CDClk;
392
Nico Huber99f10f32016-11-20 00:34:05 +0100393 procedure Power_Set_To (Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200394 begin
395 for PD in reverse Dynamic_Domain loop
396 if not Need_PD (PD, Configs) then
397 PD_Off (PD);
398 end if;
399 end loop;
400 for PD in Dynamic_Domain loop
401 if Need_PD (PD, Configs) then
402 PD_On (PD);
403 end if;
404 end loop;
405 end Power_Set_To;
406
Nico Huber99f10f32016-11-20 00:34:05 +0100407 procedure Power_Up (Old_Configs, New_Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200408 begin
409 for PD in Dynamic_Domain loop
410 if not Need_PD (PD, Old_Configs) and Need_PD (PD, New_Configs) then
411 PD_On (PD);
412 end if;
413 end loop;
414 end Power_Up;
415
Nico Huber99f10f32016-11-20 00:34:05 +0100416 procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200417 is
418 begin
419 for PD in reverse Dynamic_Domain loop
420 if (Need_PD (PD, Old_Configs) or Need_PD (PD, Tmp_Configs)) and
421 not Need_PD (PD, New_Configs)
422 then
423 PD_Off (PD);
424 end if;
425 end loop;
426 end Power_Down;
427
Angel Pons3318bf22020-07-19 18:38:32 +0200428end HW.GFX.GMA.Power_And_Clocks;