gma: Refactor Hotplug_Detect() interface and usage
Checking for hotplug events should be done before any other work to
reduce load and (spurious) debug output. Therefor, use the simpler
`Port_Type` in the interface of `Hotplug_Detect()` so we don't have to
fill the whole `Port_Cfg` before checking for events.
Also, now that it's possible, factor the disabling of a single output
out of `Update_Outputs()`.
Change-Id: I2a0ba5530c8d511fa95f9cac12297ad428a40d77
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/18119
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
diff --git a/common/haswell_shared/hw-gfx-gma-port_detect.adb b/common/haswell_shared/hw-gfx-gma-port_detect.adb
index 9987aca..2f5854d 100644
--- a/common/haswell_shared/hw-gfx-gma-port_detect.adb
+++ b/common/haswell_shared/hw-gfx-gma-port_detect.adb
@@ -1,5 +1,5 @@
--
--- Copyright (C) 2016 secunet Security Networks AG
+-- Copyright (C) 2016-2017 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
@@ -14,6 +14,7 @@
with HW.GFX.GMA.Config;
with HW.GFX.GMA.Registers;
+with HW.GFX.GMA.Config_Helpers;
package body HW.GFX.GMA.Port_Detect
is
@@ -149,11 +150,13 @@
end loop;
end Initialize;
- procedure Hotplug_Detect (Port_Cfg : in Port_Config; Detected : out Boolean)
+ procedure Hotplug_Detect (Port : in Active_Port_Type; Detected : out Boolean)
is
Ctl32 : Word32;
+ GPU_Port : constant GMA.GPU_Port :=
+ Config_Helpers.To_GPU_Port (Primary, Port);
begin
- if Port_Cfg.Display = VGA then
+ if Port = Analog then
Registers.Read (Registers.PCH_ADPA, Ctl32, Verbose => False);
Ctl32 := Ctl32 and PCH_ADPA_CRT_HPD_CHANNEL_MASK;
Detected := Ctl32 = PCH_ADPA_CRT_HPD_CHANNEL_MASK;
@@ -162,7 +165,7 @@
(Register => Registers.PCH_ADPA,
Mask => PCH_ADPA_CRT_HPD_CHANNEL_MASK);
end if;
- elsif Config.Has_HOTPLUG_CTL and then Port_Cfg.Port = DIGI_A then
+ elsif Config.Has_HOTPLUG_CTL and then GPU_Port = DIGI_A then
Registers.Read (Registers.HOTPLUG_CTL, Ctl32, Verbose => False);
Detected := (Ctl32 and HOTPLUG_CTL_DDI_A_HPD_LONG_DETECT) /= 0;
@@ -171,16 +174,15 @@
(Register => Registers.HOTPLUG_CTL,
Mask => HOTPLUG_CTL_DDI_A_HPD_STATUS);
end if;
- elsif Port_Cfg.Port in DIGI_A .. DIGI_D then
+ elsif GPU_Port in DIGI_A .. DIGI_D then
Registers.Read (Registers.SHOTPLUG_CTL, Ctl32, Verbose => False);
- Detected :=
- (Ctl32 and SHOTPLUG_CTL_LONG_DETECT (Port_Cfg.Port)) /= 0;
+ Detected := (Ctl32 and SHOTPLUG_CTL_LONG_DETECT (GPU_Port)) /= 0;
- if (Ctl32 and SHOTPLUG_CTL_HPD_STATUS (Port_Cfg.Port)) /= 0 then
+ if (Ctl32 and SHOTPLUG_CTL_HPD_STATUS (GPU_Port)) /= 0 then
Registers.Unset_And_Set_Mask
(Register => Registers.SHOTPLUG_CTL,
Mask_Unset => SHOTPLUG_CTL_DETECT_MASK,
- Mask_Set => SHOTPLUG_CTL_HPD_STATUS (Port_Cfg.Port));
+ Mask_Set => SHOTPLUG_CTL_HPD_STATUS (GPU_Port));
end if;
else
Detected := False;
diff --git a/common/hw-gfx-gma-config_helpers.ads b/common/hw-gfx-gma-config_helpers.ads
index b56e1b1..1029177 100644
--- a/common/hw-gfx-gma-config_helpers.ads
+++ b/common/hw-gfx-gma-config_helpers.ads
@@ -1,5 +1,5 @@
--
--- Copyright (C) 2015-2016 secunet Security Networks AG
+-- Copyright (C) 2015-2017 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
@@ -17,6 +17,11 @@
private package HW.GFX.GMA.Config_Helpers
is
+ function To_GPU_Port
+ (Pipe : Pipe_Index;
+ Port : Active_Port_Type)
+ return GPU_Port;
+
function To_PCH_Port (Port : Active_Port_Type) return PCH_Port;
function To_Display_Type (Port : Active_Port_Type) return Display_Type;
diff --git a/common/hw-gfx-gma-port_detect.ads b/common/hw-gfx-gma-port_detect.ads
index c9d339b..1cd8d6b 100644
--- a/common/hw-gfx-gma-port_detect.ads
+++ b/common/hw-gfx-gma-port_detect.ads
@@ -1,5 +1,5 @@
--
--- Copyright (C) 2016 secunet Security Networks AG
+-- Copyright (C) 2016-2017 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
@@ -16,6 +16,8 @@
procedure Initialize;
- procedure Hotplug_Detect (Port_Cfg : in Port_Config; Detected : out Boolean);
+ procedure Hotplug_Detect
+ (Port : in Active_Port_Type;
+ Detected : out Boolean);
end HW.GFX.GMA.Port_Detect;
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index cbb18a6..005fff7 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -1,5 +1,5 @@
--
--- Copyright (C) 2014-2016 secunet Security Networks AG
+-- Copyright (C) 2014-2017 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
@@ -61,7 +61,7 @@
type PLLs_Type is array (Pipe_Index) of PLLs.T;
type HPD_Type is array (Port_Type) of Boolean;
- type HPD_Delay_Type is array (Port_Type) of Time.T;
+ type HPD_Delay_Type is array (Active_Port_Type) of Time.T;
Allocated_PLLs : PLLs_Type;
HPD_Delay : HPD_Delay_Type;
@@ -80,21 +80,6 @@
----------------------------------------------------------------------------
- procedure Check_HPD
- (Port_Cfg : in Port_Config;
- Port : in Port_Type;
- Detected : out Boolean)
- is
- HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
- begin
- if HPD_Delay_Over then
- Port_Detect.Hotplug_Detect (Port_Cfg, Detected);
- HPD_Delay (Port) := Time.MS_From_Now (333);
- else
- Detected := False;
- end if;
- end Check_HPD;
-
procedure Enable_Output
(Pipe : in Pipe_Index;
Pipe_Cfg : in Pipe_Config;
@@ -102,6 +87,10 @@
is
Port_Cfg : Port_Config;
begin
+ pragma Debug (Debug.New_Line);
+ pragma Debug (Debug.Put_Line
+ ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
+
Config_Helpers.Fill_Port_Config
(Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
@@ -110,16 +99,7 @@
(Pipe_Cfg.Framebuffer, Port_Cfg, Pipe);
end if;
- if Success and then Wait_For_HPD (Pipe_Cfg.Port) then
- Check_HPD (Port_Cfg, Pipe_Cfg.Port, Success);
- Wait_For_HPD (Pipe_Cfg.Port) := not Success;
- end if;
-
if Success then
- pragma Debug (Debug.New_Line);
- pragma Debug (Debug.Put_Line
- ("Trying to enable port " & Port_Names (Pipe_Cfg.Port)));
-
Connector_Info.Preferred_Link_Setting (Port_Cfg, Success);
end if;
@@ -186,6 +166,27 @@
end if;
end Enable_Output;
+ procedure Disable_Output (Pipe : Pipe_Index; Pipe_Cfg : Pipe_Config)
+ is
+ Port_Cfg : Port_Config;
+ Success : Boolean;
+ begin
+ Config_Helpers.Fill_Port_Config
+ (Port_Cfg, Pipe, Pipe_Cfg.Port, Pipe_Cfg.Mode, Success);
+ if Success then
+ pragma Debug (Debug.New_Line);
+ pragma Debug (Debug.Put_Line
+ ("Disabling port " & Port_Names (Pipe_Cfg.Port)));
+ pragma Debug (Debug.New_Line);
+
+ Connectors.Pre_Off (Port_Cfg);
+ Display_Controller.Off (Pipe);
+ Connectors.Post_Off (Port_Cfg);
+
+ PLLs.Free (Allocated_PLLs (Pipe));
+ end if;
+ end Disable_Output;
+
procedure Update_Outputs (Configs : Pipe_Configs)
is
Did_Power_Up : Boolean := False;
@@ -193,7 +194,18 @@
HPD, Success : Boolean;
Old_Config, New_Config : Pipe_Config;
Old_Configs : Pipe_Configs;
- Port_Cfg : Port_Config;
+
+ procedure Check_HPD (Port : in Active_Port_Type; Detected : out Boolean)
+ is
+ HPD_Delay_Over : constant Boolean := Time.Timed_Out (HPD_Delay (Port));
+ begin
+ if HPD_Delay_Over then
+ Port_Detect.Hotplug_Detect (Port, Detected);
+ HPD_Delay (Port) := Time.MS_From_Now (333);
+ else
+ Detected := False;
+ end if;
+ end Check_HPD;
begin
Old_Configs := Cur_Configs;
@@ -203,43 +215,37 @@
Old_Config := Cur_Configs (I);
New_Config := Configs (I);
- Config_Helpers.Fill_Port_Config
- (Port_Cfg, I, Old_Configs (I).Port, Old_Configs (I).Mode, Success);
- if Success then
- Check_HPD (Port_Cfg, Old_Config.Port, HPD);
+ if Old_Config.Port /= Disabled then
+ Check_HPD (Old_Config.Port, HPD);
end if;
- -- Connector changed?
- if (Success and then HPD) or
+ -- hotplug event or configuration changed?
+ if HPD or
Old_Config.Port /= New_Config.Port or
Old_Config.Mode /= New_Config.Mode
then
+ -- disable old configuration if any
if Old_Config.Port /= Disabled then
- if Success then
- pragma Debug (Debug.New_Line);
- pragma Debug (Debug.Put_Line
- ("Disabling port " & Port_Names (Old_Config.Port)));
-
- Connectors.Pre_Off (Port_Cfg);
-
- Display_Controller.Off (I);
-
- Connectors.Post_Off (Port_Cfg);
- end if;
-
- -- Free PLL
- PLLs.Free (Allocated_PLLs (I));
-
+ Disable_Output (I, Old_Config);
Cur_Configs (I).Port := Disabled;
end if;
+ -- enable new configuration if any
if New_Config.Port /= Disabled then
- if not Did_Power_Up then
- Power_And_Clocks.Power_Up (Old_Configs, Configs);
- Did_Power_Up := True;
+ if Wait_For_HPD (New_Config.Port) then
+ Check_HPD (New_Config.Port, Success);
+ Wait_For_HPD (New_Config.Port) := not Success;
+ else
+ Success := True;
end if;
- Enable_Output (I, New_Config, Success);
+ if Success then
+ if not Did_Power_Up then
+ Power_And_Clocks.Power_Up (Old_Configs, Configs);
+ Did_Power_Up := True;
+ end if;
+ Enable_Output (I, New_Config, Success);
+ end if;
if Success then
Cur_Configs (I) := New_Config;
@@ -247,6 +253,8 @@
else
Cur_Configs (I) := New_Config;
end if;
+
+ -- update framebuffer offset only
elsif Old_Config.Framebuffer /= New_Config.Framebuffer and
Old_Config.Port /= Disabled
then
diff --git a/common/ironlake/hw-gfx-gma-port_detect.adb b/common/ironlake/hw-gfx-gma-port_detect.adb
index e8cb3fa..ff4ff88 100644
--- a/common/ironlake/hw-gfx-gma-port_detect.adb
+++ b/common/ironlake/hw-gfx-gma-port_detect.adb
@@ -1,5 +1,5 @@
--
--- Copyright (C) 2016 secunet Security Networks AG
+-- Copyright (C) 2016-2017 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
@@ -14,6 +14,7 @@
with HW.GFX.GMA.Config;
with HW.GFX.GMA.Registers;
+with HW.GFX.GMA.Config_Helpers;
package body HW.GFX.GMA.Port_Detect
is
@@ -125,15 +126,15 @@
end loop;
end Initialize;
- procedure Hotplug_Detect (Port_Cfg : in Port_Config; Detected : out Boolean)
+ procedure Hotplug_Detect (Port : in Active_Port_Type; Detected : out Boolean)
is
Ctl32 : Word32;
PCH_Port : constant GMA.PCH_Port :=
- (case Port_Cfg.PCH_Port is
- when PCH_DP_B => PCH_HDMI_B,
- when PCH_DP_C => PCH_HDMI_C,
- when PCH_DP_D => PCH_HDMI_D,
- when others => Port_Cfg.PCH_Port);
+ (case Port is
+ when DP1 => PCH_HDMI_B,
+ when DP2 => PCH_HDMI_C,
+ when DP3 => PCH_HDMI_D,
+ when others => Config_Helpers.To_PCH_Port (Port));
begin
case PCH_Port is
when PCH_DAC =>