gma broxton: Add final glue

Add new configuration flags for Broxton and hook up its DDI_Phy
implementation in the shared Haswell DDI code. Haswell and Skylake
get DDI_Phy stubs.

Tested (in Linux userspace) on ASRock J3455-ITX which exposes the
following ports:
  o VGA through an active eDP to VGA converter chip
  o HDMI 2.0 through an active DP to HDMI converter chip
  o DVI-D connected to the SoC

Change-Id: If72b228c6a4c45487261e6e7435d281ec2d97f38
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/18426
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Nico Huber
2017-02-09 13:57:04 +01:00
committed by Nico Huber
parent fdd93659e0
commit 1c3b9285ce
11 changed files with 174 additions and 55 deletions

View File

@@ -1,3 +1,4 @@
gfxinit-y += hw-gfx-gma-ddi_phy.ads
gfxinit-y += hw-gfx-gma-plls-lcpll.ads
gfxinit-y += hw-gfx-gma-plls-wrpll.adb
gfxinit-y += hw-gfx-gma-plls-wrpll.ads

View File

@@ -0,0 +1,17 @@
--
-- Copyright (C) 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
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- 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 HW.GFX.GMA.DDI_Phy_Stub;
private package HW.GFX.GMA.DDI_Phy renames HW.GFX.GMA.DDI_Phy_Stub;

View File

@@ -1,6 +1,7 @@
gfxinit-y += hw-gfx-gma-connectors-ddi.adb
gfxinit-y += hw-gfx-gma-connectors-ddi.ads
gfxinit-y += hw-gfx-gma-connectors.adb
gfxinit-y += hw-gfx-gma-ddi_phy_stub.ads
gfxinit-y += hw-gfx-gma-port_detect.adb
gfxinit-y += hw-gfx-gma-power_and_clocks_haswell.adb
gfxinit-y += hw-gfx-gma-power_and_clocks_haswell.ads

View File

@@ -21,6 +21,7 @@ with HW.GFX.GMA.PCH.VGA;
with HW.GFX.GMA.DP_Info;
with HW.GFX.GMA.DP_Aux_Ch;
with HW.GFX.GMA.SPLL;
with HW.GFX.GMA.DDI_Phy;
with HW.Debug;
with GNAT.Source_Info;
@@ -179,7 +180,9 @@ package body HW.GFX.GMA.Connectors.DDI is
is
begin
return
(if (Config.Has_Low_Voltage_Swing and Config.EDP_Low_Voltage_Swing)
(if Config.Has_DDI_PHYs then
DDI_Phy.Max_V_Swing
elsif (Config.Has_Low_Voltage_Swing and Config.EDP_Low_Voltage_Swing)
and then Port = DIGI_A
then
DP_Info.VS_Level_3
@@ -196,11 +199,14 @@ package body HW.GFX.GMA.Connectors.DDI is
is
begin
return
(case Train_Set.Voltage_Swing is
when DP_Info.VS_Level_0 => DP_Info.Emph_Level_3,
when DP_Info.VS_Level_1 => DP_Info.Emph_Level_2,
when DP_Info.VS_Level_2 => DP_Info.Emph_Level_1,
when others => DP_Info.Emph_Level_0);
(if Config.Has_DDI_PHYs then
DDI_Phy.Max_Pre_Emph (Train_Set.Voltage_Swing)
else
(case Train_Set.Voltage_Swing is
when DP_Info.VS_Level_0 => DP_Info.Emph_Level_3,
when DP_Info.VS_Level_1 => DP_Info.Emph_Level_2,
when DP_Info.VS_Level_2 => DP_Info.Emph_Level_1,
when others => DP_Info.Emph_Level_0));
end Max_Pre_Emph;
pragma Warnings (GNATprove, On, "unused variable ""Port""");
@@ -262,39 +268,43 @@ package body HW.GFX.GMA.Connectors.DDI is
Was_Enabled : Boolean;
Trans_Select : DDI_BUF_CTL_TRANS_SELECT_T;
begin
case Train_Set.Voltage_Swing is
when DP_Info.VS_Level_0 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 0;
when DP_Info.Emph_Level_1 => Trans_Select := 1;
when DP_Info.Emph_Level_2 => Trans_Select := 2;
when DP_Info.Emph_Level_3 => Trans_Select := 3;
end case;
when DP_Info.VS_Level_1 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 4;
when DP_Info.Emph_Level_1 => Trans_Select := 5;
when DP_Info.Emph_Level_2 => Trans_Select := 6;
when others => Trans_Select := 0;
end case;
when DP_Info.VS_Level_2 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 7;
when DP_Info.Emph_Level_1 => Trans_Select := 8;
when others => Trans_Select := 0;
end case;
when DP_Info.VS_Level_3 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 9;
when others => Trans_Select := 0;
end case;
end case;
Registers.Is_Set_Mask
(Register => DDI_Regs (Port).BUF_CTL,
Mask => DDI_BUF_CTL_BUFFER_ENABLE,
Result => Was_Enabled);
if Config.Has_DDI_PHYs then
Trans_Select := 0;
else
case Train_Set.Voltage_Swing is
when DP_Info.VS_Level_0 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 0;
when DP_Info.Emph_Level_1 => Trans_Select := 1;
when DP_Info.Emph_Level_2 => Trans_Select := 2;
when DP_Info.Emph_Level_3 => Trans_Select := 3;
end case;
when DP_Info.VS_Level_1 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 4;
when DP_Info.Emph_Level_1 => Trans_Select := 5;
when DP_Info.Emph_Level_2 => Trans_Select := 6;
when others => Trans_Select := 0;
end case;
when DP_Info.VS_Level_2 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 7;
when DP_Info.Emph_Level_1 => Trans_Select := 8;
when others => Trans_Select := 0;
end case;
when DP_Info.VS_Level_3 =>
case Train_Set.Pre_Emph is
when DP_Info.Emph_Level_0 => Trans_Select := 9;
when others => Trans_Select := 0;
end case;
end case;
end if;
-- enable DDI buffer
Registers.Unset_And_Set_Mask
(Register => DDI_Regs (Port).BUF_CTL,
@@ -309,6 +319,10 @@ package body HW.GFX.GMA.Connectors.DDI is
if not Was_Enabled then
Time.U_Delay (600); -- wait >= 518us (intel spec)
end if;
if Config.Has_DDI_PHYs then
DDI_Phy.Set_DP_Signal_Levels (Port, Train_Set);
end if;
end Set_Signal_Levels;
----------------------------------------------------------------------------
@@ -344,7 +358,7 @@ package body HW.GFX.GMA.Connectors.DDI is
Registers.Write
(Register => DDI_Regs (Port).PORT_CLK_SEL,
Value => PORT_CLK_SEL_NONE);
else
elsif not Config.Has_DDI_PHYs then
Registers.Set_Mask
(Register => Registers.DPLL_CTRL2,
Mask => DPLL_CTRL2_DDIx_CLOCK_OFF (Port));
@@ -472,7 +486,7 @@ package body HW.GFX.GMA.Connectors.DDI is
Registers.Write
(Register => DDI_Regs (Port_Cfg.Port).PORT_CLK_SEL,
Value => PLL_Hint);
else
elsif not Config.Has_DDI_PHYs then
Registers.Unset_And_Set_Mask
(Register => Registers.DPLL_CTRL2,
Mask_Unset => DPLL_CTRL2_DDIx_CLOCK_OFF (Port_Cfg.Port) or
@@ -489,6 +503,14 @@ package body HW.GFX.GMA.Connectors.DDI is
(Port => Port_Cfg.Port,
Link => Port_Cfg.DP,
Success => Success);
elsif Config.Has_DDI_PHYs and then
Port_Cfg.Display = HDMI and then
Port_Cfg.Port in DDI_Phy.DDI_Phy_Port
then
DDI_Phy.Set_HDMI_Signal_Levels
(Port => Port_Cfg.Port,
Level => DDI_Phy.HDMI_Buf_Trans_Range'Last);
Success := True;
else
Success := True;
end if;

View File

@@ -0,0 +1,35 @@
--
-- Copyright (C) 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
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- 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 HW.GFX.GMA.DP_Info;
private package HW.GFX.GMA.DDI_Phy_Stub is
subtype DDI_Phy_Port is GPU_Port;
Max_V_Swing : constant DP_Info.DP_Voltage_Swing := DP_Info.VS_Level_0;
type Emph_Array is array (DP_Info.DP_Voltage_Swing) of DP_Info.DP_Pre_Emph;
Max_Pre_Emph : constant Emph_Array := (others => DP_Info.Emph_Level_0);
procedure Set_DP_Signal_Levels
(Port : Digital_Port;
Train_Set : DP_Info.Train_Set) is null;
type HDMI_Buf_Trans_Range is range 0 .. 9;
procedure Set_HDMI_Signal_Levels
(Port : DDI_Phy_Port;
Level : HDMI_Buf_Trans_Range) is null;
end HW.GFX.GMA.DDI_Phy_Stub;

View File

@@ -82,10 +82,14 @@ is
if Config.Internal_Is_EDP then
-- DDI_A
Registers.Is_Set_Mask
(Register => Registers.DDI_BUF_CTL_A,
Mask => DDI_PORT_DETECTED (DIGI_A),
Result => Internal_Detected);
if Config.Has_Presence_Straps then
Registers.Is_Set_Mask
(Register => Registers.DDI_BUF_CTL_A,
Mask => DDI_PORT_DETECTED (DIGI_A),
Result => Internal_Detected);
else
Internal_Detected := True; -- XXX: Linux' i915 contains a fixme.
end if;
if Internal_Detected then
if Config.Has_HOTPLUG_CTL then
Registers.Set_Mask
@@ -114,10 +118,14 @@ is
-- DDI_[BCD]
for Port in Ext_Digital_Port range DIGI_B .. Config.Last_Digital_Port loop
Registers.Is_Set_Mask
(Register => Registers.SFUSE_STRAP,
Mask => DDI_PORT_DETECTED (Port),
Result => DDI_Detected);
if Config.Has_Presence_Straps then
Registers.Is_Set_Mask
(Register => Registers.SFUSE_STRAP,
Mask => DDI_PORT_DETECTED (Port),
Result => DDI_Detected);
else
DDI_Detected := True;
end if;
Config.Valid_Port (To_HDMI_Port (Port)) :=
Config.Valid_Port (To_HDMI_Port (Port)) and DDI_Detected;
Config.Valid_Port (To_DP_Port (Port)) :=

View File

@@ -35,6 +35,7 @@ is
Has_Internal_Display : constant Boolean := Internal_Display /= None;
Internal_Is_EDP : constant Boolean := Internal_Display = DP;
Has_Presence_Straps : constant Boolean := CPU /= Broxton;
----- CPU pipe: --------
Disable_Trickle_Feed : constant Boolean := not
@@ -57,6 +58,7 @@ is
Use_PP_VDD_Override : constant Boolean := CPU <= Ivybridge;
----- PCH/FDI: ---------
Has_PCH : constant Boolean := CPU /= Broxton;
Has_PCH_DAC : constant Boolean := CPU in Ironlake .. Ivybridge or
(CPU in Broadwell .. Haswell
and CPU_Var = Normal);
@@ -92,7 +94,11 @@ is
Need_DP_Aux_Mutex : constant Boolean := False; -- Skylake & (PSR | GTC)
Has_DDI_PHYs : constant Boolean := CPU = Broxton;
----- GMBUS: -----------
Ungate_GMBUS_Unit_Level : constant Boolean := CPU >= Skylake;
GMBUS_Alternative_Pins : constant Boolean := CPU = Broxton;
----- Power: -----------
Has_IPS : constant Boolean := (CPU = Haswell and

View File

@@ -37,6 +37,9 @@ package body HW.GFX.GMA.I2C is
GMBUS0_PIN_PAIR_SELECT_DIGI_C : constant := 4 * 2 ** 0;
GMBUS0_PIN_PAIR_SELECT_DIGI_B : constant := 5 * 2 ** 0;
GMBUS0_PIN_PAIR_SELECT_DIGI_D : constant := 6 * 2 ** 0;
-- Broxton uses different pins
GMBUS0_PIN_PAIR_SELECT_BXT_B : constant := 1 * 2 ** 0;
GMBUS0_PIN_PAIR_SELECT_BXT_C : constant := 2 * 2 ** 0;
GMBUS1_SOFTWARE_CLEAR_INTERRUPT : constant := 1 * 2 ** 31;
GMBUS1_SOFTWARE_READY : constant := 1 * 2 ** 30;
@@ -85,13 +88,19 @@ package body HW.GFX.GMA.I2C is
function GMBUS0_PIN_PAIR_SELECT (Port : PCH_Port) return Word32 is
begin
return
(case Port is
when PCH_DAC => GMBUS0_PIN_PAIR_SELECT_DAC,
when PCH_LVDS => GMBUS0_PIN_PAIR_SELECT_LVDS,
when PCH_HDMI_B => GMBUS0_PIN_PAIR_SELECT_DIGI_B,
when PCH_HDMI_C => GMBUS0_PIN_PAIR_SELECT_DIGI_C,
when PCH_HDMI_D => GMBUS0_PIN_PAIR_SELECT_DIGI_D,
when others => GMBUS0_PIN_PAIR_SELECT_NONE);
(if Config.GMBUS_Alternative_Pins then
(case Port is
when PCH_HDMI_B => GMBUS0_PIN_PAIR_SELECT_BXT_B,
when PCH_HDMI_C => GMBUS0_PIN_PAIR_SELECT_BXT_C,
when others => GMBUS0_PIN_PAIR_SELECT_NONE)
else
(case Port is
when PCH_DAC => GMBUS0_PIN_PAIR_SELECT_DAC,
when PCH_LVDS => GMBUS0_PIN_PAIR_SELECT_LVDS,
when PCH_HDMI_B => GMBUS0_PIN_PAIR_SELECT_DIGI_B,
when PCH_HDMI_C => GMBUS0_PIN_PAIR_SELECT_DIGI_C,
when PCH_HDMI_D => GMBUS0_PIN_PAIR_SELECT_DIGI_D,
when others => GMBUS0_PIN_PAIR_SELECT_NONE));
end GMBUS0_PIN_PAIR_SELECT;
----------------------------------------------------------------------------

View File

@@ -381,10 +381,12 @@ is
-------------------- Now restart from a clean state ---------------------
Power_And_Clocks.Initialize;
Registers.Unset_And_Set_Mask
(Register => Registers.PCH_RAWCLK_FREQ,
Mask_Unset => PCH_RAWCLK_FREQ_MASK,
Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
if Config.Has_PCH then
Registers.Unset_And_Set_Mask
(Register => Registers.PCH_RAWCLK_FREQ,
Mask_Unset => PCH_RAWCLK_FREQ_MASK,
Mask_Set => PCH_RAWCLK_FREQ (Config.Default_RawClk_Freq));
end if;
Initialized := True;

View File

@@ -1,3 +1,4 @@
gfxinit-y += hw-gfx-gma-ddi_phy.ads
gfxinit-y += hw-gfx-gma-plls-dpll.adb
gfxinit-y += hw-gfx-gma-plls-dpll.ads
gfxinit-y += hw-gfx-gma-plls-dpll_0.adb

View File

@@ -0,0 +1,17 @@
--
-- Copyright (C) 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
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- 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 HW.GFX.GMA.DDI_Phy_Stub;
private package HW.GFX.GMA.DDI_Phy renames HW.GFX.GMA.DDI_Phy_Stub;