blob: c95bebc9621597e9dbb40ac9daa6d956dc377519 [file] [log] [blame]
Nico Huber8c45bcf2016-11-20 17:30:57 +01001--
2-- Copyright (C) 2015-2016 secunet Security Networks AG
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
6-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
8--
9-- This program is distributed in the hope that it will be useful,
10-- but WITHOUT ANY WARRANTY; without even the implied warranty of
11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-- GNU General Public License for more details.
13--
14
15with HW.GFX.GMA.Config;
16with HW.GFX.GMA.Connector_Info;
17with HW.GFX.GMA.DP_Info;
18with HW.GFX.GMA.Registers;
19
20with HW.Debug;
21
22package body HW.GFX.GMA.Config_Helpers
23is
24
25 function To_GPU_Port
26 (Pipe : Pipe_Index;
27 Port : Active_Port_Type)
28 return GPU_Port
29 is
30 begin
31 return
Nico Huber6621a142018-06-07 23:56:54 +020032 (case Config.Gen is
33 when G45 => -- everything on GMCH
Arthur Heymans73ea0322018-03-28 17:17:07 +020034 (case Port is
35 when Internal => LVDS,
36 when HDMI1 | DP1 => DIGI_B,
37 when HDMI2 | DP2 => DIGI_C,
38 when HDMI3 | DP3 => DIGI_D,
39 when Analog => VGA),
Nico Huber6621a142018-06-07 23:56:54 +020040 when Ironlake => -- everything but eDP through FDI/PCH
Nico Huber8c45bcf2016-11-20 17:30:57 +010041 (if Config.Internal_Is_EDP and then Port = Internal then
42 DIGI_A
43 else
Nico Huber6621a142018-06-07 23:56:54 +020044 (case Pipe is -- FDIs are fixed to the CPU pipe
Nico Huber8c45bcf2016-11-20 17:30:57 +010045 when Primary => DIGI_B,
46 when Secondary => DIGI_C,
47 when Tertiary => DIGI_D)),
Nico Huber6621a142018-06-07 23:56:54 +020048 when others => -- everything but VGA directly on CPU
Nico Huber8c45bcf2016-11-20 17:30:57 +010049 (case Port is
50 when Internal => DIGI_A, -- LVDS not available
51 when HDMI1 | DP1 => DIGI_B,
52 when HDMI2 | DP2 => DIGI_C,
53 when HDMI3 | DP3 => DIGI_D,
54 when Analog => DIGI_E));
55 end To_GPU_Port;
56
57 function To_PCH_Port (Port : Active_Port_Type) return PCH_Port
58 is
59 begin
60 return
61 (case Port is
62 when Internal => PCH_LVDS, -- will be ignored if Internal is DP
63 when Analog => PCH_DAC,
64 when HDMI1 => PCH_HDMI_B,
65 when HDMI2 => PCH_HDMI_C,
66 when HDMI3 => PCH_HDMI_D,
67 when DP1 => PCH_DP_B,
68 when DP2 => PCH_DP_C,
69 when DP3 => PCH_DP_D);
70 end To_PCH_Port;
71
72 function To_Display_Type (Port : Active_Port_Type) return Display_Type
73 is
74 begin
75 return Display_Type'
76 (case Port is
77 when Internal => Config.Internal_Display,
78 when Analog => VGA,
79 when HDMI1 .. HDMI3 => HDMI,
80 when DP1 .. DP3 => DP);
81 end To_Display_Type;
82
83 ----------------------------------------------------------------------------
84
85 -- Prepares link rate and lane count settings for an FDI connection.
86 procedure Configure_FDI_Link
87 (Port_Cfg : in out Port_Config;
88 Success : out Boolean)
89 with Pre => True
90 is
91 procedure Limit_Lane_Count
92 is
93 FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
94 Enabled : Boolean;
95 begin
96 -- if DIGI_D enabled: (FDI names are off by one)
97 Registers.Is_Set_Mask
98 (Register => Registers.FDI_TX_CTL_C,
99 Mask => FDI_TX_CTL_FDI_TX_ENABLE,
100 Result => Enabled);
101 if Enabled then
102 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
103 end if;
104 end Limit_Lane_Count;
105 begin
106 Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
107 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count :=
108 Config.FDI_Lane_Count (Port_Cfg.Port);
109 Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
110 if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
111 Limit_Lane_Count;
112 end if;
113 DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
114 end Configure_FDI_Link;
115
116 -- Derives an internal port config.
117 --
118 -- This is where the magic happens that hides the hardware details
119 -- from libgfxinit's users. We have to map the pipe (Pipe_Index),
120 -- the user visible port (Port_Type) and the modeline (Mode_Type)
121 -- that we are supposed to output to an internal representation
122 -- (Port_Config) that applies to the selected hardware generation
123 -- (in GMA.Config).
124 procedure Fill_Port_Config
125 (Port_Cfg : out Port_Config;
126 Pipe : in Pipe_Index;
127 Port : in Port_Type;
128 Mode : in Mode_Type;
129 Success : out Boolean)
130 is
131 begin
132 Success :=
Nico Huberd58de7d2018-06-07 23:06:55 +0200133 (Config.Has_Tertiary_Pipe or Pipe <= Secondary) and then
Nico Huber8c45bcf2016-11-20 17:30:57 +0100134 Config.Valid_Port (Port) and then
135 Port /= Disabled; -- Valid_Port should already cover this, but the
136 -- array is writeable, so it's hard to prove this.
137
138 if Success then
139 Port_Cfg := Port_Config'
140 (Port => To_GPU_Port (Pipe, Port),
141 PCH_Port => To_PCH_Port (Port),
142 Display => To_Display_Type (Port),
143 Mode => Mode,
144 Is_FDI => Config.Is_FDI_Port (Port),
145 FDI => Default_DP,
146 DP => Default_DP);
147
Nico Huber02cfbb32017-01-09 17:41:18 +0100148 if Port_Cfg.Mode.BPC = Auto_BPC then
149 Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100150 end if;
151
Nico Huber02cfbb32017-01-09 17:41:18 +0100152 if Port_Cfg.Display = HDMI then
153 declare
154 pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
155 / Port_Cfg.Mode.BPC >= Frequency_Type'First);
156 Max_Dotclock : constant Frequency_Type :=
157 Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
158 begin
159 if Port_Cfg.Mode.Dotclock > Max_Dotclock then
160 pragma Debug (Debug.Put ("Dotclock "));
161 pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
162 pragma Debug (Debug.Put (" too high, limiting to "));
163 pragma Debug (Debug.Put_Int64 (Max_Dotclock));
164 pragma Debug (Debug.Put_Line ("."));
165 Port_Cfg.Mode.Dotclock := Max_Dotclock;
166 end if;
167 end;
168 end if;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100169
Nico Huber02cfbb32017-01-09 17:41:18 +0100170 if Port_Cfg.Is_FDI then
171 Configure_FDI_Link (Port_Cfg, Success);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100172 end if;
173 else
174 Port_Cfg := Port_Config'
175 (Port => GPU_Port'First,
176 PCH_Port => PCH_Port'First,
177 Display => Display_Type'First,
178 Mode => Invalid_Mode,
179 Is_FDI => False,
180 FDI => Default_DP,
181 DP => Default_DP);
182 end if;
183 end Fill_Port_Config;
184
185 ----------------------------------------------------------------------------
186
187 -- Validates that a given configuration should work with
188 -- a given framebuffer.
189 function Validate_Config
Nico Huberf361ec82018-06-02 18:01:45 +0200190 (FB : Framebuffer_Type;
191 Mode : Mode_Type;
192 Pipe : Pipe_Index;
193 Scaler_Available : Boolean)
Nico Huber8c45bcf2016-11-20 17:30:57 +0100194 return Boolean
195 is
196 begin
197 -- No downscaling
198 -- Respect maximum scalable width
199 -- VGA plane is only allowed on the primary pipe
200 -- Only 32bpp RGB (ignored for VGA plane)
Nico Huber0164b022017-08-24 15:12:51 +0200201 -- Stride must be big enough and a multiple of 64 bytes or the tile size
202 -- (ignored for VGA plane)
Nico Huberab69e362018-05-29 21:20:30 +0200203 -- Y-Tiling and rotation are only supported on newer generations (with
Nico Huber9b479412017-08-27 11:55:56 +0200204 -- Plane_Control)
205 -- 90 degree rotations are only supported with Y-tiling
Nico Huber8c45bcf2016-11-20 17:30:57 +0100206 return
Nico Hubercbbaade2018-01-02 13:59:36 +0100207 ((Rotated_Width (FB) = Mode.H_Visible and
208 Rotated_Height (FB) = Mode.V_Visible) or
Nico Huberf361ec82018-06-02 18:01:45 +0200209 (Scaler_Available and
210 Rotated_Width (FB) <= Config.Maximum_Scalable_Width (Pipe) and
Nico Hubercbbaade2018-01-02 13:59:36 +0100211 Rotated_Width (FB) <= Mode.H_Visible and
212 Rotated_Height (FB) <= Mode.V_Visible)) and
Nico Huber9b479412017-08-27 11:55:56 +0200213 (FB.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary) and
214 (FB.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
215 (FB.BPC = 8 and Valid_Stride (FB) and
216 (Config.Has_Plane_Control or
Nico Huberab69e362018-05-29 21:20:30 +0200217 (FB.Tiling /= Y_Tiled and FB.Rotation = No_Rotation)) and
Nico Huber9b479412017-08-27 11:55:56 +0200218 (FB.Tiling = Y_Tiled or not Rotation_90 (FB))));
Nico Huber8c45bcf2016-11-20 17:30:57 +0100219 end Validate_Config;
220
221end HW.GFX.GMA.Config_Helpers;