blob: 3a41baf56c5d6b1ccc780a5197093c594dc7c602 [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
142 if Port_Cfg.Is_FDI then
143 Configure_FDI_Link (Port_Cfg, Success);
144 end if;
145
146 if Success then
147 if Port_Cfg.Mode.BPC = Auto_BPC then
148 Port_Cfg.Mode.BPC := Connector_Info.Default_BPC (Port_Cfg);
149 end if;
150
151 if Port_Cfg.Display = HDMI then
152 declare
153 pragma Assert (Config.HDMI_Max_Clock_24bpp * 8
154 / Port_Cfg.Mode.BPC >= Frequency_Type'First);
155 Max_Dotclock : constant Frequency_Type :=
156 Config.HDMI_Max_Clock_24bpp * 8 / Port_Cfg.Mode.BPC;
157 begin
158 if Port_Cfg.Mode.Dotclock > Max_Dotclock then
159 pragma Debug (Debug.Put ("Dotclock "));
160 pragma Debug (Debug.Put_Int64 (Port_Cfg.Mode.Dotclock));
161 pragma Debug (Debug.Put (" too high, limiting to "));
162 pragma Debug (Debug.Put_Int64 (Max_Dotclock));
163 pragma Debug (Debug.Put_Line ("."));
164 Port_Cfg.Mode.Dotclock := Max_Dotclock;
165 end if;
166 end;
167 end if;
168 end if;
169 else
170 Port_Cfg := Port_Config'
171 (Port => GPU_Port'First,
172 PCH_Port => PCH_Port'First,
173 Display => Display_Type'First,
174 Mode => Invalid_Mode,
175 Is_FDI => False,
176 FDI => Default_DP,
177 DP => Default_DP);
178 end if;
179 end Fill_Port_Config;
180
181 ----------------------------------------------------------------------------
182
183 -- Validates that a given configuration should work with
184 -- a given framebuffer.
185 function Validate_Config
186 (Framebuffer : Framebuffer_Type;
187 Port_Cfg : Port_Config;
188 Pipe : Pipe_Index)
189 return Boolean
190 is
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100191 function To_Bytes (Pixels : Width_Type) return Pos32 is
192 begin
193 return Pos32 (Pixels) * 4 * Pos32 (Framebuffer.BPC) / 8;
194 end To_Bytes;
Nico Huber8c45bcf2016-11-20 17:30:57 +0100195 begin
196 -- No downscaling
197 -- Respect maximum scalable width
198 -- VGA plane is only allowed on the primary pipe
199 -- Only 32bpp RGB (ignored for VGA plane)
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100200 -- Stride must be a multiple of 64 bytes (ignored for VGA plane)
Nico Huber8c45bcf2016-11-20 17:30:57 +0100201 return
202 ((Framebuffer.Width = Pos32 (Port_Cfg.Mode.H_Visible) and
203 Framebuffer.Height = Pos32 (Port_Cfg.Mode.V_Visible)) or
204 (Framebuffer.Width <= Config.Maximum_Scalable_Width (Pipe) and
205 Framebuffer.Width <= Pos32 (Port_Cfg.Mode.H_Visible) and
206 Framebuffer.Height <= Pos32 (Port_Cfg.Mode.V_Visible))) and
207 (Framebuffer.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or Pipe = Primary)
208 and
209 (Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
210 (Framebuffer.BPC = 8 and
Nico Huberd6d6f6b2016-12-23 13:00:49 +0100211 To_Bytes (Framebuffer.Stride) mod 64 = 0));
Nico Huber8c45bcf2016-11-20 17:30:57 +0100212 end Validate_Config;
213
214end HW.GFX.GMA.Config_Helpers;