blob: 555a9b7da87e60bdbea4e611a0cb39cfd8e31166 [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 GNAT.Source_Info;
16
17with HW.Time;
18with HW.Debug;
19with HW.GFX.GMA.Config;
20with HW.GFX.GMA.Registers;
21
22package body HW.GFX.GMA.Power_And_Clocks_Haswell is
23
24 PWR_WELL_CTL_ENABLE_REQUEST : constant := 1 * 2 ** 31;
25 PWR_WELL_CTL_DISABLE_REQUEST : constant := 0 * 2 ** 31;
26 PWR_WELL_CTL_STATE_ENABLED : constant := 1 * 2 ** 30;
27
28 ----------------------------------------------------------------------------
29
30 SRD_CTL_ENABLE : constant := 1 * 2 ** 31;
31 SRD_STATUS_STATE_MASK : constant := 7 * 2 ** 29;
32
33 type Pipe is (EDP, A, B, C);
34 type SRD_Regs is record
35 CTL : Registers.Registers_Index;
36 STATUS : Registers.Registers_Index;
37 end record;
38 type SRD_Per_Pipe_Regs is array (Pipe) of SRD_Regs;
39 SRD : constant SRD_Per_Pipe_Regs := SRD_Per_Pipe_Regs'
40 (A => SRD_Regs'
41 (CTL => Registers.SRD_CTL_A,
42 STATUS => Registers.SRD_STATUS_A),
43 B => SRD_Regs'
44 (CTL => Registers.SRD_CTL_B,
45 STATUS => Registers.SRD_STATUS_B),
46 C => SRD_Regs'
47 (CTL => Registers.SRD_CTL_C,
48 STATUS => Registers.SRD_STATUS_C),
49 EDP => SRD_Regs'
50 (CTL => Registers.SRD_CTL_EDP,
51 STATUS => Registers.SRD_STATUS_EDP));
52
53 ----------------------------------------------------------------------------
54
55 IPS_CTL_ENABLE : constant := 1 * 2 ** 31;
56 DISPLAY_IPS_CONTROL : constant := 16#19#;
57
58 GT_MAILBOX_READY : constant := 1 * 2 ** 31;
59
60 ----------------------------------------------------------------------------
61
62 procedure PSR_Off
63 is
64 Enabled : Boolean;
65 begin
66 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
67
68 if Config.Has_Per_Pipe_SRD then
69 for P in Pipe loop
70 Registers.Is_Set_Mask (SRD (P).CTL, SRD_CTL_ENABLE, Enabled);
71 if Enabled then
72 Registers.Unset_Mask (SRD (P).CTL, SRD_CTL_ENABLE);
73 Registers.Wait_Unset_Mask (SRD (P).STATUS, SRD_STATUS_STATE_MASK);
74
75 pragma Debug (Debug.Put_Line ("Disabled PSR."));
76 end if;
77 end loop;
78 else
79 Registers.Is_Set_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE, Enabled);
80 if Enabled then
81 Registers.Unset_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE);
82 Registers.Wait_Unset_Mask (Registers.SRD_STATUS, SRD_STATUS_STATE_MASK);
83
84 pragma Debug (Debug.Put_Line ("Disabled PSR."));
85 end if;
86 end if;
87 end PSR_Off;
88
89 ----------------------------------------------------------------------------
90
91 procedure GT_Mailbox_Write (MBox : Word32; Value : Word32) is
92 begin
93 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
94
95 Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
96 Registers.Write (Registers.GT_MAILBOX_DATA, Value);
97 Registers.Write (Registers.GT_MAILBOX, GT_MAILBOX_READY or MBox);
98
99 Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
100 Registers.Write (Registers.GT_MAILBOX_DATA, 0);
101 end GT_Mailbox_Write;
102
103 procedure IPS_Off
104 is
105 Enabled : Boolean;
106 begin
107 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
108
109 if Config.Has_IPS then
110 Registers.Is_Set_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE, Enabled);
111 if Enabled then
112 if Config.Has_IPS_CTL_Mailbox then
113 GT_Mailbox_Write (DISPLAY_IPS_CONTROL, 0);
114 -- May take up to 42ms.
115 Registers.Wait_Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
116 else
117 Registers.Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
118 end if;
119
120 pragma Debug (Debug.Put_Line ("Disabled IPS."));
121 -- We have to wait until the next vblank here.
122 -- 20ms should be enough.
123 Time.M_Delay (20);
124 end if;
125 end if;
126 end IPS_Off;
127
128 ----------------------------------------------------------------------------
129
130 procedure PDW_Off
131 is
132 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
133 begin
134 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
135
136 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
137 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
138 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
139 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
140 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
141 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
142
143 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
144 PWR_WELL_CTL_ENABLE_REQUEST) /= 0
145 then
146 Registers.Wait_Set_Mask
147 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
148 end if;
149
150 if (Ctl1 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
151 Registers.Write (Registers.PWR_WELL_CTL_BIOS, PWR_WELL_CTL_DISABLE_REQUEST);
152 end if;
153
154 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
155 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_DISABLE_REQUEST);
156 end if;
157 end PDW_Off;
158
159 procedure PDW_On
160 is
161 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
162 begin
163 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
164
165 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
166 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
167 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
168 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
169 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
170 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
171
172 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
173 PWR_WELL_CTL_ENABLE_REQUEST) = 0
174 then
175 Registers.Wait_Unset_Mask
176 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
177 end if;
178
179 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) = 0 then
180 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_ENABLE_REQUEST);
181 Registers.Wait_Set_Mask
182 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
183 end if;
184 end PDW_On;
185
186 function Need_PDW (Checked_Configs : Configs_Type) return Boolean is
187 begin
188 return (Checked_Configs (Primary).Port /= Disabled and
189 Checked_Configs (Primary).Port /= Internal) or
190 Checked_Configs (Secondary).Port /= Disabled or
191 Checked_Configs (Tertiary).Port /= Disabled;
192 end Need_PDW;
193
194 ----------------------------------------------------------------------------
195
196 procedure Pre_All_Off is
197 begin
198 -- HSW: disable panel self refresh (PSR) on eDP if enabled
199 -- wait for PSR idling
200 PSR_Off;
201 IPS_Off;
202 end Pre_All_Off;
203
204 procedure Initialize is
205 begin
206 -- HSW: disable power down well
207 PDW_Off;
208 end Initialize;
209
210 procedure Power_Set_To (Configs : Configs_Type) is
211 begin
212 if Need_PDW (Configs) then
213 PDW_On;
214 else
215 PDW_Off;
216 end if;
217 end Power_Set_To;
218
219 procedure Power_Up (Old_Configs, New_Configs : Configs_Type) is
220 begin
221 if not Need_PDW (Old_Configs) and Need_PDW (New_Configs) then
222 PDW_On;
223 end if;
224 end Power_Up;
225
226 procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Configs_Type)
227 is
228 begin
229 if (Need_PDW (Old_Configs) or Need_PDW (Tmp_Configs)) and
230 not Need_PDW (New_Configs)
231 then
232 PDW_Off;
233 end if;
234 end Power_Down;
235
236end HW.GFX.GMA.Power_And_Clocks_Haswell;