blob: 0f60375d4c0d822b7e8443e1e26d1e9f25087380 [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
33 when Ironlake .. Ivybridge => -- everything but eDP through FDI/PCH
34 (if Config.Internal_Is_EDP and then Port = Internal then
35 DIGI_A
36 else
37 (case Pipe is
38 -- FDIs are fixed to the CPU pipe
39 when Primary => DIGI_B,
40 when Secondary => DIGI_C,
41 when Tertiary => DIGI_D)),
42 when Haswell .. Skylake => -- everything but VGA directly on CPU
43 (case Port is
44 when Internal => DIGI_A, -- LVDS not available
45 when HDMI1 | DP1 => DIGI_B,
46 when HDMI2 | DP2 => DIGI_C,
47 when HDMI3 | DP3 => DIGI_D,
48 when Analog => DIGI_E));
49 end To_GPU_Port;
50
51 function To_PCH_Port (Port : Active_Port_Type) return PCH_Port
52 is
53 begin
54 return
55 (case Port is
56 when Internal => PCH_LVDS, -- will be ignored if Internal is DP
57 when Analog => PCH_DAC,
58 when HDMI1 => PCH_HDMI_B,
59 when HDMI2 => PCH_HDMI_C,
60 when HDMI3 => PCH_HDMI_D,
61 when DP1 => PCH_DP_B,
62 when DP2 => PCH_DP_C,
63 when DP3 => PCH_DP_D);
64 end To_PCH_Port;
65
66 function To_Display_Type (Port : Active_Port_Type) return Display_Type
67 is
68 begin
69 return Display_Type'
70 (case Port is
71 when Internal => Config.Internal_Display,
72 when Analog => VGA,
73 when HDMI1 .. HDMI3 => HDMI,
74 when DP1 .. DP3 => DP);
75 end To_Display_Type;
76
77 ----------------------------------------------------------------------------
78
79 -- Prepares link rate and lane count settings for an FDI connection.
80 procedure Configure_FDI_Link
81 (Port_Cfg : in out Port_Config;
82 Success : out Boolean)
83 with Pre => True
84 is
85 procedure Limit_Lane_Count
86 is
87 FDI_TX_CTL_FDI_TX_ENABLE : constant := 1 * 2 ** 31;
88 Enabled : Boolean;
89 begin
90 -- if DIGI_D enabled: (FDI names are off by one)
91 Registers.Is_Set_Mask
92 (Register => Registers.FDI_TX_CTL_C,
93 Mask => FDI_TX_CTL_FDI_TX_ENABLE,
94 Result => Enabled);
95 if Enabled then
96 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count := DP_Lane_Count_2;
97 end if;
98 end Limit_Lane_Count;
99 begin
100 Port_Cfg.FDI.Receiver_Caps.Max_Link_Rate := DP_Bandwidth_2_7;
101 Port_Cfg.FDI.Receiver_Caps.Max_Lane_Count :=
102 Config.FDI_Lane_Count (Port_Cfg.Port);
103 Port_Cfg.FDI.Receiver_Caps.Enhanced_Framing := True;
104 if Config.Has_FDI_C and then Port_Cfg.Port = DIGI_C then
105 Limit_Lane_Count;
106 end if;
107 DP_Info.Preferred_Link_Setting (Port_Cfg.FDI, Port_Cfg.Mode, Success);
108 end Configure_FDI_Link;
109
110 -- Derives an internal port config.
111 --
112 -- This is where the magic happens that hides the hardware details
113 -- from libgfxinit's users. We have to map the pipe (Pipe_Index),
114 -- the user visible port (Port_Type) and the modeline (Mode_Type)
115 -- that we are supposed to output to an internal representation
116 -- (Port_Config) that applies to the selected hardware generation
117 -- (in GMA.Config).
118 procedure Fill_Port_Config
119 (Port_Cfg : out Port_Config;
120 Pipe : in Pipe_Index;
121 Port : in Port_Type;
122 Mode : in Mode_Type;
123 Success : out Boolean)
124 is
125 begin
126 Success :=
127 Config.Supported_Pipe (Pipe) and then
128 Config.Valid_Port (Port) and then
129 Port /= Disabled; -- Valid_Port should already cover this, but the
130 -- array is writeable, so it's hard to prove this.
131
132 if Success then
133 Port_Cfg := Port_Config'
134 (Port => To_GPU_Port (Pipe, Port),
135 PCH_Port => To_PCH_Port (Port),
136 Display => To_Display_Type (Port),
137 Mode => Mode,
138 Is_FDI => Config.Is_FDI_Port (Port),
139 FDI => Default_DP,
140 DP => Default_DP);
141
Nico Huber02cfbb32017-01-09 17:41:18 +0100142 if Port_Cfg.Mode.BPC = Auto_BPC then
143 Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100144 end if;
145
Nico Huber02cfbb32017-01-09 17:41:18 +0100146 if Port_Cfg.Display = HDMI then
147 declare
148 pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
149 / Port_Cfg.Mode.BPC >= Frequency_Type'First);
150 Max_Dotclock : constant Frequency_Type :=
151 Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
152 begin
153 if Port_Cfg.Mode.Dotclock > Max_Dotclock then
154 pragma Debug (Debug.Put ("Dotclock "));
155 pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
156 pragma Debug (Debug.Put (" too high, limiting to "));
157 pragma Debug (Debug.Put_Int64 (Max_Dotclock));
158 pragma Debug (Debug.Put_Line ("."));
159 Port_Cfg.Mode.Dotclock := Max_Dotclock;
160 end if;
161 end;
162 end if;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100163
Nico Huber02cfbb32017-01-09 17:41:18 +0100164 if Port_Cfg.Is_FDI then
165 Configure_FDI_Link (Port_Cfg, Success);
Nico Huber8c45bcf2016-11-20 17:30:57 +0100166 end if;
167 else
168 Port_Cfg := Port_Config'
169 (Port => GPU_Port'First,
170 PCH_Port => PCH_Port'First,
171 Display => Display_Type'First,
172 Mode => Invalid_Mode,
173 Is_FDI => False,
174 FDI => Default_DP,
175 DP => Default_DP);
176 end if;
177 end Fill_Port_Config;
178
179 ----------------------------------------------------------------------------
180
181 -- Validates that a given configuration should work with
182 -- a given framebuffer.
183 function Validate_Config
184 (Framebuffer : Framebuffer_Type;
185 Port_Cfg : Port_Config;
186 Pipe : Pipe_Index)
187 return Boolean
188 is
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100189 function To_Bytes (Pixels : Width_Type) return Pos32 is
190 begin
191 return Pos32 (Pixels) * 4 * Pos32 (Framebuffer.BPC) / 8;
192 end To_Bytes;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100193 begin
194 -- No downscaling
195 -- Respect maximum scalable width
196 -- VGA plane is only allowed on the primary pipe
197 -- Only 32bpp RGB (ignored for VGA plane)
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100198 -- Stride must be a multiple of 64 bytes (ignored for VGA plane)
Nico Huber8c45bcf2016-11-20 17:30:57 +0100199 return
200 ((Framebuffer.Width = Pos32 (Port_Cfg.Mode.H_Visible) and
201 Framebuffer.Height = Pos32 (Port_Cfg.Mode.V_Visible)) or
202 (Framebuffer.Width <= Config.Maximum_Scalable_Width (Pipe) and
203 Framebuffer.Width <= Pos32 (Port_Cfg.Mode.H_Visible) and
204 Framebuffer.Height <= Pos32 (Port_Cfg.Mode.V_Visible))) and
205 (Framebuffer.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary)
206 and
207 (Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
208 (Framebuffer.BPC = 8 and
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100209 To_Bytes (Framebuffer.Stride) mod 64 = 0));
Nico Huber8c45bcf2016-11-20 17:30:57 +0100210 end Validate_Config;
211
212end HW.GFX.GMA.Config_Helpers;