blob: 1282e89e6fc1c3b467f031302a00a4902bf2f967 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber3d06de82018-05-29 01:35:04 +02002-- Copyright (C) 2015-2018 secunet Security Networks AG
Nico Huber194e57e2017-07-15 21:15:46 +02003-- Copyright (C) 2017 Nico Huber <nico.h@gmx.de>
Nico Huber83693c82016-10-08 22:17:55 +02004--
5-- This program is free software; you can redistribute it and/or modify
6-- it under the terms of the GNU General Public License as published by
Nico Huber125a29e2016-10-18 00:23:54 +02007-- the Free Software Foundation; either version 2 of the License, or
8-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02009--
10-- This program is distributed in the hope that it will be useful,
11-- but WITHOUT ANY WARRANTY; without even the implied warranty of
12-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13-- GNU General Public License for more details.
14--
15
Nico Huber194e57e2017-07-15 21:15:46 +020016with HW.Config;
Nico Huber83693c82016-10-08 22:17:55 +020017with HW.Time;
Nico Huberc5c66ec2019-09-28 23:59:45 +020018with HW.PCI;
Nico Huber83693c82016-10-08 22:17:55 +020019with HW.Port_IO;
Nico Hubercf88f3d2018-06-05 13:27:34 +020020with HW.GFX.Framebuffer_Filler;
Nico Huber83693c82016-10-08 22:17:55 +020021
Elyes Haouas066e52e2022-09-26 12:48:47 +020022use type HW.Word32;
23
Nico Huber83693c82016-10-08 22:17:55 +020024package HW.GFX.GMA
25with
26 Abstract_State =>
27 (State,
28 Init_State,
Nico Huber83693c82016-10-08 22:17:55 +020029 (Device_State with External)),
Nico Huber27088aa2018-06-10 13:28:05 +020030 Initializes => Init_State
Nico Huber83693c82016-10-08 22:17:55 +020031is
32
Nico Hubera02b2c62018-01-09 15:58:34 +010033 GTT_Page_Size : constant := 4096;
34 type GTT_Address_Type is mod 2 ** 39;
35 subtype GTT_Range is Natural range 0 .. 16#8_0000# - 1;
36 GTT_Rotation_Offset : constant GTT_Range := GTT_Range'Last / 2 + 1;
37
Nico Huber6621a142018-06-07 23:56:54 +020038 type Generation is (G45, Ironlake, Haswell, Broxton, Skylake);
39
Nico Huber83693c82016-10-08 22:17:55 +020040 type CPU_Type is
Arthur Heymans73ea0322018-03-28 17:17:07 +020041 (G45,
Nico Huber7f3e2802019-09-28 20:40:55 +020042 GM45,
Arthur Heymans73ea0322018-03-28 17:17:07 +020043 Ironlake,
Nico Huber83693c82016-10-08 22:17:55 +020044 Sandybridge,
45 Ivybridge,
46 Haswell,
47 Broadwell,
Nico Huber21da5742017-01-20 14:00:53 +010048 Broxton,
Nico Huber88badbe2018-09-27 16:36:47 +020049 Skylake,
50 Kabylake);
Nico Huber83693c82016-10-08 22:17:55 +020051
Nico Huber25fdb152019-02-17 15:54:39 +010052 type CPU_Variant is (Normal, ULT, ULX);
Nico Huber83693c82016-10-08 22:17:55 +020053
Nico Hubere79babd2020-12-20 01:33:26 +010054 type PCH_Type is
55 (No_PCH,
56 Ibex_Peak,
57 Cougar_Point, -- Panther Point compatible
58 Lynx_Point, -- Wildcat Point compatible
Nico Huberdde06302020-12-20 02:18:30 +010059 Sunrise_Point, -- Union Point compatible
60 Cannon_Point);
Nico Hubere79babd2020-12-20 01:33:26 +010061
Nico Huber83693c82016-10-08 22:17:55 +020062 type Port_Type is
63 (Disabled,
Nico Huber8beafd72020-01-07 14:59:44 +010064 LVDS,
65 eDP,
Nico Huber83693c82016-10-08 22:17:55 +020066 DP1,
67 DP2,
68 DP3,
Nico Huber0d454cd2016-11-21 13:33:43 +010069 HDMI1, -- or DVI
70 HDMI2, -- or DVI
71 HDMI3, -- or DVI
Nico Huber83693c82016-10-08 22:17:55 +020072 Analog);
Nico Huber040d9b62019-02-18 00:52:00 +010073 subtype Active_Port_Type is Port_Type
74 range Port_Type'Succ (Disabled) .. Port_Type'Last;
Nico Huber8beafd72020-01-07 14:59:44 +010075 subtype Internal_Port_Type is Port_Type range LVDS .. eDP;
Nico Huber83693c82016-10-08 22:17:55 +020076
Nico Hubera02b2c62018-01-09 15:58:34 +010077 type Cursor_Mode is (No_Cursor, ARGB_Cursor);
78 type Cursor_Size is (Cursor_64x64, Cursor_128x128, Cursor_256x256);
79 Cursor_Width : constant array (Cursor_Size) of Width_Type := (64, 128, 256);
80
81 subtype Cursor_Pos is Int32 range Int32'First / 2 .. Int32'Last / 2;
82
83 type Cursor_Type is record
84 Mode : Cursor_Mode;
85 Size : Cursor_Size;
86 Center_X : Cursor_Pos;
87 Center_Y : Cursor_Pos;
88 GTT_Offset : GTT_Range;
89 end record;
90 Default_Cursor : constant Cursor_Type :=
91 (Mode => No_Cursor,
92 Size => Cursor_Size'First,
93 Center_X => 0,
94 Center_Y => 0,
95 GTT_Offset => 0);
96
Nico Huber99f10f32016-11-20 00:34:05 +010097 type Pipe_Config is record
Nico Huber83693c82016-10-08 22:17:55 +020098 Port : Port_Type;
99 Framebuffer : Framebuffer_Type;
Nico Hubera02b2c62018-01-09 15:58:34 +0100100 Cursor : Cursor_Type;
Nico Huber83693c82016-10-08 22:17:55 +0200101 Mode : Mode_Type;
102 end record;
Nico Huber99f10f32016-11-20 00:34:05 +0100103 type Pipe_Index is (Primary, Secondary, Tertiary);
104 type Pipe_Configs is array (Pipe_Index) of Pipe_Config;
Nico Huber83693c82016-10-08 22:17:55 +0200105
Nico Huber3675db52016-11-04 16:27:29 +0100106 -- Special framebuffer offset to indicate legacy VGA plane.
107 -- Only valid on primary pipe.
108 VGA_PLANE_FRAMEBUFFER_OFFSET : constant := 16#ffff_ffff#;
109
Nico Huberbebca132017-06-12 23:04:46 +0200110 pragma Warnings (GNATprove, Off, "unused variable ""Write_Delay""",
111 Reason => "Write_Delay is used for debugging only");
Nico Huber83693c82016-10-08 22:17:55 +0200112 procedure Initialize
Nico Huber2b6f6992017-07-09 18:11:34 +0200113 (Write_Delay : in Word64 := 0;
Nico Huber793a8d42016-11-21 18:57:03 +0100114 Clean_State : in Boolean := False;
Nico Huber83693c82016-10-08 22:17:55 +0200115 Success : out Boolean)
116 with
117 Global =>
Nico Huber27088aa2018-06-10 13:28:05 +0200118 (In_Out => (Device_State, Port_IO.State),
Nico Hubere317e9c2019-09-29 03:03:18 +0200119 Output => (State, Init_State),
Nico Huber83693c82016-10-08 22:17:55 +0200120 Input => (Time.State)),
121 Post => Success = Is_Initialized;
122 function Is_Initialized return Boolean
123 with
124 Global => (Input => Init_State);
Nico Huberbebca132017-06-12 23:04:46 +0200125 pragma Warnings (GNATprove, On, "unused variable ""Write_Delay""");
Nico Huber83693c82016-10-08 22:17:55 +0200126
Nico Huber42fb2d02017-09-01 17:01:51 +0200127 procedure Power_Up_VGA
128 with
Nico Hubercf88f3d2018-06-05 13:27:34 +0200129 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200130 (Input => (State, Time.State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200131 In_Out => (Device_State),
132 Proof_In => (Init_State)),
Nico Huber42fb2d02017-09-01 17:01:51 +0200133 Pre => Is_Initialized;
134
Nico Hubercf88f3d2018-06-05 13:27:34 +0200135 ----------------------------------------------------------------------------
Nico Huber83693c82016-10-08 22:17:55 +0200136
Nico Hubercf88f3d2018-06-05 13:27:34 +0200137 procedure Update_Outputs (Configs : Pipe_Configs)
138 with
139 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200140 (Input => (Time.State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200141 In_Out => (State, Device_State, Port_IO.State),
142 Proof_In => (Init_State)),
143 Pre => Is_Initialized;
144
145 procedure Update_Cursor (Pipe : Pipe_Index; Cursor : Cursor_Type)
146 with
147 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200148 (In_Out => (State, Device_State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200149 Proof_In => (Init_State)),
Nico Hubere317e9c2019-09-29 03:03:18 +0200150 Pre => Is_Initialized;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200151
Nico Huber15ffc4f2018-01-11 14:44:43 +0100152 procedure Place_Cursor
153 (Pipe : Pipe_Index;
154 X : Cursor_Pos;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200155 Y : Cursor_Pos)
156 with
157 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200158 (In_Out => (State, Device_State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200159 Proof_In => (Init_State)),
Nico Hubere317e9c2019-09-29 03:03:18 +0200160 Pre => Is_Initialized;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200161
Nico Huber15ffc4f2018-01-11 14:44:43 +0100162 procedure Move_Cursor
163 (Pipe : Pipe_Index;
164 X : Cursor_Pos;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200165 Y : Cursor_Pos)
166 with
167 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200168 (In_Out => (State, Device_State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200169 Proof_In => (Init_State)),
Nico Hubere317e9c2019-09-29 03:03:18 +0200170 Pre => Is_Initialized;
Nico Huber15ffc4f2018-01-11 14:44:43 +0100171
Nico Hubercf88f3d2018-06-05 13:27:34 +0200172 ----------------------------------------------------------------------------
Nico Huber83693c82016-10-08 22:17:55 +0200173
Nico Huberbc0588e2020-07-21 12:17:19 +0200174 procedure Backlight_On (Port : Active_Port_Type)
175 with
176 Global => (In_Out => Device_State);
177
178 procedure Backlight_Off (Port : Active_Port_Type)
179 with
180 Global => (In_Out => Device_State);
181
182 procedure Set_Brightness (Port : Active_Port_Type; Level : Word32)
183 with
184 Global => (In_Out => Device_State);
185
186 procedure Get_Max_Brightness (Port : Active_Port_Type; Level : out Word32)
187 with
188 Global => (In_Out => Device_State);
189
190 ----------------------------------------------------------------------------
191
Nico Huber83693c82016-10-08 22:17:55 +0200192 procedure Write_GTT
193 (GTT_Page : GTT_Range;
194 Device_Address : GTT_Address_Type;
Nico Hubercf88f3d2018-06-05 13:27:34 +0200195 Valid : Boolean)
196 with
Nico Huberadfe11f2018-06-10 14:59:04 +0200197 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200198 (Input => State,
Nico Huberadfe11f2018-06-10 14:59:04 +0200199 In_Out => Device_State, Proof_In => Init_State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200200 Pre => Is_Initialized;
Nico Huber83693c82016-10-08 22:17:55 +0200201
Nico Huberceda17d2018-06-09 22:00:29 +0200202 procedure Read_GTT
203 (Device_Address : out GTT_Address_Type;
204 Valid : out Boolean;
205 GTT_Page : in GTT_Range)
206 with
Nico Huberadfe11f2018-06-10 14:59:04 +0200207 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200208 (Input => State,
Nico Huberadfe11f2018-06-10 14:59:04 +0200209 In_Out => Device_State, Proof_In => Init_State),
Nico Huberceda17d2018-06-09 22:00:29 +0200210 Pre => Is_Initialized;
211
Nico Huber5374c3a2017-07-15 21:48:06 +0200212 procedure Setup_Default_FB
213 (FB : in Framebuffer_Type;
214 Clear : in Boolean := True;
215 Success : out Boolean)
Nico Huber194e57e2017-07-15 21:15:46 +0200216 with
Nico Hubercf88f3d2018-06-05 13:27:34 +0200217 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200218 (In_Out =>
Nico Hubercf88f3d2018-06-05 13:27:34 +0200219 (State, Device_State,
220 Framebuffer_Filler.State, Framebuffer_Filler.Base_Address),
221 Proof_In => (Init_State)),
Nico Huber5374c3a2017-07-15 21:48:06 +0200222 Pre => Is_Initialized and HW.Config.Dynamic_MMIO;
Nico Huber83693c82016-10-08 22:17:55 +0200223
Nico Huberc3f66f62017-07-16 21:39:54 +0200224 procedure Map_Linear_FB (Linear_FB : out Word64; FB : in Framebuffer_Type)
225 with
Nico Hubercf88f3d2018-06-05 13:27:34 +0200226 Global =>
Nico Hubere317e9c2019-09-29 03:03:18 +0200227 (In_Out => (State, Device_State),
Nico Hubercf88f3d2018-06-05 13:27:34 +0200228 Proof_In => (Init_State)),
Nico Hubere317e9c2019-09-29 03:03:18 +0200229 Pre => Is_Initialized and HW.Config.Dynamic_MMIO;
Nico Huberc3f66f62017-07-16 21:39:54 +0200230
Nico Hubercf88f3d2018-06-05 13:27:34 +0200231 ----------------------------------------------------------------------------
232
233 pragma Warnings (GNATprove, Off, "subprogram ""Dump_Configs"" has no effect",
234 Reason => "It's only used for debugging");
235 procedure Dump_Configs (Configs : Pipe_Configs);
236
Nico Huber83693c82016-10-08 22:17:55 +0200237private
238
Nico Huberc5c66ec2019-09-28 23:59:45 +0200239 PCI_Usable : Boolean with Part_Of => State;
240 use type HW.PCI.Index;
241 procedure PCI_Read16 (Value : out Word16; Offset : HW.PCI.Index)
242 with
243 Pre => PCI_Usable and Offset mod 2 = 0;
244
245 ----------------------------------------------------------------------------
246
Nico Huber3299ad52018-06-02 16:53:39 +0200247 -- For the default framebuffer setup (see below) with 90 degree rotations,
248 -- we expect the offset which is used for the final scanout to be above
249 -- `GTT_Rotation_Offset`. So we can use `Offset - GTT_Rotation_Offset` for
250 -- the physical memory location and aperture mapping.
251 function Phys_Offset (FB : Framebuffer_Type) return Word32 is
252 (if Rotation_90 (FB)
253 then FB.Offset - Word32 (GTT_Rotation_Offset) * GTT_Page_Size
254 else FB.Offset);
255
Nico Huber8c45bcf2016-11-20 17:30:57 +0100256 ----------------------------------------------------------------------------
257 -- State tracking for the currently configured pipes
258
259 Cur_Configs : Pipe_Configs with Part_Of => State;
260
Nico Huber3d06de82018-05-29 01:35:04 +0200261 function Requires_Scaling (Pipe_Cfg : Pipe_Config) return Boolean is
262 (Requires_Scaling (Pipe_Cfg.Framebuffer, Pipe_Cfg.Mode));
263
Nico Huberb217ece2018-06-02 16:56:35 +0200264 function Scaling_Type (Pipe_Cfg : Pipe_Config) return Scaling_Aspect is
265 (Scaling_Type (Pipe_Cfg.Framebuffer, Pipe_Cfg.Mode));
266
Nico Huber8c45bcf2016-11-20 17:30:57 +0100267 ----------------------------------------------------------------------------
268 -- Internal representation of a single pipe's configuration
269
Arthur Heymans5d08a932018-03-28 17:00:18 +0200270 type GPU_Port is (DIGI_A, DIGI_B, DIGI_C, DIGI_D, DIGI_E, LVDS, VGA);
Nico Huber83693c82016-10-08 22:17:55 +0200271
272 subtype Digital_Port is GPU_Port range DIGI_A .. DIGI_E;
Arthur Heymans5d08a932018-03-28 17:00:18 +0200273 subtype GMCH_DP_Port is GPU_Port range DIGI_B .. DIGI_D;
274 subtype GMCH_HDMI_Port is GPU_Port range DIGI_B .. DIGI_C;
Nico Huber83693c82016-10-08 22:17:55 +0200275
276 type PCH_Port is
277 (PCH_DAC, PCH_LVDS,
278 PCH_HDMI_B, PCH_HDMI_C, PCH_HDMI_D,
279 PCH_DP_B, PCH_DP_C, PCH_DP_D);
280
281 subtype PCH_HDMI_Port is PCH_Port range PCH_HDMI_B .. PCH_HDMI_D;
282 subtype PCH_DP_Port is PCH_Port range PCH_DP_B .. PCH_DP_D;
283
Nico Huber5dbaf4b2020-01-08 17:24:58 +0100284 type Panel_Control is (No_Panel, Panel_1, Panel_2);
285 subtype Valid_Panels is Panel_Control range Panel_1 .. Panel_2;
Nico Huber2bbd6e72020-01-07 18:22:59 +0100286
Nico Huber83693c82016-10-08 22:17:55 +0200287 type Port_Config is
288 record
289 Port : GPU_Port;
290 PCH_Port : GMA.PCH_Port;
291 Display : Display_Type;
Nico Huber2bbd6e72020-01-07 18:22:59 +0100292 Panel : Panel_Control;
Nico Huber83693c82016-10-08 22:17:55 +0200293 Mode : Mode_Type;
294 Is_FDI : Boolean;
295 FDI : DP_Link;
296 DP : DP_Link;
297 end record;
298
299 type FDI_Training_Type is (Simple_Training, Full_Training, Auto_Training);
300
301 ----------------------------------------------------------------------------
302
303 type DP_Port is (DP_A, DP_B, DP_C, DP_D);
304
Nico Huber247adf32017-06-12 14:39:11 +0200305 ----------------------------------------------------------------------------
306
307 subtype DDI_HDMI_Buf_Trans_Range is Integer range 0 .. 11;
308
Nico Huber0164b022017-08-24 15:12:51 +0200309 ----------------------------------------------------------------------------
310
Nico Huberc5c767a2018-06-03 01:09:04 +0200311 Tile_Width : constant array (Tiling_Type) of Width_Type :=
Nico Huber0164b022017-08-24 15:12:51 +0200312 (Linear => 16, X_Tiled => 128, Y_Tiled => 32);
Nico Huberc5c767a2018-06-03 01:09:04 +0200313 Tile_Rows : constant array (Tiling_Type) of Height_Type :=
Nico Huber9b479412017-08-27 11:55:56 +0200314 (Linear => 1, X_Tiled => 8, Y_Tiled => 32);
Nico Huber0164b022017-08-24 15:12:51 +0200315
Nico Huber5ef4d602017-12-13 13:56:47 +0100316 function FB_Pitch (Px : Pos_Pixel_Type; FB : Framebuffer_Type) return Natural
317 is (Natural (Div_Round_Up
318 (Pixel_To_Bytes (Px, FB), Tile_Width (FB.Tiling) * 4)));
Nico Huber0164b022017-08-24 15:12:51 +0200319
320 function Valid_Stride (FB : Framebuffer_Type) return Boolean is
Nico Huber5ef4d602017-12-13 13:56:47 +0100321 (FB.Width + FB.Start_X <= FB.Stride and
Nico Huber9b479412017-08-27 11:55:56 +0200322 Pixel_To_Bytes (FB.Stride, FB) mod (Tile_Width (FB.Tiling) * 4) = 0 and
Nico Huber5ef4d602017-12-13 13:56:47 +0100323 FB.Height + FB.Start_Y <= FB.V_Stride and
Nico Huber9b479412017-08-27 11:55:56 +0200324 FB.V_Stride mod Tile_Rows (FB.Tiling) = 0);
Nico Huber0164b022017-08-24 15:12:51 +0200325
Nico Huber83693c82016-10-08 22:17:55 +0200326end HW.GFX.GMA;