gma: Move transcoder setup into own package
Split the transcoder setup out of `Pipe_Setup` into a new package
`Transcoder`. This comes closer to how Intel's manuals describe the
hardware.
Also rework the related constant definitions to make things more
human readable.
Change-Id: Ife0f0d635d87b874d4b713a00ca7a1bec688c672
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/17764
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
diff --git a/common/Makefile.inc b/common/Makefile.inc
index 11215ee..0583143 100644
--- a/common/Makefile.inc
+++ b/common/Makefile.inc
@@ -36,6 +36,8 @@
gfxinit-y += hw-gfx-gma-port_detect.ads
gfxinit-y += hw-gfx-gma-registers.adb
gfxinit-y += hw-gfx-gma-registers.ads
+gfxinit-y += hw-gfx-gma-transcoder.adb
+gfxinit-y += hw-gfx-gma-transcoder.ads
gfxinit-y += hw-gfx-gma.adb
gfxinit-y += hw-gfx-gma.ads
gfxinit-y += hw-gfx-i2c.ads
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index 00a46e1..b3492f4 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -40,7 +40,7 @@
Disable_Trickle_Feed : constant Boolean := not
(CPU in Haswell .. Broadwell);
Pipe_Enabled_Workaround : constant Boolean := CPU = Broadwell;
- Has_EDP_Pipe : constant Boolean := CPU >= Haswell;
+ Has_EDP_Transcoder : constant Boolean := CPU >= Haswell;
Has_Pipe_DDI_Func : constant Boolean := CPU >= Haswell;
Has_Trans_Clk_Sel : constant Boolean := CPU >= Haswell;
Has_Pipe_MSA_Misc : constant Boolean := CPU >= Haswell;
diff --git a/common/hw-gfx-gma-pipe_setup.adb b/common/hw-gfx-gma-pipe_setup.adb
index 40b31c8..3525ea3 100644
--- a/common/hw-gfx-gma-pipe_setup.adb
+++ b/common/hw-gfx-gma-pipe_setup.adb
@@ -16,42 +16,19 @@
with GNAT.Source_Info;
with HW.GFX.GMA.Config;
-with HW.GFX.GMA.DP_Info;
-with HW.GFX.GMA.Registers;
-
-use type HW.Word64;
-use type HW.Pos16;
-use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
+with HW.GFX.GMA.Transcoder;
package body HW.GFX.GMA.Pipe_Setup is
- type Default_Head_Array is array (Pipe_Index) of Pipe_Head;
- Default_Pipe_Head : constant Default_Head_Array :=
- (Primary => Head_A,
- Secondary => Head_B,
- Tertiary => Head_C);
-
- function Get_Pipe_Head (Pipe : Pipe_Index; Port : GPU_Port) return Pipe_Head
- is
- begin
- return
- (if Config.Has_EDP_Pipe and then Port = DIGI_A then
- Head_EDP
- else
- Default_Pipe_Head (Pipe));
- end Get_Pipe_Head;
-
- ----------------------------------------------------------------------------
-
ILK_DISPLAY_CHICKEN1_VGA_MASK : constant := 7 * 2 ** 29;
ILK_DISPLAY_CHICKEN1_VGA_ENABLE : constant := 5 * 2 ** 29;
ILK_DISPLAY_CHICKEN2_VGA_MASK : constant := 1 * 2 ** 25;
ILK_DISPLAY_CHICKEN2_VGA_ENABLE : constant := 0 * 2 ** 25;
- DSPCNTR_ENABLE : constant := 1 * 2 ** 31;
- DSPCNTR_GAMMA_CORRECTION : constant := 1 * 2 ** 30;
- DSPCNTR_DISABLE_TRICKLE_FEED : constant := 1 * 2 ** 14;
- DSPCNTR_FORMAT_MASK : constant := 15 * 2 ** 26;
+ DSPCNTR_ENABLE : constant := 1 * 2 ** 31;
+ DSPCNTR_GAMMA_CORRECTION : constant := 1 * 2 ** 30;
+ DSPCNTR_DISABLE_TRICKLE_FEED : constant := 1 * 2 ** 14;
+ DSPCNTR_FORMAT_MASK : constant := 15 * 2 ** 26;
DSPCNTR_MASK : constant Word32 :=
DSPCNTR_ENABLE or
@@ -68,8 +45,6 @@
PLANE_WM_LINES_MASK : constant := 16#001f# * 2 ** 14;
PLANE_WM_BLOCKS_MASK : constant := 16#03ff# * 2 ** 0;
- SPCNTR_ENABLE : constant := 1 * 2 ** 31;
-
VGA_SR_INDEX : constant := 16#03c4#;
VGA_SR_DATA : constant := 16#03c5#;
VGA_SR01 : constant := 16#01#;
@@ -89,170 +64,13 @@
return Word32 (Cycles) / 2 - 1;
end VGA_CONTROL_VSYNC_BLINK_RATE;
- TRANS_CLK_SEL_PORT_NONE : constant := 0 * 2 ** 29;
+ PF_CTRL_ENABLE : constant := 1 * 2 ** 31;
+ PF_CTRL_PIPE_SELECT_MASK : constant := 3 * 2 ** 29;
+ PF_CTRL_FILTER_MED : constant := 1 * 2 ** 23;
- type TRANS_CLK_SEL_PORT_Array is
- array (Digital_Port) of Word32;
- TRANS_CLK_SEL_PORT : constant TRANS_CLK_SEL_PORT_Array :=
- TRANS_CLK_SEL_PORT_Array'
- (DIGI_A => 0 * 2 ** 29, -- DDI A is not selectable
- DIGI_B => 2 * 2 ** 29,
- DIGI_C => 3 * 2 ** 29,
- DIGI_D => 4 * 2 ** 29,
- DIGI_E => 5 * 2 ** 29);
-
- PIPECONF_ENABLE : constant := 1 * 2 ** 31;
- PIPECONF_ENABLED_STATUS : constant := 1 * 2 ** 30;
- PIPECONF_ENABLE_DITHER : constant := 1 * 2 ** 4;
- PIPECONF_DITHER_TEMPORAL : constant := 1 * 2 ** 2;
-
- function PIPECONF_BPC (Bits_Per_Color : BPC_Type) return Word32
- with
- Pre => True
- is
- begin
- return
- (case Bits_Per_Color is
- when 6 => 2 * 2 ** 5,
- when 10 => 1 * 2 ** 5,
- when 12 => 3 * 2 ** 5,
- when others => 0 * 2 ** 5);
- end PIPECONF_BPC;
-
- function PIPECONF_Misc (BPC : BPC_Type; Dither : Boolean) return Word32
- with
- Pre => True
- is
- begin
- return
- (if Config.Has_Pipeconf_BPC then PIPECONF_BPC (BPC) else 0) or
- (if Dither then PIPECONF_ENABLE_DITHER else 0);
- end PIPECONF_Misc;
-
- PF_CTRL_ENABLE : constant := 1 * 2 ** 31;
- PF_CTRL_PIPE_SELECT_MASK : constant := 3 * 2 ** 29;
- PF_CTRL_FILTER_MED : constant := 1 * 2 ** 23;
-
- PS_CTRL_ENABLE_SCALER : constant := 1 * 2 ** 31;
- PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant := 1 * 2 ** 28;
- PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant := 1 * 2 ** 23;
-
- PIPE_DDI_FUNC_CTL_ENABLE : constant := 1 * 2 ** 31;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_MASK : constant := 7 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_NONE : constant := 0 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_B : constant := 1 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_C : constant := 2 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_D : constant := 3 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_DDI_SELECT_E : constant := 4 * 2 ** 28;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_MASK : constant := 7 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_HDMI : constant := 0 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_DVI : constant := 1 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_SST : constant := 2 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_MST : constant := 3 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_MODE_SELECT_FDI : constant := 4 * 2 ** 24;
- PIPE_DDI_FUNC_CTL_BPC_MASK : constant := 7 * 2 ** 20;
- PIPE_DDI_FUNC_CTL_BPC_8BITS : constant := 0 * 2 ** 20;
- PIPE_DDI_FUNC_CTL_BPC_10BITS : constant := 1 * 2 ** 20;
- PIPE_DDI_FUNC_CTL_BPC_6BITS : constant := 2 * 2 ** 20;
- PIPE_DDI_FUNC_CTL_BPC_12BITS : constant := 3 * 2 ** 20;
- PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_LOW : constant := 0 * 2 ** 17;
- PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 17;
- PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_LOW : constant := 0 * 2 ** 16;
- PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 16;
- PIPE_DDI_FUNC_CTL_EDP_SELECT_MASK : constant := 7 * 2 ** 12;
- PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON : constant := 0 * 2 ** 12;
- PIPE_DDI_FUNC_CTL_EDP_SELECT_A : constant := 4 * 2 ** 12;
- PIPE_DDI_FUNC_CTL_EDP_SELECT_B : constant := 5 * 2 ** 12;
- PIPE_DDI_FUNC_CTL_EDP_SELECT_C : constant := 6 * 2 ** 12;
- PIPE_DDI_FUNC_CTL_DP_VC_PAYLOAD_ALLOC : constant := 1 * 2 ** 8;
- PIPE_DDI_FUNC_CTL_BFI_ENABLE : constant := 1 * 2 ** 4;
- PIPE_DDI_FUNC_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 1;
- PIPE_DDI_FUNC_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 1;
- PIPE_DDI_FUNC_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 1;
- PIPE_DDI_FUNC_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 1;
-
- type DDI_Select_Array is array (Digital_Port) of Word32;
- PIPE_DDI_FUNC_CTL_DDI_SELECT : constant DDI_Select_Array :=
- DDI_Select_Array'
- (DIGI_A => PIPE_DDI_FUNC_CTL_DDI_SELECT_NONE,
- DIGI_B => PIPE_DDI_FUNC_CTL_DDI_SELECT_B,
- DIGI_C => PIPE_DDI_FUNC_CTL_DDI_SELECT_C,
- DIGI_D => PIPE_DDI_FUNC_CTL_DDI_SELECT_D,
- DIGI_E => PIPE_DDI_FUNC_CTL_DDI_SELECT_E);
-
- type DDI_Mode_Array is array (Display_Type) of Word32;
- PIPE_DDI_FUNC_CTL_MODE_SELECT : constant DDI_Mode_Array :=
- DDI_Mode_Array'
- (VGA => PIPE_DDI_FUNC_CTL_MODE_SELECT_FDI,
- HDMI => PIPE_DDI_FUNC_CTL_MODE_SELECT_DVI,
- DP => PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_SST,
- others => 0);
-
- type HV_Sync_Array is array (Boolean) of Word32;
- PIPE_DDI_FUNC_CTL_VSYNC : constant HV_Sync_Array := HV_Sync_Array'
- (False => PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_LOW,
- True => PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_HIGH);
- PIPE_DDI_FUNC_CTL_HSYNC : constant HV_Sync_Array := HV_Sync_Array'
- (False => PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_LOW,
- True => PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_HIGH);
-
- type EDP_Select_Array is array (Pipe_Index) of Word32;
- PIPE_DDI_FUNC_CTL_EDP_SELECT : constant EDP_Select_Array :=
- (Primary => PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON, -- we never use
- -- panel fitter
- Secondary => PIPE_DDI_FUNC_CTL_EDP_SELECT_B,
- Tertiary => PIPE_DDI_FUNC_CTL_EDP_SELECT_C);
- PIPE_DDI_FUNC_CTL_EDP_SELECT_ONOFF : constant EDP_Select_Array :=
- (Primary => PIPE_DDI_FUNC_CTL_EDP_SELECT_A,
- Secondary => PIPE_DDI_FUNC_CTL_EDP_SELECT_B,
- Tertiary => PIPE_DDI_FUNC_CTL_EDP_SELECT_C);
-
- type Port_Width_Array is array (HW.GFX.DP_Lane_Count) of Word32;
- PIPE_DDI_FUNC_CTL_PORT_WIDTH : constant Port_Width_Array :=
- Port_Width_Array'
- (HW.GFX.DP_Lane_Count_1 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_1_LANE,
- HW.GFX.DP_Lane_Count_2 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_2_LANES,
- HW.GFX.DP_Lane_Count_4 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_4_LANES);
-
- function PIPE_DDI_FUNC_CTL_BPC (BPC : HW.GFX.BPC_Type) return Word32
- is
- Result : Word32;
- begin
- case BPC is
- when 6 => Result := PIPE_DDI_FUNC_CTL_BPC_6BITS;
- when 8 => Result := PIPE_DDI_FUNC_CTL_BPC_8BITS;
- when 10 => Result := PIPE_DDI_FUNC_CTL_BPC_10BITS;
- when 12 => Result := PIPE_DDI_FUNC_CTL_BPC_12BITS;
- when others => Result := PIPE_DDI_FUNC_CTL_BPC_8BITS;
- end case;
- return Result;
- end PIPE_DDI_FUNC_CTL_BPC;
-
- function PIPE_DATA_M_TU (Transfer_Unit : Positive) return Word32 is
- begin
- return Shift_Left (Word32 (Transfer_Unit - 1), 25);
- end PIPE_DATA_M_TU;
-
- PIPE_MSA_MISC_SYNC_CLK : constant := 1 * 2 ** 0;
- PIPE_MSA_MISC_BPC_6BITS : constant := 0 * 2 ** 5;
- PIPE_MSA_MISC_BPC_8BITS : constant := 1 * 2 ** 5;
- PIPE_MSA_MISC_BPC_10BITS : constant := 2 * 2 ** 5;
- PIPE_MSA_MISC_BPC_12BITS : constant := 3 * 2 ** 5;
- PIPE_MSA_MISC_BPC_16BITS : constant := 4 * 2 ** 5;
-
- function PIPE_MSA_MISC_BPC (BPC : HW.GFX.BPC_Type) return Word32 is
- Result : Word32;
- begin
- case BPC is
- when 6 => Result := PIPE_MSA_MISC_BPC_6BITS;
- when 8 => Result := PIPE_MSA_MISC_BPC_8BITS;
- when 10 => Result := PIPE_MSA_MISC_BPC_10BITS;
- when 12 => Result := PIPE_MSA_MISC_BPC_12BITS;
- --when 16 => Result := PIPE_MSA_MISC_BPC_16BITS;
- when others => Result := PIPE_MSA_MISC_BPC_8BITS;
- end case;
- return Result;
- end PIPE_MSA_MISC_BPC;
+ PS_CTRL_ENABLE_SCALER : constant := 1 * 2 ** 31;
+ PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant := 1 * 2 ** 28;
+ PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant := 1 * 2 ** 23;
---------------------------------------------------------------------------
@@ -271,57 +89,11 @@
function Encode (LSW, MSW : Pos16) return Word32 is
begin
- return Shift_Left (Word32 (MSW - 1), 16) or Word32 (LSW - 1);
+ return Shift_Left (Word32 (MSW) - 1, 16) or (Word32 (LSW) - 1);
end Encode;
----------------------------------------------------------------------------
- procedure Setup_Link
- (Head : Head_Type;
- Link : DP_Link;
- Mode : Mode_Type)
- with
- Global => (In_Out => Registers.Register_State),
- Depends => (Registers.Register_State =>+ (Head, Link, Mode))
- is
- Data_M, Link_M : DP_Info.M_Type;
- Data_N, Link_N : DP_Info.N_Type;
- begin
- pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
-
- DP_Info.Calculate_M_N
- (Link => Link,
- Mode => Mode,
- Data_M => Data_M,
- Data_N => Data_N,
- Link_M => Link_M,
- Link_N => Link_N);
-
- Registers.Write
- (Register => Head.PIPE_DATA_M1,
- Value => PIPE_DATA_M_TU (64) or
- Word32 (Data_M));
- Registers.Write
- (Register => Head.PIPE_DATA_N1,
- Value => Word32 (Data_N));
-
- Registers.Write
- (Register => Head.PIPE_LINK_M1,
- Value => Word32 (Link_M));
- Registers.Write
- (Register => Head.PIPE_LINK_N1,
- Value => Word32 (Link_N));
-
- if Config.Has_Pipe_MSA_Misc then
- Registers.Write
- (Register => Head.PIPE_MSA_MISC,
- Value => PIPE_MSA_MISC_SYNC_CLK or
- PIPE_MSA_MISC_BPC (Mode.BPC));
- end if;
- end Setup_Link;
-
- ----------------------------------------------------------------------------
-
procedure Clear_Watermarks (Controller : Controller_Type) is
begin
Registers.Write
@@ -480,40 +252,10 @@
if Config.Has_Pipeconf_Misc then
Registers.Write
(Register => Controller.PIPEMISC,
- Value => PIPECONF_Misc (Dither_BPC, Dither));
+ Value => Transcoder.BPC_Conf (Dither_BPC, Dither));
end if;
end Setup_Display;
- procedure Setup_Transcoder
- (Head : Head_Type;
- Port_Cfg : Port_Config)
- is
- M : constant Mode_Type := Port_Cfg.Mode;
- begin
- pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
-
- if Config.Has_Trans_Clk_Sel and then
- Head.TRANS_CLK_SEL /= Registers.Invalid_Register
- then
- Registers.Write
- (Register => Head.TRANS_CLK_SEL,
- Value => TRANS_CLK_SEL_PORT (Port_Cfg.Port));
- end if;
-
- if Port_Cfg.Is_FDI then
- Setup_Link (Head, Port_Cfg.FDI, Port_Cfg.Mode);
- elsif Port_Cfg.Display = DP then
- Setup_Link (Head, Port_Cfg.DP, Port_Cfg.Mode);
- end if;
-
- Registers.Write (Head.HTOTAL, Encode (M.H_Visible, M.H_Total));
- Registers.Write (Head.HBLANK, Encode (M.H_Visible, M.H_Total));
- Registers.Write (Head.HSYNC, Encode (M.H_Sync_Begin, M.H_Sync_End));
- Registers.Write (Head.VTOTAL, Encode (M.V_Visible, M.V_Total));
- Registers.Write (Head.VBLANK, Encode (M.V_Visible, M.V_Total));
- Registers.Write (Head.VSYNC, Encode (M.V_Sync_Begin, M.V_Sync_End));
- end Setup_Transcoder;
-
----------------------------------------------------------------------------
procedure Scale_Keep_Aspect
@@ -551,6 +293,8 @@
Framebuffer.Width <= Pos32 (Mode.H_Visible) and
Framebuffer.Height <= Pos32 (Mode.V_Visible)
is
+ use type Registers.Registers_Invalid_Index;
+
-- Enable 7x5 extended mode where possible:
Scaler_Mode : constant Word32 :=
(if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
@@ -658,36 +402,6 @@
----------------------------------------------------------------------------
- procedure Transcoder_On
- (Pipe : Pipe_Index;
- Head : Head_Type;
- Port_Cfg : Port_Config;
- Dither : Boolean)
- is
- begin
- if Config.Has_Pipe_DDI_Func then
- Registers.Write
- (Register => Head.PIPE_DDI_FUNC_CTL,
- Value => PIPE_DDI_FUNC_CTL_ENABLE or
- PIPE_DDI_FUNC_CTL_DDI_SELECT (Port_Cfg.Port) or
- PIPE_DDI_FUNC_CTL_MODE_SELECT (Port_Cfg.Display) or
- PIPE_DDI_FUNC_CTL_BPC (Port_Cfg.Mode.BPC) or
- PIPE_DDI_FUNC_CTL_VSYNC (Port_Cfg.Mode.V_Sync_Active_High) or
- PIPE_DDI_FUNC_CTL_HSYNC (Port_Cfg.Mode.H_Sync_Active_High) or
- PIPE_DDI_FUNC_CTL_EDP_SELECT (Pipe) or
- PIPE_DDI_FUNC_CTL_PORT_WIDTH (Port_Cfg.DP.Lane_Count));
- end if;
-
- Registers.Write
- (Register => Head.PIPECONF,
- Value => PIPECONF_ENABLE or
- (if not Config.Has_Pipeconf_Misc then
- PIPECONF_Misc (Port_Cfg.Mode.BPC, Dither) else 0));
- Registers.Posting_Read (Head.PIPECONF);
- end Transcoder_On;
-
- ----------------------------------------------------------------------------
-
procedure On
(Pipe : Pipe_Index;
Port_Cfg : Port_Config;
@@ -696,25 +410,24 @@
-- Enable dithering if framebuffer BPC differs from port BPC,
-- as smooth gradients look really bad without.
Dither : constant Boolean := Framebuffer.BPC /= Port_Cfg.Mode.BPC;
- Head : constant Pipe_Head := Get_Pipe_Head (Pipe, Port_Cfg.Port);
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
- Setup_Transcoder (Heads (Head), Port_Cfg);
+ Transcoder.Setup (Pipe, Port_Cfg);
Setup_Display
(Controllers (Pipe), Framebuffer, Port_Cfg.Mode.BPC, Dither);
Setup_Scaling (Controllers (Pipe), Port_Cfg.Mode, Framebuffer);
- Transcoder_On (Pipe, Heads (Head), Port_Cfg, Dither);
+ Transcoder.On (Pipe, Port_Cfg, Dither);
end On;
----------------------------------------------------------------------------
procedure Planes_Off (Controller : Controller_Type) is
begin
- Registers.Unset_Mask (Controller.SPCNTR, SPCNTR_ENABLE);
+ Registers.Unset_Mask (Controller.SPCNTR, DSPCNTR_ENABLE);
if Config.Has_Plane_Control then
Clear_Watermarks (Controller);
Registers.Unset_Mask (Controller.PLANE_CTL, PLANE_CTL_PLANE_ENABLE);
@@ -724,51 +437,9 @@
end if;
end Planes_Off;
- procedure Head_Off (Head : Head_Type)
+ procedure Panel_Fitter_Off (Controller : Controller_Type)
is
- Enabled : Boolean;
- begin
- Registers.Is_Set_Mask (Head.PIPECONF, PIPECONF_ENABLE, Enabled);
-
- if Enabled then
- Registers.Unset_Mask (Head.PIPECONF, PIPECONF_ENABLE);
- end if;
-
- -- Workaround for Broadwell:
- -- Status may be wrong if pipe hasn't been enabled since reset.
- if not Config.Pipe_Enabled_Workaround or else Enabled then
- -- synchronously wait until pipe is truly off
- Registers.Wait_Unset_Mask
- (Register => Head.PIPECONF,
- Mask => PIPECONF_ENABLED_STATUS,
- TOut_MS => 40);
- end if;
-
- if Config.Has_Pipe_DDI_Func then
- Registers.Write (Head.PIPE_DDI_FUNC_CTL, 0);
- end if;
- end Head_Off;
-
- procedure Transcoder_Off (Pipe : Pipe_Index)
- is
- DDI_Func_Ctl : Word32;
- begin
- if Config.Has_EDP_Pipe then
- Registers.Read (Registers.PIPE_EDP_DDI_FUNC_CTL, DDI_Func_Ctl);
- DDI_Func_Ctl := DDI_Func_Ctl and PIPE_DDI_FUNC_CTL_EDP_SELECT_MASK;
-
- if (Pipe = Primary and
- DDI_Func_Ctl = PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON) or
- DDI_Func_Ctl = PIPE_DDI_FUNC_CTL_EDP_SELECT_ONOFF (Pipe)
- then
- Head_Off (Heads (Head_EDP));
- end if;
- end if;
-
- Head_Off (Heads (Default_Pipe_Head (Pipe)));
- end Transcoder_Off;
-
- procedure Panel_Fitter_Off (Controller : Controller_Type) is
+ use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
begin
-- Writes to WIN_SZ arm the PS/PF registers.
if Config.Has_Plane_Control then
@@ -786,25 +457,15 @@
end if;
end Panel_Fitter_Off;
- procedure Trans_Clk_Off (Head : Head_Type) is
- begin
- if Config.Has_Trans_Clk_Sel and then
- Head.TRANS_CLK_SEL /= Registers.Invalid_Register
- then
- Registers.Write (Head.TRANS_CLK_SEL, TRANS_CLK_SEL_PORT_NONE);
- end if;
- end Trans_Clk_Off;
-
- procedure Off (Pipe : Pipe_Index; Port_Cfg : Port_Config)
+ procedure Off (Pipe : Pipe_Index)
is
- Head : constant Pipe_Head := Get_Pipe_Head (Pipe, Port_Cfg.Port);
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
Planes_Off (Controllers (Pipe));
- Transcoder_Off (Pipe);
+ Transcoder.Off (Pipe);
Panel_Fitter_Off (Controllers (Pipe));
- Trans_Clk_Off (Heads (Head));
+ Transcoder.Clk_Off (Pipe);
end Off;
procedure Legacy_VGA_Off
@@ -828,9 +489,9 @@
for Pipe in Pipe_Index loop
Planes_Off (Controllers (Pipe));
- Transcoder_Off (Pipe);
+ Transcoder.Off (Pipe);
Panel_Fitter_Off (Controllers (Pipe));
- Trans_Clk_Off (Heads (Default_Pipe_Head (Pipe)));
+ Transcoder.Clk_Off (Pipe);
end loop;
end All_Off;
diff --git a/common/hw-gfx-gma-pipe_setup.ads b/common/hw-gfx-gma-pipe_setup.ads
index 250ab5a..5a85c7e 100644
--- a/common/hw-gfx-gma-pipe_setup.ads
+++ b/common/hw-gfx-gma-pipe_setup.ads
@@ -28,7 +28,7 @@
Framebuffer.Width <= Pos32 (Port_Cfg.Mode.H_Visible) and
Framebuffer.Height <= Pos32 (Port_Cfg.Mode.V_Visible);
- procedure Off (Pipe : Pipe_Index; Port_Cfg : Port_Config);
+ procedure Off (Pipe : Pipe_Index);
procedure Legacy_VGA_Off;
@@ -43,8 +43,6 @@
subtype WM_Levels is Natural range 0 .. 7;
type PLANE_WM_Type is array (WM_Levels) of Registers.Registers_Index;
- ----------------------------------------------------------------------------
-
type Controller_Type is
record
Pipe : Pipe_Index;
@@ -78,33 +76,6 @@
type Controller_Array is array (Pipe_Index) of Controller_Type;
- ----------------------------------------------------------------------------
-
- type Pipe_Head is (Head_EDP, Head_A, Head_B, Head_C);
-
- type Head_Type is
- record
- Head : Pipe_Head;
- HTOTAL : Registers.Registers_Index;
- HBLANK : Registers.Registers_Index;
- HSYNC : Registers.Registers_Index;
- VTOTAL : Registers.Registers_Index;
- VBLANK : Registers.Registers_Index;
- VSYNC : Registers.Registers_Index;
- PIPECONF : Registers.Registers_Index;
- PIPE_DATA_M1 : Registers.Registers_Index;
- PIPE_DATA_N1 : Registers.Registers_Index;
- PIPE_LINK_M1 : Registers.Registers_Index;
- PIPE_LINK_N1 : Registers.Registers_Index;
- PIPE_DDI_FUNC_CTL : Registers.Registers_Index;
- PIPE_MSA_MISC : Registers.Registers_Index;
- TRANS_CLK_SEL : Registers.Registers_Invalid_Index;
- end record;
-
- type Head_Array is array (Pipe_Head) of Head_Type;
-
- ----------------------------------------------------------------------------
-
Controllers : constant Controller_Array :=
(Primary => Controller_Type'
(Pipe => Primary,
@@ -212,70 +183,4 @@
Registers.PLANE_WM_1_C_6,
Registers.PLANE_WM_1_C_7)));
- Heads : constant Head_Array := Head_Array'
- (Head_EDP => Head_Type'
- (Head => Head_EDP,
- HTOTAL => Registers.HTOTAL_EDP,
- HBLANK => Registers.HBLANK_EDP,
- HSYNC => Registers.HSYNC_EDP,
- VTOTAL => Registers.VTOTAL_EDP,
- VBLANK => Registers.VBLANK_EDP,
- VSYNC => Registers.VSYNC_EDP,
- PIPECONF => Registers.PIPE_EDP_CONF,
- PIPE_DATA_M1 => Registers.PIPE_EDP_DATA_M1,
- PIPE_DATA_N1 => Registers.PIPE_EDP_DATA_N1,
- PIPE_LINK_M1 => Registers.PIPE_EDP_LINK_M1,
- PIPE_LINK_N1 => Registers.PIPE_EDP_LINK_N1,
- PIPE_DDI_FUNC_CTL => Registers.PIPE_EDP_DDI_FUNC_CTL,
- PIPE_MSA_MISC => Registers.PIPE_EDP_MSA_MISC,
- TRANS_CLK_SEL => Registers.Invalid_Register),
- Head_A => Head_Type'
- (Head => Head_A,
- HTOTAL => Registers.HTOTAL_A,
- HBLANK => Registers.HBLANK_A,
- HSYNC => Registers.HSYNC_A,
- VTOTAL => Registers.VTOTAL_A,
- VBLANK => Registers.VBLANK_A,
- VSYNC => Registers.VSYNC_A,
- PIPECONF => Registers.PIPEACONF,
- PIPE_DATA_M1 => Registers.PIPEA_DATA_M1,
- PIPE_DATA_N1 => Registers.PIPEA_DATA_N1,
- PIPE_LINK_M1 => Registers.PIPEA_LINK_M1,
- PIPE_LINK_N1 => Registers.PIPEA_LINK_N1,
- PIPE_DDI_FUNC_CTL => Registers.PIPEA_DDI_FUNC_CTL,
- PIPE_MSA_MISC => Registers.PIPEA_MSA_MISC,
- TRANS_CLK_SEL => Registers.TRANSA_CLK_SEL),
- Head_B => Head_Type'
- (Head => Head_B,
- HTOTAL => Registers.HTOTAL_B,
- HBLANK => Registers.HBLANK_B,
- HSYNC => Registers.HSYNC_B,
- VTOTAL => Registers.VTOTAL_B,
- VBLANK => Registers.VBLANK_B,
- VSYNC => Registers.VSYNC_B,
- PIPECONF => Registers.PIPEBCONF,
- PIPE_DATA_M1 => Registers.PIPEB_DATA_M1,
- PIPE_DATA_N1 => Registers.PIPEB_DATA_N1,
- PIPE_LINK_M1 => Registers.PIPEB_LINK_M1,
- PIPE_LINK_N1 => Registers.PIPEB_LINK_N1,
- PIPE_DDI_FUNC_CTL => Registers.PIPEB_DDI_FUNC_CTL,
- PIPE_MSA_MISC => Registers.PIPEB_MSA_MISC,
- TRANS_CLK_SEL => Registers.TRANSB_CLK_SEL),
- Head_C => Head_Type'
- (Head => Head_C,
- HTOTAL => Registers.HTOTAL_C,
- HBLANK => Registers.HBLANK_C,
- HSYNC => Registers.HSYNC_C,
- VTOTAL => Registers.VTOTAL_C,
- VBLANK => Registers.VBLANK_C,
- VSYNC => Registers.VSYNC_C,
- PIPECONF => Registers.PIPECCONF,
- PIPE_DATA_M1 => Registers.PIPEC_DATA_M1,
- PIPE_DATA_N1 => Registers.PIPEC_DATA_N1,
- PIPE_LINK_M1 => Registers.PIPEC_LINK_M1,
- PIPE_LINK_N1 => Registers.PIPEC_LINK_N1,
- PIPE_DDI_FUNC_CTL => Registers.PIPEC_DDI_FUNC_CTL,
- PIPE_MSA_MISC => Registers.PIPEC_MSA_MISC,
- TRANS_CLK_SEL => Registers.TRANSC_CLK_SEL));
-
end HW.GFX.GMA.Pipe_Setup;
diff --git a/common/hw-gfx-gma-transcoder.adb b/common/hw-gfx-gma-transcoder.adb
new file mode 100644
index 0000000..27edf31
--- /dev/null
+++ b/common/hw-gfx-gma-transcoder.adb
@@ -0,0 +1,330 @@
+--
+-- 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.Debug;
+with GNAT.Source_Info;
+
+with HW.GFX.GMA.Config;
+with HW.GFX.GMA.DP_Info;
+
+package body HW.GFX.GMA.Transcoder is
+
+ type Default_Transcoder_Array is array (Pipe_Index) of Transcoder_Index;
+ Default_Transcoder : constant Default_Transcoder_Array :=
+ (Primary => Trans_A,
+ Secondary => Trans_B,
+ Tertiary => Trans_C);
+
+ function Get_Idx (Pipe : Pipe_Index; Port : GPU_Port) return Transcoder_Index
+ is
+ begin
+ return
+ (if Config.Has_EDP_Transcoder and then Port = DIGI_A then
+ Trans_EDP
+ else
+ Default_Transcoder (Pipe));
+ end Get_Idx;
+
+ ----------------------------------------------------------------------------
+
+ TRANS_CLK_SEL_PORT_NONE : constant := 0 * 2 ** 29;
+
+ type TRANS_CLK_SEL_PORT_Array is
+ array (Digital_Port) of Word32;
+ TRANS_CLK_SEL_PORT : constant TRANS_CLK_SEL_PORT_Array :=
+ (DIGI_A => 0 * 2 ** 29, -- DDI A is not selectable
+ DIGI_B => 2 * 2 ** 29,
+ DIGI_C => 3 * 2 ** 29,
+ DIGI_D => 4 * 2 ** 29,
+ DIGI_E => 5 * 2 ** 29);
+
+ TRANS_CONF_ENABLE : constant := 1 * 2 ** 31;
+ TRANS_CONF_ENABLED_STATUS : constant := 1 * 2 ** 30;
+ TRANS_CONF_ENABLE_DITHER : constant := 1 * 2 ** 4;
+
+ type BPC_Array is array (BPC_Type) of Word32;
+ TRANS_CONF_BPC : constant BPC_Array :=
+ (6 => 2 * 2 ** 5,
+ 8 => 0 * 2 ** 5,
+ 10 => 1 * 2 ** 5,
+ 12 => 3 * 2 ** 5,
+ others => 0 * 2 ** 5); -- default to 8 BPC
+
+ function BPC_Conf (BPC : BPC_Type; Dither : Boolean) return Word32 is
+ begin
+ return
+ (if Config.Has_Pipeconf_BPC then TRANS_CONF_BPC (BPC) else 0) or
+ (if Dither then TRANS_CONF_ENABLE_DITHER else 0);
+ end BPC_Conf;
+
+ ----------------------------------------------------------------------------
+
+ DDI_FUNC_CTL_ENABLE : constant := 1 * 2 ** 31;
+ DDI_FUNC_CTL_MODE_SELECT_MASK : constant := 7 * 2 ** 24;
+ DDI_FUNC_CTL_MODE_SELECT_HDMI : constant := 0 * 2 ** 24;
+ DDI_FUNC_CTL_MODE_SELECT_DVI : constant := 1 * 2 ** 24;
+ DDI_FUNC_CTL_MODE_SELECT_DP_SST : constant := 2 * 2 ** 24;
+ DDI_FUNC_CTL_MODE_SELECT_DP_MST : constant := 3 * 2 ** 24;
+ DDI_FUNC_CTL_MODE_SELECT_FDI : constant := 4 * 2 ** 24;
+ DDI_FUNC_CTL_EDP_SELECT_MASK : constant := 7 * 2 ** 12;
+ DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON : constant := 0 * 2 ** 12;
+ DDI_FUNC_CTL_EDP_SELECT_A : constant := 4 * 2 ** 12;
+ DDI_FUNC_CTL_EDP_SELECT_B : constant := 5 * 2 ** 12;
+ DDI_FUNC_CTL_EDP_SELECT_C : constant := 6 * 2 ** 12;
+
+ type DDI_Select_Array is array (Digital_Port) of Word32;
+ DDI_FUNC_CTL_DDI_SELECT : constant DDI_Select_Array :=
+ (DIGI_A => 0 * 2 ** 28,
+ DIGI_B => 1 * 2 ** 28,
+ DIGI_C => 2 * 2 ** 28,
+ DIGI_D => 3 * 2 ** 28,
+ DIGI_E => 4 * 2 ** 28);
+
+ 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,
+ HDMI => DDI_FUNC_CTL_MODE_SELECT_DVI,
+ DP => DDI_FUNC_CTL_MODE_SELECT_DP_SST,
+ others => 0);
+
+ type HV_Sync_Array is array (Boolean) of Word32;
+ DDI_FUNC_CTL_VSYNC : constant HV_Sync_Array :=
+ (False => 0 * 2 ** 17,
+ True => 1 * 2 ** 17);
+ DDI_FUNC_CTL_HSYNC : constant HV_Sync_Array :=
+ (False => 0 * 2 ** 16,
+ True => 1 * 2 ** 16);
+
+ type EDP_Select_Array is array (Pipe_Index) of Word32;
+ DDI_FUNC_CTL_EDP_SELECT : constant EDP_Select_Array :=
+ (Primary => DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON, -- we never use
+ -- panel fitter
+ Secondary => DDI_FUNC_CTL_EDP_SELECT_B,
+ Tertiary => DDI_FUNC_CTL_EDP_SELECT_C);
+ DDI_FUNC_CTL_EDP_SELECT_ONOFF : constant EDP_Select_Array :=
+ (Primary => DDI_FUNC_CTL_EDP_SELECT_A,
+ Secondary => DDI_FUNC_CTL_EDP_SELECT_B,
+ Tertiary => DDI_FUNC_CTL_EDP_SELECT_C);
+
+ type Port_Width_Array is array (DP_Lane_Count) of Word32;
+ DDI_FUNC_CTL_PORT_WIDTH : constant Port_Width_Array :=
+ (DP_Lane_Count_1 => 0 * 2 ** 1,
+ DP_Lane_Count_2 => 1 * 2 ** 1,
+ DP_Lane_Count_4 => 3 * 2 ** 1);
+
+ DDI_FUNC_CTL_BPC : constant BPC_Array :=
+ (6 => 2 * 2 ** 20,
+ 8 => 0 * 2 ** 20,
+ 10 => 1 * 2 ** 20,
+ 12 => 3 * 2 ** 20,
+ others => 0 * 2 ** 20); -- default to 8 BPC
+
+ ----------------------------------------------------------------------------
+
+ TRANS_MSA_MISC_SYNC_CLK : constant := 1 * 2 ** 0;
+ TRANS_MSA_MISC_BPC : constant BPC_Array :=
+ (6 => 0 * 2 ** 5,
+ 8 => 1 * 2 ** 5,
+ 10 => 2 * 2 ** 5,
+ 12 => 3 * 2 ** 5,
+ 16 => 4 * 2 ** 5,
+ others => 1 * 2 ** 5); -- default to 8 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;
+
+ ----------------------------------------------------------------------------
+
+ function Encode (LSW, MSW : Pos16) return Word32
+ is
+ use type HW.Pos16;
+ begin
+ return Shift_Left (Word32 (MSW - 1), 16) or Word32 (LSW - 1);
+ end Encode;
+
+ ----------------------------------------------------------------------------
+
+ procedure Setup_Link
+ (Trans : Transcoder_Regs;
+ Link : DP_Link;
+ Mode : Mode_Type)
+ with
+ Global => (In_Out => Registers.Register_State),
+ Depends => (Registers.Register_State =>+ (Trans, Link, Mode))
+ is
+ Data_M, Link_M : DP_Info.M_Type;
+ Data_N, Link_N : DP_Info.N_Type;
+ begin
+ pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+ DP_Info.Calculate_M_N
+ (Link => Link,
+ Mode => Mode,
+ Data_M => Data_M,
+ Data_N => Data_N,
+ Link_M => Link_M,
+ Link_N => Link_N);
+
+ Registers.Write
+ (Register => Trans.DATA_M1,
+ Value => TRANS_DATA_M_TU (64) or
+ Word32 (Data_M));
+ Registers.Write
+ (Register => Trans.DATA_N1,
+ Value => Word32 (Data_N));
+
+ Registers.Write
+ (Register => Trans.LINK_M1,
+ Value => Word32 (Link_M));
+ Registers.Write
+ (Register => Trans.LINK_N1,
+ Value => Word32 (Link_N));
+
+ if Config.Has_Pipe_MSA_Misc then
+ Registers.Write
+ (Register => Trans.MSA_MISC,
+ Value => TRANS_MSA_MISC_SYNC_CLK or
+ TRANS_MSA_MISC_BPC (Mode.BPC));
+ end if;
+ end Setup_Link;
+
+ ----------------------------------------------------------------------------
+
+ procedure Setup
+ (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));
+ M : constant Mode_Type := Port_Cfg.Mode;
+ begin
+ pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+ if Config.Has_Trans_Clk_Sel and then
+ Trans.CLK_SEL /= Registers.Invalid_Register
+ then
+ Registers.Write
+ (Register => Trans.CLK_SEL,
+ Value => TRANS_CLK_SEL_PORT (Port_Cfg.Port));
+ end if;
+
+ if Port_Cfg.Is_FDI then
+ Setup_Link (Trans, Port_Cfg.FDI, Port_Cfg.Mode);
+ elsif Port_Cfg.Display = DP then
+ Setup_Link (Trans, Port_Cfg.DP, Port_Cfg.Mode);
+ end if;
+
+ Registers.Write (Trans.HTOTAL, Encode (M.H_Visible, M.H_Total));
+ Registers.Write (Trans.HBLANK, Encode (M.H_Visible, M.H_Total));
+ Registers.Write (Trans.HSYNC, Encode (M.H_Sync_Begin, M.H_Sync_End));
+ Registers.Write (Trans.VTOTAL, Encode (M.V_Visible, M.V_Total));
+ Registers.Write (Trans.VBLANK, Encode (M.V_Visible, M.V_Total));
+ Registers.Write (Trans.VSYNC, Encode (M.V_Sync_Begin, M.V_Sync_End));
+ end Setup;
+
+ ----------------------------------------------------------------------------
+
+ procedure On
+ (Pipe : Pipe_Index;
+ Port_Cfg : Port_Config;
+ Dither : Boolean)
+ is
+ Trans : Transcoder_Regs renames
+ Transcoders (Get_Idx (Pipe, Port_Cfg.Port));
+ begin
+ if Config.Has_Pipe_DDI_Func then
+ Registers.Write
+ (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
+ DDI_FUNC_CTL_EDP_SELECT (Pipe) or
+ DDI_FUNC_CTL_PORT_WIDTH (Port_Cfg.DP.Lane_Count));
+ end if;
+
+ Registers.Write
+ (Register => Trans.CONF,
+ Value => TRANS_CONF_ENABLE or
+ (if not Config.Has_Pipeconf_Misc then
+ BPC_Conf (Port_Cfg.Mode.BPC, Dither) else 0));
+ Registers.Posting_Read (Trans.CONF);
+ end On;
+
+ ----------------------------------------------------------------------------
+
+ procedure Trans_Off (Trans : Transcoder_Regs)
+ is
+ Enabled : Boolean;
+ begin
+ Registers.Is_Set_Mask (Trans.CONF, TRANS_CONF_ENABLE, Enabled);
+
+ if Enabled then
+ Registers.Unset_Mask (Trans.CONF, TRANS_CONF_ENABLE);
+ end if;
+
+ -- Workaround for Broadwell:
+ -- Status may be wrong if pipe hasn't been enabled since reset.
+ if not Config.Pipe_Enabled_Workaround or else Enabled then
+ -- synchronously wait until pipe is truly off
+ Registers.Wait_Unset_Mask
+ (Register => Trans.CONF,
+ Mask => TRANS_CONF_ENABLED_STATUS,
+ TOut_MS => 40);
+ end if;
+
+ if Config.Has_Pipe_DDI_Func then
+ Registers.Write (Trans.DDI_FUNC_CTL, 0);
+ end if;
+ end Trans_Off;
+
+ procedure Off (Pipe : Pipe_Index)
+ is
+ DDI_Func_Ctl : Word32;
+ begin
+ if Config.Has_EDP_Transcoder then
+ Registers.Read (Registers.PIPE_EDP_DDI_FUNC_CTL, DDI_Func_Ctl);
+ DDI_Func_Ctl := DDI_Func_Ctl and DDI_FUNC_CTL_EDP_SELECT_MASK;
+
+ if (Pipe = Primary and
+ DDI_Func_Ctl = DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON) or
+ DDI_Func_Ctl = DDI_FUNC_CTL_EDP_SELECT_ONOFF (Pipe)
+ then
+ Trans_Off (Transcoders (Trans_EDP));
+ end if;
+ end if;
+
+ Trans_Off (Transcoders (Default_Transcoder (Pipe)));
+ end Off;
+
+ procedure Clk_Off (Pipe : Pipe_Index)
+ is
+ use type Registers.Registers_Invalid_Index;
+
+ Trans : Transcoder_Regs renames Transcoders (Default_Transcoder (Pipe));
+ begin
+ if Config.Has_Trans_Clk_Sel and then
+ Trans.CLK_SEL /= Registers.Invalid_Register
+ then
+ Registers.Write (Trans.CLK_SEL, TRANS_CLK_SEL_PORT_NONE);
+ end if;
+ end Clk_Off;
+
+end HW.GFX.GMA.Transcoder;
diff --git a/common/hw-gfx-gma-transcoder.ads b/common/hw-gfx-gma-transcoder.ads
new file mode 100644
index 0000000..aa67eb4
--- /dev/null
+++ b/common/hw-gfx-gma-transcoder.ads
@@ -0,0 +1,114 @@
+--
+-- 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.GFX.GMA.Registers;
+
+private package HW.GFX.GMA.Transcoder
+is
+
+ procedure Setup (Pipe : Pipe_Index; Port_Cfg : Port_Config);
+ procedure On (Pipe : Pipe_Index; Port_Cfg : Port_Config; Dither : Boolean);
+
+ procedure Off (Pipe : Pipe_Index);
+ procedure Clk_Off (Pipe : Pipe_Index);
+
+ function BPC_Conf (BPC : BPC_Type; Dither : Boolean) return Word32;
+
+private
+
+ type Transcoder_Index is (Trans_EDP, Trans_A, Trans_B, Trans_C);
+
+ type Transcoder_Regs 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;
+ DATA_M1 : Registers.Registers_Index;
+ DATA_N1 : Registers.Registers_Index;
+ LINK_M1 : Registers.Registers_Index;
+ LINK_N1 : Registers.Registers_Index;
+ DDI_FUNC_CTL : Registers.Registers_Index;
+ MSA_MISC : Registers.Registers_Index;
+ CLK_SEL : Registers.Registers_Invalid_Index;
+ end record;
+
+ type Transcoder_Array is array (Transcoder_Index) of Transcoder_Regs;
+
+ Transcoders : constant Transcoder_Array :=
+ (Trans_EDP =>
+ (HTOTAL => Registers.HTOTAL_EDP,
+ HBLANK => Registers.HBLANK_EDP,
+ HSYNC => Registers.HSYNC_EDP,
+ VTOTAL => Registers.VTOTAL_EDP,
+ VBLANK => Registers.VBLANK_EDP,
+ VSYNC => Registers.VSYNC_EDP,
+ CONF => Registers.PIPE_EDP_CONF,
+ DATA_M1 => Registers.PIPE_EDP_DATA_M1,
+ DATA_N1 => Registers.PIPE_EDP_DATA_N1,
+ LINK_M1 => Registers.PIPE_EDP_LINK_M1,
+ 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),
+ Trans_A =>
+ (HTOTAL => Registers.HTOTAL_A,
+ HBLANK => Registers.HBLANK_A,
+ HSYNC => Registers.HSYNC_A,
+ VTOTAL => Registers.VTOTAL_A,
+ VBLANK => Registers.VBLANK_A,
+ VSYNC => Registers.VSYNC_A,
+ CONF => Registers.PIPEACONF,
+ DATA_M1 => Registers.PIPEA_DATA_M1,
+ DATA_N1 => Registers.PIPEA_DATA_N1,
+ LINK_M1 => Registers.PIPEA_LINK_M1,
+ LINK_N1 => Registers.PIPEA_LINK_N1,
+ DDI_FUNC_CTL => Registers.PIPEA_DDI_FUNC_CTL,
+ MSA_MISC => Registers.PIPEA_MSA_MISC,
+ CLK_SEL => Registers.TRANSA_CLK_SEL),
+ Trans_B =>
+ (HTOTAL => Registers.HTOTAL_B,
+ HBLANK => Registers.HBLANK_B,
+ HSYNC => Registers.HSYNC_B,
+ VTOTAL => Registers.VTOTAL_B,
+ VBLANK => Registers.VBLANK_B,
+ VSYNC => Registers.VSYNC_B,
+ CONF => Registers.PIPEBCONF,
+ DATA_M1 => Registers.PIPEB_DATA_M1,
+ DATA_N1 => Registers.PIPEB_DATA_N1,
+ LINK_M1 => Registers.PIPEB_LINK_M1,
+ LINK_N1 => Registers.PIPEB_LINK_N1,
+ DDI_FUNC_CTL => Registers.PIPEB_DDI_FUNC_CTL,
+ MSA_MISC => Registers.PIPEB_MSA_MISC,
+ CLK_SEL => Registers.TRANSB_CLK_SEL),
+ Trans_C =>
+ (HTOTAL => Registers.HTOTAL_C,
+ HBLANK => Registers.HBLANK_C,
+ HSYNC => Registers.HSYNC_C,
+ VTOTAL => Registers.VTOTAL_C,
+ VBLANK => Registers.VBLANK_C,
+ VSYNC => Registers.VSYNC_C,
+ CONF => Registers.PIPECCONF,
+ DATA_M1 => Registers.PIPEC_DATA_M1,
+ DATA_N1 => Registers.PIPEC_DATA_N1,
+ LINK_M1 => Registers.PIPEC_LINK_M1,
+ 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));
+
+end HW.GFX.GMA.Transcoder;
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index 0fb4e5d..8d304b6 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -135,7 +135,7 @@
Connectors.Pre_Off (Port_Cfg);
- Display_Controller.Off (I, Port_Cfg);
+ Display_Controller.Off (I);
Connectors.Post_Off (Port_Cfg);
end if;
@@ -212,7 +212,7 @@
Success => Success);
if not Success then
- Display_Controller.Off (I, Port_Cfg);
+ Display_Controller.Off (I);
Connectors.Post_Off (Port_Cfg);
end if;
end if;