From 3be61d4f7e79907db981d67e620e0b10ee49181e Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Mon, 9 Jan 2017 13:58:18 +0100 Subject: [PATCH] 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 Reviewed-on: https://review.coreboot.org/18119 Tested-by: Nico Huber Reviewed-by: Patrick Georgi --- .../haswell_shared/hw-gfx-gma-port_detect.adb | 20 ++-- common/hw-gfx-gma-config_helpers.ads | 7 +- common/hw-gfx-gma-port_detect.ads | 6 +- common/hw-gfx-gma.adb | 112 ++++++++++-------- common/ironlake/hw-gfx-gma-port_detect.adb | 15 +-- 5 files changed, 89 insertions(+), 71 deletions(-) diff --git a/common/haswell_shared/hw-gfx-gma-port_detect.adb b/common/haswell_shared/hw-gfx-gma-port_detect.adb index 9987aca7b9..2f5854dc26 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 @@ is 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 @@ is (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 @@ is (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 b56e1b1b08..1029177c26 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 @@ with HW; 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 c9d339b2d6..1cd8d6b747 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 @@ private package HW.GFX.GMA.Port_Detect is 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 cbb18a6859..005fff7129 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 @@ is 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 @@ is ---------------------------------------------------------------------------- - 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 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 @@ is (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 @@ is 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 @@ is 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 @@ is 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 @@ is 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 e8cb3fa53f..ff4ff887f5 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 @@ is 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 =>