blob: 941a5e725be6a4d2079541821fb8f3e4cab2b8e0 [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huberfdb0df12018-02-07 14:30:34 +01002-- Copyright (C) 2015-2018 secunet Security Networks AG
Nico Huber83693c82016-10-08 22:17:55 +02003--
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
Nico Huber125a29e2016-10-18 00:23:54 +02006-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02008--
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.Debug;
16with GNAT.Source_Info;
17
Nico Huber7ad2d652016-12-07 15:19:32 +010018with HW.GFX.GMA.Transcoder;
Nico Huber83693c82016-10-08 22:17:55 +020019
20package body HW.GFX.GMA.Pipe_Setup is
21
Nico Huberfbb42202016-11-07 15:08:26 +010022 ILK_DISPLAY_CHICKEN1_VGA_MASK : constant := 7 * 2 ** 29;
23 ILK_DISPLAY_CHICKEN1_VGA_ENABLE : constant := 5 * 2 ** 29;
24 ILK_DISPLAY_CHICKEN2_VGA_MASK : constant := 1 * 2 ** 25;
25 ILK_DISPLAY_CHICKEN2_VGA_ENABLE : constant := 0 * 2 ** 25;
26
Nico Huber7ad2d652016-12-07 15:19:32 +010027 DSPCNTR_ENABLE : constant := 1 * 2 ** 31;
28 DSPCNTR_GAMMA_CORRECTION : constant := 1 * 2 ** 30;
Nico Huber7ad2d652016-12-07 15:19:32 +010029 DSPCNTR_FORMAT_MASK : constant := 15 * 2 ** 26;
Arthur Heymans960e2392026-03-03 19:45:24 +010030 DSPCNTR_PIPE_SEL_MASK : constant := 3 * 2 ** 24;
31 DSPCNTR_PIPE_B_SELECT : constant := 1 * 2 ** 24;
Nico Huberab69e362018-05-29 21:20:30 +020032 DSPCNTR_DISABLE_TRICKLE_FEED : constant := 1 * 2 ** 14;
33 DSPCNTR_TILED_SURFACE_LINEAR : constant := 0 * 2 ** 10;
34 DSPCNTR_TILED_SURFACE_X_TILED : constant := 1 * 2 ** 10;
35
36 DSPCNTR_TILED_SURFACE : constant array (Tiling_Type) of Word32 :=
37 (Linear => DSPCNTR_TILED_SURFACE_LINEAR,
38 X_Tiled => DSPCNTR_TILED_SURFACE_X_TILED,
39 Y_Tiled => 0); -- unsupported
Nico Huber83693c82016-10-08 22:17:55 +020040
Arthur Heymans960e2392026-03-03 19:45:24 +010041 function DSPCNTR_PIPE_SEL (Pipe : Pipe_Index) return Word32 is
42 (if Pipe = Secondary then DSPCNTR_PIPE_B_SELECT else 0);
43
Nico Huber83693c82016-10-08 22:17:55 +020044 DSPCNTR_MASK : constant Word32 :=
45 DSPCNTR_ENABLE or
46 DSPCNTR_GAMMA_CORRECTION or
47 DSPCNTR_FORMAT_MASK or
Arthur Heymans960e2392026-03-03 19:45:24 +010048 DSPCNTR_PIPE_SEL_MASK or
Nico Huberab69e362018-05-29 21:20:30 +020049 DSPCNTR_DISABLE_TRICKLE_FEED or
50 DSPCNTR_TILED_SURFACE_X_TILED;
Nico Huber83693c82016-10-08 22:17:55 +020051
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -060052 PLANE_COLOR_CTL_PLANE_GAMMA_DISABLE : constant := 1 * 2 ** 13;
53
Nico Huber83693c82016-10-08 22:17:55 +020054 PLANE_CTL_PLANE_ENABLE : constant := 1 * 2 ** 31;
55 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 : constant := 4 * 2 ** 24;
56 PLANE_CTL_PLANE_GAMMA_DISABLE : constant := 1 * 2 ** 13;
Nico Huber0164b022017-08-24 15:12:51 +020057 PLANE_CTL_TILED_SURFACE_MASK : constant := 7 * 2 ** 10;
58 PLANE_CTL_TILED_SURFACE_LINEAR : constant := 0 * 2 ** 10;
59 PLANE_CTL_TILED_SURFACE_X_TILED : constant := 1 * 2 ** 10;
60 PLANE_CTL_TILED_SURFACE_Y_TILED : constant := 4 * 2 ** 10;
61 PLANE_CTL_TILED_SURFACE_YF_TILED : constant := 5 * 2 ** 10;
62
63 PLANE_CTL_TILED_SURFACE : constant array (Tiling_Type) of Word32 :=
64 (Linear => PLANE_CTL_TILED_SURFACE_LINEAR,
65 X_Tiled => PLANE_CTL_TILED_SURFACE_X_TILED,
66 Y_Tiled => PLANE_CTL_TILED_SURFACE_Y_TILED);
Nico Huber83693c82016-10-08 22:17:55 +020067
Nico Huber9b479412017-08-27 11:55:56 +020068 PLANE_CTL_PLANE_ROTATION_MASK : constant := 3 * 2 ** 0;
69 PLANE_CTL_PLANE_ROTATION : constant array (Rotation_Type) of Word32 :=
70 (No_Rotation => 0 * 2 ** 0,
71 Rotated_90 => 1 * 2 ** 0,
72 Rotated_180 => 2 * 2 ** 0,
73 Rotated_270 => 3 * 2 ** 0);
74
Nico Huber83693c82016-10-08 22:17:55 +020075 PLANE_WM_ENABLE : constant := 1 * 2 ** 31;
76 PLANE_WM_LINES_SHIFT : constant := 14;
77 PLANE_WM_LINES_MASK : constant := 16#001f# * 2 ** 14;
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -060078 PLANE_WM_BLOCKS_MASK : constant :=
79 (if Config.Has_Wide_Watermarks then 16#7ff# else 16#3ff#);
80
81 PIPEMISC_HDR_MODE_PRECISION : constant := 1 * 2 ** 23;
82 PIPEMISC_PIXEL_ROUNDING_TRUNC : constant := 1 * 2 ** 8;
Nico Huber83693c82016-10-08 22:17:55 +020083
Nico Huber33912aa2016-12-06 20:36:23 +010084 VGA_SR_INDEX : constant := 16#03c4#;
85 VGA_SR_DATA : constant := 16#03c5#;
86 VGA_SR01 : constant := 16#01#;
87 VGA_SR01_SCREEN_OFF : constant := 1 * 2 ** 5;
Nico Huber3675db52016-11-04 16:27:29 +010088
89 VGA_CONTROL_VGA_DISPLAY_DISABLE : constant := 1 * 2 ** 31;
90 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK : constant := 16#0003# * 2 ** 6;
91 VGA_CONTROL_BLINK_DUTY_CYCLE_50 : constant := 2 * 2 ** 6;
92 VGA_CONTROL_VSYNC_BLINK_RATE_MASK : constant := 16#003f# * 2 ** 0;
93
Nico Huber4dc4c612018-01-10 15:55:09 +010094 CUR_CTL_PIPE_SELECT : constant array (Pipe_Index) of Word32 :=
95 (Primary => 0 * 2 ** 28,
96 Secondary => 1 * 2 ** 28,
97 Tertiary => 2 * 2 ** 28);
98 CUR_CTL_MODE : constant array (Cursor_Mode, Cursor_Size) of Word32 :=
99 (No_Cursor => (others => 16#00#),
100 ARGB_Cursor =>
101 (Cursor_64x64 => 16#27#,
102 Cursor_128x128 => 16#22#,
103 Cursor_256x256 => 16#23#));
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600104 subtype ARB_Slots is Natural range 0 .. 7;
105 function MCURSOR_ARB_SLOTS (N : ARB_Slots) return Word32 is
106 (Shift_Left (Word32 (N), 28));
Nico Huber4dc4c612018-01-10 15:55:09 +0100107
108 function CUR_POS_Y (Y : Int32) return Word32 is
109 ((if Y >= 0 then 0 else 1 * 2 ** 31) or Shift_Left (Word32 (abs Y), 16))
110 with
111 Pre => Y > Int32'First;
112 function CUR_POS_X (X : Int32) return Word32 is
113 ((if X >= 0 then 0 else 1 * 2 ** 15) or Word32 (abs X))
114 with
115 Pre => X > Int32'First;
116
Nico Huber3675db52016-11-04 16:27:29 +0100117 subtype VGA_Cycle_Count is Pos32 range 2 .. 128;
118 function VGA_CONTROL_VSYNC_BLINK_RATE
119 (Cycles : VGA_Cycle_Count)
120 return Word32
121 is
122 begin
123 return Word32 (Cycles) / 2 - 1;
124 end VGA_CONTROL_VSYNC_BLINK_RATE;
125
Nico Huber7ad2d652016-12-07 15:19:32 +0100126 PF_CTRL_ENABLE : constant := 1 * 2 ** 31;
127 PF_CTRL_PIPE_SELECT_MASK : constant := 3 * 2 ** 29;
128 PF_CTRL_FILTER_MED : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +0200129
Nico Huber7ad2d652016-12-07 15:19:32 +0100130 PS_CTRL_ENABLE_SCALER : constant := 1 * 2 ** 31;
131 PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant := 1 * 2 ** 28;
132 PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +0200133
Arthur Heymansd5198442018-03-28 17:05:12 +0200134 GMCH_PFIT_CONTROL_SELECT_MASK : constant := 3 * 2 ** 29;
135 GMCH_PFIT_CONTROL_SELECT_PIPE_A : constant := 0 * 2 ** 29;
136 GMCH_PFIT_CONTROL_SELECT_PIPE_B : constant := 1 * 2 ** 29;
Nico Huber958c5642018-06-02 16:59:31 +0200137 GMCH_PFIT_CONTROL_SCALING_MASK : constant := 3 * 2 ** 26;
138 GMCH_PFIT_CONTROL_SCALING : constant array (Scaling_Aspect) of Word32 :=
139 (Uniform => 0 * 2 ** 26,
140 Pillarbox => 2 * 2 ** 26,
141 Letterbox => 3 * 2 ** 26);
Arthur Heymansd5198442018-03-28 17:05:12 +0200142
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200143 VGACNTRL_REG : constant Registers.Registers_Index :=
144 (if Config.Has_GMCH_VGACNTRL then
145 Registers.GMCH_VGACNTRL
146 else Registers.CPU_VGACNTRL);
147
Nico Huber83693c82016-10-08 22:17:55 +0200148 ---------------------------------------------------------------------------
149
Nico Huber83693c82016-10-08 22:17:55 +0200150 function PLANE_WM_LINES (Lines : Natural) return Word32 is
151 begin
152 return Shift_Left (Word32 (Lines), PLANE_WM_LINES_SHIFT)
153 and PLANE_WM_LINES_MASK;
154 end PLANE_WM_LINES;
155
156 function PLANE_WM_BLOCKS (Blocks : Natural) return Word32 is
157 begin
158 return Word32 (Blocks) and PLANE_WM_BLOCKS_MASK;
159 end PLANE_WM_BLOCKS;
160
161 ---------------------------------------------------------------------------
162
Nico Huberc5c767a2018-06-03 01:09:04 +0200163 function Encode (LSW, MSW : Pos32) return Word32 is
Nico Huber83693c82016-10-08 22:17:55 +0200164 begin
Nico Huber7ad2d652016-12-07 15:19:32 +0100165 return Shift_Left (Word32 (MSW) - 1, 16) or (Word32 (LSW) - 1);
Nico Huber83693c82016-10-08 22:17:55 +0200166 end Encode;
167
168 ----------------------------------------------------------------------------
169
Nico Huber83693c82016-10-08 22:17:55 +0200170 procedure Clear_Watermarks (Controller : Controller_Type) is
171 begin
Nico Huber4dc4c612018-01-10 15:55:09 +0100172 Registers.Write (Controller.CUR_BUF_CFG, 16#0000_0000#);
173 for Level in WM_Levels loop
174 Registers.Write (Controller.CUR_WM (Level), 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200175 end loop;
Nico Huber4dc4c612018-01-10 15:55:09 +0100176 Registers.Write (Controller.PLANE_BUF_CFG, 16#0000_0000#);
177 for Level in WM_Levels loop
178 Registers.Write (Controller.PLANE_WM (Level), 16#0000_0000#);
179 end loop;
180 Registers.Write (Controller.WM_LINETIME, 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200181 end Clear_Watermarks;
182
183 procedure Setup_Watermarks (Controller : Controller_Type)
184 is
Nico Huberf3e23662016-12-05 21:33:03 +0100185 type Per_Plane_Buffer_Range is array (Pipe_Index) of Word32;
Nico Huber4dc4c612018-01-10 15:55:09 +0100186 Cur_Buffer_Range : constant Per_Plane_Buffer_Range :=
187 (Primary => Shift_Left ( 7, 16) or 0,
188 Secondary => Shift_Left (167, 16) or 160,
189 Tertiary => Shift_Left (327, 16) or 320);
190 Plane_Buffer_Range : constant Per_Plane_Buffer_Range :=
191 (Primary => Shift_Left (159, 16) or 8,
192 Secondary => Shift_Left (319, 16) or 168,
193 Tertiary => Shift_Left (479, 16) or 328);
Nico Huber83693c82016-10-08 22:17:55 +0200194 begin
195 Registers.Write
196 (Register => Controller.PLANE_BUF_CFG,
Nico Huber4dc4c612018-01-10 15:55:09 +0100197 Value => Plane_Buffer_Range (Controller.Pipe));
Nico Huber83693c82016-10-08 22:17:55 +0200198 Registers.Write
199 (Register => Controller.PLANE_WM (0),
200 Value => PLANE_WM_ENABLE or
201 PLANE_WM_LINES (2) or
Nico Huber4dc4c612018-01-10 15:55:09 +0100202 PLANE_WM_BLOCKS (152));
203 Registers.Write
204 (Register => Controller.CUR_BUF_CFG,
205 Value => Cur_Buffer_Range (Controller.Pipe));
206 Registers.Write
207 (Register => Controller.CUR_WM (0),
208 Value => PLANE_WM_ENABLE or
209 PLANE_WM_LINES (2) or
210 PLANE_WM_BLOCKS (8));
Nico Huber83693c82016-10-08 22:17:55 +0200211 end Setup_Watermarks;
212
213 ----------------------------------------------------------------------------
214
Nico Huber3675db52016-11-04 16:27:29 +0100215 procedure Setup_Hires_Plane
Nico Huber6a4dfc82016-11-04 15:50:58 +0100216 (Controller : Controller_Type;
Nico Huber0164b022017-08-24 15:12:51 +0200217 FB : HW.GFX.Framebuffer_Type)
Nico Huber83693c82016-10-08 22:17:55 +0200218 with
Nico Huber5ef4d602017-12-13 13:56:47 +0100219 Pre => FB.Height + FB.Start_Y <= FB.V_Stride
Nico Huber83693c82016-10-08 22:17:55 +0200220 is
221 -- FIXME: setup correct format, based on framebuffer RGB format
222 Format : constant Word32 := 6 * 2 ** 26;
Arthur Heymans960e2392026-03-03 19:45:24 +0100223 PRI : Word32 := Format;
Nico Huber83693c82016-10-08 22:17:55 +0200224 begin
225 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
226
Nico Huber83693c82016-10-08 22:17:55 +0200227 if Config.Has_Plane_Control then
Nico Huber9b479412017-08-27 11:55:56 +0200228 declare
Nico Huber34be6542017-12-13 09:26:24 +0100229 Stride, Offset : Word32;
Nico Huberc5c767a2018-06-03 01:09:04 +0200230 Width : constant Width_Type := Rotated_Width (FB);
231 Height : constant Width_Type := Rotated_Height (FB);
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600232
233 function PLANE_CTL_ARB_SLOTS (N : Word32) return Word32 is
234 (if Config.Need_Pipe_Arb_Slots then Shift_Left (N, 28) else 0);
235
236 -- TODO: Hard coded format and arbitration slots for now,
237 -- for 4B-per-pixel XRGB, just like `Format` above.
238 -- ARB_SLOTS(1) matches the 4B per pixel.
239 Plane_Ctl : constant Word32 :=
240 PLANE_CTL_PLANE_ENABLE or
241 PLANE_CTL_TILED_SURFACE (FB.Tiling) or
242 PLANE_CTL_PLANE_ROTATION (FB.Rotation) or
243 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 or
244 PLANE_CTL_ARB_SLOTS (1) or
245 (if not Config.Has_Plane_Color_Control
246 then PLANE_CTL_PLANE_GAMMA_DISABLE
247 else 0);
Nico Huber9b479412017-08-27 11:55:56 +0200248 begin
249 if Rotation_90 (FB) then
Nico Huber5ef4d602017-12-13 13:56:47 +0100250 Stride := Word32 (FB_Pitch (FB.V_Stride, FB));
251 Offset := Shift_Left (Word32 (FB.Start_X), 16) or
252 Word32 (FB.V_Stride - FB.Height - FB.Start_Y);
Nico Huber9b479412017-08-27 11:55:56 +0200253 else
Nico Huber5ef4d602017-12-13 13:56:47 +0100254 Stride := Word32 (FB_Pitch (FB.Stride, FB));
255 Offset := Shift_Left (Word32 (FB.Start_Y), 16) or
256 Word32 (FB.Start_X);
Nico Huber9b479412017-08-27 11:55:56 +0200257 end if;
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600258
259 if Config.Has_Plane_Color_Control then
260 Registers.Write
261 (Register => Controller.PLANE_COLOR_CTL,
262 Value => PLANE_COLOR_CTL_PLANE_GAMMA_DISABLE);
263 end if;
264 Registers.Write (Controller.PLANE_AUX_DIST, 0);
265 Registers.Write (Controller.PLANE_CTL, Plane_Ctl);
Nico Huber9b479412017-08-27 11:55:56 +0200266 Registers.Write (Controller.PLANE_OFFSET, Offset);
267 Registers.Write (Controller.PLANE_SIZE, Encode (Width, Height));
268 Registers.Write (Controller.PLANE_STRIDE, Stride);
269 Registers.Write (Controller.PLANE_POS, 16#0000_0000#);
Nico Huber34be6542017-12-13 09:26:24 +0100270 Registers.Write (Controller.PLANE_SURF, FB.Offset and 16#ffff_f000#);
Nico Huber9b479412017-08-27 11:55:56 +0200271 end;
Nico Huber83693c82016-10-08 22:17:55 +0200272 else
Arthur Heymans960e2392026-03-03 19:45:24 +0100273 if Config.Has_DSPCNTR_Pipe_Select then
274 PRI := PRI or DSPCNTR_PIPE_SEL (Controller.Pipe);
275 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200276 if Config.Disable_Trickle_Feed then
277 PRI := PRI or DSPCNTR_DISABLE_TRICKLE_FEED;
278 end if;
Arthur Heymans960e2392026-03-03 19:45:24 +0100279
280 -- Write DSPCNTR *without* the enable bit first. On pre-SKL
281 -- hardware the control register self-arms when the plane
282 -- transitions from disabled to enabled, latching whatever
283 -- stride/size/offset values happen to be in the registers at
284 -- that moment. Programming format, pipe-select, and trickle-
285 -- feed now avoids a glitch with stale geometry values.
Nico Huber83693c82016-10-08 22:17:55 +0200286 Registers.Unset_And_Set_Mask
287 (Register => Controller.DSPCNTR,
288 Mask_Unset => DSPCNTR_MASK,
Nico Huberab69e362018-05-29 21:20:30 +0200289 Mask_Set => PRI or DSPCNTR_TILED_SURFACE (FB.Tiling));
Nico Huber83693c82016-10-08 22:17:55 +0200290
Nico Huber0164b022017-08-24 15:12:51 +0200291 Registers.Write
292 (Controller.DSPSTRIDE, Word32 (Pixel_To_Bytes (FB.Stride, FB)));
Arthur Heymans960e2392026-03-03 19:45:24 +0100293
294 -- Gen3 (i945): program DSPSIZE and DSPPOS before the surface
295 -- address write that arms the double-buffered plane registers.
296 if Config.Gen_I945 then
297 Registers.Write
298 (Controller.DSPSIZE,
299 Encode (Rotated_Width (FB), Rotated_Height (FB)));
300 Registers.Write (Controller.DSPPOS, 16#0000_0000#);
301 end if;
302
Nico Huberab69e362018-05-29 21:20:30 +0200303 if Config.Has_DSP_Linoff and then FB.Tiling = Linear then
Nico Huberd49b56b2018-06-18 17:19:15 +0200304 pragma Assert_And_Cut (True);
305 declare
306 Linear_Offset : constant Pixel_Type :=
307 FB.Start_Y * FB.Stride + FB.Start_X;
308 begin
309 Registers.Write
310 (Register => Controller.DSPLINOFF,
Arthur Heymans960e2392026-03-03 19:45:24 +0100311 Value => (if Config.Has_DSPSURF
312 then Word32 (Pixel_To_Bytes (Linear_Offset, FB))
313 else (FB.Offset and 16#ffff_f000#) or
314 Word32 (Pixel_To_Bytes (Linear_Offset, FB))));
Nico Huberd49b56b2018-06-18 17:19:15 +0200315 Registers.Write (Controller.DSPTILEOFF, 0);
316 end;
Nico Huber5ef4d602017-12-13 13:56:47 +0100317 else
Nico Huberab69e362018-05-29 21:20:30 +0200318 if Config.Has_DSP_Linoff then
Arthur Heymans960e2392026-03-03 19:45:24 +0100319 Registers.Write (Controller.DSPLINOFF,
320 (if Config.Has_DSPSURF then 0
321 else FB.Offset and 16#ffff_f000#));
Nico Huberab69e362018-05-29 21:20:30 +0200322 end if;
Nico Huber5ef4d602017-12-13 13:56:47 +0100323 Registers.Write
324 (Register => Controller.DSPTILEOFF,
325 Value => Shift_Left (Word32 (FB.Start_Y), 16) or
326 Word32 (FB.Start_X));
Nico Huber83693c82016-10-08 22:17:55 +0200327 end if;
Arthur Heymans960e2392026-03-03 19:45:24 +0100328 if Config.Has_DSPSURF then
329 Registers.Write (Controller.DSPSURF, FB.Offset and 16#ffff_f000#);
330 end if;
331
332 -- Now enable the plane. All geometry registers are in place,
333 -- so the self-arm latches correct values.
334 Registers.Write
335 (Register => Controller.DSPCNTR,
336 Value => DSPCNTR_ENABLE or PRI or
337 DSPCNTR_TILED_SURFACE (FB.Tiling));
Nico Huber83693c82016-10-08 22:17:55 +0200338 end if;
Nico Huber3675db52016-11-04 16:27:29 +0100339 end Setup_Hires_Plane;
340
341 procedure Setup_Display
Nico Huber113a14b2016-12-06 21:59:15 +0100342 (Controller : Controller_Type;
343 Framebuffer : Framebuffer_Type;
344 Dither_BPC : BPC_Type;
345 Dither : Boolean)
Nico Huber3675db52016-11-04 16:27:29 +0100346 with
Nico Huber9b479412017-08-27 11:55:56 +0200347 Pre =>
348 Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
Nico Huber5ef4d602017-12-13 13:56:47 +0100349 Framebuffer.Height + Framebuffer.Start_Y <= Framebuffer.V_Stride
Nico Huber3675db52016-11-04 16:27:29 +0100350 is
351 use type Word8;
352
353 Reg8 : Word8;
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600354
355 type BW_Credit is new Natural range 0 .. 3;
356 function MBUS_DBOX_BW_CREDIT (C : BW_Credit) return Word32 is
357 (Shift_Left (Word32 (C), 14));
358
359 type B_Credit is new Natural range 0 .. 31;
360 function MBUS_DBOX_B_CREDIT (C : B_Credit) return Word32 is
361 (Shift_Left (Word32 (C), 8));
362
363 type A_Credit is new Natural range 0 .. 15;
364 function MBUS_DBOX_A_CREDIT (C : A_Credit) return Word32 is
365 (Word32 (C));
366
367 type B2B_Trans_Max is new Natural range 0 .. 31;
368 function MBUS_DBOX_B2B_TRANSACTIONS_MAX (B : B2B_Trans_Max) return Word32 is
369 (Shift_Left (Word32 (B), 20));
370
371 type B2B_Trans_Delay is new Natural range 0 .. 7;
372 function MBUS_DBOX_B2B_TRANSACTIONS_DELAY (B : B2B_Trans_Delay) return Word32 is
373 (Shift_Left (Word32 (B), 17));
374 MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN : constant := 1 * 2 ** 16;
375
376 procedure Program_Mbus_Dbox_Credits is
377 Tmp : Word32;
378 begin
379 Tmp := MBUS_DBOX_B2B_TRANSACTIONS_MAX (16) or
380 MBUS_DBOX_B2B_TRANSACTIONS_DELAY (1) or
381 MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN;
382
383 if Config.Has_New_Mbus_Dbox_Credits then
384 Tmp := Tmp or MBUS_DBOX_BW_CREDIT (2) or
385 MBUS_DBOX_B_CREDIT (8) or
386 MBUS_DBOX_A_CREDIT (4); -- No joined MBus support,
387 -- hence always use 4 for now.
388 else
389 Tmp := Tmp or MBUS_DBOX_BW_CREDIT (2) or
390 MBUS_DBOX_B_CREDIT (12) or
391 MBUS_DBOX_A_CREDIT (2);
392 end if;
393
394 Registers.Write
395 (Register => Controller.MBUS_DBOX_CTL,
396 Value => Tmp);
397 end Program_Mbus_Dbox_Credits;
398
399 -- Display WA # 1605353570: icl
400 -- Set the pixel rounding bit to 1 for allowing
401 -- passthrough of Frame buffer pixels unmodified
402 -- across pipe
403 PIXEL_ROUNDING_TRUNC_FB_PASSTHRU : constant := 1 * 2 ** 15;
404
405 -- Display WA #1153: icl
406 -- enable hardware to bypass the alpha math
407 -- and rounding for per-pixel values 00 and 0xff
408 PER_PIXEL_ALPHA_BYPASS_EN : constant := 1 * 2 ** 7;
409
410 -- ADL_P requires that we disable underrun recovery when
411 -- downscaling (or using the scaler for YUV420 pipe output),
412 -- using DSC, or using PSR2.
413 -- i915 always disables underrun recovery for gen 13+.
414 UNDERRUN_RECOVERY_DISABLE : constant := 1 * 2 ** 30;
Nico Huber3675db52016-11-04 16:27:29 +0100415 begin
416 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
417
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600418 if Config.Has_Type_C_Ports then
419 Registers.Set_Mask
420 (Register => Controller.PIPE_CHICKEN,
421 Mask => PER_PIXEL_ALPHA_BYPASS_EN or
422 PIXEL_ROUNDING_TRUNC_FB_PASSTHRU or
423 (if Config.Need_Underrun_Rec_Disable
424 then UNDERRUN_RECOVERY_DISABLE
425 else 0));
426 end if;
427
Nico Huber3675db52016-11-04 16:27:29 +0100428 if Config.Has_Plane_Control then
429 Setup_Watermarks (Controller);
430 end if;
431
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600432 if Config.Has_Mbus_Dbox_Credits then
433 Program_Mbus_Dbox_Credits;
434 end if;
435
Nico Huber3675db52016-11-04 16:27:29 +0100436 if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
Nico Huberfbb42202016-11-07 15:08:26 +0100437 if Config.VGA_Plane_Workaround then
438 Registers.Unset_And_Set_Mask
439 (Register => Registers.ILK_DISPLAY_CHICKEN1,
440 Mask_Unset => ILK_DISPLAY_CHICKEN1_VGA_MASK,
441 Mask_Set => ILK_DISPLAY_CHICKEN1_VGA_ENABLE);
442 Registers.Unset_And_Set_Mask
443 (Register => Registers.ILK_DISPLAY_CHICKEN2,
444 Mask_Unset => ILK_DISPLAY_CHICKEN2_VGA_MASK,
445 Mask_Set => ILK_DISPLAY_CHICKEN2_VGA_ENABLE);
446 end if;
447
Nico Huber3675db52016-11-04 16:27:29 +0100448 Registers.Unset_And_Set_Mask
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200449 (Register => VGACNTRL_REG,
Nico Huber3675db52016-11-04 16:27:29 +0100450 Mask_Unset => VGA_CONTROL_VGA_DISPLAY_DISABLE or
451 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK or
452 VGA_CONTROL_VSYNC_BLINK_RATE_MASK,
453 Mask_Set => VGA_CONTROL_BLINK_DUTY_CYCLE_50 or
454 VGA_CONTROL_VSYNC_BLINK_RATE (30));
455
456 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
457 Port_IO.InB (Reg8, VGA_SR_DATA);
458 Port_IO.OutB (VGA_SR_DATA, Reg8 and not (VGA_SR01_SCREEN_OFF));
459 else
Nico Huber6a4dfc82016-11-04 15:50:58 +0100460 Setup_Hires_Plane (Controller, Framebuffer);
Nico Huber3675db52016-11-04 16:27:29 +0100461 end if;
462
463 Registers.Write
464 (Register => Controller.PIPESRC,
465 Value => Encode
Nico Huber9b479412017-08-27 11:55:56 +0200466 (Rotated_Height (Framebuffer), Rotated_Width (Framebuffer)));
Nico Huber83693c82016-10-08 22:17:55 +0200467
Nico Huber113a14b2016-12-06 21:59:15 +0100468 if Config.Has_Pipeconf_Misc then
469 Registers.Write
470 (Register => Controller.PIPEMISC,
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600471 Value => Transcoder.BPC_Conf (Dither_BPC, Dither) or
472 -- FIXME: Should we set these at all?
473 (if Config.Has_Plane_Color_Control then
474 (PIPEMISC_PIXEL_ROUNDING_TRUNC or PIPEMISC_HDR_MODE_PRECISION) else 0));
Nico Huber113a14b2016-12-06 21:59:15 +0100475 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200476 end Setup_Display;
477
478 ----------------------------------------------------------------------------
479
Nico Huber4dc4c612018-01-10 15:55:09 +0100480 procedure Update_Cursor
481 (Pipe : Pipe_Index;
482 FB : Framebuffer_Type;
483 Cursor : Cursor_Type)
484 is
485 begin
486 -- on some platforms writing CUR_CTL disables self-arming of CUR_POS
487 -- so keep it first
488 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200489 (Register => Cursors (Pipe).CTL,
Tim Wawrzynczak0da761a2022-09-09 10:42:36 -0600490 Value => CUR_CTL_MODE (Cursor.Mode, Cursor.Size) or
491 (if Config.Need_Pipe_Arb_Slots
492 then MCURSOR_ARB_SLOTS (1)
493 else CUR_CTL_PIPE_SELECT (Pipe)));
Nico Huber4dc4c612018-01-10 15:55:09 +0100494 Place_Cursor (Pipe, FB, Cursor);
495 end Update_Cursor;
496
497 procedure Place_Cursor
498 (Pipe : Pipe_Index;
499 FB : Framebuffer_Type;
500 Cursor : Cursor_Type)
501 is
502 Width : constant Width_Type := Cursor_Width (Cursor.Size);
503 X : Int32 := Cursor.Center_X - Width / 2;
504 Y : Int32 := Cursor.Center_Y - Width / 2;
505 begin
506 -- off-screen cursor needs special care
507 if X <= -Width or Y <= -Width or
Nico Huberc5c767a2018-06-03 01:09:04 +0200508 X >= Rotated_Width (FB) or Y >= Rotated_Height (FB) or
Nico Huber4dc4c612018-01-10 15:55:09 +0100509 X > Config.Maximum_Cursor_X or Y > Config.Maximum_Cursor_Y
510 then
511 X := -Width;
512 Y := -Width;
513 end if;
514 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200515 (Register => Cursors (Pipe).POS,
Nico Huber4dc4c612018-01-10 15:55:09 +0100516 Value => CUR_POS_Y (Y) or CUR_POS_X (X));
517 -- write to CUR_BASE always arms other CUR_* registers
518 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200519 (Register => Cursors (Pipe).BASE,
Nico Huber4dc4c612018-01-10 15:55:09 +0100520 Value => Shift_Left (Word32 (Cursor.GTT_Offset), 12));
521 end Place_Cursor;
522
523 ----------------------------------------------------------------------------
524
Nico Huber4916e342016-11-04 14:37:53 +0100525 procedure Scale_Keep_Aspect
Nico Huberc5c767a2018-06-03 01:09:04 +0200526 (Width : out Width_Type;
527 Height : out Height_Type;
528 Max_Width : in Width_Type;
529 Max_Height : in Height_Type;
Nico Huber4916e342016-11-04 14:37:53 +0100530 Framebuffer : in Framebuffer_Type)
531 with
532 Pre =>
Nico Huberc5c767a2018-06-03 01:09:04 +0200533 Rotated_Width (Framebuffer) <= Max_Width and
534 Rotated_Height (Framebuffer) <= Max_Height,
Nico Huber4916e342016-11-04 14:37:53 +0100535 Post =>
536 Width <= Max_Width and Height <= Max_Height
537 is
Nico Huberc5c767a2018-06-03 01:09:04 +0200538 Src_Width : constant Width_Type := Rotated_Width (Framebuffer);
539 Src_Height : constant Height_Type := Rotated_Height (Framebuffer);
Nico Huber4916e342016-11-04 14:37:53 +0100540 begin
Nico Huberda1185e2018-06-03 01:07:46 +0200541 case Scaling_Type (Src_Width, Src_Height, Max_Width, Max_Height) is
542 when Letterbox =>
Nico Huber99200fe2026-04-14 16:37:45 +0200543 Height := (Src_Height * Max_Width) / Src_Width;
544 pragma Assert (Height <= Max_Height);
Nico Huberda1185e2018-06-03 01:07:46 +0200545 Width := Max_Width;
Nico Huberda1185e2018-06-03 01:07:46 +0200546 when Pillarbox =>
Nico Huber99200fe2026-04-14 16:37:45 +0200547 Width := (Src_Width * Max_Height) / Src_Height;
548 pragma Assert (Max_Height * Src_Width < Max_Width * Src_Height);
549 pragma Assert ((Max_Height * Src_Width) / Src_Height < Max_Width);
550 pragma Assert (Width <= Max_Width);
Nico Huberda1185e2018-06-03 01:07:46 +0200551 Height := Max_Height;
552 when Uniform =>
553 Width := Max_Width;
554 Height := Max_Height;
555 end case;
Nico Huber4916e342016-11-04 14:37:53 +0100556 end Scale_Keep_Aspect;
557
558 procedure Setup_Skylake_Pipe_Scaler
559 (Controller : in Controller_Type;
560 Mode : in HW.GFX.Mode_Type;
561 Framebuffer : in HW.GFX.Framebuffer_Type)
562 with
563 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200564 Rotated_Width (Framebuffer) <= Mode.H_Visible and
565 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100566 is
Nico Huber7ad2d652016-12-07 15:19:32 +0100567 use type Registers.Registers_Invalid_Index;
568
Nico Huber4916e342016-11-04 14:37:53 +0100569 -- Enable 7x5 extended mode where possible:
570 Scaler_Mode : constant Word32 :=
571 (if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
572 PS_CTRL_SCALER_MODE_7X5_EXTENDED else 0);
573
Nico Huberc5c767a2018-06-03 01:09:04 +0200574 Width_In : constant Width_Type := Rotated_Width (Framebuffer);
575 Height_In : constant Height_Type := Rotated_Height (Framebuffer);
Nico Huber9b479412017-08-27 11:55:56 +0200576
Nico Huber4916e342016-11-04 14:37:53 +0100577 -- We can scale up to 2.99x horizontally:
Nico Huber9b479412017-08-27 11:55:56 +0200578 Horizontal_Limit : constant Pos32 := (Width_In * 299) / 100;
Nico Huber4916e342016-11-04 14:37:53 +0100579 -- The third scaler is limited to 1.99x
580 -- vertical scaling for source widths > 2048:
581 Vertical_Limit : constant Pos32 :=
Nico Huber9b479412017-08-27 11:55:56 +0200582 (Height_In *
Nico Huber4916e342016-11-04 14:37:53 +0100583 (if Controller.PS_CTRL_2 = Registers.Invalid_Register and
Nico Huber9b479412017-08-27 11:55:56 +0200584 Width_In > 2048
Nico Huber4916e342016-11-04 14:37:53 +0100585 then
586 199
587 else
588 299)) / 100;
589
Nico Huberc5c767a2018-06-03 01:09:04 +0200590 Width : Width_Type;
591 Height : Height_Type;
Nico Huber4916e342016-11-04 14:37:53 +0100592 begin
593 -- Writes to WIN_SZ arm the PS registers.
594
595 Scale_Keep_Aspect
596 (Width => Width,
597 Height => Height,
Nico Huberc5c767a2018-06-03 01:09:04 +0200598 Max_Width => Pos32'Min (Horizontal_Limit, Mode.H_Visible),
599 Max_Height => Pos32'Min (Vertical_Limit, Mode.V_Visible),
Nico Huber4916e342016-11-04 14:37:53 +0100600 Framebuffer => Framebuffer);
601
602 Registers.Write
603 (Register => Controller.PS_CTRL_1,
604 Value => PS_CTRL_ENABLE_SCALER or Scaler_Mode);
605 Registers.Write
606 (Register => Controller.PS_WIN_POS_1,
607 Value =>
Nico Huberc5c767a2018-06-03 01:09:04 +0200608 Shift_Left (Word32 (Mode.H_Visible - Width) / 2, 16) or
609 Word32 (Mode.V_Visible - Height) / 2);
Nico Huber4916e342016-11-04 14:37:53 +0100610 Registers.Write
611 (Register => Controller.PS_WIN_SZ_1,
612 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
613 end Setup_Skylake_Pipe_Scaler;
614
615 procedure Setup_Ironlake_Panel_Fitter
616 (Controller : in Controller_Type;
617 Mode : in HW.GFX.Mode_Type;
618 Framebuffer : in HW.GFX.Framebuffer_Type)
619 with
620 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200621 Rotated_Width (Framebuffer) <= Mode.H_Visible and
622 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100623 is
624 -- Force 1:1 mapping of panel fitter:pipe
625 PF_Ctrl_Pipe_Sel : constant Word32 :=
626 (if Config.Has_PF_Pipe_Select then
627 (case Controller.PF_CTRL is
628 when Registers.PFA_CTL_1 => 0 * 2 ** 29,
629 when Registers.PFB_CTL_1 => 1 * 2 ** 29,
630 when Registers.PFC_CTL_1 => 2 * 2 ** 29,
631 when others => 0) else 0);
632
Nico Huberc5c767a2018-06-03 01:09:04 +0200633 Width : Width_Type;
634 Height : Height_Type;
Nico Huberfdb0df12018-02-07 14:30:34 +0100635 X, Y : Int32;
Nico Huber4916e342016-11-04 14:37:53 +0100636 begin
637 -- Writes to WIN_SZ arm the PF registers.
638
639 Scale_Keep_Aspect
640 (Width => Width,
641 Height => Height,
Nico Huberc5c767a2018-06-03 01:09:04 +0200642 Max_Width => Mode.H_Visible,
643 Max_Height => Mode.V_Visible,
Nico Huber4916e342016-11-04 14:37:53 +0100644 Framebuffer => Framebuffer);
645
Nico Huberfdb0df12018-02-07 14:30:34 +0100646 -- Do not scale to odd width (at least Haswell has trouble with this).
Nico Huberc5c767a2018-06-03 01:09:04 +0200647 if Width < Mode.H_Visible and Width mod 2 = 1 then
Nico Huberfdb0df12018-02-07 14:30:34 +0100648 Width := Width + 1;
649 end if;
Nico Huberb3b9fa32018-06-18 16:16:41 +0200650 -- Do not scale to odd height (at least Sandy Bridge makes trouble).
651 if Height < Mode.V_Visible and Height mod 2 = 1 then
652 Height := Height + 1;
653 end if;
Nico Huberfdb0df12018-02-07 14:30:34 +0100654
Nico Huberc5c767a2018-06-03 01:09:04 +0200655 X := (Mode.H_Visible - Width) / 2;
656 Y := (Mode.V_Visible - Height) / 2;
Nico Huberfdb0df12018-02-07 14:30:34 +0100657
658 -- Hardware is picky about minimal horizontal gaps.
Nico Huberc5c767a2018-06-03 01:09:04 +0200659 if Mode.H_Visible - Width <= 3 then
660 Width := Mode.H_Visible;
Nico Huberfdb0df12018-02-07 14:30:34 +0100661 X := 0;
662 end if;
663
Nico Huber4916e342016-11-04 14:37:53 +0100664 Registers.Write
665 (Register => Controller.PF_CTRL,
666 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel or PF_CTRL_FILTER_MED);
667 Registers.Write
668 (Register => Controller.PF_WIN_POS,
Nico Huberfdb0df12018-02-07 14:30:34 +0100669 Value => Shift_Left (Word32 (X), 16) or Word32 (Y));
Nico Huber4916e342016-11-04 14:37:53 +0100670 Registers.Write
671 (Register => Controller.PF_WIN_SZ,
672 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
673 end Setup_Ironlake_Panel_Fitter;
674
Arthur Heymansd5198442018-03-28 17:05:12 +0200675 procedure Setup_Gmch_Panel_Fitter
Nico Huber958c5642018-06-02 16:59:31 +0200676 (Controller : in Controller_Type;
677 Mode : in HW.GFX.Mode_Type;
678 Framebuffer : in HW.GFX.Framebuffer_Type)
Arthur Heymansd5198442018-03-28 17:05:12 +0200679 is
680 PF_Ctrl_Pipe_Sel : constant Word32 :=
681 (case Controller.Pipe is
682 when Primary => GMCH_PFIT_CONTROL_SELECT_PIPE_A,
683 when Secondary => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
684 when others => 0);
Nico Huber958c5642018-06-02 16:59:31 +0200685
Arthur Heymansf70edda2018-08-21 18:37:00 +0200686 -- Work around a quirk:
687 -- In legacy VGA mode Pillarbox fails to display anything so just force
688 -- 'auto' mode on all displays, which will the output stretched to
689 -- fullscreen .
Nico Huber958c5642018-06-02 16:59:31 +0200690 PF_Ctrl_Scaling : constant Word32 :=
Arthur Heymansf70edda2018-08-21 18:37:00 +0200691 (if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
692 GMCH_PFIT_CONTROL_SCALING (Uniform)
693 else
694 GMCH_PFIT_CONTROL_SCALING (Scaling_Type (Framebuffer, Mode)));
Nico Huber958c5642018-06-02 16:59:31 +0200695
Arthur Heymansd5198442018-03-28 17:05:12 +0200696 In_Use : Boolean;
697 begin
698 Registers.Is_Set_Mask
699 (Register => Registers.GMCH_PFIT_CONTROL,
700 Mask => PF_CTRL_ENABLE,
701 Result => In_Use);
702
703 if not In_Use then
704 Registers.Write
705 (Register => Registers.GMCH_PFIT_CONTROL,
Nico Huber958c5642018-06-02 16:59:31 +0200706 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel or PF_Ctrl_Scaling);
Arthur Heymansd5198442018-03-28 17:05:12 +0200707 else
Nico Huber7ba7bd62018-06-06 12:27:09 +0200708 pragma Debug (Debug.Put_Line
709 ("GMCH Pannel fitter already in use, skipping..."));
Arthur Heymansd5198442018-03-28 17:05:12 +0200710 end if;
711 end Setup_Gmch_Panel_Fitter;
712
Nico Huberf361ec82018-06-02 18:01:45 +0200713 procedure Gmch_Panel_Fitter_Pipe (Pipe : out Pipe_Index)
714 is
715 Used_For_Secondary : Boolean;
716 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100717 if Config.Gen_I945 then
718 -- Gen3: panel fitter is hardwired to Pipe B (Secondary).
719 -- The PFIT_PIPE field (bits 30:29) does not exist on Gen3.
720 Pipe := Secondary;
721 else
722 Registers.Is_Set_Mask
723 (Register => Registers.GMCH_PFIT_CONTROL,
724 Mask => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
725 Result => Used_For_Secondary);
726 Pipe := (if Used_For_Secondary then Secondary else Primary);
727 end if;
Nico Huberf361ec82018-06-02 18:01:45 +0200728 end;
729
Nico Huberb4b72792018-01-02 13:45:41 +0100730 procedure Panel_Fitter_Off (Controller : Controller_Type)
731 is
732 use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
Nico Huberf361ec82018-06-02 18:01:45 +0200733 Pipe_Using_PF : Pipe_Index;
Nico Huberb4b72792018-01-02 13:45:41 +0100734 begin
735 -- Writes to WIN_SZ arm the PS/PF registers.
736 if Config.Has_Plane_Control then
737 Registers.Unset_Mask (Controller.PS_CTRL_1, PS_CTRL_ENABLE_SCALER);
738 Registers.Write (Controller.PS_WIN_SZ_1, 16#0000_0000#);
739 if Controller.PS_CTRL_2 /= Registers.Invalid_Register and
740 Controller.PS_WIN_SZ_2 /= Registers.Invalid_Register
741 then
742 Registers.Unset_Mask (Controller.PS_CTRL_2, PS_CTRL_ENABLE_SCALER);
743 Registers.Write (Controller.PS_WIN_SZ_2, 16#0000_0000#);
744 end if;
Arthur Heymansd5198442018-03-28 17:05:12 +0200745 elsif Config.Has_GMCH_PFIT_CONTROL then
Nico Huberf361ec82018-06-02 18:01:45 +0200746 Gmch_Panel_Fitter_Pipe (Pipe_Using_PF);
747 if Pipe_Using_PF = Controller.Pipe then
Arthur Heymans960e2392026-03-03 19:45:24 +0100748 -- Write 0 to clear all bits (enable, scaling mode, auto-scale,
749 -- interpolation). Just clearing the enable bit can leave stale
750 -- Gen3 auto-scale bits that confuse the hardware.
751 Registers.Write (Registers.GMCH_PFIT_CONTROL, 16#0000_0000#);
Arthur Heymansd5198442018-03-28 17:05:12 +0200752 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100753 else
754 Registers.Unset_Mask (Controller.PF_CTRL, PF_CTRL_ENABLE);
755 Registers.Write (Controller.PF_WIN_SZ, 16#0000_0000#);
756 end if;
757 end Panel_Fitter_Off;
758
Nico Huber4916e342016-11-04 14:37:53 +0100759 procedure Setup_Scaling
760 (Controller : in Controller_Type;
761 Mode : in HW.GFX.Mode_Type;
762 Framebuffer : in HW.GFX.Framebuffer_Type)
763 with
764 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200765 Rotated_Width (Framebuffer) <= Mode.H_Visible and
766 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100767 is
768 begin
Nico Huber3d06de82018-05-29 01:35:04 +0200769 if Requires_Scaling (Framebuffer, Mode) then
Nico Huber4916e342016-11-04 14:37:53 +0100770 if Config.Has_Plane_Control then
771 Setup_Skylake_Pipe_Scaler (Controller, Mode, Framebuffer);
Arthur Heymansd5198442018-03-28 17:05:12 +0200772 elsif Config.Has_GMCH_PFIT_CONTROL then
Nico Huber958c5642018-06-02 16:59:31 +0200773 Setup_Gmch_Panel_Fitter (Controller, Mode, Framebuffer);
Nico Huber4916e342016-11-04 14:37:53 +0100774 else
775 Setup_Ironlake_Panel_Fitter (Controller, Mode, Framebuffer);
776 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100777 else
778 Panel_Fitter_Off (Controller);
Nico Huber4916e342016-11-04 14:37:53 +0100779 end if;
780 end Setup_Scaling;
781
Nico Huber9a4c4c32019-09-16 22:05:11 +0200782 procedure Reserve_Scaler
783 (Success : out Boolean;
784 Reservation : in out Scaler_Reservation;
785 Pipe : in Pipe_Index)
Nico Huberf361ec82018-06-02 18:01:45 +0200786 is
787 Pipe_Using_PF : Pipe_Index := Pipe_Index'First;
788 PF_Enabled : Boolean;
789 begin
790 if Config.Has_GMCH_PFIT_CONTROL then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200791 if Reservation.Reserved then
792 Success := Reservation.Pipe = Pipe;
793 return;
794 end if;
795
Nico Huberf361ec82018-06-02 18:01:45 +0200796 Registers.Is_Set_Mask
797 (Register => Registers.GMCH_PFIT_CONTROL,
798 Mask => PF_CTRL_ENABLE,
799 Result => PF_Enabled);
800 if PF_Enabled then
801 Gmch_Panel_Fitter_Pipe (Pipe_Using_PF);
802 end if;
803
Nico Huber9a4c4c32019-09-16 22:05:11 +0200804 Success := not PF_Enabled or Pipe_Using_PF = Pipe;
805 if Success then
806 Reservation.Reserved := True;
807 Reservation.Pipe := Pipe;
808 end if;
Nico Huberf361ec82018-06-02 18:01:45 +0200809 else
Nico Huber9a4c4c32019-09-16 22:05:11 +0200810 Success := True;
Nico Huberf361ec82018-06-02 18:01:45 +0200811 end if;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200812 end Reserve_Scaler;
Nico Huberf361ec82018-06-02 18:01:45 +0200813
Nico Huber4916e342016-11-04 14:37:53 +0100814 ----------------------------------------------------------------------------
815
Nico Huberf7f537e2018-01-02 14:15:43 +0100816 procedure Setup_FB
817 (Pipe : Pipe_Index;
818 Mode : Mode_Type;
819 Framebuffer : Framebuffer_Type)
820 is
821 -- Enable dithering if framebuffer BPC differs from port BPC,
822 -- as smooth gradients look really bad without.
823 Dither : constant Boolean := Framebuffer.BPC /= Mode.BPC;
824 begin
825 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
826
Nico Huber4dc4c612018-01-10 15:55:09 +0100827 -- Disable the cursor first.
828 Update_Cursor (Pipe, Framebuffer, Default_Cursor);
829
Nico Huberf7f537e2018-01-02 14:15:43 +0100830 Setup_Display (Controllers (Pipe), Framebuffer, Mode.BPC, Dither);
831 Setup_Scaling (Controllers (Pipe), Mode, Framebuffer);
832 end Setup_FB;
833
Nico Huber83693c82016-10-08 22:17:55 +0200834 procedure On
Nico Huberf3e23662016-12-05 21:33:03 +0100835 (Pipe : Pipe_Index;
Nico Huber83693c82016-10-08 22:17:55 +0200836 Port_Cfg : Port_Config;
Nico Huber4dc4c612018-01-10 15:55:09 +0100837 Framebuffer : Framebuffer_Type;
838 Cursor : Cursor_Type)
Nico Huber83693c82016-10-08 22:17:55 +0200839 is
840 begin
841 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
842
Nico Huber7ad2d652016-12-07 15:19:32 +0100843 Transcoder.Setup (Pipe, Port_Cfg);
Nico Huber83693c82016-10-08 22:17:55 +0200844
Nico Huberf7f537e2018-01-02 14:15:43 +0100845 Setup_FB (Pipe, Port_Cfg.Mode, Framebuffer);
Nico Huber4dc4c612018-01-10 15:55:09 +0100846 Update_Cursor (Pipe, Framebuffer, Cursor);
Nico Huber83693c82016-10-08 22:17:55 +0200847
Nico Huberabb16d92018-05-29 01:44:26 +0200848 Transcoder.On
849 (Pipe => Pipe,
850 Port_Cfg => Port_Cfg,
851 Dither => Framebuffer.BPC /= Port_Cfg.Mode.BPC,
852 Scale => Requires_Scaling (Framebuffer, Port_Cfg.Mode));
Nico Huber83693c82016-10-08 22:17:55 +0200853 end On;
854
855 ----------------------------------------------------------------------------
856
Nico Huber75a707f2018-06-18 16:28:33 +0200857 procedure Planes_Off (Controller : Controller_Type; CUR : Cursor_Regs)
858 is
859 use type Registers.Registers_Invalid_Index;
Nico Huber83693c82016-10-08 22:17:55 +0200860 begin
Nico Huber75a707f2018-06-18 16:28:33 +0200861 Registers.Write (CUR.CTL, 16#0000_0000#);
862 if CUR.FBC_CTL /= Registers.Invalid_Register then
863 Registers.Write (CUR.FBC_CTL, 16#0000_0000#);
Nico Huber4dc4c612018-01-10 15:55:09 +0100864 end if;
Nico Huber7ad2d652016-12-07 15:19:32 +0100865 Registers.Unset_Mask (Controller.SPCNTR, DSPCNTR_ENABLE);
Nico Huber83693c82016-10-08 22:17:55 +0200866 if Config.Has_Plane_Control then
867 Clear_Watermarks (Controller);
868 Registers.Unset_Mask (Controller.PLANE_CTL, PLANE_CTL_PLANE_ENABLE);
869 Registers.Write (Controller.PLANE_SURF, 16#0000_0000#);
870 else
871 Registers.Unset_Mask (Controller.DSPCNTR, DSPCNTR_ENABLE);
872 end if;
873 end Planes_Off;
874
Nico Huber7ad2d652016-12-07 15:19:32 +0100875 procedure Off (Pipe : Pipe_Index)
Nico Huberf3e23662016-12-05 21:33:03 +0100876 is
Nico Huber83693c82016-10-08 22:17:55 +0200877 begin
878 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
879
Nico Huber75a707f2018-06-18 16:28:33 +0200880 Planes_Off (Controllers (Pipe), Cursors (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100881 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100882 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100883 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200884 end Off;
885
Nico Huber33912aa2016-12-06 20:36:23 +0100886 procedure Legacy_VGA_Off
887 is
888 use type HW.Word8;
889 Reg8 : Word8;
890 begin
891 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
892 Port_IO.InB (Reg8, VGA_SR_DATA);
893 Port_IO.OutB (VGA_SR_DATA, Reg8 or VGA_SR01_SCREEN_OFF);
894 Time.U_Delay (100); -- PRM says 100us, Linux does 300
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200895 Registers.Set_Mask (VGACNTRL_REG, VGA_CONTROL_VGA_DISPLAY_DISABLE);
Nico Huber33912aa2016-12-06 20:36:23 +0100896 end Legacy_VGA_Off;
897
Nico Huber83693c82016-10-08 22:17:55 +0200898 procedure All_Off
899 is
Nico Huber83693c82016-10-08 22:17:55 +0200900 begin
901 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
902
Nico Huber33912aa2016-12-06 20:36:23 +0100903 Legacy_VGA_Off;
904
Arthur Heymans960e2392026-03-03 19:45:24 +0100905 for Pipe in Pipe_Index range Pipe_Index'First .. Config.Max_Pipe loop
Nico Huber75a707f2018-06-18 16:28:33 +0200906 Planes_Off (Controllers (Pipe), Cursors (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100907 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100908 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100909 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200910 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200911 end All_Off;
912
Nico Huber83693c82016-10-08 22:17:55 +0200913end HW.GFX.GMA.Pipe_Setup;