blob: 128b52beb56bbdbf4e825d79e22ac9cb3f7bb283 [file] [log] [blame]
--
-- 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.Config;
with HW.GFX.GMA.Connector_Info;
with HW.GFX.GMA.DP_Info;
with HW.GFX.GMA.Registers;
with HW.Debug;
package body HW.GFX.GMA.Config_Helpers
is
function To_GPU_Port
(Pipe : Pipe_Index;
Port : Active_Port_Type)
return GPU_Port
is
begin
return
(case Config.CPU is
when G45 =>
(case Port is
when Internal => LVDS,
when HDMI1 | DP1 => DIGI_B,
when HDMI2 | DP2 => DIGI_C,
when HDMI3 | DP3 => DIGI_D,
when Analog => VGA),
when Ironlake .. Ivybridge => -- everything but eDP through FDI/PCH
(if Config.Internal_Is_EDP and then Port = Internal then
DIGI_A
else
(case Pipe is
-- FDIs are fixed to the CPU pipe
when Primary => DIGI_B,
when Secondary => DIGI_C,
when Tertiary => DIGI_D)),
when Haswell .. Skylake => -- everything but VGA directly on CPU
(case Port is
when Internal => DIGI_A, -- LVDS not available
when HDMI1 | DP1 => DIGI_B,
when HDMI2 | DP2 => DIGI_C,
when HDMI3 | DP3 => DIGI_D,
when Analog => DIGI_E));
end To_GPU_Port;
function To_PCH_Port (Port : Active_Port_Type) return PCH_Port
is
begin
return
(case Port is
when Internal => PCH_LVDS, -- will be ignored if Internal is DP
when Analog => PCH_DAC,
when HDMI1 => PCH_HDMI_B,
when HDMI2 => PCH_HDMI_C,
when HDMI3 => PCH_HDMI_D,
when DP1 => PCH_DP_B,
when DP2 => PCH_DP_C,
when DP3 => PCH_DP_D);
end To_PCH_Port;
function To_Display_Type (Port : Active_Port_Type) return Display_Type
is
begin
return Display_Type'
(case Port is
when Internal => Config.Internal_Display,
when Analog => VGA,
when HDMI1 .. HDMI3 => HDMI,
when DP1 .. DP3 => DP);
end To_Display_Type;
----------------------------------------------------------------------------
-- Prepares link rate and lane count settings for an FDI connection.
procedure Configure_FDI_Link
(Port_Cfg : in out Port_Config;
Success : out Boolean)
with Pre => True
is
procedure Limit_Lane_Count
is
FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
Enabled : Boolean;
begin
-- if DIGI_D enabled: (FDI names are off by one)
Registers.Is_Set_Mask
(Register => Registers.FDI_TX_CTL_C,
Mask => FDI_TX_CTL_FDI_TX_ENABLE,
Result => Enabled);
if Enabled then
Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
end if;
end Limit_Lane_Count;
begin
Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count :=
Config.FDI_Lane_Count (Port_Cfg.Port);
Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
Limit_Lane_Count;
end if;
DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
end Configure_FDI_Link;
-- Derives an internal port config.
--
-- This is where the magic happens that hides the hardware details
-- from libgfxinit's users. We have to map the pipe (Pipe_Index),
-- the user visible port (Port_Type) and the modeline (Mode_Type)
-- that we are supposed to output to an internal representation
-- (Port_Config) that applies to the selected hardware generation
-- (in GMA.Config).
procedure Fill_Port_Config
(Port_Cfg : out Port_Config;
Pipe : in Pipe_Index;
Port : in Port_Type;
Mode : in Mode_Type;
Success : out Boolean)
is
begin
Success :=
Config.Supported_Pipe (Pipe) and then
Config.Valid_Port (Port) and then
Port /= Disabled; -- Valid_Port should already cover this, but the
-- array is writeable, so it's hard to prove this.
if Success then
Port_Cfg := Port_Config'
(Port => To_GPU_Port (Pipe, Port),
PCH_Port => To_PCH_Port (Port),
Display => To_Display_Type (Port),
Mode => Mode,
Is_FDI => Config.Is_FDI_Port (Port),
FDI => Default_DP,
DP => Default_DP);
if Port_Cfg.Mode.BPC = Auto_BPC then
Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
end if;
if Port_Cfg.Display = HDMI then
declare
pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
/ Port_Cfg.Mode.BPC >= Frequency_Type'First);
Max_Dotclock : constant Frequency_Type :=
Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
begin
if Port_Cfg.Mode.Dotclock > Max_Dotclock then
pragma Debug (Debug.Put ("Dotclock "));
pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
pragma Debug (Debug.Put (" too high, limiting to "));
pragma Debug (Debug.Put_Int64 (Max_Dotclock));
pragma Debug (Debug.Put_Line ("."));
Port_Cfg.Mode.Dotclock := Max_Dotclock;
end if;
end;
end if;
if Port_Cfg.Is_FDI then
Configure_FDI_Link (Port_Cfg, Success);
end if;
else
Port_Cfg := Port_Config'
(Port => GPU_Port'First,
PCH_Port => PCH_Port'First,
Display => Display_Type'First,
Mode => Invalid_Mode,
Is_FDI => False,
FDI => Default_DP,
DP => Default_DP);
end if;
end Fill_Port_Config;
----------------------------------------------------------------------------
-- Validates that a given configuration should work with
-- a given framebuffer.
function Validate_Config
(FB : Framebuffer_Type;
Mode : Mode_Type;
Pipe : Pipe_Index)
return Boolean
is
begin
-- No downscaling
-- Respect maximum scalable width
-- VGA plane is only allowed on the primary pipe
-- Only 32bpp RGB (ignored for VGA plane)
-- Stride must be big enough and a multiple of 64 bytes or the tile size
-- (ignored for VGA plane)
-- Y-Tiling and rotation are only supported on newer generations (with
-- Plane_Control)
-- 90 degree rotations are only supported with Y-tiling
return
((Rotated_Width (FB) = Mode.H_Visible and
Rotated_Height (FB) = Mode.V_Visible) or
(Rotated_Width (FB) <= Config.Maximum_Scalable_Width (Pipe) and
Rotated_Width (FB) <= Mode.H_Visible and
Rotated_Height (FB) <= Mode.V_Visible)) and
(FB.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary) and
(FB.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
(FB.BPC = 8 and Valid_Stride (FB) and
(Config.Has_Plane_Control or
(FB.Tiling /= Y_Tiled and FB.Rotation = No_Rotation)) and
(FB.Tiling = Y_Tiled or not Rotation_90 (FB))));
end Validate_Config;
end HW.GFX.GMA.Config_Helpers;