--
-- Copyright (C) 2015-2016 secunet Security Networks AG
-- Copyright (C) 2016 Nico Huber <nico.h@gmx.de>
--
-- 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.Config;
with HW.GFX.GMA.DP_Info;
with HW.GFX.GMA.Registers;

with HW.Debug;
with GNAT.Source_Info;

package body HW.GFX.GMA.PCH.Transcoder is

   type DPLL_SEL_Array is array (FDI_Port_Type) of Word32;
   DPLL_SEL_TRANSCODER_x_DPLL_ENABLE : constant DPLL_SEL_Array :=
     (FDI_A => 1 * 2 **  3,
      FDI_B => 1 * 2 **  7,
      FDI_C => 1 * 2 ** 11);
   DPLL_SEL_TRANSCODER_x_DPLL_SEL_MASK : constant DPLL_SEL_Array :=
     (FDI_A => 1 * 2 **  0,
      FDI_B => 1 * 2 **  4,
      FDI_C => 1 * 2 **  8);
   function DPLL_SEL_TRANSCODER_x_DPLL_SEL
     (Port : FDI_Port_Type;
      PLL  : Word32)
      return Word32
   is
   begin
      case Port is
         when FDI_A => return Shift_Left (PLL, 0);
         when FDI_B => return Shift_Left (PLL, 4);
         when FDI_C => return Shift_Left (PLL, 8);
      end case;
   end DPLL_SEL_TRANSCODER_x_DPLL_SEL;

   TRANS_CONF_TRANSCODER_ENABLE        : constant := 1 * 2 ** 31;
   TRANS_CONF_TRANSCODER_STATE         : constant := 1 * 2 ** 30;

   TRANS_CHICKEN2_TIMING_OVERRIDE      : constant := 1 * 2 ** 31;

   TRANS_DP_CTL_OUTPUT_ENABLE          : constant := 1 * 2 ** 31;
   TRANS_DP_CTL_PORT_SELECT_MASK       : constant := 3 * 2 ** 29;
   TRANS_DP_CTL_PORT_SELECT_NONE       : constant := 3 * 2 ** 29;
   TRANS_DP_CTL_ENHANCED_FRAMING       : constant := 1 * 2 ** 18;
   TRANS_DP_CTL_VSYNC_ACTIVE_HIGH      : constant := 1 * 2 **  4;
   TRANS_DP_CTL_HSYNC_ACTIVE_HIGH      : constant := 1 * 2 **  3;

   type TRANS_DP_CTL_PORT_SELECT_Array is array (PCH_Port) of Word32;
   TRANS_DP_CTL_PORT_SELECT : constant TRANS_DP_CTL_PORT_SELECT_Array :=
     (PCH_DP_B => 0 * 2 ** 29,
      PCH_DP_C => 1 * 2 ** 29,
      PCH_DP_D => 2 * 2 ** 29,
      others   => 0);

   function TRANS_DP_CTL_BPC (BPC : BPC_Type) return Word32
   is
   begin
      return
        (case BPC is
            when      6 => 2 * 2 ** 9,
            when     10 => 1 * 2 ** 9,
            when     12 => 3 * 2 ** 9,
            when others => 0 * 2 ** 9);
   end TRANS_DP_CTL_BPC;

   function TRANS_DATA_M_TU (Transfer_Unit : Positive) return Word32 is
   begin
      return Shift_Left (Word32 (Transfer_Unit - 1), 25);
   end TRANS_DATA_M_TU;

   ----------------------------------------------------------------------------

   type Transcoder_Registers is record
      HTOTAL   : Registers.Registers_Index;
      HBLANK   : Registers.Registers_Index;
      HSYNC    : Registers.Registers_Index;
      VTOTAL   : Registers.Registers_Index;
      VBLANK   : Registers.Registers_Index;
      VSYNC    : Registers.Registers_Index;
      CONF     : Registers.Registers_Index;
      DP_CTL   : Registers.Registers_Index;
      DATA_M   : Registers.Registers_Index;
      DATA_N   : Registers.Registers_Index;
      LINK_M   : Registers.Registers_Index;
      LINK_N   : Registers.Registers_Index;
      CHICKEN2 : Registers.Registers_Index;
   end record;

   type Transcoder_Registers_Array is
      array (FDI_Port_Type) of Transcoder_Registers;

   TRANS : constant Transcoder_Registers_Array := Transcoder_Registers_Array'
     (FDI_A =>
        (HTOTAL   => Registers.TRANS_HTOTAL_A,
         HBLANK   => Registers.TRANS_HBLANK_A,
         HSYNC    => Registers.TRANS_HSYNC_A,
         VTOTAL   => Registers.TRANS_VTOTAL_A,
         VBLANK   => Registers.TRANS_VBLANK_A,
         VSYNC    => Registers.TRANS_VSYNC_A,
         CONF     => Registers.TRANSACONF,
         DP_CTL   => Registers.TRANS_DP_CTL_A,
         DATA_M   => Registers.TRANSA_DATA_M1,
         DATA_N   => Registers.TRANSA_DATA_N1,
         LINK_M   => Registers.TRANSA_DP_LINK_M1,
         LINK_N   => Registers.TRANSA_DP_LINK_N1,
         CHICKEN2 => Registers.TRANSA_CHICKEN2),
      FDI_B =>
        (HTOTAL   => Registers.TRANS_HTOTAL_B,
         HBLANK   => Registers.TRANS_HBLANK_B,
         HSYNC    => Registers.TRANS_HSYNC_B,
         VTOTAL   => Registers.TRANS_VTOTAL_B,
         VBLANK   => Registers.TRANS_VBLANK_B,
         VSYNC    => Registers.TRANS_VSYNC_B,
         CONF     => Registers.TRANSBCONF,
         DP_CTL   => Registers.TRANS_DP_CTL_B,
         DATA_M   => Registers.TRANSB_DATA_M1,
         DATA_N   => Registers.TRANSB_DATA_N1,
         LINK_M   => Registers.TRANSB_DP_LINK_M1,
         LINK_N   => Registers.TRANSB_DP_LINK_N1,
         CHICKEN2 => Registers.TRANSB_CHICKEN2),
      FDI_C =>
        (HTOTAL   => Registers.TRANS_HTOTAL_C,
         HBLANK   => Registers.TRANS_HBLANK_C,
         HSYNC    => Registers.TRANS_HSYNC_C,
         VTOTAL   => Registers.TRANS_VTOTAL_C,
         VBLANK   => Registers.TRANS_VBLANK_C,
         VSYNC    => Registers.TRANS_VSYNC_C,
         CONF     => Registers.TRANSCCONF,
         DP_CTL   => Registers.TRANS_DP_CTL_C,
         DATA_M   => Registers.TRANSC_DATA_M1,
         DATA_N   => Registers.TRANSC_DATA_N1,
         LINK_M   => Registers.TRANSC_DP_LINK_M1,
         LINK_N   => Registers.TRANSC_DP_LINK_N1,
         CHICKEN2 => Registers.TRANSC_CHICKEN2));

   ----------------------------------------------------------------------------

   procedure On
     (Port_Cfg : Port_Config;
      Port     : FDI_Port_Type;
      PLL      : Word32)
   is
      Mode : constant Mode_Type := Port_Cfg.Mode;

      function Encode (LSW, MSW : Pos32) return Word32 is
      begin
         return (Word32 (LSW) - 1) or ((Word32 (MSW) - 1) * 2 ** 16);
      end Encode;
   begin
      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));

      if Config.Has_DPLL_SEL then
         Registers.Unset_And_Set_Mask
           (Register    => Registers.PCH_DPLL_SEL,
            Mask_Unset  => DPLL_SEL_TRANSCODER_x_DPLL_SEL_MASK (Port),
            Mask_Set    => DPLL_SEL_TRANSCODER_x_DPLL_ENABLE (Port) or
                           DPLL_SEL_TRANSCODER_x_DPLL_SEL (Port, PLL));
      end if;

      Registers.Write
        (Register => TRANS (Port).HTOTAL,
         Value    => Encode (Mode.H_Visible,    Mode.H_Total));
      Registers.Write
        (Register => TRANS (Port).HBLANK,
         Value    => Encode (Mode.H_Visible,    Mode.H_Total));
      Registers.Write
        (Register => TRANS (Port).HSYNC,
         Value    => Encode (Mode.H_Sync_Begin, Mode.H_Sync_End));
      Registers.Write
        (Register => TRANS (Port).VTOTAL,
         Value    => Encode (Mode.V_Visible,    Mode.V_Total));
      Registers.Write
        (Register => TRANS (Port).VBLANK,
         Value    => Encode (Mode.V_Visible,    Mode.V_Total));
      Registers.Write
        (Register => TRANS (Port).VSYNC,
         Value    => Encode (Mode.V_Sync_Begin, Mode.V_Sync_End));

      if Port_Cfg.Display = DP then
         declare
            Data_M, Link_M : DP_Info.M_Type;
            Data_N, Link_N : DP_Info.N_Type;
         begin
            DP_Info.Calculate_M_N
              (Link     => Port_Cfg.DP,
               Mode     => Port_Cfg.Mode,
               Data_M   => Data_M,
               Data_N   => Data_N,
               Link_M   => Link_M,
               Link_N   => Link_N);
            Registers.Write
              (Register => TRANS (Port).DATA_M,
               Value    => TRANS_DATA_M_TU (64) or
                           Word32 (Data_M));
            Registers.Write
              (Register => TRANS (Port).DATA_N,
               Value    => Word32 (Data_N));
            Registers.Write
              (Register => TRANS (Port).LINK_M,
               Value    => Word32 (Link_M));
            Registers.Write
              (Register => TRANS (Port).LINK_N,
               Value    => Word32 (Link_N));
         end;

         if Config.Has_Trans_DP_Ctl then
            declare
               Polarity : constant Word32 :=
                 (if Port_Cfg.Mode.H_Sync_Active_High then
                     TRANS_DP_CTL_HSYNC_ACTIVE_HIGH else 0) or
                 (if Port_Cfg.Mode.V_Sync_Active_High then
                     TRANS_DP_CTL_VSYNC_ACTIVE_HIGH else 0);
               Enhanced_Framing : constant Word32 :=
                 (if Port_Cfg.DP.Enhanced_Framing then
                     TRANS_DP_CTL_ENHANCED_FRAMING else 0);
            begin
               Registers.Write
                 (Register => TRANS (Port).DP_CTL,
                  Value    => TRANS_DP_CTL_OUTPUT_ENABLE or
                              TRANS_DP_CTL_PORT_SELECT (Port_Cfg.PCH_Port) or
                              Enhanced_Framing or
                              TRANS_DP_CTL_BPC (Port_Cfg.Mode.BPC) or
                              Polarity);
            end;
         end if;
      end if;

      if Config.Has_Trans_Timing_Ovrrde then
         Registers.Set_Mask
           (Register => TRANS (Port).CHICKEN2,
            Mask     => TRANS_CHICKEN2_TIMING_OVERRIDE);
      end if;

      Registers.Write
        (Register => TRANS (Port).CONF,
         Value    => TRANS_CONF_TRANSCODER_ENABLE);
   end On;

   procedure Off (Port : FDI_Port_Type) is
   begin
      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));

      Registers.Unset_Mask
        (Register => TRANS (Port).CONF,
         Mask     => TRANS_CONF_TRANSCODER_ENABLE);
      Registers.Wait_Unset_Mask
        (Register => TRANS (Port).CONF,
         Mask     => TRANS_CONF_TRANSCODER_STATE,
         TOut_MS  => 50);

      if Config.Has_Trans_Timing_Ovrrde then
         Registers.Unset_Mask
           (Register => TRANS (Port).CHICKEN2,
            Mask     => TRANS_CHICKEN2_TIMING_OVERRIDE);
      end if;

      if Config.Has_Trans_DP_Ctl then
         Registers.Write
           (Register => TRANS (Port).DP_CTL,
            Value    => TRANS_DP_CTL_PORT_SELECT_NONE);
      end if;

      if Config.Has_DPLL_SEL then
         Registers.Unset_Mask
           (Register => Registers.PCH_DPLL_SEL,
            Mask     => DPLL_SEL_TRANSCODER_x_DPLL_ENABLE (Port));
      end if;
   end Off;

end HW.GFX.GMA.PCH.Transcoder;
