blob: 69d83a8d2c791f105054baaf3a62d0fa22b8eab7 [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
52 PLANE_CTL_PLANE_ENABLE : constant := 1 * 2 ** 31;
53 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 : constant := 4 * 2 ** 24;
54 PLANE_CTL_PLANE_GAMMA_DISABLE : constant := 1 * 2 ** 13;
Nico Huber0164b022017-08-24 15:12:51 +020055 PLANE_CTL_TILED_SURFACE_MASK : constant := 7 * 2 ** 10;
56 PLANE_CTL_TILED_SURFACE_LINEAR : constant := 0 * 2 ** 10;
57 PLANE_CTL_TILED_SURFACE_X_TILED : constant := 1 * 2 ** 10;
58 PLANE_CTL_TILED_SURFACE_Y_TILED : constant := 4 * 2 ** 10;
59 PLANE_CTL_TILED_SURFACE_YF_TILED : constant := 5 * 2 ** 10;
60
61 PLANE_CTL_TILED_SURFACE : constant array (Tiling_Type) of Word32 :=
62 (Linear => PLANE_CTL_TILED_SURFACE_LINEAR,
63 X_Tiled => PLANE_CTL_TILED_SURFACE_X_TILED,
64 Y_Tiled => PLANE_CTL_TILED_SURFACE_Y_TILED);
Nico Huber83693c82016-10-08 22:17:55 +020065
Nico Huber9b479412017-08-27 11:55:56 +020066 PLANE_CTL_PLANE_ROTATION_MASK : constant := 3 * 2 ** 0;
67 PLANE_CTL_PLANE_ROTATION : constant array (Rotation_Type) of Word32 :=
68 (No_Rotation => 0 * 2 ** 0,
69 Rotated_90 => 1 * 2 ** 0,
70 Rotated_180 => 2 * 2 ** 0,
71 Rotated_270 => 3 * 2 ** 0);
72
Nico Huber83693c82016-10-08 22:17:55 +020073 PLANE_WM_ENABLE : constant := 1 * 2 ** 31;
74 PLANE_WM_LINES_SHIFT : constant := 14;
75 PLANE_WM_LINES_MASK : constant := 16#001f# * 2 ** 14;
76 PLANE_WM_BLOCKS_MASK : constant := 16#03ff# * 2 ** 0;
77
Nico Huber33912aa2016-12-06 20:36:23 +010078 VGA_SR_INDEX : constant := 16#03c4#;
79 VGA_SR_DATA : constant := 16#03c5#;
80 VGA_SR01 : constant := 16#01#;
81 VGA_SR01_SCREEN_OFF : constant := 1 * 2 ** 5;
Nico Huber3675db52016-11-04 16:27:29 +010082
83 VGA_CONTROL_VGA_DISPLAY_DISABLE : constant := 1 * 2 ** 31;
84 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK : constant := 16#0003# * 2 ** 6;
85 VGA_CONTROL_BLINK_DUTY_CYCLE_50 : constant := 2 * 2 ** 6;
86 VGA_CONTROL_VSYNC_BLINK_RATE_MASK : constant := 16#003f# * 2 ** 0;
87
Nico Huber4dc4c612018-01-10 15:55:09 +010088 CUR_CTL_PIPE_SELECT : constant array (Pipe_Index) of Word32 :=
89 (Primary => 0 * 2 ** 28,
90 Secondary => 1 * 2 ** 28,
91 Tertiary => 2 * 2 ** 28);
92 CUR_CTL_MODE : constant array (Cursor_Mode, Cursor_Size) of Word32 :=
93 (No_Cursor => (others => 16#00#),
94 ARGB_Cursor =>
95 (Cursor_64x64 => 16#27#,
96 Cursor_128x128 => 16#22#,
97 Cursor_256x256 => 16#23#));
98
99 function CUR_POS_Y (Y : Int32) return Word32 is
100 ((if Y >= 0 then 0 else 1 * 2 ** 31) or Shift_Left (Word32 (abs Y), 16))
101 with
102 Pre => Y > Int32'First;
103 function CUR_POS_X (X : Int32) return Word32 is
104 ((if X >= 0 then 0 else 1 * 2 ** 15) or Word32 (abs X))
105 with
106 Pre => X > Int32'First;
107
Nico Huber3675db52016-11-04 16:27:29 +0100108 subtype VGA_Cycle_Count is Pos32 range 2 .. 128;
109 function VGA_CONTROL_VSYNC_BLINK_RATE
110 (Cycles : VGA_Cycle_Count)
111 return Word32
112 is
113 begin
114 return Word32 (Cycles) / 2 - 1;
115 end VGA_CONTROL_VSYNC_BLINK_RATE;
116
Nico Huber7ad2d652016-12-07 15:19:32 +0100117 PF_CTRL_ENABLE : constant := 1 * 2 ** 31;
118 PF_CTRL_PIPE_SELECT_MASK : constant := 3 * 2 ** 29;
119 PF_CTRL_FILTER_MED : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +0200120
Nico Huber7ad2d652016-12-07 15:19:32 +0100121 PS_CTRL_ENABLE_SCALER : constant := 1 * 2 ** 31;
122 PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant := 1 * 2 ** 28;
123 PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +0200124
Arthur Heymansd5198442018-03-28 17:05:12 +0200125 GMCH_PFIT_CONTROL_SELECT_MASK : constant := 3 * 2 ** 29;
126 GMCH_PFIT_CONTROL_SELECT_PIPE_A : constant := 0 * 2 ** 29;
127 GMCH_PFIT_CONTROL_SELECT_PIPE_B : constant := 1 * 2 ** 29;
Nico Huber958c5642018-06-02 16:59:31 +0200128 GMCH_PFIT_CONTROL_SCALING_MASK : constant := 3 * 2 ** 26;
129 GMCH_PFIT_CONTROL_SCALING : constant array (Scaling_Aspect) of Word32 :=
130 (Uniform => 0 * 2 ** 26,
131 Pillarbox => 2 * 2 ** 26,
132 Letterbox => 3 * 2 ** 26);
Arthur Heymansd5198442018-03-28 17:05:12 +0200133
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200134 VGACNTRL_REG : constant Registers.Registers_Index :=
135 (if Config.Has_GMCH_VGACNTRL then
136 Registers.GMCH_VGACNTRL
137 else Registers.CPU_VGACNTRL);
138
Nico Huber83693c82016-10-08 22:17:55 +0200139 ---------------------------------------------------------------------------
140
Nico Huber83693c82016-10-08 22:17:55 +0200141 function PLANE_WM_LINES (Lines : Natural) return Word32 is
142 begin
143 return Shift_Left (Word32 (Lines), PLANE_WM_LINES_SHIFT)
144 and PLANE_WM_LINES_MASK;
145 end PLANE_WM_LINES;
146
147 function PLANE_WM_BLOCKS (Blocks : Natural) return Word32 is
148 begin
149 return Word32 (Blocks) and PLANE_WM_BLOCKS_MASK;
150 end PLANE_WM_BLOCKS;
151
152 ---------------------------------------------------------------------------
153
Nico Huberc5c767a2018-06-03 01:09:04 +0200154 function Encode (LSW, MSW : Pos32) return Word32 is
Nico Huber83693c82016-10-08 22:17:55 +0200155 begin
Nico Huber7ad2d652016-12-07 15:19:32 +0100156 return Shift_Left (Word32 (MSW) - 1, 16) or (Word32 (LSW) - 1);
Nico Huber83693c82016-10-08 22:17:55 +0200157 end Encode;
158
159 ----------------------------------------------------------------------------
160
Nico Huber83693c82016-10-08 22:17:55 +0200161 procedure Clear_Watermarks (Controller : Controller_Type) is
162 begin
Nico Huber4dc4c612018-01-10 15:55:09 +0100163 Registers.Write (Controller.CUR_BUF_CFG, 16#0000_0000#);
164 for Level in WM_Levels loop
165 Registers.Write (Controller.CUR_WM (Level), 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200166 end loop;
Nico Huber4dc4c612018-01-10 15:55:09 +0100167 Registers.Write (Controller.PLANE_BUF_CFG, 16#0000_0000#);
168 for Level in WM_Levels loop
169 Registers.Write (Controller.PLANE_WM (Level), 16#0000_0000#);
170 end loop;
171 Registers.Write (Controller.WM_LINETIME, 16#0000_0000#);
Nico Huber83693c82016-10-08 22:17:55 +0200172 end Clear_Watermarks;
173
174 procedure Setup_Watermarks (Controller : Controller_Type)
175 is
Nico Huberf3e23662016-12-05 21:33:03 +0100176 type Per_Plane_Buffer_Range is array (Pipe_Index) of Word32;
Nico Huber4dc4c612018-01-10 15:55:09 +0100177 Cur_Buffer_Range : constant Per_Plane_Buffer_Range :=
178 (Primary => Shift_Left ( 7, 16) or 0,
179 Secondary => Shift_Left (167, 16) or 160,
180 Tertiary => Shift_Left (327, 16) or 320);
181 Plane_Buffer_Range : constant Per_Plane_Buffer_Range :=
182 (Primary => Shift_Left (159, 16) or 8,
183 Secondary => Shift_Left (319, 16) or 168,
184 Tertiary => Shift_Left (479, 16) or 328);
Nico Huber83693c82016-10-08 22:17:55 +0200185 begin
186 Registers.Write
187 (Register => Controller.PLANE_BUF_CFG,
Nico Huber4dc4c612018-01-10 15:55:09 +0100188 Value => Plane_Buffer_Range (Controller.Pipe));
Nico Huber83693c82016-10-08 22:17:55 +0200189 Registers.Write
190 (Register => Controller.PLANE_WM (0),
191 Value => PLANE_WM_ENABLE or
192 PLANE_WM_LINES (2) or
Nico Huber4dc4c612018-01-10 15:55:09 +0100193 PLANE_WM_BLOCKS (152));
194 Registers.Write
195 (Register => Controller.CUR_BUF_CFG,
196 Value => Cur_Buffer_Range (Controller.Pipe));
197 Registers.Write
198 (Register => Controller.CUR_WM (0),
199 Value => PLANE_WM_ENABLE or
200 PLANE_WM_LINES (2) or
201 PLANE_WM_BLOCKS (8));
Nico Huber83693c82016-10-08 22:17:55 +0200202 end Setup_Watermarks;
203
204 ----------------------------------------------------------------------------
205
Nico Huber3675db52016-11-04 16:27:29 +0100206 procedure Setup_Hires_Plane
Nico Huber6a4dfc82016-11-04 15:50:58 +0100207 (Controller : Controller_Type;
Nico Huber0164b022017-08-24 15:12:51 +0200208 FB : HW.GFX.Framebuffer_Type)
Nico Huber83693c82016-10-08 22:17:55 +0200209 with
210 Global => (In_Out => Registers.Register_State),
211 Depends =>
212 (Registers.Register_State
213 =>+
214 (Registers.Register_State,
215 Controller,
Nico Huber9b479412017-08-27 11:55:56 +0200216 FB)),
Nico Huber5ef4d602017-12-13 13:56:47 +0100217 Pre => FB.Height + FB.Start_Y <= FB.V_Stride
Nico Huber83693c82016-10-08 22:17:55 +0200218 is
219 -- FIXME: setup correct format, based on framebuffer RGB format
220 Format : constant Word32 := 6 * 2 ** 26;
Arthur Heymans960e2392026-03-03 19:45:24 +0100221 PRI : Word32 := Format;
Nico Huber83693c82016-10-08 22:17:55 +0200222 begin
223 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
224
Nico Huber83693c82016-10-08 22:17:55 +0200225 if Config.Has_Plane_Control then
Nico Huber9b479412017-08-27 11:55:56 +0200226 declare
Nico Huber34be6542017-12-13 09:26:24 +0100227 Stride, Offset : Word32;
Nico Huberc5c767a2018-06-03 01:09:04 +0200228 Width : constant Width_Type := Rotated_Width (FB);
229 Height : constant Width_Type := Rotated_Height (FB);
Nico Huber9b479412017-08-27 11:55:56 +0200230 begin
231 if Rotation_90 (FB) then
Nico Huber5ef4d602017-12-13 13:56:47 +0100232 Stride := Word32 (FB_Pitch (FB.V_Stride, FB));
233 Offset := Shift_Left (Word32 (FB.Start_X), 16) or
234 Word32 (FB.V_Stride - FB.Height - FB.Start_Y);
Nico Huber9b479412017-08-27 11:55:56 +0200235 else
Nico Huber5ef4d602017-12-13 13:56:47 +0100236 Stride := Word32 (FB_Pitch (FB.Stride, FB));
237 Offset := Shift_Left (Word32 (FB.Start_Y), 16) or
238 Word32 (FB.Start_X);
Nico Huber9b479412017-08-27 11:55:56 +0200239 end if;
240 Registers.Write
241 (Register => Controller.PLANE_CTL,
242 Value => PLANE_CTL_PLANE_ENABLE or
243 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 or
244 PLANE_CTL_PLANE_GAMMA_DISABLE or
245 PLANE_CTL_TILED_SURFACE (FB.Tiling) or
246 PLANE_CTL_PLANE_ROTATION (FB.Rotation));
247 Registers.Write (Controller.PLANE_OFFSET, Offset);
248 Registers.Write (Controller.PLANE_SIZE, Encode (Width, Height));
249 Registers.Write (Controller.PLANE_STRIDE, Stride);
250 Registers.Write (Controller.PLANE_POS, 16#0000_0000#);
Nico Huber34be6542017-12-13 09:26:24 +0100251 Registers.Write (Controller.PLANE_SURF, FB.Offset and 16#ffff_f000#);
Nico Huber9b479412017-08-27 11:55:56 +0200252 end;
Nico Huber83693c82016-10-08 22:17:55 +0200253 else
Arthur Heymans960e2392026-03-03 19:45:24 +0100254 if Config.Has_DSPCNTR_Pipe_Select then
255 PRI := PRI or DSPCNTR_PIPE_SEL (Controller.Pipe);
256 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200257 if Config.Disable_Trickle_Feed then
258 PRI := PRI or DSPCNTR_DISABLE_TRICKLE_FEED;
259 end if;
Arthur Heymans960e2392026-03-03 19:45:24 +0100260
261 -- Write DSPCNTR *without* the enable bit first. On pre-SKL
262 -- hardware the control register self-arms when the plane
263 -- transitions from disabled to enabled, latching whatever
264 -- stride/size/offset values happen to be in the registers at
265 -- that moment. Programming format, pipe-select, and trickle-
266 -- feed now avoids a glitch with stale geometry values.
Nico Huber83693c82016-10-08 22:17:55 +0200267 Registers.Unset_And_Set_Mask
268 (Register => Controller.DSPCNTR,
269 Mask_Unset => DSPCNTR_MASK,
Nico Huberab69e362018-05-29 21:20:30 +0200270 Mask_Set => PRI or DSPCNTR_TILED_SURFACE (FB.Tiling));
Nico Huber83693c82016-10-08 22:17:55 +0200271
Nico Huber0164b022017-08-24 15:12:51 +0200272 Registers.Write
273 (Controller.DSPSTRIDE, Word32 (Pixel_To_Bytes (FB.Stride, FB)));
Arthur Heymans960e2392026-03-03 19:45:24 +0100274
275 -- Gen3 (i945): program DSPSIZE and DSPPOS before the surface
276 -- address write that arms the double-buffered plane registers.
277 if Config.Gen_I945 then
278 Registers.Write
279 (Controller.DSPSIZE,
280 Encode (Rotated_Width (FB), Rotated_Height (FB)));
281 Registers.Write (Controller.DSPPOS, 16#0000_0000#);
282 end if;
283
Nico Huberab69e362018-05-29 21:20:30 +0200284 if Config.Has_DSP_Linoff and then FB.Tiling = Linear then
Nico Huberd49b56b2018-06-18 17:19:15 +0200285 pragma Assert_And_Cut (True);
286 declare
287 Linear_Offset : constant Pixel_Type :=
288 FB.Start_Y * FB.Stride + FB.Start_X;
289 begin
290 Registers.Write
291 (Register => Controller.DSPLINOFF,
Arthur Heymans960e2392026-03-03 19:45:24 +0100292 Value => (if Config.Has_DSPSURF
293 then Word32 (Pixel_To_Bytes (Linear_Offset, FB))
294 else (FB.Offset and 16#ffff_f000#) or
295 Word32 (Pixel_To_Bytes (Linear_Offset, FB))));
Nico Huberd49b56b2018-06-18 17:19:15 +0200296 Registers.Write (Controller.DSPTILEOFF, 0);
297 end;
Nico Huber5ef4d602017-12-13 13:56:47 +0100298 else
Nico Huberab69e362018-05-29 21:20:30 +0200299 if Config.Has_DSP_Linoff then
Arthur Heymans960e2392026-03-03 19:45:24 +0100300 Registers.Write (Controller.DSPLINOFF,
301 (if Config.Has_DSPSURF then 0
302 else FB.Offset and 16#ffff_f000#));
Nico Huberab69e362018-05-29 21:20:30 +0200303 end if;
Nico Huber5ef4d602017-12-13 13:56:47 +0100304 Registers.Write
305 (Register => Controller.DSPTILEOFF,
306 Value => Shift_Left (Word32 (FB.Start_Y), 16) or
307 Word32 (FB.Start_X));
Nico Huber83693c82016-10-08 22:17:55 +0200308 end if;
Arthur Heymans960e2392026-03-03 19:45:24 +0100309 if Config.Has_DSPSURF then
310 Registers.Write (Controller.DSPSURF, FB.Offset and 16#ffff_f000#);
311 end if;
312
313 -- Now enable the plane. All geometry registers are in place,
314 -- so the self-arm latches correct values.
315 Registers.Write
316 (Register => Controller.DSPCNTR,
317 Value => DSPCNTR_ENABLE or PRI or
318 DSPCNTR_TILED_SURFACE (FB.Tiling));
Nico Huber83693c82016-10-08 22:17:55 +0200319 end if;
Nico Huber3675db52016-11-04 16:27:29 +0100320 end Setup_Hires_Plane;
321
322 procedure Setup_Display
Nico Huber113a14b2016-12-06 21:59:15 +0100323 (Controller : Controller_Type;
324 Framebuffer : Framebuffer_Type;
325 Dither_BPC : BPC_Type;
326 Dither : Boolean)
Nico Huber3675db52016-11-04 16:27:29 +0100327 with
Nico Huber9b479412017-08-27 11:55:56 +0200328 Pre =>
329 Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
Nico Huber5ef4d602017-12-13 13:56:47 +0100330 Framebuffer.Height + Framebuffer.Start_Y <= Framebuffer.V_Stride
Nico Huber3675db52016-11-04 16:27:29 +0100331 is
332 use type Word8;
333
334 Reg8 : Word8;
335 begin
336 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
337
338 if Config.Has_Plane_Control then
339 Setup_Watermarks (Controller);
340 end if;
341
342 if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
Nico Huberfbb42202016-11-07 15:08:26 +0100343 if Config.VGA_Plane_Workaround then
344 Registers.Unset_And_Set_Mask
345 (Register => Registers.ILK_DISPLAY_CHICKEN1,
346 Mask_Unset => ILK_DISPLAY_CHICKEN1_VGA_MASK,
347 Mask_Set => ILK_DISPLAY_CHICKEN1_VGA_ENABLE);
348 Registers.Unset_And_Set_Mask
349 (Register => Registers.ILK_DISPLAY_CHICKEN2,
350 Mask_Unset => ILK_DISPLAY_CHICKEN2_VGA_MASK,
351 Mask_Set => ILK_DISPLAY_CHICKEN2_VGA_ENABLE);
352 end if;
353
Nico Huber3675db52016-11-04 16:27:29 +0100354 Registers.Unset_And_Set_Mask
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200355 (Register => VGACNTRL_REG,
Nico Huber3675db52016-11-04 16:27:29 +0100356 Mask_Unset => VGA_CONTROL_VGA_DISPLAY_DISABLE or
357 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK or
358 VGA_CONTROL_VSYNC_BLINK_RATE_MASK,
359 Mask_Set => VGA_CONTROL_BLINK_DUTY_CYCLE_50 or
360 VGA_CONTROL_VSYNC_BLINK_RATE (30));
361
362 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
363 Port_IO.InB (Reg8, VGA_SR_DATA);
364 Port_IO.OutB (VGA_SR_DATA, Reg8 and not (VGA_SR01_SCREEN_OFF));
365 else
Nico Huber6a4dfc82016-11-04 15:50:58 +0100366 Setup_Hires_Plane (Controller, Framebuffer);
Nico Huber3675db52016-11-04 16:27:29 +0100367 end if;
368
369 Registers.Write
370 (Register => Controller.PIPESRC,
371 Value => Encode
Nico Huber9b479412017-08-27 11:55:56 +0200372 (Rotated_Height (Framebuffer), Rotated_Width (Framebuffer)));
Nico Huber83693c82016-10-08 22:17:55 +0200373
Nico Huber113a14b2016-12-06 21:59:15 +0100374 if Config.Has_Pipeconf_Misc then
375 Registers.Write
376 (Register => Controller.PIPEMISC,
Nico Huber7ad2d652016-12-07 15:19:32 +0100377 Value => Transcoder.BPC_Conf (Dither_BPC, Dither));
Nico Huber113a14b2016-12-06 21:59:15 +0100378 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200379 end Setup_Display;
380
381 ----------------------------------------------------------------------------
382
Nico Huber4dc4c612018-01-10 15:55:09 +0100383 procedure Update_Cursor
384 (Pipe : Pipe_Index;
385 FB : Framebuffer_Type;
386 Cursor : Cursor_Type)
387 is
388 begin
389 -- on some platforms writing CUR_CTL disables self-arming of CUR_POS
390 -- so keep it first
391 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200392 (Register => Cursors (Pipe).CTL,
Nico Huber4dc4c612018-01-10 15:55:09 +0100393 Value => CUR_CTL_PIPE_SELECT (Pipe) or
394 CUR_CTL_MODE (Cursor.Mode, Cursor.Size));
395 Place_Cursor (Pipe, FB, Cursor);
396 end Update_Cursor;
397
398 procedure Place_Cursor
399 (Pipe : Pipe_Index;
400 FB : Framebuffer_Type;
401 Cursor : Cursor_Type)
402 is
403 Width : constant Width_Type := Cursor_Width (Cursor.Size);
404 X : Int32 := Cursor.Center_X - Width / 2;
405 Y : Int32 := Cursor.Center_Y - Width / 2;
406 begin
407 -- off-screen cursor needs special care
408 if X <= -Width or Y <= -Width or
Nico Huberc5c767a2018-06-03 01:09:04 +0200409 X >= Rotated_Width (FB) or Y >= Rotated_Height (FB) or
Nico Huber4dc4c612018-01-10 15:55:09 +0100410 X > Config.Maximum_Cursor_X or Y > Config.Maximum_Cursor_Y
411 then
412 X := -Width;
413 Y := -Width;
414 end if;
415 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200416 (Register => Cursors (Pipe).POS,
Nico Huber4dc4c612018-01-10 15:55:09 +0100417 Value => CUR_POS_Y (Y) or CUR_POS_X (X));
418 -- write to CUR_BASE always arms other CUR_* registers
419 Registers.Write
Nico Huber75a707f2018-06-18 16:28:33 +0200420 (Register => Cursors (Pipe).BASE,
Nico Huber4dc4c612018-01-10 15:55:09 +0100421 Value => Shift_Left (Word32 (Cursor.GTT_Offset), 12));
422 end Place_Cursor;
423
424 ----------------------------------------------------------------------------
425
Nico Huber4916e342016-11-04 14:37:53 +0100426 procedure Scale_Keep_Aspect
Nico Huberc5c767a2018-06-03 01:09:04 +0200427 (Width : out Width_Type;
428 Height : out Height_Type;
429 Max_Width : in Width_Type;
430 Max_Height : in Height_Type;
Nico Huber4916e342016-11-04 14:37:53 +0100431 Framebuffer : in Framebuffer_Type)
432 with
433 Pre =>
Nico Huberc5c767a2018-06-03 01:09:04 +0200434 Rotated_Width (Framebuffer) <= Max_Width and
435 Rotated_Height (Framebuffer) <= Max_Height,
Nico Huber4916e342016-11-04 14:37:53 +0100436 Post =>
437 Width <= Max_Width and Height <= Max_Height
438 is
Nico Huberc5c767a2018-06-03 01:09:04 +0200439 Src_Width : constant Width_Type := Rotated_Width (Framebuffer);
440 Src_Height : constant Height_Type := Rotated_Height (Framebuffer);
Nico Huber4916e342016-11-04 14:37:53 +0100441 begin
Nico Huberda1185e2018-06-03 01:07:46 +0200442 case Scaling_Type (Src_Width, Src_Height, Max_Width, Max_Height) is
443 when Letterbox =>
Nico Huber99200fe2026-04-14 16:37:45 +0200444 Height := (Src_Height * Max_Width) / Src_Width;
445 pragma Assert (Height <= Max_Height);
Nico Huberda1185e2018-06-03 01:07:46 +0200446 Width := Max_Width;
Nico Huberda1185e2018-06-03 01:07:46 +0200447 when Pillarbox =>
Nico Huber99200fe2026-04-14 16:37:45 +0200448 Width := (Src_Width * Max_Height) / Src_Height;
449 pragma Assert (Max_Height * Src_Width < Max_Width * Src_Height);
450 pragma Assert ((Max_Height * Src_Width) / Src_Height < Max_Width);
451 pragma Assert (Width <= Max_Width);
Nico Huberda1185e2018-06-03 01:07:46 +0200452 Height := Max_Height;
453 when Uniform =>
454 Width := Max_Width;
455 Height := Max_Height;
456 end case;
Nico Huber4916e342016-11-04 14:37:53 +0100457 end Scale_Keep_Aspect;
458
459 procedure Setup_Skylake_Pipe_Scaler
460 (Controller : in Controller_Type;
461 Mode : in HW.GFX.Mode_Type;
462 Framebuffer : in HW.GFX.Framebuffer_Type)
463 with
464 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200465 Rotated_Width (Framebuffer) <= Mode.H_Visible and
466 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100467 is
Nico Huber7ad2d652016-12-07 15:19:32 +0100468 use type Registers.Registers_Invalid_Index;
469
Nico Huber4916e342016-11-04 14:37:53 +0100470 -- Enable 7x5 extended mode where possible:
471 Scaler_Mode : constant Word32 :=
472 (if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
473 PS_CTRL_SCALER_MODE_7X5_EXTENDED else 0);
474
Nico Huberc5c767a2018-06-03 01:09:04 +0200475 Width_In : constant Width_Type := Rotated_Width (Framebuffer);
476 Height_In : constant Height_Type := Rotated_Height (Framebuffer);
Nico Huber9b479412017-08-27 11:55:56 +0200477
Nico Huber4916e342016-11-04 14:37:53 +0100478 -- We can scale up to 2.99x horizontally:
Nico Huber9b479412017-08-27 11:55:56 +0200479 Horizontal_Limit : constant Pos32 := (Width_In * 299) / 100;
Nico Huber4916e342016-11-04 14:37:53 +0100480 -- The third scaler is limited to 1.99x
481 -- vertical scaling for source widths > 2048:
482 Vertical_Limit : constant Pos32 :=
Nico Huber9b479412017-08-27 11:55:56 +0200483 (Height_In *
Nico Huber4916e342016-11-04 14:37:53 +0100484 (if Controller.PS_CTRL_2 = Registers.Invalid_Register and
Nico Huber9b479412017-08-27 11:55:56 +0200485 Width_In > 2048
Nico Huber4916e342016-11-04 14:37:53 +0100486 then
487 199
488 else
489 299)) / 100;
490
Nico Huberc5c767a2018-06-03 01:09:04 +0200491 Width : Width_Type;
492 Height : Height_Type;
Nico Huber4916e342016-11-04 14:37:53 +0100493 begin
494 -- Writes to WIN_SZ arm the PS registers.
495
496 Scale_Keep_Aspect
497 (Width => Width,
498 Height => Height,
Nico Huberc5c767a2018-06-03 01:09:04 +0200499 Max_Width => Pos32'Min (Horizontal_Limit, Mode.H_Visible),
500 Max_Height => Pos32'Min (Vertical_Limit, Mode.V_Visible),
Nico Huber4916e342016-11-04 14:37:53 +0100501 Framebuffer => Framebuffer);
502
503 Registers.Write
504 (Register => Controller.PS_CTRL_1,
505 Value => PS_CTRL_ENABLE_SCALER or Scaler_Mode);
506 Registers.Write
507 (Register => Controller.PS_WIN_POS_1,
508 Value =>
Nico Huberc5c767a2018-06-03 01:09:04 +0200509 Shift_Left (Word32 (Mode.H_Visible - Width) / 2, 16) or
510 Word32 (Mode.V_Visible - Height) / 2);
Nico Huber4916e342016-11-04 14:37:53 +0100511 Registers.Write
512 (Register => Controller.PS_WIN_SZ_1,
513 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
514 end Setup_Skylake_Pipe_Scaler;
515
516 procedure Setup_Ironlake_Panel_Fitter
517 (Controller : in Controller_Type;
518 Mode : in HW.GFX.Mode_Type;
519 Framebuffer : in HW.GFX.Framebuffer_Type)
520 with
521 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200522 Rotated_Width (Framebuffer) <= Mode.H_Visible and
523 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100524 is
525 -- Force 1:1 mapping of panel fitter:pipe
526 PF_Ctrl_Pipe_Sel : constant Word32 :=
527 (if Config.Has_PF_Pipe_Select then
528 (case Controller.PF_CTRL is
529 when Registers.PFA_CTL_1 => 0 * 2 ** 29,
530 when Registers.PFB_CTL_1 => 1 * 2 ** 29,
531 when Registers.PFC_CTL_1 => 2 * 2 ** 29,
532 when others => 0) else 0);
533
Nico Huberc5c767a2018-06-03 01:09:04 +0200534 Width : Width_Type;
535 Height : Height_Type;
Nico Huberfdb0df12018-02-07 14:30:34 +0100536 X, Y : Int32;
Nico Huber4916e342016-11-04 14:37:53 +0100537 begin
538 -- Writes to WIN_SZ arm the PF registers.
539
540 Scale_Keep_Aspect
541 (Width => Width,
542 Height => Height,
Nico Huberc5c767a2018-06-03 01:09:04 +0200543 Max_Width => Mode.H_Visible,
544 Max_Height => Mode.V_Visible,
Nico Huber4916e342016-11-04 14:37:53 +0100545 Framebuffer => Framebuffer);
546
Nico Huberfdb0df12018-02-07 14:30:34 +0100547 -- Do not scale to odd width (at least Haswell has trouble with this).
Nico Huberc5c767a2018-06-03 01:09:04 +0200548 if Width < Mode.H_Visible and Width mod 2 = 1 then
Nico Huberfdb0df12018-02-07 14:30:34 +0100549 Width := Width + 1;
550 end if;
Nico Huberb3b9fa32018-06-18 16:16:41 +0200551 -- Do not scale to odd height (at least Sandy Bridge makes trouble).
552 if Height < Mode.V_Visible and Height mod 2 = 1 then
553 Height := Height + 1;
554 end if;
Nico Huberfdb0df12018-02-07 14:30:34 +0100555
Nico Huberc5c767a2018-06-03 01:09:04 +0200556 X := (Mode.H_Visible - Width) / 2;
557 Y := (Mode.V_Visible - Height) / 2;
Nico Huberfdb0df12018-02-07 14:30:34 +0100558
559 -- Hardware is picky about minimal horizontal gaps.
Nico Huberc5c767a2018-06-03 01:09:04 +0200560 if Mode.H_Visible - Width <= 3 then
561 Width := Mode.H_Visible;
Nico Huberfdb0df12018-02-07 14:30:34 +0100562 X := 0;
563 end if;
564
Nico Huber4916e342016-11-04 14:37:53 +0100565 Registers.Write
566 (Register => Controller.PF_CTRL,
567 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel or PF_CTRL_FILTER_MED);
568 Registers.Write
569 (Register => Controller.PF_WIN_POS,
Nico Huberfdb0df12018-02-07 14:30:34 +0100570 Value => Shift_Left (Word32 (X), 16) or Word32 (Y));
Nico Huber4916e342016-11-04 14:37:53 +0100571 Registers.Write
572 (Register => Controller.PF_WIN_SZ,
573 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
574 end Setup_Ironlake_Panel_Fitter;
575
Arthur Heymansd5198442018-03-28 17:05:12 +0200576 procedure Setup_Gmch_Panel_Fitter
Nico Huber958c5642018-06-02 16:59:31 +0200577 (Controller : in Controller_Type;
578 Mode : in HW.GFX.Mode_Type;
579 Framebuffer : in HW.GFX.Framebuffer_Type)
Arthur Heymansd5198442018-03-28 17:05:12 +0200580 is
581 PF_Ctrl_Pipe_Sel : constant Word32 :=
582 (case Controller.Pipe is
583 when Primary => GMCH_PFIT_CONTROL_SELECT_PIPE_A,
584 when Secondary => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
585 when others => 0);
Nico Huber958c5642018-06-02 16:59:31 +0200586
Arthur Heymansf70edda2018-08-21 18:37:00 +0200587 -- Work around a quirk:
588 -- In legacy VGA mode Pillarbox fails to display anything so just force
589 -- 'auto' mode on all displays, which will the output stretched to
590 -- fullscreen .
Nico Huber958c5642018-06-02 16:59:31 +0200591 PF_Ctrl_Scaling : constant Word32 :=
Arthur Heymansf70edda2018-08-21 18:37:00 +0200592 (if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
593 GMCH_PFIT_CONTROL_SCALING (Uniform)
594 else
595 GMCH_PFIT_CONTROL_SCALING (Scaling_Type (Framebuffer, Mode)));
Nico Huber958c5642018-06-02 16:59:31 +0200596
Arthur Heymansd5198442018-03-28 17:05:12 +0200597 In_Use : Boolean;
598 begin
599 Registers.Is_Set_Mask
600 (Register => Registers.GMCH_PFIT_CONTROL,
601 Mask => PF_CTRL_ENABLE,
602 Result => In_Use);
603
604 if not In_Use then
605 Registers.Write
606 (Register => Registers.GMCH_PFIT_CONTROL,
Nico Huber958c5642018-06-02 16:59:31 +0200607 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel or PF_Ctrl_Scaling);
Arthur Heymansd5198442018-03-28 17:05:12 +0200608 else
Nico Huber7ba7bd62018-06-06 12:27:09 +0200609 pragma Debug (Debug.Put_Line
610 ("GMCH Pannel fitter already in use, skipping..."));
Arthur Heymansd5198442018-03-28 17:05:12 +0200611 end if;
612 end Setup_Gmch_Panel_Fitter;
613
Nico Huberf361ec82018-06-02 18:01:45 +0200614 procedure Gmch_Panel_Fitter_Pipe (Pipe : out Pipe_Index)
615 is
616 Used_For_Secondary : Boolean;
617 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100618 if Config.Gen_I945 then
619 -- Gen3: panel fitter is hardwired to Pipe B (Secondary).
620 -- The PFIT_PIPE field (bits 30:29) does not exist on Gen3.
621 Pipe := Secondary;
622 else
623 Registers.Is_Set_Mask
624 (Register => Registers.GMCH_PFIT_CONTROL,
625 Mask => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
626 Result => Used_For_Secondary);
627 Pipe := (if Used_For_Secondary then Secondary else Primary);
628 end if;
Nico Huberf361ec82018-06-02 18:01:45 +0200629 end;
630
Nico Huberb4b72792018-01-02 13:45:41 +0100631 procedure Panel_Fitter_Off (Controller : Controller_Type)
632 is
633 use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
Nico Huberf361ec82018-06-02 18:01:45 +0200634 Pipe_Using_PF : Pipe_Index;
Nico Huberb4b72792018-01-02 13:45:41 +0100635 begin
636 -- Writes to WIN_SZ arm the PS/PF registers.
637 if Config.Has_Plane_Control then
638 Registers.Unset_Mask (Controller.PS_CTRL_1, PS_CTRL_ENABLE_SCALER);
639 Registers.Write (Controller.PS_WIN_SZ_1, 16#0000_0000#);
640 if Controller.PS_CTRL_2 /= Registers.Invalid_Register and
641 Controller.PS_WIN_SZ_2 /= Registers.Invalid_Register
642 then
643 Registers.Unset_Mask (Controller.PS_CTRL_2, PS_CTRL_ENABLE_SCALER);
644 Registers.Write (Controller.PS_WIN_SZ_2, 16#0000_0000#);
645 end if;
Arthur Heymansd5198442018-03-28 17:05:12 +0200646 elsif Config.Has_GMCH_PFIT_CONTROL then
Nico Huberf361ec82018-06-02 18:01:45 +0200647 Gmch_Panel_Fitter_Pipe (Pipe_Using_PF);
648 if Pipe_Using_PF = Controller.Pipe then
Arthur Heymans960e2392026-03-03 19:45:24 +0100649 -- Write 0 to clear all bits (enable, scaling mode, auto-scale,
650 -- interpolation). Just clearing the enable bit can leave stale
651 -- Gen3 auto-scale bits that confuse the hardware.
652 Registers.Write (Registers.GMCH_PFIT_CONTROL, 16#0000_0000#);
Arthur Heymansd5198442018-03-28 17:05:12 +0200653 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100654 else
655 Registers.Unset_Mask (Controller.PF_CTRL, PF_CTRL_ENABLE);
656 Registers.Write (Controller.PF_WIN_SZ, 16#0000_0000#);
657 end if;
658 end Panel_Fitter_Off;
659
Nico Huber4916e342016-11-04 14:37:53 +0100660 procedure Setup_Scaling
661 (Controller : in Controller_Type;
662 Mode : in HW.GFX.Mode_Type;
663 Framebuffer : in HW.GFX.Framebuffer_Type)
664 with
665 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200666 Rotated_Width (Framebuffer) <= Mode.H_Visible and
667 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100668 is
669 begin
Nico Huber3d06de82018-05-29 01:35:04 +0200670 if Requires_Scaling (Framebuffer, Mode) then
Nico Huber4916e342016-11-04 14:37:53 +0100671 if Config.Has_Plane_Control then
672 Setup_Skylake_Pipe_Scaler (Controller, Mode, Framebuffer);
Arthur Heymansd5198442018-03-28 17:05:12 +0200673 elsif Config.Has_GMCH_PFIT_CONTROL then
Nico Huber958c5642018-06-02 16:59:31 +0200674 Setup_Gmch_Panel_Fitter (Controller, Mode, Framebuffer);
Nico Huber4916e342016-11-04 14:37:53 +0100675 else
676 Setup_Ironlake_Panel_Fitter (Controller, Mode, Framebuffer);
677 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100678 else
679 Panel_Fitter_Off (Controller);
Nico Huber4916e342016-11-04 14:37:53 +0100680 end if;
681 end Setup_Scaling;
682
Nico Huber9a4c4c32019-09-16 22:05:11 +0200683 procedure Reserve_Scaler
684 (Success : out Boolean;
685 Reservation : in out Scaler_Reservation;
686 Pipe : in Pipe_Index)
Nico Huberf361ec82018-06-02 18:01:45 +0200687 is
688 Pipe_Using_PF : Pipe_Index := Pipe_Index'First;
689 PF_Enabled : Boolean;
690 begin
691 if Config.Has_GMCH_PFIT_CONTROL then
Nico Huber9a4c4c32019-09-16 22:05:11 +0200692 if Reservation.Reserved then
693 Success := Reservation.Pipe = Pipe;
694 return;
695 end if;
696
Nico Huberf361ec82018-06-02 18:01:45 +0200697 Registers.Is_Set_Mask
698 (Register => Registers.GMCH_PFIT_CONTROL,
699 Mask => PF_CTRL_ENABLE,
700 Result => PF_Enabled);
701 if PF_Enabled then
702 Gmch_Panel_Fitter_Pipe (Pipe_Using_PF);
703 end if;
704
Nico Huber9a4c4c32019-09-16 22:05:11 +0200705 Success := not PF_Enabled or Pipe_Using_PF = Pipe;
706 if Success then
707 Reservation.Reserved := True;
708 Reservation.Pipe := Pipe;
709 end if;
Nico Huberf361ec82018-06-02 18:01:45 +0200710 else
Nico Huber9a4c4c32019-09-16 22:05:11 +0200711 Success := True;
Nico Huberf361ec82018-06-02 18:01:45 +0200712 end if;
Nico Huber9a4c4c32019-09-16 22:05:11 +0200713 end Reserve_Scaler;
Nico Huberf361ec82018-06-02 18:01:45 +0200714
Nico Huber4916e342016-11-04 14:37:53 +0100715 ----------------------------------------------------------------------------
716
Nico Huberf7f537e2018-01-02 14:15:43 +0100717 procedure Setup_FB
718 (Pipe : Pipe_Index;
719 Mode : Mode_Type;
720 Framebuffer : Framebuffer_Type)
721 is
722 -- Enable dithering if framebuffer BPC differs from port BPC,
723 -- as smooth gradients look really bad without.
724 Dither : constant Boolean := Framebuffer.BPC /= Mode.BPC;
725 begin
726 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
727
Nico Huber4dc4c612018-01-10 15:55:09 +0100728 -- Disable the cursor first.
729 Update_Cursor (Pipe, Framebuffer, Default_Cursor);
730
Nico Huberf7f537e2018-01-02 14:15:43 +0100731 Setup_Display (Controllers (Pipe), Framebuffer, Mode.BPC, Dither);
732 Setup_Scaling (Controllers (Pipe), Mode, Framebuffer);
733 end Setup_FB;
734
Nico Huber83693c82016-10-08 22:17:55 +0200735 procedure On
Nico Huberf3e23662016-12-05 21:33:03 +0100736 (Pipe : Pipe_Index;
Nico Huber83693c82016-10-08 22:17:55 +0200737 Port_Cfg : Port_Config;
Nico Huber4dc4c612018-01-10 15:55:09 +0100738 Framebuffer : Framebuffer_Type;
739 Cursor : Cursor_Type)
Nico Huber83693c82016-10-08 22:17:55 +0200740 is
741 begin
742 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
743
Nico Huber7ad2d652016-12-07 15:19:32 +0100744 Transcoder.Setup (Pipe, Port_Cfg);
Nico Huber83693c82016-10-08 22:17:55 +0200745
Nico Huberf7f537e2018-01-02 14:15:43 +0100746 Setup_FB (Pipe, Port_Cfg.Mode, Framebuffer);
Nico Huber4dc4c612018-01-10 15:55:09 +0100747 Update_Cursor (Pipe, Framebuffer, Cursor);
Nico Huber83693c82016-10-08 22:17:55 +0200748
Nico Huberabb16d92018-05-29 01:44:26 +0200749 Transcoder.On
750 (Pipe => Pipe,
751 Port_Cfg => Port_Cfg,
752 Dither => Framebuffer.BPC /= Port_Cfg.Mode.BPC,
753 Scale => Requires_Scaling (Framebuffer, Port_Cfg.Mode));
Nico Huber83693c82016-10-08 22:17:55 +0200754 end On;
755
756 ----------------------------------------------------------------------------
757
Nico Huber75a707f2018-06-18 16:28:33 +0200758 procedure Planes_Off (Controller : Controller_Type; CUR : Cursor_Regs)
759 is
760 use type Registers.Registers_Invalid_Index;
Nico Huber83693c82016-10-08 22:17:55 +0200761 begin
Nico Huber75a707f2018-06-18 16:28:33 +0200762 Registers.Write (CUR.CTL, 16#0000_0000#);
763 if CUR.FBC_CTL /= Registers.Invalid_Register then
764 Registers.Write (CUR.FBC_CTL, 16#0000_0000#);
Nico Huber4dc4c612018-01-10 15:55:09 +0100765 end if;
Nico Huber7ad2d652016-12-07 15:19:32 +0100766 Registers.Unset_Mask (Controller.SPCNTR, DSPCNTR_ENABLE);
Nico Huber83693c82016-10-08 22:17:55 +0200767 if Config.Has_Plane_Control then
768 Clear_Watermarks (Controller);
769 Registers.Unset_Mask (Controller.PLANE_CTL, PLANE_CTL_PLANE_ENABLE);
770 Registers.Write (Controller.PLANE_SURF, 16#0000_0000#);
771 else
772 Registers.Unset_Mask (Controller.DSPCNTR, DSPCNTR_ENABLE);
773 end if;
774 end Planes_Off;
775
Nico Huber7ad2d652016-12-07 15:19:32 +0100776 procedure Off (Pipe : Pipe_Index)
Nico Huberf3e23662016-12-05 21:33:03 +0100777 is
Nico Huber83693c82016-10-08 22:17:55 +0200778 begin
779 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
780
Nico Huber75a707f2018-06-18 16:28:33 +0200781 Planes_Off (Controllers (Pipe), Cursors (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100782 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100783 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100784 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200785 end Off;
786
Nico Huber33912aa2016-12-06 20:36:23 +0100787 procedure Legacy_VGA_Off
788 is
789 use type HW.Word8;
790 Reg8 : Word8;
791 begin
792 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
793 Port_IO.InB (Reg8, VGA_SR_DATA);
794 Port_IO.OutB (VGA_SR_DATA, Reg8 or VGA_SR01_SCREEN_OFF);
795 Time.U_Delay (100); -- PRM says 100us, Linux does 300
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200796 Registers.Set_Mask (VGACNTRL_REG, VGA_CONTROL_VGA_DISPLAY_DISABLE);
Nico Huber33912aa2016-12-06 20:36:23 +0100797 end Legacy_VGA_Off;
798
Nico Huber83693c82016-10-08 22:17:55 +0200799 procedure All_Off
800 is
Nico Huber83693c82016-10-08 22:17:55 +0200801 begin
802 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
803
Nico Huber33912aa2016-12-06 20:36:23 +0100804 Legacy_VGA_Off;
805
Arthur Heymans960e2392026-03-03 19:45:24 +0100806 for Pipe in Pipe_Index range Pipe_Index'First .. Config.Max_Pipe loop
Nico Huber75a707f2018-06-18 16:28:33 +0200807 Planes_Off (Controllers (Pipe), Cursors (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100808 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100809 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100810 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200811 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200812 end All_Off;
813
Nico Huber83693c82016-10-08 22:17:55 +0200814end HW.GFX.GMA.Pipe_Setup;