| -- |
| -- 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; 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.Time; |
| with HW.GFX.DP_Training; |
| with HW.GFX.GMA.Config; |
| with HW.GFX.GMA.PCH.FDI; |
| with HW.GFX.GMA.PCH.Transcoder; |
| 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.Debug; |
| with GNAT.Source_Info; |
| |
| package body HW.GFX.GMA.Connectors.DDI is |
| |
| DDI_BUF_CTL_BUFFER_ENABLE : constant := 1 * 2 ** 31; |
| DDI_BUF_CTL_TRANS_SELECT_MASK : constant := 15 * 2 ** 24; |
| DDI_BUF_CTL_PORT_REVERSAL : constant := 1 * 2 ** 16; |
| DDI_BUF_CTL_IDLE_STATUS : constant := 1 * 2 ** 7; |
| DDI_BUF_CTL_DDI_A_LANE_CAP : constant := 1 * 2 ** 4; |
| DDI_BUF_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 1; |
| DDI_BUF_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 1; |
| DDI_BUF_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 1; |
| DDI_BUF_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 1; |
| DDI_BUF_CTL_INIT_DISPLAY_DETECT : constant := 1 * 2 ** 0; |
| |
| subtype DDI_BUF_CTL_TRANS_SELECT_T is Natural range 0 .. 9; |
| function DDI_BUF_CTL_TRANS_SELECT |
| (Sel : DDI_BUF_CTL_TRANS_SELECT_T) |
| return Word32; |
| |
| type DDI_BUF_CTL_PORT_WIDTH_T is array (HW.GFX.DP_Lane_Count) of Word32; |
| DDI_BUF_CTL_PORT_WIDTH : constant DDI_BUF_CTL_PORT_WIDTH_T := |
| DDI_BUF_CTL_PORT_WIDTH_T' |
| (HW.GFX.DP_Lane_Count_1 => DDI_BUF_CTL_PORT_WIDTH_1_LANE, |
| HW.GFX.DP_Lane_Count_2 => DDI_BUF_CTL_PORT_WIDTH_2_LANES, |
| HW.GFX.DP_Lane_Count_4 => DDI_BUF_CTL_PORT_WIDTH_4_LANES); |
| |
| DP_TP_CTL_TRANSPORT_ENABLE : constant := 1 * 2 ** 31; |
| DP_TP_CTL_MODE_SST : constant := 0 * 2 ** 27; |
| DP_TP_CTL_MODE_MST : constant := 1 * 2 ** 27; |
| DP_TP_CTL_FORCE_ACT : constant := 1 * 2 ** 25; |
| DP_TP_CTL_ENHANCED_FRAME_ENABLE : constant := 1 * 2 ** 18; |
| DP_TP_CTL_FDI_AUTOTRAIN : constant := 1 * 2 ** 15; |
| DP_TP_CTL_LINK_TRAIN_MASK : constant := 7 * 2 ** 8; |
| DP_TP_CTL_LINK_TRAIN_PAT1 : constant := 0 * 2 ** 8; |
| DP_TP_CTL_LINK_TRAIN_PAT2 : constant := 1 * 2 ** 8; |
| DP_TP_CTL_LINK_TRAIN_PAT3 : constant := 4 * 2 ** 8; |
| DP_TP_CTL_LINK_TRAIN_IDLE : constant := 2 * 2 ** 8; |
| DP_TP_CTL_LINK_TRAIN_NORMAL : constant := 3 * 2 ** 8; |
| DP_TP_CTL_SCRAMBLE_DISABLE : constant := 1 * 2 ** 7; |
| DP_TP_CTL_ALT_SCRAMBLER_RESET : constant := 1 * 2 ** 6; |
| |
| type DP_TP_CTL_LINK_TRAIN_Array is |
| array (DP_Info.Training_Pattern) of Word32; |
| DP_TP_CTL_LINK_TRAIN : constant DP_TP_CTL_LINK_TRAIN_Array := |
| DP_TP_CTL_LINK_TRAIN_Array' |
| (DP_Info.TP_1 => DP_TP_CTL_LINK_TRAIN_PAT1 or DP_TP_CTL_SCRAMBLE_DISABLE, |
| DP_Info.TP_2 => DP_TP_CTL_LINK_TRAIN_PAT2 or DP_TP_CTL_SCRAMBLE_DISABLE, |
| DP_Info.TP_3 => DP_TP_CTL_LINK_TRAIN_PAT3 or DP_TP_CTL_SCRAMBLE_DISABLE, |
| DP_Info.TP_Idle => DP_TP_CTL_LINK_TRAIN_IDLE, |
| DP_Info.TP_None => DP_TP_CTL_LINK_TRAIN_NORMAL); |
| |
| DP_TP_STATUS_MIN_IDLES_SENT : constant := 1 * 2 ** 25; |
| DP_TP_STATUS_FDI_AUTO_TRAIN_DONE : constant := 1 * 2 ** 12; |
| |
| PORT_CLK_SEL_LCPLL2700 : constant := 0 * 2 ** 29; -- not on ULX |
| PORT_CLK_SEL_LCPLL1350 : constant := 1 * 2 ** 29; |
| PORT_CLK_SEL_LCPLL810 : constant := 2 * 2 ** 29; |
| PORT_CLK_SEL_SPLL : constant := 3 * 2 ** 29; |
| PORT_CLK_SEL_WRPLL1 : constant := 4 * 2 ** 29; |
| PORT_CLK_SEL_WRPLL2 : constant := 5 * 2 ** 29; |
| PORT_CLK_SEL_NONE : constant := 7 * 2 ** 29; |
| |
| type PORT_CLK_SEL_LCPLL_T is array (HW.GFX.DP_Bandwidth) of Word32; |
| PORT_CLK_SEL_LCPLL : constant PORT_CLK_SEL_LCPLL_T := |
| PORT_CLK_SEL_LCPLL_T' |
| (HW.GFX.DP_Bandwidth_1_62 => PORT_CLK_SEL_LCPLL810, |
| HW.GFX.DP_Bandwidth_2_7 => PORT_CLK_SEL_LCPLL1350, |
| HW.GFX.DP_Bandwidth_5_4 => PORT_CLK_SEL_LCPLL2700); |
| |
| type DDI_Registers is record |
| BUF_CTL : Registers.Registers_Index; |
| DP_TP_CTL : Registers.Registers_Index; |
| DP_TP_STATUS : Registers.Registers_Invalid_Index; |
| PORT_CLK_SEL : Registers.Registers_Index; |
| end record; |
| |
| type DDI_Registers_Array is array (Digital_Port) of DDI_Registers; |
| |
| DDI_Regs : constant DDI_Registers_Array := DDI_Registers_Array' |
| (DIGI_A => DDI_Registers' |
| (BUF_CTL => Registers.DDI_BUF_CTL_A, |
| DP_TP_CTL => Registers.DP_TP_CTL_A, |
| DP_TP_STATUS => Registers.Invalid_Register, |
| PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIA), |
| DIGI_B => DDI_Registers' |
| (BUF_CTL => Registers.DDI_BUF_CTL_B, |
| DP_TP_CTL => Registers.DP_TP_CTL_B, |
| DP_TP_STATUS => Registers.DP_TP_STATUS_B, |
| PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIB), |
| DIGI_C => DDI_Registers' |
| (BUF_CTL => Registers.DDI_BUF_CTL_C, |
| DP_TP_CTL => Registers.DP_TP_CTL_C, |
| DP_TP_STATUS => Registers.DP_TP_STATUS_C, |
| PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIC), |
| DIGI_D => DDI_Registers' |
| (BUF_CTL => Registers.DDI_BUF_CTL_D, |
| DP_TP_CTL => Registers.DP_TP_CTL_D, |
| DP_TP_STATUS => Registers.DP_TP_STATUS_D, |
| PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDID), |
| DIGI_E => DDI_Registers' |
| (BUF_CTL => Registers.DDI_BUF_CTL_E, |
| DP_TP_CTL => Registers.DP_TP_CTL_E, |
| DP_TP_STATUS => Registers.DP_TP_STATUS_E, |
| PORT_CLK_SEL => Registers.PORT_CLK_SEL_DDIE)); |
| |
| ---------------------------------------------------------------------------- |
| |
| type Values is array (Digital_Port) of Word32; |
| type Shifts is array (Digital_Port) of Natural; |
| |
| DPLL_CTRL2_DDIx_CLOCK_OFF : constant Values := Values' |
| (DIGI_A => 1 * 2 ** 15, |
| DIGI_B => 1 * 2 ** 16, |
| DIGI_C => 1 * 2 ** 17, |
| DIGI_D => 1 * 2 ** 18, |
| DIGI_E => 1 * 2 ** 19); |
| |
| DPLL_CTRL2_DDIx_SELECT_MASK : constant Values := Values' |
| (DIGI_A => 3 * 2 ** 1, |
| DIGI_B => 3 * 2 ** 4, |
| DIGI_C => 3 * 2 ** 7, |
| DIGI_D => 3 * 2 ** 10, |
| DIGI_E => 3 * 2 ** 13); |
| DPLL_CTRL2_DDIx_SELECT_SHIFT : constant Shifts := Shifts' |
| (DIGI_A => 1, |
| DIGI_B => 4, |
| DIGI_C => 7, |
| DIGI_D => 10, |
| DIGI_E => 13); |
| |
| DPLL_CTRL2_DDIx_SELECT_OVERRIDE : constant Values := Values' |
| (DIGI_A => 1 * 2 ** 0, |
| DIGI_B => 1 * 2 ** 3, |
| DIGI_C => 1 * 2 ** 6, |
| DIGI_D => 1 * 2 ** 9, |
| DIGI_E => 1 * 2 ** 12); |
| |
| ---------------------------------------------------------------------------- |
| |
| function DDI_BUF_CTL_TRANS_SELECT |
| (Sel : DDI_BUF_CTL_TRANS_SELECT_T) |
| return Word32 |
| is |
| begin |
| return Word32 (Sel) * 2 ** 24; |
| end DDI_BUF_CTL_TRANS_SELECT; |
| |
| ---------------------------------------------------------------------------- |
| |
| function Max_V_Swing |
| (Port : Digital_Port) |
| return DP_Info.DP_Voltage_Swing |
| is |
| begin |
| return |
| (if (Config.Has_Low_Voltage_Swing and Config.EDP_Low_Voltage_Swing) |
| and then Port = DIGI_A |
| then |
| DP_Info.VS_Level_3 |
| else |
| DP_Info.VS_Level_2); |
| end Max_V_Swing; |
| |
| pragma Warnings (GNATprove, Off, "unused variable ""Port""", |
| Reason => "Needed for a common interface"); |
| 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_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"""); |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Set_TP_CTL |
| (Port : Digital_Port; |
| Link : DP_Link; |
| Pattern : DP_Info.Training_Pattern) |
| is |
| DP_TP_CTL_Enhanced_Frame : Word32 := 0; |
| begin |
| if Link.Enhanced_Framing then |
| DP_TP_CTL_Enhanced_Frame := DP_TP_CTL_ENHANCED_FRAME_ENABLE; |
| end if; |
| |
| Registers.Write |
| (Register => DDI_Regs (Port).DP_TP_CTL, |
| Value => DP_TP_CTL_TRANSPORT_ENABLE or |
| DP_TP_CTL_Enhanced_Frame or |
| DP_TP_CTL_LINK_TRAIN (Pattern)); |
| end Set_TP_CTL; |
| |
| 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 |
| Set_TP_CTL (Port, Link, Pattern); |
| else |
| -- send at least 5 idle patterns |
| Set_TP_CTL (Port, Link, DP_Info.TP_Idle); |
| |
| -- switch to normal frame delivery |
| if Config.End_EDP_Training_Late and then Port = DIGI_A then |
| null; -- do it later in Post_On procedure |
| -- TODO: if there are problems getting the pipe up, |
| -- wait here some time |
| -- Time.U_Delay (100); |
| else |
| if Port /= DIGI_A then |
| Registers.Wait_Set_Mask |
| (Register => DDI_Regs (Port).DP_TP_STATUS, |
| Mask => DP_TP_STATUS_MIN_IDLES_SENT); |
| end if; |
| Set_TP_CTL (Port, Link, DP_Info.TP_None); |
| end if; |
| end if; |
| end Set_Training_Pattern; |
| |
| procedure Set_Signal_Levels |
| (Port : Digital_Port; |
| Link : DP_Link; |
| Train_Set : DP_Info.Train_Set) |
| 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); |
| |
| -- enable DDI buffer |
| Registers.Unset_And_Set_Mask |
| (Register => DDI_Regs (Port).BUF_CTL, |
| Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or |
| DDI_BUF_CTL_PORT_REVERSAL or |
| DDI_BUF_CTL_PORT_WIDTH_MASK, |
| Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or |
| DDI_BUF_CTL_TRANS_SELECT (Trans_Select) or |
| DDI_BUF_CTL_PORT_WIDTH (Link.Lane_Count)); |
| Registers.Posting_Read (DDI_Regs (Port).BUF_CTL); |
| |
| if not Was_Enabled then |
| Time.U_Delay (600); -- wait >= 518us (intel spec) |
| end if; |
| end Set_Signal_Levels; |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Digital_Off (Port : Digital_Port) |
| is |
| Enabled : Boolean; |
| begin |
| pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| |
| Registers.Is_Set_Mask |
| (Register => DDI_Regs (Port).BUF_CTL, |
| Mask => DDI_BUF_CTL_BUFFER_ENABLE, |
| Result => Enabled); |
| |
| if Enabled then |
| Registers.Unset_Mask |
| (Register => DDI_Regs (Port).BUF_CTL, |
| Mask => DDI_BUF_CTL_BUFFER_ENABLE); |
| end if; |
| |
| Registers.Unset_Mask |
| (Register => DDI_Regs (Port).DP_TP_CTL, |
| Mask => DP_TP_CTL_TRANSPORT_ENABLE); |
| |
| if Enabled then |
| Registers.Wait_Set_Mask |
| (Register => DDI_Regs (Port).BUF_CTL, |
| Mask => DDI_BUF_CTL_IDLE_STATUS); |
| end if; |
| |
| if Config.Has_Per_DDI_Clock_Sel then |
| Registers.Write |
| (Register => DDI_Regs (Port).PORT_CLK_SEL, |
| Value => PORT_CLK_SEL_NONE); |
| else |
| Registers.Set_Mask |
| (Register => Registers.DPLL_CTRL2, |
| Mask => DPLL_CTRL2_DDIx_CLOCK_OFF (Port)); |
| end if; |
| end Digital_Off; |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Train_FDI |
| (Port_Cfg : in Port_Config; |
| Success : out Boolean) |
| is |
| begin |
| PCH.FDI.Pre_Train (PCH.FDI_A, Port_Cfg); |
| |
| -- always use SPLL for FDI |
| SPLL.On; |
| Registers.Write |
| (Register => DDI_Regs (DIGI_E).PORT_CLK_SEL, |
| Value => PORT_CLK_SEL_SPLL); |
| |
| -- try each preemph/voltage pair twice |
| for Trans2 in Natural range 0 .. DDI_BUF_CTL_TRANS_SELECT_T'Last * 2 + 1 |
| loop |
| Registers.Write |
| (Register => DDI_Regs (DIGI_E).DP_TP_CTL, |
| Value => DP_TP_CTL_TRANSPORT_ENABLE or |
| DP_TP_CTL_ENHANCED_FRAME_ENABLE or |
| DP_TP_CTL_FDI_AUTOTRAIN or |
| DP_TP_CTL_LINK_TRAIN_PAT1); |
| |
| Registers.Unset_And_Set_Mask |
| (Register => DDI_Regs (DIGI_E).BUF_CTL, |
| Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or |
| DDI_BUF_CTL_PORT_REVERSAL or |
| DDI_BUF_CTL_PORT_WIDTH_MASK, |
| Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or |
| DDI_BUF_CTL_TRANS_SELECT (Trans2 / 2) or |
| DDI_BUF_CTL_PORT_WIDTH (Port_Cfg.FDI.Lane_Count)); |
| Registers.Posting_Read (DDI_Regs (DIGI_E).BUF_CTL); |
| Time.U_Delay (600); -- wait >= 518us (intel spec) |
| |
| PCH.FDI.Auto_Train (PCH.FDI_A); |
| Registers.Is_Set_Mask |
| (Register => DDI_Regs (DIGI_E).DP_TP_STATUS, |
| Mask => DP_TP_STATUS_FDI_AUTO_TRAIN_DONE, |
| Result => Success); |
| exit when Success; |
| |
| Registers.Unset_Mask |
| (Register => DDI_Regs (DIGI_E).BUF_CTL, |
| Mask => DDI_BUF_CTL_BUFFER_ENABLE); |
| Registers.Posting_Read (DDI_Regs (DIGI_E).BUF_CTL); |
| |
| Registers.Unset_And_Set_Mask |
| (Register => DDI_Regs (DIGI_E).DP_TP_CTL, |
| Mask_Unset => DP_TP_CTL_TRANSPORT_ENABLE or |
| DP_TP_CTL_LINK_TRAIN_MASK, |
| Mask_Set => DP_TP_CTL_LINK_TRAIN_PAT1); |
| Registers.Posting_Read (DDI_Regs (DIGI_E).DP_TP_CTL); |
| |
| Registers.Wait_Set_Mask |
| (Register => DDI_Regs (DIGI_E).BUF_CTL, |
| Mask => DDI_BUF_CTL_IDLE_STATUS); |
| |
| PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Lanes_Off); |
| end loop; |
| |
| if Success then |
| -- start normal frame delivery |
| Registers.Write |
| (Register => DDI_Regs (DIGI_E).DP_TP_CTL, |
| Value => DP_TP_CTL_TRANSPORT_ENABLE or |
| DP_TP_CTL_ENHANCED_FRAME_ENABLE or |
| DP_TP_CTL_FDI_AUTOTRAIN or |
| DP_TP_CTL_LINK_TRAIN_NORMAL); |
| else |
| Registers.Write |
| (Register => DDI_Regs (DIGI_E).PORT_CLK_SEL, |
| Value => PORT_CLK_SEL_NONE); |
| SPLL.Off; |
| |
| PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Clock_Off); |
| end if; |
| end Train_FDI; |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Pre_On |
| (Port_Cfg : in Port_Config; |
| PLL_Hint : in Word32; |
| Success : out Boolean) |
| is |
| function To_DP (Port : Digital_Port) return DP_Port |
| is |
| begin |
| return |
| (case Port is |
| when DIGI_A => DP_A, |
| when DIGI_B => DP_B, |
| when DIGI_C => DP_C, |
| when DIGI_D => DP_D, |
| when others => DP_Port'First); |
| end To_DP; |
| package Training is new DP_Training |
| (TPS3_Supported => True, |
| 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 => Digital_Off); |
| begin |
| pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| |
| if Port_Cfg.Display = VGA then |
| Train_FDI (Port_Cfg, Success); |
| else |
| -- direct configured PLL output to this port |
| if Config.Has_Per_DDI_Clock_Sel then |
| Registers.Write |
| (Register => DDI_Regs (Port_Cfg.Port).PORT_CLK_SEL, |
| Value => PLL_Hint); |
| else |
| Registers.Unset_And_Set_Mask |
| (Register => Registers.DPLL_CTRL2, |
| Mask_Unset => DPLL_CTRL2_DDIx_CLOCK_OFF (Port_Cfg.Port) or |
| DPLL_CTRL2_DDIx_SELECT_MASK (Port_Cfg.Port), |
| Mask_Set => Shift_Left |
| (PLL_Hint, |
| DPLL_CTRL2_DDIx_SELECT_SHIFT (Port_Cfg.Port)) |
| or |
| DPLL_CTRL2_DDIx_SELECT_OVERRIDE (Port_Cfg.Port)); |
| end if; |
| |
| if Port_Cfg.Display = DP then |
| Training.Train_DP |
| (Port => Port_Cfg.Port, |
| Link => Port_Cfg.DP, |
| Success => Success); |
| else |
| Success := True; |
| end if; |
| end if; |
| end Pre_On; |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Post_On (Port_Cfg : Port_Config) |
| is |
| begin |
| pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| |
| if Port_Cfg.Port = DIGI_A then |
| if Config.End_EDP_Training_Late then |
| Registers.Unset_And_Set_Mask |
| (Register => DDI_Regs (DIGI_A).DP_TP_CTL, |
| Mask_Unset => DP_TP_CTL_LINK_TRAIN_MASK, |
| Mask_Set => DP_TP_CTL_LINK_TRAIN_NORMAL); |
| end if; |
| end if; |
| |
| case Port_Cfg.Display is |
| when HDMI => |
| Registers.Unset_And_Set_Mask |
| (Register => DDI_Regs (Port_Cfg.Port).BUF_CTL, |
| Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or |
| DDI_BUF_CTL_PORT_REVERSAL, |
| Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE); |
| Time.U_Delay (600); -- wait >= 518us (intel spec) |
| when VGA => |
| PCH.VGA.Clock_On (Port_Cfg.Mode); |
| PCH.Transcoder.On (Port_Cfg, PCH.FDI_A, 0); |
| PCH.VGA.On |
| (Port => PCH.FDI_A, |
| Mode => Port_Cfg.Mode); |
| when others => |
| null; |
| end case; |
| end Post_On; |
| |
| ---------------------------------------------------------------------------- |
| |
| procedure Off (Port : Digital_Port) |
| is |
| begin |
| pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| |
| if Port = DIGI_E then |
| PCH.VGA.Off; |
| PCH.Transcoder.Off (PCH.FDI_A); |
| -- PCH.VGA.Clock_Off; -- Can't tell what Linux does, if anything. |
| PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Rx_Off); |
| end if; |
| |
| Digital_Off (Port); |
| |
| if Port = DIGI_E then |
| SPLL.Off; |
| PCH.FDI.Off (PCH.FDI_A, PCH.FDI.Clock_Off); |
| end if; |
| end Off; |
| |
| end HW.GFX.GMA.Connectors.DDI; |