blob: e343deb68e5c2ae704ce2bf5fad7f7601b43823a [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2015-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 HW.GFX.GMA.Config;
16
17with HW.Debug;
18with GNAT.Source_Info;
19
20package body HW.GFX.GMA.Panel
21with
22 Refined_State =>
23 (Panel_State =>
24 (Delays_US, Power_Cycle_Timer, Power_Up_Timer))
25is
26 type Delays_Enum is
27 (Power_Up_Delay,
28 Power_Up_To_BL_On,
29 Power_Down_Delay,
30 BL_Off_To_Power_Down,
31 Power_Cycle_Delay);
32
33 type Panel_Power_Delays is array (Delays_Enum) of Natural;
34 Default_EDP_Delays_US : constant Panel_Power_Delays := Panel_Power_Delays'
35 (Power_Up_Delay => 210_000,
36 Power_Up_To_BL_On => 50_000,
37 Power_Down_Delay => 500_000,
38 BL_Off_To_Power_Down => 50_000,
39 Power_Cycle_Delay => 510_000);
40
Nico Huber5dbaf4b2020-01-08 17:24:58 +010041 Delays_US : array (Valid_Panels) of Panel_Power_Delays;
Nico Huber83693c82016-10-08 22:17:55 +020042
43 ----------------------------------------------------------------------------
44
45 -- And here the mess starts: We have this pretty hardware power sequencer
46 -- that should ensure the panel's timing constraints are satisfied. But
47 -- (at least on some generations) it doesn't do it's job. On Haswell, it
48 -- seems to ignore the Power_Cycle_Delay, so we ensure the delay in soft-
49 -- ware. On at least Ivy Bridge and Broadwell Power_Up_Delay is ignored.
50 --
51 -- If we ever do all delays in software, there are two ways: Either confi-
52 -- gure the hardware to zero delays or wait for both the software timeout
53 -- and the hardware power sequencer. The latter option would be less error
54 -- prone, as the hardware might just don't work as expected.
55
Nico Huber5dbaf4b2020-01-08 17:24:58 +010056 type Panel_Times is array (Valid_Panels) of Time.T;
57 Power_Cycle_Timer : Panel_Times;
58 Power_Up_Timer : Panel_Times;
Nico Huber83693c82016-10-08 22:17:55 +020059
60 ----------------------------------------------------------------------------
61
Nico Huber57bebc72018-06-04 14:42:13 +020062 function Div_Round_Up32 (Num : Natural; Denom : Positive) return Word32 is
63 ((Word32 (Num) + Word32 (Denom) - 1) / Word32 (Denom));
Nico Huber83693c82016-10-08 22:17:55 +020064
65 PCH_PP_STATUS_ENABLED : constant := 16#00_0001# * 2 ** 31;
66 PCH_PP_STATUS_REQUIRE_ASSET : constant := 16#00_0001# * 2 ** 30;
67 PCH_PP_STATUS_PWR_SEQ_PROGRESS_MASK : constant := 16#00_0003# * 2 ** 28;
68 PCH_PP_STATUS_PWR_SEQ_PROGRESS_NONE : constant := 16#00_0000# * 2 ** 28;
69 PCH_PP_STATUS_PWR_SEQ_PROGRESS_UP : constant := 16#00_0001# * 2 ** 28;
70 PCH_PP_STATUS_PWR_SEQ_PROGRESS_DOWN : constant := 16#00_0002# * 2 ** 28;
71 PCH_PP_STATUS_PWR_CYC_DELAY_ACTIVE : constant := 16#00_0001# * 2 ** 27;
72
73 PCH_PP_CONTROL_WRITE_PROTECT_MASK : constant := 16#00_ffff# * 2 ** 16;
74 PCH_PP_CONTROL_WRITE_PROTECT_KEY : constant := 16#00_abcd# * 2 ** 16;
75 PCH_PP_CONTROL_VDD_OVERRIDE : constant := 16#00_0001# * 2 ** 3;
76 PCH_PP_CONTROL_BACKLIGHT_ENABLE : constant := 16#00_0001# * 2 ** 2;
77 PCH_PP_CONTROL_POWER_DOWN_ON_RESET : constant := 16#00_0001# * 2 ** 1;
78 PCH_PP_CONTROL_TARGET_ON : constant := 16#00_0001# * 2 ** 0;
79
Nico Huber3ea5d602020-01-06 17:57:59 +010080 BXT_PP_CONTROL_PWR_CYC_DELAY_SHIFT : constant := 4;
81 BXT_PP_CONTROL_PWR_CYC_DELAY_MASK : constant := 16#00_001f# * 2 ** 4;
82 function BXT_PP_CONTROL_PWR_CYC_DELAY (US : Natural) return Word32 is
83 (Shift_Left (Div_Round_Up32 (US, 100_000) + 1, BXT_PP_CONTROL_PWR_CYC_DELAY_SHIFT));
84
Nico Huber83693c82016-10-08 22:17:55 +020085 PCH_PP_ON_DELAYS_PORT_SELECT_MASK : constant := 16#00_0003# * 2 ** 30;
86 PCH_PP_ON_DELAYS_PORT_SELECT_LVDS : constant := 16#00_0000# * 2 ** 30;
87 PCH_PP_ON_DELAYS_PORT_SELECT_DP_A : constant := 16#00_0001# * 2 ** 30;
88 PCH_PP_ON_DELAYS_PORT_SELECT_DP_C : constant := 16#00_0002# * 2 ** 30;
89 PCH_PP_ON_DELAYS_PORT_SELECT_DP_D : constant := 16#00_0003# * 2 ** 30;
90 PCH_PP_ON_DELAYS_PWR_UP_MASK : constant := 16#00_1fff# * 2 ** 16;
91 PCH_PP_ON_DELAYS_PWR_UP_BL_ON_MASK : constant := 16#00_1fff# * 2 ** 0;
Arthur Heymanse87d0d12018-03-28 17:02:49 +020092
93 type PP_Regs is record
94 STATUS : Registers.Registers_Index;
95 CONTROL : Registers.Registers_Index;
96 ON_DELAYS : Registers.Registers_Index;
97 OFF_DELAYS : Registers.Registers_Index;
98 DIVISOR : Registers.Registers_Index;
99 end record;
100
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100101 PP : constant array (Valid_Panels) of PP_Regs :=
102 (if Config.Has_PCH_Panel_Power then
103 (Panel_1 =>
104 (STATUS => Registers.PCH_PP_STATUS,
105 CONTROL => Registers.PCH_PP_CONTROL,
106 ON_DELAYS => Registers.PCH_PP_ON_DELAYS,
107 OFF_DELAYS => Registers.PCH_PP_OFF_DELAYS,
108 DIVISOR => Registers.PCH_PP_DIVISOR),
109 Panel_2 =>
110 (STATUS => Registers.BXT_PP_STATUS_2,
111 CONTROL => Registers.BXT_PP_CONTROL_2,
112 ON_DELAYS => Registers.BXT_PP_ON_DELAYS_2,
113 OFF_DELAYS => Registers.BXT_PP_OFF_DELAYS_2,
114 DIVISOR => Registers.PCH_PP_DIVISOR)) -- won't be used
115
116 else
117 (Panel_1 .. Panel_2 =>
118 (STATUS => Registers.GMCH_PP_STATUS,
119 CONTROL => Registers.GMCH_PP_CONTROL,
120 ON_DELAYS => Registers.GMCH_PP_ON_DELAYS,
121 OFF_DELAYS => Registers.GMCH_PP_OFF_DELAYS,
122 DIVISOR => Registers.GMCH_PP_DIVISOR)));
Arthur Heymanse87d0d12018-03-28 17:02:49 +0200123
Nico Huber83693c82016-10-08 22:17:55 +0200124 function PCH_PP_ON_DELAYS_PWR_UP (US : Natural) return Word32 is
125 begin
126 return Shift_Left (Div_Round_Up32 (US, 100), 16);
127 end PCH_PP_ON_DELAYS_PWR_UP;
128 function PCH_PP_ON_DELAYS_PWR_UP_BL_ON (US : Natural) return Word32 is
129 begin
130 return Div_Round_Up32 (US, 100);
131 end PCH_PP_ON_DELAYS_PWR_UP_BL_ON;
132
133 PCH_PP_OFF_DELAYS_PWR_DOWN_MASK : constant := 16#1fff# * 2 ** 16;
134 PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN_MASK : constant := 16#1fff# * 2 ** 0;
135 function PCH_PP_OFF_DELAYS_PWR_DOWN (US : Natural) return Word32 is
136 begin
137 return Shift_Left (Div_Round_Up32 (US, 100), 16);
138 end PCH_PP_OFF_DELAYS_PWR_DOWN;
139 function PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN (US : Natural) return Word32 is
140 begin
141 return Div_Round_Up32 (US, 100);
142 end PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN;
143
144 PCH_PP_DIVISOR_REF_DIVIDER_MASK : constant := 16#ff_ffff# * 2 ** 8;
145 PCH_PP_DIVISOR_PWR_CYC_DELAY_MASK : constant := 16#00_001f# * 2 ** 0;
146 function PCH_PP_DIVISOR_PWR_CYC_DELAY (US : Natural) return Word32 is
147 begin
148 return Div_Round_Up32 (US, 100_000) + 1;
149 end PCH_PP_DIVISOR_PWR_CYC_DELAY;
150
151 CPU_BLC_PWM_CTL_ENABLE : constant := 16#00_0001# * 2 ** 31;
152 CPU_BLC_PWM_CTL_PIPE_SELECT_MASK : constant := 16#00_0003# * 2 ** 29;
153 CPU_BLC_PWM_CTL_PIPE_SELECT_PIPE_A : constant := 16#00_0000# * 2 ** 29;
154 CPU_BLC_PWM_CTL_PIPE_SELECT_PIPE_B : constant := 16#00_0001# * 2 ** 29;
155 CPU_BLC_PWM_CTL_PIPE_SELECT_PIPE_C : constant := 16#00_0002# * 2 ** 29;
156
157 CPU_BLC_PWM_DATA_BL_DUTY_CYC_MASK : constant := 16#00_ffff# * 2 ** 0;
158
159 PCH_BLC_PWM_CTL1_ENABLE : constant := 16#00_0001# * 2 ** 31;
160 PCH_BLC_PWM_CTL1_BL_POLARITY_MASK : constant := 16#00_0001# * 2 ** 29;
161 PCH_BLC_PWM_CTL1_PHASE_IN_INTR_STAT : constant := 16#00_0001# * 2 ** 26;
162 PCH_BLC_PWM_CTL1_PHASE_IN_ENABLE : constant := 16#00_0001# * 2 ** 25;
163 PCH_BLC_PWM_CTL1_PHASE_IN_INTR_EN : constant := 16#00_0001# * 2 ** 24;
164 PCH_BLC_PWM_CTL1_PHASE_IN_TIME_BASE : constant := 16#00_00ff# * 2 ** 16;
165 PCH_BLC_PWM_CTL1_PHASE_IN_COUNT : constant := 16#00_00ff# * 2 ** 8;
166 PCH_BLC_PWM_CTL1_PHASE_IN_INCREMENT : constant := 16#00_00ff# * 2 ** 0;
167
168 PCH_BLC_PWM_CTL2_BL_MOD_FREQ_MASK : constant := 16#00_ffff# * 2 ** 16;
Nico Huber1f63d512020-01-08 14:10:40 +0100169 PCH_BLC_PWM_CTL2_BL_MOD_FREQ_SHIFT : constant := 16;
Nico Huber83693c82016-10-08 22:17:55 +0200170 PCH_BLC_PWM_CTL2_BL_DUTY_CYC_MASK : constant := 16#00_ffff# * 2 ** 0;
171
Nico Huber1f63d512020-01-08 14:10:40 +0100172 BXT_BLC_PWM_CTL_ENABLE : constant := 16#00_0001# * 2 ** 31;
173
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100174 type BLC_Regs is record
175 CTL : Registers.Registers_Index;
176 FREQ : Registers.Registers_Index;
177 DUTY : Registers.Registers_Index;
178 end record;
179
180 BLC : constant array (Valid_Panels) of BLC_Regs :=
181 (Panel_1 =>
182 (CTL => Registers.BXT_BLC_PWM_CTL_1,
183 FREQ => Registers.BXT_BLC_PWM_FREQ_1,
184 DUTY => Registers.BXT_BLC_PWM_DUTY_1),
185 Panel_2 =>
186 (CTL => Registers.BXT_BLC_PWM_CTL_2,
187 FREQ => Registers.BXT_BLC_PWM_FREQ_2,
188 DUTY => Registers.BXT_BLC_PWM_DUTY_2));
189
Nico Huber83693c82016-10-08 22:17:55 +0200190 ----------------------------------------------------------------------------
191
192 procedure Static_Init
193 with
194 Refined_Global =>
195 (Output => (Power_Cycle_Timer, Power_Up_Timer, Delays_US),
196 Input => (Time.State))
197 is
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100198 Now : constant Time.T := Time.Now;
Nico Huber83693c82016-10-08 22:17:55 +0200199 begin
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100200 Power_Cycle_Timer := (others => Now);
Nico Huber83693c82016-10-08 22:17:55 +0200201 Power_Up_Timer := Power_Cycle_Timer;
202
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100203 Delays_US := (others => Default_EDP_Delays_US);
Nico Huber83693c82016-10-08 22:17:55 +0200204 end Static_Init;
205
206 ----------------------------------------------------------------------------
207
208 procedure Check_PP_Delays
209 (Delays : in out Panel_Power_Delays;
210 Override : in out Boolean) is
211 begin
212 for D in Delays_Enum loop
213 if Delays (D) = 0 then
214 Delays (D) := Default_EDP_Delays_US (D);
215 Override := True;
216 end if;
217 end loop;
218 end Check_PP_Delays;
219
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100220 procedure Setup_PP_Sequencer (Panel : Valid_Panels; Default_Delays : Boolean)
Nico Huber83693c82016-10-08 22:17:55 +0200221 is
222 Power_Delay, Port_Select : Word32;
223
224 Override_Delays : Boolean := False;
225 begin
226 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
227
Nico Huber83693c82016-10-08 22:17:55 +0200228 if Default_Delays then
229 Override_Delays := True;
230 else
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100231 Registers.Read (PP (Panel).ON_DELAYS, Power_Delay);
232 Delays_US (Panel) (Power_Up_Delay) := 100 * Natural
Nico Huber83693c82016-10-08 22:17:55 +0200233 (Shift_Right (Power_Delay and PCH_PP_ON_DELAYS_PWR_UP_MASK, 16));
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100234 Delays_US (Panel) (Power_Up_To_BL_On) := 100 * Natural
Nico Huber83693c82016-10-08 22:17:55 +0200235 (Power_Delay and PCH_PP_ON_DELAYS_PWR_UP_BL_ON_MASK);
236
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100237 Registers.Read (PP (Panel).OFF_DELAYS, Power_Delay);
238 Delays_US (Panel) (Power_Down_Delay) := 100 * Natural
Nico Huber83693c82016-10-08 22:17:55 +0200239 (Shift_Right (Power_Delay and PCH_PP_OFF_DELAYS_PWR_DOWN_MASK, 16));
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100240 Delays_US (Panel) (BL_Off_To_Power_Down) := 100 * Natural
Nico Huber83693c82016-10-08 22:17:55 +0200241 (Power_Delay and PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN_MASK);
242
Nico Huber3ea5d602020-01-06 17:57:59 +0100243 if Config.Has_PP_Divisor_Reg then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100244 Registers.Read (PP (Panel).DIVISOR, Power_Delay);
Nico Huber3ea5d602020-01-06 17:57:59 +0100245 else
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100246 Registers.Read (PP (Panel).CONTROL, Power_Delay);
247 Power_Delay := Shift_Right
248 (Power_Delay, BXT_PP_CONTROL_PWR_CYC_DELAY_SHIFT);
Nico Huber3ea5d602020-01-06 17:57:59 +0100249 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200250 if (Power_Delay and PCH_PP_DIVISOR_PWR_CYC_DELAY_MASK) > 1 then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100251 Delays_US (Panel) (Power_Cycle_Delay) := 100_000 * (Natural
Nico Huber83693c82016-10-08 22:17:55 +0200252 (Power_Delay and PCH_PP_DIVISOR_PWR_CYC_DELAY_MASK) - 1);
253 end if;
254
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100255 Check_PP_Delays (Delays_US (Panel), Override_Delays);
Nico Huber83693c82016-10-08 22:17:55 +0200256 end if;
257
258 if Override_Delays then
259 if Config.Has_PP_Port_Select then
Nico Huber8a6e7bd2020-01-07 16:36:38 +0100260 Port_Select :=
Nico Huber2bbd6e72020-01-07 18:22:59 +0100261 (case Config.Panel_Ports (Panel_1) is
Nico Huber8a6e7bd2020-01-07 16:36:38 +0100262 when LVDS => PCH_PP_ON_DELAYS_PORT_SELECT_LVDS,
263 when eDP => PCH_PP_ON_DELAYS_PORT_SELECT_DP_A,
264 when DP2 | HDMI2 => PCH_PP_ON_DELAYS_PORT_SELECT_DP_C,
265 when DP3 | HDMI3 => PCH_PP_ON_DELAYS_PORT_SELECT_DP_D,
266 when others => 0);
Nico Huber83693c82016-10-08 22:17:55 +0200267 else
268 Port_Select := 0;
269 end if;
270
271 -- Force power-up to backlight-on delay to 100us as recommended by PRM.
272 Registers.Unset_And_Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100273 (Register => PP (Panel).ON_DELAYS,
Nico Huber83693c82016-10-08 22:17:55 +0200274 Mask_Unset => PCH_PP_ON_DELAYS_PORT_SELECT_MASK or
275 PCH_PP_ON_DELAYS_PWR_UP_MASK or
276 PCH_PP_ON_DELAYS_PWR_UP_BL_ON_MASK,
277 Mask_Set => Port_Select or
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100278 PCH_PP_ON_DELAYS_PWR_UP
279 (Delays_US (Panel) (Power_Up_Delay))
Nico Huber83693c82016-10-08 22:17:55 +0200280 or PCH_PP_ON_DELAYS_PWR_UP_BL_ON (100));
281
282 Registers.Unset_And_Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100283 (Register => PP (Panel).OFF_DELAYS,
Nico Huber83693c82016-10-08 22:17:55 +0200284 Mask_Unset => PCH_PP_OFF_DELAYS_PWR_DOWN_MASK or
285 PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN_MASK,
286 Mask_Set => PCH_PP_OFF_DELAYS_PWR_DOWN
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100287 (Delays_US (Panel) (Power_Down_Delay)) or
Nico Huber83693c82016-10-08 22:17:55 +0200288 PCH_PP_OFF_DELAYS_BL_OFF_PWR_DOWN
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100289 (Delays_US (Panel) (BL_Off_To_Power_Down)));
Nico Huber83693c82016-10-08 22:17:55 +0200290
Nico Huber3ea5d602020-01-06 17:57:59 +0100291 if Config.Has_PP_Divisor_Reg then
292 Registers.Unset_And_Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100293 (Register => PP (Panel).DIVISOR,
Nico Huber3ea5d602020-01-06 17:57:59 +0100294 Mask_Unset => PCH_PP_DIVISOR_PWR_CYC_DELAY_MASK,
295 Mask_Set => PCH_PP_DIVISOR_PWR_CYC_DELAY
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100296 (Delays_US (Panel) (Power_Cycle_Delay)));
Nico Huber3ea5d602020-01-06 17:57:59 +0100297 else
298 Registers.Unset_And_Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100299 (Register => PP (Panel).CONTROL,
Nico Huber3ea5d602020-01-06 17:57:59 +0100300 Mask_Unset => BXT_PP_CONTROL_PWR_CYC_DELAY_MASK,
301 Mask_Set => BXT_PP_CONTROL_PWR_CYC_DELAY
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100302 (Delays_US (Panel) (Power_Cycle_Delay)));
Nico Huber3ea5d602020-01-06 17:57:59 +0100303 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200304 end if;
305
306 if Config.Has_PP_Write_Protection then
307 Registers.Unset_And_Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100308 (Register => PP (Panel).CONTROL,
Nico Huber83693c82016-10-08 22:17:55 +0200309 Mask_Unset => PCH_PP_CONTROL_WRITE_PROTECT_MASK,
310 Mask_Set => PCH_PP_CONTROL_WRITE_PROTECT_KEY or
311 PCH_PP_CONTROL_POWER_DOWN_ON_RESET);
312 else
313 Registers.Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100314 (Register => PP (Panel).CONTROL,
Nico Huber83693c82016-10-08 22:17:55 +0200315 Mask => PCH_PP_CONTROL_POWER_DOWN_ON_RESET);
316 end if;
317 end Setup_PP_Sequencer;
318
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100319 procedure Setup_PP_Sequencer (Default_Delays : Boolean := False) is
320 begin
321 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
322
323 for Panel in Valid_Panels loop
324 if Config.Panel_Ports (Panel) /= Disabled then
325 Setup_PP_Sequencer (Panel, Default_Delays);
326 end if;
327 end loop;
328 end Setup_PP_Sequencer;
329
Nico Huber83693c82016-10-08 22:17:55 +0200330 ----------------------------------------------------------------------------
331
Nico Huber2bbd6e72020-01-07 18:22:59 +0100332 procedure VDD_Override (Panel : Panel_Control) is
Nico Huber83693c82016-10-08 22:17:55 +0200333 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100334 if Panel not in Valid_Panels then
335 return;
336 end if;
337
Nico Huber83693c82016-10-08 22:17:55 +0200338 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
339
340 -- Yeah, We could do, what we are supposed to do here. But OTOH, we
341 -- are should wait for the full Power Up Delay, which we would have
342 -- to do later again. And just powering on the display seems to work
343 -- too. Also this function vanished on newer hardware.
Nico Huber2bbd6e72020-01-07 18:22:59 +0100344 On (Panel);
Nico Huber83693c82016-10-08 22:17:55 +0200345 end VDD_Override;
346
Nico Huber2bbd6e72020-01-07 18:22:59 +0100347 procedure On (Panel : Panel_Control; Wait : Boolean := True)
Nico Huber83693c82016-10-08 22:17:55 +0200348 is
349 Was_On : Boolean;
350 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100351 if Panel not in Valid_Panels then
352 return;
353 end if;
354
Nico Huber83693c82016-10-08 22:17:55 +0200355 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
356
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100357 Registers.Is_Set_Mask (PP (Panel).CONTROL, PCH_PP_CONTROL_TARGET_ON, Was_On);
Nico Huber83693c82016-10-08 22:17:55 +0200358 if not Was_On then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100359 Time.Delay_Until (Power_Cycle_Timer (Panel));
Nico Huber83693c82016-10-08 22:17:55 +0200360 end if;
361
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100362 Registers.Set_Mask (PP (Panel).CONTROL, PCH_PP_CONTROL_TARGET_ON);
Nico Huber83693c82016-10-08 22:17:55 +0200363 if not Was_On then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100364 Power_Up_Timer (Panel) :=
365 Time.US_From_Now (Delays_US (Panel) (Power_Up_Delay));
Nico Huber83693c82016-10-08 22:17:55 +0200366 end if;
367 if Wait then
Nico Huber2bbd6e72020-01-07 18:22:59 +0100368 Wait_On (Panel);
Nico Huber83693c82016-10-08 22:17:55 +0200369 end if;
370 end On;
371
Nico Huber2bbd6e72020-01-07 18:22:59 +0100372 procedure Wait_On (Panel : Panel_Control) is
Nico Huber83693c82016-10-08 22:17:55 +0200373 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100374 if Panel not in Valid_Panels then
375 return;
376 end if;
377
Nico Huber83693c82016-10-08 22:17:55 +0200378 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
379
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100380 Time.Delay_Until (Power_Up_Timer (Panel));
Nico Huber83693c82016-10-08 22:17:55 +0200381 Registers.Wait_Unset_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100382 (Register => PP (Panel).STATUS,
Nico Huber83693c82016-10-08 22:17:55 +0200383 Mask => PCH_PP_STATUS_PWR_SEQ_PROGRESS_MASK,
384 TOut_MS => 300);
385
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100386 Registers.Unset_Mask (PP (Panel).CONTROL, PCH_PP_CONTROL_VDD_OVERRIDE);
Nico Huber83693c82016-10-08 22:17:55 +0200387 end Wait_On;
388
Nico Huber2bbd6e72020-01-07 18:22:59 +0100389 procedure Off (Panel : Panel_Control)
Nico Huber83693c82016-10-08 22:17:55 +0200390 is
391 Was_On : Boolean;
392 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100393 if Panel not in Valid_Panels then
394 return;
395 end if;
396
Nico Huber83693c82016-10-08 22:17:55 +0200397 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
398
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100399 Registers.Is_Set_Mask (PP (Panel).CONTROL, PCH_PP_CONTROL_TARGET_ON, Was_On);
Nico Huber83693c82016-10-08 22:17:55 +0200400 Registers.Unset_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100401 (Register => PP (Panel).CONTROL,
Nico Huber83693c82016-10-08 22:17:55 +0200402 Mask => PCH_PP_CONTROL_TARGET_ON or
403 PCH_PP_CONTROL_VDD_OVERRIDE);
404 if Was_On then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100405 Time.U_Delay (Delays_US (Panel) (Power_Down_Delay));
Nico Huber83693c82016-10-08 22:17:55 +0200406 end if;
407 Registers.Wait_Unset_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100408 (Register => PP (Panel).STATUS,
Nico Huber83693c82016-10-08 22:17:55 +0200409 Mask => PCH_PP_STATUS_PWR_SEQ_PROGRESS_MASK,
410 TOut_MS => 600);
411 if Was_On then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100412 Power_Cycle_Timer (Panel) :=
413 Time.US_From_Now (Delays_US (Panel) (Power_Cycle_Delay));
Nico Huber83693c82016-10-08 22:17:55 +0200414 end if;
415 end Off;
416
417 ----------------------------------------------------------------------------
418
Nico Huber2bbd6e72020-01-07 18:22:59 +0100419 procedure Backlight_On (Panel : Panel_Control) is
Nico Huber83693c82016-10-08 22:17:55 +0200420 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100421 if Panel not in Valid_Panels then
422 return;
423 end if;
424
Nico Huber83693c82016-10-08 22:17:55 +0200425 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
426
Nico Huber1f63d512020-01-08 14:10:40 +0100427 if Config.Has_New_Backlight_Control then
428 Registers.Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100429 (Register => BLC (Panel).CTL,
Nico Huber1f63d512020-01-08 14:10:40 +0100430 Mask => BXT_BLC_PWM_CTL_ENABLE);
431 else
432 Registers.Set_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100433 (Register => PP (Panel).CONTROL,
Nico Huber1f63d512020-01-08 14:10:40 +0100434 Mask => PCH_PP_CONTROL_BACKLIGHT_ENABLE);
435 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200436 end Backlight_On;
437
Nico Huber2bbd6e72020-01-07 18:22:59 +0100438 procedure Backlight_Off (Panel : Panel_Control) is
Nico Huber83693c82016-10-08 22:17:55 +0200439 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100440 if Panel not in Valid_Panels then
441 return;
442 end if;
443
Nico Huber83693c82016-10-08 22:17:55 +0200444 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
445
Nico Huber1f63d512020-01-08 14:10:40 +0100446 if Config.Has_New_Backlight_Control then
447 Registers.Unset_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100448 (Register => BLC (Panel).CTL,
Nico Huber1f63d512020-01-08 14:10:40 +0100449 Mask => BXT_BLC_PWM_CTL_ENABLE);
450 else
451 Registers.Unset_Mask
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100452 (Register => PP (Panel).CONTROL,
Nico Huber1f63d512020-01-08 14:10:40 +0100453 Mask => PCH_PP_CONTROL_BACKLIGHT_ENABLE);
454 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200455 end Backlight_Off;
456
Nico Huber1f63d512020-01-08 14:10:40 +0100457 procedure Set_Backlight (Panel : Panel_Control; Level : Word32) is
Nico Huber83693c82016-10-08 22:17:55 +0200458 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100459 if Panel not in Valid_Panels then
460 return;
461 end if;
462
Nico Huber83693c82016-10-08 22:17:55 +0200463 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
464
Nico Huber1f63d512020-01-08 14:10:40 +0100465 if Config.Has_New_Backlight_Control then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100466 Registers.Write (BLC (Panel).DUTY, Level);
Nico Huber1f63d512020-01-08 14:10:40 +0100467 else
468 Registers.Unset_And_Set_Mask
469 (Register => Registers.BLC_PWM_CPU_CTL,
470 Mask_Unset => CPU_BLC_PWM_DATA_BL_DUTY_CYC_MASK,
471 Mask_Set => Level);
472 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200473 end Set_Backlight;
474
Nico Huber1f63d512020-01-08 14:10:40 +0100475 procedure Get_Max_Backlight (Panel : Panel_Control; Level : out Word32) is
Nico Huber83693c82016-10-08 22:17:55 +0200476 begin
Nico Huber2bbd6e72020-01-07 18:22:59 +0100477 if Panel not in Valid_Panels then
478 Level := 0;
479 return;
480 end if;
481
Nico Huber83693c82016-10-08 22:17:55 +0200482 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
483
Nico Huber1f63d512020-01-08 14:10:40 +0100484 if Config.Has_New_Backlight_Control then
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100485 Registers.Read (BLC (Panel).FREQ, Level);
Nico Huber1f63d512020-01-08 14:10:40 +0100486 else
487 Registers.Read (Registers.BLC_PWM_PCH_CTL2, Level);
488 Level := Shift_Right (Level, PCH_BLC_PWM_CTL2_BL_MOD_FREQ_SHIFT);
489 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200490 end Get_Max_Backlight;
491
492end HW.GFX.GMA.Panel;