libgfxinit/common/haswell_shared/hw-gfx-gma-power_and_clocks...

236 lines
8.0 KiB
Ada

--
-- Copyright (C) 2014-2016 secunet Security Networks AG
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; version 2 of the License.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
with GNAT.Source_Info;
with HW.Time;
with HW.Debug;
with HW.GFX.GMA.Config;
with HW.GFX.GMA.Registers;
package body HW.GFX.GMA.Power_And_Clocks_Haswell is
PWR_WELL_CTL_ENABLE_REQUEST : constant := 1 * 2 ** 31;
PWR_WELL_CTL_DISABLE_REQUEST : constant := 0 * 2 ** 31;
PWR_WELL_CTL_STATE_ENABLED : constant := 1 * 2 ** 30;
----------------------------------------------------------------------------
SRD_CTL_ENABLE : constant := 1 * 2 ** 31;
SRD_STATUS_STATE_MASK : constant := 7 * 2 ** 29;
type Pipe is (EDP, A, B, C);
type SRD_Regs is record
CTL : Registers.Registers_Index;
STATUS : Registers.Registers_Index;
end record;
type SRD_Per_Pipe_Regs is array (Pipe) of SRD_Regs;
SRD : constant SRD_Per_Pipe_Regs := SRD_Per_Pipe_Regs'
(A => SRD_Regs'
(CTL => Registers.SRD_CTL_A,
STATUS => Registers.SRD_STATUS_A),
B => SRD_Regs'
(CTL => Registers.SRD_CTL_B,
STATUS => Registers.SRD_STATUS_B),
C => SRD_Regs'
(CTL => Registers.SRD_CTL_C,
STATUS => Registers.SRD_STATUS_C),
EDP => SRD_Regs'
(CTL => Registers.SRD_CTL_EDP,
STATUS => Registers.SRD_STATUS_EDP));
----------------------------------------------------------------------------
IPS_CTL_ENABLE : constant := 1 * 2 ** 31;
DISPLAY_IPS_CONTROL : constant := 16#19#;
GT_MAILBOX_READY : constant := 1 * 2 ** 31;
----------------------------------------------------------------------------
procedure PSR_Off
is
Enabled : Boolean;
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
if Config.Has_Per_Pipe_SRD then
for P in Pipe loop
Registers.Is_Set_Mask (SRD (P).CTL, SRD_CTL_ENABLE, Enabled);
if Enabled then
Registers.Unset_Mask (SRD (P).CTL, SRD_CTL_ENABLE);
Registers.Wait_Unset_Mask (SRD (P).STATUS, SRD_STATUS_STATE_MASK);
pragma Debug (Debug.Put_Line ("Disabled PSR."));
end if;
end loop;
else
Registers.Is_Set_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE, Enabled);
if Enabled then
Registers.Unset_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE);
Registers.Wait_Unset_Mask (Registers.SRD_STATUS, SRD_STATUS_STATE_MASK);
pragma Debug (Debug.Put_Line ("Disabled PSR."));
end if;
end if;
end PSR_Off;
----------------------------------------------------------------------------
procedure GT_Mailbox_Write (MBox : Word32; Value : Word32) is
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
Registers.Write (Registers.GT_MAILBOX_DATA, Value);
Registers.Write (Registers.GT_MAILBOX, GT_MAILBOX_READY or MBox);
Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
Registers.Write (Registers.GT_MAILBOX_DATA, 0);
end GT_Mailbox_Write;
procedure IPS_Off
is
Enabled : Boolean;
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
if Config.Has_IPS then
Registers.Is_Set_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE, Enabled);
if Enabled then
if Config.Has_IPS_CTL_Mailbox then
GT_Mailbox_Write (DISPLAY_IPS_CONTROL, 0);
-- May take up to 42ms.
Registers.Wait_Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
else
Registers.Unset_Mask (Registers.IPS_CTL, IPS_CTL_ENABLE);
end if;
pragma Debug (Debug.Put_Line ("Disabled IPS."));
-- We have to wait until the next vblank here.
-- 20ms should be enough.
Time.M_Delay (20);
end if;
end if;
end IPS_Off;
----------------------------------------------------------------------------
procedure PDW_Off
is
Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
PWR_WELL_CTL_ENABLE_REQUEST) /= 0
then
Registers.Wait_Set_Mask
(Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
end if;
if (Ctl1 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
Registers.Write (Registers.PWR_WELL_CTL_BIOS, PWR_WELL_CTL_DISABLE_REQUEST);
end if;
if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) /= 0 then
Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_DISABLE_REQUEST);
end if;
end PDW_Off;
procedure PDW_On
is
Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); -- Result for debugging only
pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); -- Result for debugging only
if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
PWR_WELL_CTL_ENABLE_REQUEST) = 0
then
Registers.Wait_Unset_Mask
(Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
end if;
if (Ctl2 and PWR_WELL_CTL_ENABLE_REQUEST) = 0 then
Registers.Write (Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_ENABLE_REQUEST);
Registers.Wait_Set_Mask
(Registers.PWR_WELL_CTL_DRIVER, PWR_WELL_CTL_STATE_ENABLED);
end if;
end PDW_On;
function Need_PDW (Checked_Configs : Configs_Type) return Boolean is
begin
return (Checked_Configs (Primary).Port /= Disabled and
Checked_Configs (Primary).Port /= Internal) or
Checked_Configs (Secondary).Port /= Disabled or
Checked_Configs (Tertiary).Port /= Disabled;
end Need_PDW;
----------------------------------------------------------------------------
procedure Pre_All_Off is
begin
-- HSW: disable panel self refresh (PSR) on eDP if enabled
-- wait for PSR idling
PSR_Off;
IPS_Off;
end Pre_All_Off;
procedure Initialize is
begin
-- HSW: disable power down well
PDW_Off;
end Initialize;
procedure Power_Set_To (Configs : Configs_Type) is
begin
if Need_PDW (Configs) then
PDW_On;
else
PDW_Off;
end if;
end Power_Set_To;
procedure Power_Up (Old_Configs, New_Configs : Configs_Type) is
begin
if not Need_PDW (Old_Configs) and Need_PDW (New_Configs) then
PDW_On;
end if;
end Power_Up;
procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Configs_Type)
is
begin
if (Need_PDW (Old_Configs) or Need_PDW (Tmp_Configs)) and
not Need_PDW (New_Configs)
then
PDW_Off;
end if;
end Power_Down;
end HW.GFX.GMA.Power_And_Clocks_Haswell;