blob: 332c3dfa06c3dae4d497997d694cc3faf29932c1 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber3d06de82018-05-29 01:35:04 +02002-- Copyright (C) 2014-2018 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;
Nico Huber312433c2019-09-28 03:15:48 +020020with HW.GFX.GMA.PCode;
Nico Huber83693c82016-10-08 22:17:55 +020021with HW.GFX.GMA.Registers;
22
23package body HW.GFX.GMA.Power_And_Clocks_Haswell is
24
25 PWR_WELL_CTL_ENABLE_REQUEST : constant := 1 * 2 ** 31;
26 PWR_WELL_CTL_DISABLE_REQUEST : constant := 0 * 2 ** 31;
27 PWR_WELL_CTL_STATE_ENABLED : constant := 1 * 2 ** 30;
28
29 ----------------------------------------------------------------------------
30
31 SRD_CTL_ENABLE : constant := 1 * 2 ** 31;
32 SRD_STATUS_STATE_MASK : constant := 7 * 2 ** 29;
33
34 type Pipe is (EDP, A, B, C);
35 type SRD_Regs is record
36 CTL : Registers.Registers_Index;
37 STATUS : Registers.Registers_Index;
38 end record;
39 type SRD_Per_Pipe_Regs is array (Pipe) of SRD_Regs;
40 SRD : constant SRD_Per_Pipe_Regs := SRD_Per_Pipe_Regs'
41 (A => SRD_Regs'
42 (CTL => Registers.SRD_CTL_A,
43 STATUS => Registers.SRD_STATUS_A),
44 B => SRD_Regs'
45 (CTL => Registers.SRD_CTL_B,
46 STATUS => Registers.SRD_STATUS_B),
47 C => SRD_Regs'
48 (CTL => Registers.SRD_CTL_C,
49 STATUS => Registers.SRD_STATUS_C),
50 EDP => SRD_Regs'
51 (CTL => Registers.SRD_CTL_EDP,
52 STATUS => Registers.SRD_STATUS_EDP));
53
54 ----------------------------------------------------------------------------
55
56 IPS_CTL_ENABLE : constant := 1 * 2 ** 31;
57 DISPLAY_IPS_CONTROL : constant := 16#19#;
58
Nico Huber83693c82016-10-08 22:17:55 +020059 ----------------------------------------------------------------------------
60
61 procedure PSR_Off
62 is
63 Enabled : Boolean;
64 begin
65 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
66
67 if Config.Has_Per_Pipe_SRD then
68 for P in Pipe loop
69 Registers.Is_Set_Mask (SRD (P).CTL, SRD_CTL_ENABLE, Enabled);
70 if Enabled then
71 Registers.Unset_Mask (SRD (P).CTL, SRD_CTL_ENABLE);
72 Registers.Wait_Unset_Mask (SRD (P).STATUS, SRD_STATUS_STATE_MASK);
73
74 pragma Debug (Debug.Put_Line ("Disabled PSR."));
75 end if;
76 end loop;
77 else
78 Registers.Is_Set_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE, Enabled);
79 if Enabled then
80 Registers.Unset_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE);
81 Registers.Wait_Unset_Mask (Registers.SRD_STATUS, SRD_STATUS_STATE_MASK);
82
83 pragma Debug (Debug.Put_Line ("Disabled PSR."));
84 end if;
85 end if;
86 end PSR_Off;
87
88 ----------------------------------------------------------------------------
89
Nico Huber83693c82016-10-08 22:17:55 +020090 procedure IPS_Off
91 is
92 Enabled : Boolean;
93 begin
94 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
95
96 if Config.Has_IPS then
97 Registers.Is_Set_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE, Enabled);
98 if Enabled then
99 if Config.Has_IPS_CTL_Mailbox then
Nico Huber312433c2019-09-28 03:15:48 +0200100 PCode.Mailbox_Write (DISPLAY_IPS_CONTROL, 0, Wait_Ready => True);
Nico Huber43cf8d52016-09-08 17:24:52 +0200101 Registers.Wait_Unset_Mask
102 (Register => Registers.IPS_CTL,
103 Mask => IPS_CTL_ENABLE,
104 TOut_MS => 42);
Nico Huber83693c82016-10-08 22:17:55 +0200105 else
106 Registers.Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
107 end if;
108
109 pragma Debug (Debug.Put_Line ("Disabled IPS."));
110 -- We have to wait until the next vblank here.
111 -- 20ms should be enough.
112 Time.M_Delay (20);
113 end if;
114 end if;
115 end IPS_Off;
116
117 ----------------------------------------------------------------------------
118
119 procedure PDW_Off
120 is
121 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
122 begin
123 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
124
125 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
126 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
127 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
128 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
129 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
130 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
131
132 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
133 PWR_WELL_CTL_ENABLE_REQUEST) /= 0
134 then
135 Registers.Wait_Set_Mask
136 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
137 end if;
138
139 if (Ctl1 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
140 Registers.Write (Registers.PWR_WELL_CTL_BIOS, PWR_WELL_CTL_DISABLE_REQUEST);
141 end if;
142
143 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
144 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_DISABLE_REQUEST);
145 end if;
146 end PDW_Off;
147
148 procedure PDW_On
149 is
150 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
151 begin
152 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
153
154 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
155 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
156 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
157 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
158 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
159 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
160
161 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
162 PWR_WELL_CTL_ENABLE_REQUEST) = 0
163 then
164 Registers.Wait_Unset_Mask
165 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
166 end if;
167
168 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) = 0 then
169 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_ENABLE_REQUEST);
170 Registers.Wait_Set_Mask
171 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
172 end if;
173 end PDW_On;
174
Nico Huber3d06de82018-05-29 01:35:04 +0200175 function Need_PDW (Checked_Configs : Pipe_Configs) return Boolean
176 is
177 Primary : Pipe_Config renames Checked_Configs (GMA.Primary);
Nico Huber83693c82016-10-08 22:17:55 +0200178 begin
Nico Huber3d06de82018-05-29 01:35:04 +0200179 return
180 (Config.Use_PDW_For_EDP_Scaling and then
181 (Primary.Port = Internal and Requires_Scaling (Primary)))
182 or
183 (Primary.Port /= Disabled and Primary.Port /= Internal)
184 or
185 Checked_Configs (Secondary).Port /= Disabled
186 or
187 Checked_Configs (Tertiary).Port /= Disabled;
Nico Huber83693c82016-10-08 22:17:55 +0200188 end Need_PDW;
189
190 ----------------------------------------------------------------------------
191
192 procedure Pre_All_Off is
193 begin
194 -- HSW: disable panel self refresh (PSR) on eDP if enabled
195 -- wait for PSR idling
196 PSR_Off;
197 IPS_Off;
198 end Pre_All_Off;
199
200 procedure Initialize is
201 begin
202 -- HSW: disable power down well
203 PDW_Off;
Arthur Heymansd1988d12018-03-28 16:27:57 +0200204 Config.Raw_Clock := Config.Default_RawClk_Freq;
Nico Huber83693c82016-10-08 22:17:55 +0200205 end Initialize;
206
Nico Huber99f10f32016-11-20 00:34:05 +0100207 procedure Power_Set_To (Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200208 begin
209 if Need_PDW (Configs) then
210 PDW_On;
211 else
212 PDW_Off;
213 end if;
214 end Power_Set_To;
215
Nico Huber99f10f32016-11-20 00:34:05 +0100216 procedure Power_Up (Old_Configs, New_Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200217 begin
218 if not Need_PDW (Old_Configs) and Need_PDW (New_Configs) then
219 PDW_On;
220 end if;
221 end Power_Up;
222
Nico Huber99f10f32016-11-20 00:34:05 +0100223 procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200224 is
225 begin
226 if (Need_PDW (Old_Configs) or Need_PDW (Tmp_Configs)) and
227 not Need_PDW (New_Configs)
228 then
229 PDW_Off;
230 end if;
231 end Power_Down;
232
233end HW.GFX.GMA.Power_And_Clocks_Haswell;