blob: adc749cd448427beebb435466744d01ad40884b8 [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
32 (case Config.CPU is
Arthur Heymans73ea0322018-03-28 17:17:07 +020033 when G45 =>
34 (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 Huber8c45bcf2016-11-20 17:30:57 +010040 when Ironlake .. Ivybridge => -- everything but eDP through FDI/PCH
41 (if Config.Internal_Is_EDP and then Port = Internal then
42 DIGI_A
43 else
44 (case Pipe is
45 -- FDIs are fixed to the CPU pipe
46 when Primary => DIGI_B,
47 when Secondary => DIGI_C,
48 when Tertiary => DIGI_D)),
49 when Haswell .. Skylake => -- everything but VGA directly on CPU
50 (case Port is
51 when Internal => DIGI_A, -- LVDS not available
52 when HDMI1 | DP1 => DIGI_B,
53 when HDMI2 | DP2 => DIGI_C,
54 when HDMI3 | DP3 => DIGI_D,
55 when Analog => DIGI_E));
56 end To_GPU_Port;
57
58 function To_PCH_Port (Port : Active_Port_Type) return PCH_Port
59 is
60 begin
61 return
62 (case Port is
63 when Internal => PCH_LVDS, -- will be ignored if Internal is DP
64 when Analog => PCH_DAC,
65 when HDMI1 => PCH_HDMI_B,
66 when HDMI2 => PCH_HDMI_C,
67 when HDMI3 => PCH_HDMI_D,
68 when DP1 => PCH_DP_B,
69 when DP2 => PCH_DP_C,
70 when DP3 => PCH_DP_D);
71 end To_PCH_Port;
72
73 function To_Display_Type (Port : Active_Port_Type) return Display_Type
74 is
75 begin
76 return Display_Type'
77 (case Port is
78 when Internal => Config.Internal_Display,
79 when Analog => VGA,
80 when HDMI1 .. HDMI3 => HDMI,
81 when DP1 .. DP3 => DP);
82 end To_Display_Type;
83
84 ----------------------------------------------------------------------------
85
86 -- Prepares link rate and lane count settings for an FDI connection.
87 procedure Configure_FDI_Link
88 (Port_Cfg : in out Port_Config;
89 Success : out Boolean)
90 with Pre => True
91 is
92 procedure Limit_Lane_Count
93 is
94 FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
95 Enabled : Boolean;
96 begin
97 -- if DIGI_D enabled: (FDI names are off by one)
98 Registers.Is_Set_Mask
99 (Register => Registers.FDI_TX_CTL_C,
100 Mask => FDI_TX_CTL_FDI_TX_ENABLE,
101 Result => Enabled);
102 if Enabled then
103 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
104 end if;
105 end Limit_Lane_Count;
106 begin
107 Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
108 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count :=
109 Config.FDI_Lane_Count (Port_Cfg.Port);
110 Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
111 if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
112 Limit_Lane_Count;
113 end if;
114 DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
115 end Configure_FDI_Link;
116
117 -- Derives an internal port config.
118 --
119 -- This is where the magic happens that hides the hardware details
120 -- from libgfxinit's users. We have to map the pipe (Pipe_Index),
121 -- the user visible port (Port_Type) and the modeline (Mode_Type)
122 -- that we are supposed to output to an internal representation
123 -- (Port_Config) that applies to the selected hardware generation
124 -- (in GMA.Config).
125 procedure Fill_Port_Config
126 (Port_Cfg : out Port_Config;
127 Pipe : in Pipe_Index;
128 Port : in Port_Type;
129 Mode : in Mode_Type;
130 Success : out Boolean)
131 is
132 begin
133 Success :=
134 Config.Supported_Pipe (Pipe) and then
135 Config.Valid_Port (Port) and then
136 Port /= Disabled; -- Valid_Port should already cover this, but the
137 -- array is writeable, so it's hard to prove this.
138
139 if Success then
140 Port_Cfg := Port_Config'
141 (Port => To_GPU_Port (Pipe, Port),
142 PCH_Port => To_PCH_Port (Port),
143 Display => To_Display_Type (Port),
144 Mode => Mode,
145 Is_FDI => Config.Is_FDI_Port (Port),
146 FDI => Default_DP,
147 DP => Default_DP);
148
Nico Huber02cfbb32017-01-09 17:41:18 +0100149 if Port_Cfg.Mode.BPC = Auto_BPC then
150 Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100151 end if;
152
Nico Huber02cfbb32017-01-09 17:41:18 +0100153 if Port_Cfg.Display = HDMI then
154 declare
155 pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
156 / Port_Cfg.Mode.BPC >= Frequency_Type'First);
157 Max_Dotclock : constant Frequency_Type :=
158 Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
159 begin
160 if Port_Cfg.Mode.Dotclock > Max_Dotclock then
161 pragma Debug (Debug.Put ("Dotclock "));
162 pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
163 pragma Debug (Debug.Put (" too high, limiting to "));
164 pragma Debug (Debug.Put_Int64 (Max_Dotclock));
165 pragma Debug (Debug.Put_Line ("."));
166 Port_Cfg.Mode.Dotclock := Max_Dotclock;
167 end if;
168 end;
169 end if;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100170
Nico Huber02cfbb32017-01-09 17:41:18 +0100171 if Port_Cfg.Is_FDI then
172 Configure_FDI_Link (Port_Cfg, Success);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100173 end if;
174 else
175 Port_Cfg := Port_Config'
176 (Port => GPU_Port'First,
177 PCH_Port => PCH_Port'First,
178 Display => Display_Type'First,
179 Mode => Invalid_Mode,
180 Is_FDI => False,
181 FDI => Default_DP,
182 DP => Default_DP);
183 end if;
184 end Fill_Port_Config;
185
186 ----------------------------------------------------------------------------
187
188 -- Validates that a given configuration should work with
189 -- a given framebuffer.
190 function Validate_Config
Nico Hubercbbaade2018-01-02 13:59:36 +0100191 (FB : Framebuffer_Type;
192 Mode : Mode_Type;
193 Pipe : Pipe_Index)
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 Huber9b479412017-08-27 11:55:56 +0200203 -- Tiling and rotation is only supported on newer generations (with
204 -- 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 Huber9b479412017-08-27 11:55:56 +0200209 (Rotated_Width (FB) <= Config.Maximum_Scalable_Width (Pipe) and
Nico Hubercbbaade2018-01-02 13:59:36 +0100210 Rotated_Width (FB) <= Mode.H_Visible and
211 Rotated_Height (FB) <= Mode.V_Visible)) and
Nico Huber9b479412017-08-27 11:55:56 +0200212 (FB.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary) and
213 (FB.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
214 (FB.BPC = 8 and Valid_Stride (FB) and
215 (Config.Has_Plane_Control or
216 (FB.Tiling = Linear and FB.Rotation = No_Rotation)) and
217 (FB.Tiling = Y_Tiled or not Rotation_90 (FB))));
Nico Huber8c45bcf2016-11-20 17:30:57 +0100218 end Validate_Config;
219
220end HW.GFX.GMA.Config_Helpers;