gma: Update transcoder setup for TGL

Tiger Lake requires configuration (but not enablement) of the
transcoder during the modeset sequence itself, so this patch adds a
new Config option to accommodate that and refactors the transcoder
setup into two new procedures.  There should be no functional
differences for other generations.

(cherry picked from commit 4be2e75658602356cfa2fab5cdb1157ab27f1b3a)

Original-Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Original-Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Original-Change-Id: I4d7e2a24c54fcd9994f44bb0b10924dce48068e5
Original-Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/67493
Original-Tested-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-by: Nico Huber <nico.h@gmx.de>
GitOrigin-RevId: 4be2e75658602356cfa2fab5cdb1157ab27f1b3a
Change-Id: I5f37fc36f724dae7691c8734340b8ccf813b5ee6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/libgfxinit/+/5343639
Tested-by: Jonathon Murphy <jpmurphy@google.com>
Reviewed-by: Jonathon Murphy <jpmurphy@google.com>
Commit-Queue: Jonathon Murphy <jpmurphy@google.com>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index 0bc7d80..dd6c2f8 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -196,7 +196,7 @@
    Has_Tertiary_Pipe             : <ilkbool> := Ivybridge_On;
    Disable_Trickle_Feed          : <genbool> := not Gen_Haswell;
    Pipe_Enabled_Workaround       : <hswbool> := CPU_Broadwell;
-   Has_EDP_Transcoder            : <genbool> := Haswell_On;
+   Has_EDP_Transcoder            : <genbool> := Haswell_On and not Tigerlake_On;
    Use_PDW_For_EDP_Scaling       : <hswbool> := CPU_Haswell;
    Has_Pipe_DDI_Func             : <genbool> := Haswell_On;
    Has_Trans_Clk_Sel             : <genbool> := Haswell_On;
@@ -212,6 +212,9 @@
    Has_GMCH_VGACNTRL             : <genbool> := Gen_G45;
    Has_GMCH_PFIT_CONTROL         : <genbool> := Gen_G45;
 
+   ----------- Transcoder -------
+   Need_Early_Transcoder_Setup   : <genbool> := Tigerlake_On;
+
    --------- Panel power: -------
    Has_PP_Write_Protection       : <genbool> := Up_To_Ironlake;
    Has_PP_Port_Select            : <genbool> := Up_To_Ironlake;
@@ -263,6 +266,8 @@
    -- might be disabled by x4 eDP:
    Has_DDI_E                     : <hswsklbool> := Has_DDI_D;
 
+   Has_TGL_DDI_Select            : <genbool> := Tigerlake_On;
+
    Has_DDI_Buffer_Trans          : <genbool> := Haswell_On and not Has_DDI_PHYs;
    Has_Low_Voltage_Swing         : <genbool> := Broxton_On;
    Has_Iboost_Config             : <genbool> := Skylake_On;
diff --git a/common/hw-gfx-gma-transcoder.adb b/common/hw-gfx-gma-transcoder.adb
index e74d769..9e85b75 100644
--- a/common/hw-gfx-gma-transcoder.adb
+++ b/common/hw-gfx-gma-transcoder.adb
@@ -15,6 +15,7 @@
 with HW.Debug;
 with GNAT.Source_Info;
 
+with HW.GFX.GMA.Config_Helpers;
 with HW.GFX.GMA.DP_Info;
 
 package body HW.GFX.GMA.Transcoder is
@@ -38,6 +39,7 @@
    ----------------------------------------------------------------------------
 
    TRANS_CLK_SEL_PORT_NONE : constant := 0 * 2 ** 29;
+   TRANS_CLK_SEL_MASK : constant := 16#f000_0000#;
 
    type TRANS_CLK_SEL_PORT_Array is
       array (Digital_Port) of Word32;
@@ -48,6 +50,19 @@
       DIGI_D => 4 * 2 ** 29,
       DIGI_E => 5 * 2 ** 29);
 
+   function TGL_TRANS_CLK_SEL_PORT (Port : TGL_Digital_Port) return Word32 is
+   (case Port is
+      when DIGI_A  => 1 * 2 ** 28,
+      when DIGI_B  => 2 * 2 ** 28,
+      when DIGI_C  => 3 * 2 ** 28,
+      when DDI_TC1 => 4 * 2 ** 28,
+      when DDI_TC2 => 5 * 2 ** 28,
+      when DDI_TC3 => 6 * 2 ** 28,
+      when DDI_TC4 => 7 * 2 ** 28,
+      when DDI_TC5 => 8 * 2 ** 28,
+      when DDI_TC6 => 9 * 2 ** 28,
+      when others  => 0);
+
    TRANS_CONF_ENABLE          : constant := 1 * 2 ** 31;
    TRANS_CONF_ENABLED_STATUS  : constant := 1 * 2 ** 30;
    TRANS_CONF_ENABLE_DITHER   : constant := 1 * 2 **  4;
@@ -85,6 +100,21 @@
       DIGI_D => 3 * 2 ** 28,
       DIGI_E => 4 * 2 ** 28);
 
+   function TGL_DDI_FUNC_CTL_DDI_SELECT (Port : TGL_Digital_Port)
+      return Word32
+   is
+     (case Port is
+      when DIGI_A  => 1 * 2 ** 27,
+      when DIGI_B  => 2 * 2 ** 27,
+      when DIGI_C  => 3 * 2 ** 27,
+      when DDI_TC1 => 4 * 2 ** 27,
+      when DDI_TC2 => 5 * 2 ** 27,
+      when DDI_TC3 => 6 * 2 ** 27,
+      when DDI_TC4 => 7 * 2 ** 27,
+      when DDI_TC5 => 8 * 2 ** 27,
+      when DDI_TC6 => 9 * 2 ** 27,
+      when others  => 0);
+
    type DDI_Mode_Array is array (Display_Type) of Word32;
    DDI_FUNC_CTL_MODE_SELECT : constant DDI_Mode_Array :=
      (VGA      => DDI_FUNC_CTL_MODE_SELECT_FDI,
@@ -204,6 +234,7 @@
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
 
       if Config.Has_Trans_Clk_Sel and then
+         not Config.Need_Early_Transcoder_Setup and then
          Trans.CLK_SEL /= Registers.Invalid_Register and then
          Port_Cfg.Port in Digital_Port
       then
@@ -228,6 +259,69 @@
 
    ----------------------------------------------------------------------------
 
+   procedure Enable_Pipe_Clock (Pipe : Pipe_Index; Port_Cfg : Port_Config)
+   is
+      use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
+
+      Trans : Transcoder_Regs renames
+               Transcoders (Get_Idx (Pipe, Port_Cfg.Port));
+   begin
+      if Config.Need_Early_Transcoder_Setup and then
+         Trans.CLK_SEL /= Registers.Invalid_Register and then
+         Port_Cfg.Port in TGL_Digital_Port
+         then
+            Registers.Unset_And_Set_Mask
+              (Register   => Trans.CLK_SEL,
+               Mask_Unset => TRANS_CLK_SEL_MASK,
+               Mask_Set   => TGL_TRANS_CLK_SEL_PORT (Port_Cfg.Port));
+      end if;
+   end Enable_Pipe_Clock;
+
+   ----------------------------------------------------------------------------
+
+   procedure Configure (Pipe : Pipe_Index; Port_Cfg : Port_Config; Scale : Boolean)
+   is
+      Trans : Transcoder_Regs renames
+               Transcoders (Get_Idx (Pipe, Port_Cfg.Port));
+      Lane_Count : constant DP_Lane_Count :=
+        (if Port_Cfg.Is_FDI then Port_Cfg.FDI.Lane_Count else Port_Cfg.DP.Lane_Count);
+      EDP_Select : constant Word32 :=
+        (if Config.Has_TGL_DDI_Select
+         then 0
+         else
+           (if Pipe = Primary and
+            (not Config.Use_PDW_For_EDP_Scaling or else not Scale)
+            then
+               DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON
+            else
+               DDI_FUNC_CTL_EDP_SELECT (Pipe)));
+      DDI_Select : constant Word32 :=
+        (if Config.Has_TGL_DDI_Select and Port_Cfg.Port in TGL_Digital_Port then
+            TGL_DDI_FUNC_CTL_DDI_SELECT (Port_Cfg.Port)
+         else
+            (if Port_Cfg.Port in Digital_Port
+             then
+                DDI_FUNC_CTL_DDI_SELECT (Port_Cfg.Port)
+             else 0));
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+      if Config.Has_Pipe_DDI_Func then
+         if Is_Digital_Port (Port_Cfg.Port) then
+            Registers.Write
+              (Register => Trans.DDI_FUNC_CTL,
+               Value    => DDI_Select or
+                        DDI_FUNC_CTL_MODE_SELECT (Port_Cfg.Display) or
+                        DDI_FUNC_CTL_BPC (Port_Cfg.Mode.BPC) or
+                        DDI_FUNC_CTL_VSYNC (Port_Cfg.Mode.V_Sync_Active_High) or
+                        DDI_FUNC_CTL_HSYNC (Port_Cfg.Mode.H_Sync_Active_High) or
+                        EDP_Select or
+                        DDI_FUNC_CTL_PORT_WIDTH (Lane_Count));
+         end if;
+      end if;
+   end Configure;
+
+   ----------------------------------------------------------------------------
+
    procedure On
      (Pipe     : Pipe_Index;
       Port_Cfg : Port_Config;
@@ -236,27 +330,16 @@
    is
       Trans : Transcoder_Regs renames
                Transcoders (Get_Idx (Pipe, Port_Cfg.Port));
-      Lane_Count : constant DP_Lane_Count :=
-        (if Port_Cfg.Is_FDI then Port_Cfg.FDI.Lane_Count else Port_Cfg.DP.Lane_Count);
-      EDP_Select : constant Word32 :=
-        (if Pipe = Primary and
-            (not Config.Use_PDW_For_EDP_Scaling or else not Scale)
-         then
-            DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON
-         else
-            DDI_FUNC_CTL_EDP_SELECT (Pipe));
    begin
-      if Config.Has_Pipe_DDI_Func and Port_Cfg.Port in Digital_Port then
-         Registers.Write
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+      if not Config.Need_Early_Transcoder_Setup then
+         Configure (Pipe, Port_Cfg, Scale);
+      end if;
+
+      if Config.Has_Pipe_DDI_Func and Is_Digital_Port (Port_Cfg.Port) then
+         Registers.Set_Mask
            (Register => Trans.DDI_FUNC_CTL,
-            Value    => DDI_FUNC_CTL_ENABLE or
-                        DDI_FUNC_CTL_DDI_SELECT (Port_Cfg.Port) or
-                        DDI_FUNC_CTL_MODE_SELECT (Port_Cfg.Display) or
-                        DDI_FUNC_CTL_BPC (Port_Cfg.Mode.BPC) or
-                        DDI_FUNC_CTL_VSYNC (Port_Cfg.Mode.V_Sync_Active_High) or
-                        DDI_FUNC_CTL_HSYNC (Port_Cfg.Mode.H_Sync_Active_High) or
-                        EDP_Select or
-                        DDI_FUNC_CTL_PORT_WIDTH (Lane_Count));
+            Mask     => DDI_FUNC_CTL_ENABLE);
       end if;
 
       Registers.Write
@@ -360,15 +443,20 @@
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
 
       if Config.Has_Per_Pipe_SRD then
-         for P in Transcoder_Index 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);
+         declare
+            First_Transcoder : constant Transcoder_Index :=
+              (if Config.Has_EDP_Transcoder then Trans_EDP else Trans_A);
+         begin
+            for P in Transcoder_Index range First_Transcoder .. Transcoder_Index'Last 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;
+                  pragma Debug (Debug.Put_Line ("Disabled PSR."));
+               end if;
+            end loop;
+         end;
       else
          Registers.Is_Set_Mask (Registers.SRD_CTL, SRD_CTL_ENABLE, Enabled);
          if Enabled then
diff --git a/common/hw-gfx-gma-transcoder.ads b/common/hw-gfx-gma-transcoder.ads
index 4a24996..c89ee57 100644
--- a/common/hw-gfx-gma-transcoder.ads
+++ b/common/hw-gfx-gma-transcoder.ads
@@ -18,6 +18,8 @@
 private package HW.GFX.GMA.Transcoder
 is
 
+   procedure Enable_Pipe_Clock (Pipe : Pipe_Index; Port_Cfg : Port_Config);
+   procedure Configure (Pipe : Pipe_Index; Port_Cfg : Port_Config; Scale : Boolean);
    procedure Setup (Pipe : Pipe_Index; Port_Cfg : Port_Config);
    procedure On
      (Pipe     : Pipe_Index;
@@ -52,6 +54,7 @@
          DDI_FUNC_CTL   : Registers.Registers_Index;
          MSA_MISC       : Registers.Registers_Index;
          CLK_SEL        : Registers.Registers_Invalid_Index;
+         PIPE_ARB_CTL   : Registers.Registers_Invalid_Index;
       end record;
 
    type Transcoder_Array is array (Transcoder_Index) of Transcoder_Regs;
@@ -100,7 +103,8 @@
          LINK_N1        => Registers.PIPE_EDP_LINK_N1,
          DDI_FUNC_CTL   => Registers.PIPE_EDP_DDI_FUNC_CTL,
          MSA_MISC       => Registers.PIPE_EDP_MSA_MISC,
-         CLK_SEL        => Registers.Invalid_Register),
+         CLK_SEL        => Registers.Invalid_Register,
+         PIPE_ARB_CTL   => Registers.Invalid_Register),
       Trans_A =>
         (HTOTAL         => Registers.HTOTAL_A,
          HBLANK         => Registers.HBLANK_A,
@@ -115,7 +119,8 @@
          LINK_N1        => PIPE_LINK_N1 (0),
          DDI_FUNC_CTL   => Registers.PIPEA_DDI_FUNC_CTL,
          MSA_MISC       => Registers.PIPEA_MSA_MISC,
-         CLK_SEL        => Registers.TRANSA_CLK_SEL),
+         CLK_SEL        => Registers.TRANSA_CLK_SEL,
+         PIPE_ARB_CTL   => Registers.PIPEA_ARB_CTL),
       Trans_B =>
         (HTOTAL         => Registers.HTOTAL_B,
          HBLANK         => Registers.HBLANK_B,
@@ -130,7 +135,8 @@
          LINK_N1        => PIPE_LINK_N1 (1),
          DDI_FUNC_CTL   => Registers.PIPEB_DDI_FUNC_CTL,
          MSA_MISC       => Registers.PIPEB_MSA_MISC,
-         CLK_SEL        => Registers.TRANSB_CLK_SEL),
+         CLK_SEL        => Registers.TRANSB_CLK_SEL,
+         PIPE_ARB_CTL   => Registers.PIPEB_ARB_CTL),
       Trans_C =>
         (HTOTAL         => Registers.HTOTAL_C,
          HBLANK         => Registers.HBLANK_C,
@@ -145,6 +151,7 @@
          LINK_N1        => Registers.PIPEC_LINK_N1,
          DDI_FUNC_CTL   => Registers.PIPEC_DDI_FUNC_CTL,
          MSA_MISC       => Registers.PIPEC_MSA_MISC,
-         CLK_SEL        => Registers.TRANSC_CLK_SEL));
+         CLK_SEL        => Registers.TRANSC_CLK_SEL,
+         PIPE_ARB_CTL   => Registers.PIPEC_ARB_CTL));
 
 end HW.GFX.GMA.Transcoder;