Initial upstream commit

The history contained unlicensed code so everything got squashed, sorry.

Change-Id: I9f5775208f9df6fb29074bf3bc498f68cb17b3a0
Signed-off-by: Nico Huber <nico.huber@secunet.com>
diff --git a/common/ironlake/hw-gfx-gma-connectors-edp.adb b/common/ironlake/hw-gfx-gma-connectors-edp.adb
new file mode 100644
index 0000000..96930f3
--- /dev/null
+++ b/common/ironlake/hw-gfx-gma-connectors-edp.adb
@@ -0,0 +1,297 @@
+--
+-- Copyright (C) 2015-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 HW.Time;
+with HW.GFX.DP_Training;
+with HW.GFX.GMA.DP_Info;
+with HW.GFX.GMA.DP_Aux_Ch;
+with HW.GFX.GMA.Registers;
+
+with HW.Debug;
+with GNAT.Source_Info;
+
+package body HW.GFX.GMA.Connectors.EDP
+is
+
+   DP_CTL_DISPLAYPORT_ENABLE        : constant :=  1 * 2 ** 31;
+   DP_CTL_PIPE_SELECT_MASK          : constant :=  3 * 2 ** 29;
+   DP_CTL_PIPE_SELECT_SHIFT         : constant :=           29;
+   DP_CTL_VSWING_EMPH_SET_MASK      : constant := 63 * 2 ** 22;
+   DP_CTL_PORT_WIDTH_MASK           : constant :=  7 * 2 ** 19;
+   DP_CTL_PORT_WIDTH_1_LANE         : constant :=  0 * 2 ** 19;
+   DP_CTL_PORT_WIDTH_2_LANES        : constant :=  1 * 2 ** 19;
+   DP_CTL_PORT_WIDTH_4_LANES        : constant :=  3 * 2 ** 19;
+   DP_CTL_ENHANCED_FRAMING_ENABLE   : constant :=  1 * 2 ** 18;
+   DP_CTL_PLL_FREQUENCY_MASK        : constant :=  3 * 2 ** 16;
+   DP_CTL_PLL_FREQUENCY_270         : constant :=  0 * 2 ** 16;
+   DP_CTL_PLL_FREQUENCY_162         : constant :=  1 * 2 ** 16;
+   DP_CTL_PORT_REVERSAL             : constant :=  1 * 2 ** 15;
+   DP_CTL_PLL_ENABLE                : constant :=  1 * 2 ** 14;
+   DP_CTL_LINK_TRAIN_MASK           : constant :=  3 * 2 **  8;
+   DP_CTL_LINK_TRAIN_PAT1           : constant :=  0 * 2 **  8;
+   DP_CTL_LINK_TRAIN_PAT2           : constant :=  1 * 2 **  8;
+   DP_CTL_LINK_TRAIN_IDLE           : constant :=  2 * 2 **  8;
+   DP_CTL_LINK_TRAIN_NORMAL         : constant :=  3 * 2 **  8;
+   DP_CTL_ALT_SCRAMBLER_RESET       : constant :=  1 * 2 **  6;
+   DP_CTL_VSYNC_ACTIVE_HIGH         : constant :=  1 * 2 **  4;
+   DP_CTL_HSYNC_ACTIVE_HIGH         : constant :=  1 * 2 **  3;
+   DP_CTL_PORT_DETECT               : constant :=  1 * 2 **  2;
+
+   -- TODO? Values are for Ivy Bridge only
+   DP_CTL_VSWING_0_EMPH_0 : constant := 1 * 2 ** 27 + 1 * 2 ** 24 + 0 * 2 ** 22;
+   DP_CTL_VSWING_0_EMPH_1 : constant := 1 * 2 ** 27 + 2 * 2 ** 24 + 2 * 2 ** 22;
+   DP_CTL_VSWING_0_EMPH_2 : constant := 1 * 2 ** 27 + 3 * 2 ** 24 + 3 * 2 ** 22;
+   DP_CTL_VSWING_1_EMPH_0 : constant := 1 * 2 ** 27 + 4 * 2 ** 24 + 0 * 2 ** 22;
+   DP_CTL_VSWING_1_EMPH_1 : constant := 1 * 2 ** 27 + 5 * 2 ** 24 + 2 * 2 ** 22;
+   DP_CTL_VSWING_2_EMPH_0 : constant := 1 * 2 ** 27 + 6 * 2 ** 24 + 0 * 2 ** 22;
+   DP_CTL_VSWING_2_EMPH_1 : constant := 1 * 2 ** 27 + 7 * 2 ** 24 + 2 * 2 ** 22;
+
+   type DP_CTL_PORT_WIDTH_T is array (DP_Lane_Count) of Word32;
+   DP_CTL_PORT_WIDTH : constant DP_CTL_PORT_WIDTH_T :=
+      DP_CTL_PORT_WIDTH_T'
+     (DP_Lane_Count_1 => DP_CTL_PORT_WIDTH_1_LANE,
+      DP_Lane_Count_2 => DP_CTL_PORT_WIDTH_2_LANES,
+      DP_Lane_Count_4 => DP_CTL_PORT_WIDTH_4_LANES);
+
+   type DP_CTL_LINK_TRAIN_Array is array (DP_Info.Training_Pattern) of Word32;
+   DP_CTL_LINK_TRAIN : constant DP_CTL_LINK_TRAIN_Array :=
+      DP_CTL_LINK_TRAIN_Array'
+     (DP_Info.TP_1      => DP_CTL_LINK_TRAIN_PAT1,
+      DP_Info.TP_2      => DP_CTL_LINK_TRAIN_PAT2,
+      DP_Info.TP_3      => DP_CTL_LINK_TRAIN_PAT2,
+      DP_Info.TP_Idle   => DP_CTL_LINK_TRAIN_IDLE,
+      DP_Info.TP_None   => DP_CTL_LINK_TRAIN_NORMAL);
+
+   ----------------------------------------------------------------------------
+
+   procedure Pre_Training is
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Registers.Unset_And_Set_Mask
+        (Register    => Registers.DP_CTL_A,
+         Mask_Unset  => DP_CTL_LINK_TRAIN_MASK,
+         Mask_Set    => DP_CTL_LINK_TRAIN (DP_Info.TP_1) or
+                        DP_CTL_DISPLAYPORT_ENABLE);
+   end Pre_Training;
+
+   ----------------------------------------------------------------------------
+
+   pragma Warnings (GNATprove, Off, "unused variable ""Port""",
+                    Reason => "Needed for a common interface");
+   function Max_V_Swing
+     (Port : Digital_Port)
+      return DP_Info.DP_Voltage_Swing
+   is
+   begin
+      return DP_Info.VS_Level_2;
+   end Max_V_Swing;
+
+   function Max_Pre_Emph
+     (Port        : Digital_Port;
+      Train_Set   : DP_Info.Train_Set)
+      return DP_Info.DP_Pre_Emph
+   is
+   begin
+      return
+        (case Train_Set.Voltage_Swing is
+            when DP_Info.VS_Level_0 => DP_Info.Emph_Level_2,
+            when DP_Info.VS_Level_1 |
+                 DP_Info.VS_Level_2 => DP_Info.Emph_Level_1,
+            when others             => DP_Info.Emph_Level_0);
+   end Max_Pre_Emph;
+
+   ----------------------------------------------------------------------------
+
+   pragma Warnings (GNATprove, Off, "unused variable ""Link""",
+                    Reason => "Needed for a common interface");
+   procedure Set_Training_Pattern
+     (Port     : Digital_Port;
+      Link     : DP_Link;
+      Pattern  : DP_Info.Training_Pattern)
+   is
+      use type DP_Info.Training_Pattern;
+   begin
+      if Pattern < DP_Info.TP_Idle then
+         Registers.Unset_And_Set_Mask
+           (Register    => Registers.DP_CTL_A,
+            Mask_Unset  => DP_CTL_LINK_TRAIN_MASK,
+            Mask_Set    => DP_CTL_LINK_TRAIN (Pattern));
+      else
+         -- send at least 5 idle patterns
+         Registers.Unset_And_Set_Mask
+           (Register    => Registers.DP_CTL_A,
+            Mask_Unset  => DP_CTL_LINK_TRAIN_MASK,
+            Mask_Set    => DP_CTL_LINK_TRAIN (DP_Info.TP_Idle));
+
+         -- we switch to normal frame delivery later in Post_On procedure
+      end if;
+   end Set_Training_Pattern;
+
+   procedure Set_Signal_Levels
+     (Port        : Digital_Port;
+      Link        : DP_Link;
+      Train_Set   : DP_Info.Train_Set)
+   is
+      VSwing_Emph : Word32;
+   begin
+      VSwing_Emph :=
+        (case Train_Set.Voltage_Swing is
+            when DP_Info.VS_Level_0 =>
+              (case Train_Set.Pre_Emph is
+                  when DP_Info.Emph_Level_0  => DP_CTL_VSWING_0_EMPH_0,
+                  when DP_Info.Emph_Level_1  => DP_CTL_VSWING_0_EMPH_1,
+                  when DP_Info.Emph_Level_2  => DP_CTL_VSWING_0_EMPH_2,
+                  when others                => DP_CTL_VSWING_0_EMPH_0),
+            when DP_Info.VS_Level_1 =>
+              (case Train_Set.Pre_Emph is
+                  when DP_Info.Emph_Level_0  => DP_CTL_VSWING_1_EMPH_0,
+                  when DP_Info.Emph_Level_1  => DP_CTL_VSWING_1_EMPH_1,
+                  when others                => DP_CTL_VSWING_1_EMPH_0),
+            when DP_Info.VS_Level_2 =>
+              (case Train_Set.Pre_Emph is
+                  when DP_Info.Emph_Level_0  => DP_CTL_VSWING_2_EMPH_0,
+                  when DP_Info.Emph_Level_1  => DP_CTL_VSWING_2_EMPH_1,
+                  when others                => DP_CTL_VSWING_2_EMPH_0),
+            when others                      => DP_CTL_VSWING_0_EMPH_0);
+
+      Registers.Unset_And_Set_Mask
+        (Register    => Registers.DP_CTL_A,
+         Mask_Unset  => DP_CTL_VSWING_EMPH_SET_MASK,
+         Mask_Set    => VSwing_Emph);
+   end Set_Signal_Levels;
+   pragma Warnings (GNATprove, On, "unused variable ""Port""");
+   pragma Warnings (GNATprove, On, "unused variable ""Link""");
+
+   ----------------------------------------------------------------------------
+
+   procedure Pre_On
+     (Port_Cfg    : Port_Config;
+      Pipe_Hint   : Word32)
+   is
+      DP_CTL_Set : Word32;
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      DP_CTL_Set :=
+         Shift_Left (Pipe_Hint, DP_CTL_PIPE_SELECT_SHIFT) or
+         DP_CTL_PORT_WIDTH (Port_Cfg.DP.Lane_Count);
+
+      if Port_Cfg.DP.Enhanced_Framing then
+         DP_CTL_Set := DP_CTL_Set or DP_CTL_ENHANCED_FRAMING_ENABLE;
+      end if;
+
+      case Port_Cfg.DP.Bandwidth is
+         when DP_Bandwidth_1_62 =>
+            DP_CTL_Set := DP_CTL_Set or DP_CTL_PLL_FREQUENCY_162;
+         when DP_Bandwidth_2_7 =>
+            DP_CTL_Set := DP_CTL_Set or DP_CTL_PLL_FREQUENCY_270;
+         when others =>
+            null;
+      end case;
+
+      if Port_Cfg.Mode.V_Sync_Active_High then
+         DP_CTL_Set := DP_CTL_Set or DP_CTL_VSYNC_ACTIVE_HIGH;
+      end if;
+      if Port_Cfg.Mode.H_Sync_Active_High then
+         DP_CTL_Set := DP_CTL_Set or DP_CTL_HSYNC_ACTIVE_HIGH;
+      end if;
+
+      Registers.Write
+        (Register => Registers.DP_CTL_A,
+         Value    => DP_CTL_Set);
+
+      Registers.Write
+        (Register => Registers.DP_CTL_A,
+         Value    => DP_CTL_PLL_ENABLE or DP_CTL_Set);
+      Registers.Posting_Read (Registers.DP_CTL_A);
+      Time.U_Delay (20);
+   end Pre_On;
+
+   ----------------------------------------------------------------------------
+
+   procedure Post_On
+     (Link     : in     DP_Link;
+      Success  :    out Boolean)
+   is
+      pragma Warnings (GNATprove, Off, "unused variable ""Port""",
+                       Reason => "Needed for a common interface");
+      function To_DP (Port : Digital_Port) return DP_Port
+      is
+      begin
+         return DP_A;
+      end To_DP;
+      pragma Warnings (GNATprove, On, "unused variable ""Port""");
+      package Training is new DP_Training
+        (TPS3_Supported    => False,
+         T                 => Digital_Port,
+         Aux_T             => DP_Port,
+         Aux_Ch            => DP_Aux_Ch,
+         DP_Info           => DP_Info,
+         To_Aux            => To_DP,
+         Max_V_Swing       => Max_V_Swing,
+         Max_Pre_Emph      => Max_Pre_Emph,
+         Set_Pattern       => Set_Training_Pattern,
+         Set_Signal_Levels => Set_Signal_Levels,
+         Off               => Off);
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Training.Train_DP
+        (Port        => DIGI_A,
+         Link        => Link,
+         Success     => Success);
+
+      if Success then
+         Registers.Unset_And_Set_Mask
+           (Register    => Registers.DP_CTL_A,
+            Mask_Unset  => DP_CTL_LINK_TRAIN_MASK,
+            Mask_Set    => DP_CTL_LINK_TRAIN_NORMAL);
+      end if;
+   end Post_On;
+
+   ----------------------------------------------------------------------------
+
+   procedure Off (Port : Digital_Port)
+   is
+      Enabled : Boolean;
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Registers.Unset_And_Set_Mask
+        (Register    => Registers.DP_CTL_A,
+         Mask_Unset  => DP_CTL_LINK_TRAIN_MASK,
+         Mask_Set    => DP_CTL_LINK_TRAIN_IDLE);
+      Registers.Posting_Read (Registers.DP_CTL_A);
+
+      Registers.Unset_Mask
+        (Register => Registers.DP_CTL_A,
+         Mask     => DP_CTL_DISPLAYPORT_ENABLE);
+      -- implicit Posting_Read below
+
+      Registers.Is_Set_Mask
+        (Register => Registers.DP_CTL_A,
+         Mask     => DP_CTL_PLL_ENABLE,
+         Result   => Enabled);
+
+      Registers.Write
+        (Register => Registers.DP_CTL_A,
+         Value    => 16#0000_0000#);
+      Registers.Posting_Read (Registers.DP_CTL_A);
+
+      if Enabled then
+         Time.U_Delay (20);
+      end if;
+   end Off;
+
+end HW.GFX.GMA.Connectors.EDP;