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