blob: c0d1e78c531071909339e516142187f5ab2e2c6c [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);
Nico Huber43cf8d52016-09-08 17:24:52 +0200114 Registers.Wait_Unset_Mask
115 (Register => Registers.IPS_CTL,
116 Mask => IPS_CTL_ENABLE,
117 TOut_MS => 42);
Nico Huber83693c82016-10-08 22:17:55 +0200118 else
119 Registers.Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
120 end if;
121
122 pragma Debug (Debug.Put_Line ("Disabled IPS."));
123 -- We have to wait until the next vblank here.
124 -- 20ms should be enough.
125 Time.M_Delay (20);
126 end if;
127 end if;
128 end IPS_Off;
129
130 ----------------------------------------------------------------------------
131
132 procedure PDW_Off
133 is
134 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
135 begin
136 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
137
138 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
139 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
140 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
141 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
142 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
143 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
144
145 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
146 PWR_WELL_CTL_ENABLE_REQUEST) /= 0
147 then
148 Registers.Wait_Set_Mask
149 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
150 end if;
151
152 if (Ctl1 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
153 Registers.Write (Registers.PWR_WELL_CTL_BIOS, PWR_WELL_CTL_DISABLE_REQUEST);
154 end if;
155
156 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
157 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_DISABLE_REQUEST);
158 end if;
159 end PDW_Off;
160
161 procedure PDW_On
162 is
163 Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
164 begin
165 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
166
167 Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
168 Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
169 Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
170 Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
171 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
172 pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
173
174 if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
175 PWR_WELL_CTL_ENABLE_REQUEST) = 0
176 then
177 Registers.Wait_Unset_Mask
178 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
179 end if;
180
181 if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) = 0 then
182 Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_ENABLE_REQUEST);
183 Registers.Wait_Set_Mask
184 (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
185 end if;
186 end PDW_On;
187
Nico Huber99f10f32016-11-20 00:34:05 +0100188 function Need_PDW (Checked_Configs : Pipe_Configs) return Boolean is
Nico Huber83693c82016-10-08 22:17:55 +0200189 begin
190 return (Checked_Configs (Primary).Port /= Disabled and
191 Checked_Configs (Primary).Port /= Internal) or
192 Checked_Configs (Secondary).Port /= Disabled or
193 Checked_Configs (Tertiary).Port /= Disabled;
194 end Need_PDW;
195
196 ----------------------------------------------------------------------------
197
198 procedure Pre_All_Off is
199 begin
200 -- HSW: disable panel self refresh (PSR) on eDP if enabled
201 -- wait for PSR idling
202 PSR_Off;
203 IPS_Off;
204 end Pre_All_Off;
205
206 procedure Initialize is
207 begin
208 -- HSW: disable power down well
209 PDW_Off;
Arthur Heymansd1988d12018-03-28 16:27:57 +0200210 Config.Raw_Clock := Config.Default_RawClk_Freq;
Nico Huber83693c82016-10-08 22:17:55 +0200211 end Initialize;
212
Nico Huber99f10f32016-11-20 00:34:05 +0100213 procedure Power_Set_To (Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200214 begin
215 if Need_PDW (Configs) then
216 PDW_On;
217 else
218 PDW_Off;
219 end if;
220 end Power_Set_To;
221
Nico Huber99f10f32016-11-20 00:34:05 +0100222 procedure Power_Up (Old_Configs, New_Configs : Pipe_Configs) is
Nico Huber83693c82016-10-08 22:17:55 +0200223 begin
224 if not Need_PDW (Old_Configs) and Need_PDW (New_Configs) then
225 PDW_On;
226 end if;
227 end Power_Up;
228
Nico Huber99f10f32016-11-20 00:34:05 +0100229 procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Pipe_Configs)
Nico Huber83693c82016-10-08 22:17:55 +0200230 is
231 begin
232 if (Need_PDW (Old_Configs) or Need_PDW (Tmp_Configs)) and
233 not Need_PDW (New_Configs)
234 then
235 PDW_Off;
236 end if;
237 end Power_Down;
238
239end HW.GFX.GMA.Power_And_Clocks_Haswell;