blob: ffa140fab5a5144786c353e85c81c06f7cd5c508 [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
18with HW.GFX.GMA.Config;
Nico Huber7ad2d652016-12-07 15:19:32 +010019with HW.GFX.GMA.Transcoder;
Nico Huber83693c82016-10-08 22:17:55 +020020
21package body HW.GFX.GMA.Pipe_Setup is
22
Nico Huberfbb42202016-11-07 15:08:26 +010023 ILK_DISPLAY_CHICKEN1_VGA_MASK : constant := 7 * 2 ** 29;
24 ILK_DISPLAY_CHICKEN1_VGA_ENABLE : constant := 5 * 2 ** 29;
25 ILK_DISPLAY_CHICKEN2_VGA_MASK : constant := 1 * 2 ** 25;
26 ILK_DISPLAY_CHICKEN2_VGA_ENABLE : constant := 0 * 2 ** 25;
27
Nico Huber7ad2d652016-12-07 15:19:32 +010028 DSPCNTR_ENABLE : constant := 1 * 2 ** 31;
29 DSPCNTR_GAMMA_CORRECTION : constant := 1 * 2 ** 30;
30 DSPCNTR_DISABLE_TRICKLE_FEED : constant := 1 * 2 ** 14;
31 DSPCNTR_FORMAT_MASK : constant := 15 * 2 ** 26;
Nico Huber83693c82016-10-08 22:17:55 +020032
33 DSPCNTR_MASK : constant Word32 :=
34 DSPCNTR_ENABLE or
35 DSPCNTR_GAMMA_CORRECTION or
36 DSPCNTR_FORMAT_MASK or
37 DSPCNTR_DISABLE_TRICKLE_FEED;
38
39 PLANE_CTL_PLANE_ENABLE : constant := 1 * 2 ** 31;
40 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 : constant := 4 * 2 ** 24;
41 PLANE_CTL_PLANE_GAMMA_DISABLE : constant := 1 * 2 ** 13;
Nico Huber0164b022017-08-24 15:12:51 +020042 PLANE_CTL_TILED_SURFACE_MASK : constant := 7 * 2 ** 10;
43 PLANE_CTL_TILED_SURFACE_LINEAR : constant := 0 * 2 ** 10;
44 PLANE_CTL_TILED_SURFACE_X_TILED : constant := 1 * 2 ** 10;
45 PLANE_CTL_TILED_SURFACE_Y_TILED : constant := 4 * 2 ** 10;
46 PLANE_CTL_TILED_SURFACE_YF_TILED : constant := 5 * 2 ** 10;
47
48 PLANE_CTL_TILED_SURFACE : constant array (Tiling_Type) of Word32 :=
49 (Linear => PLANE_CTL_TILED_SURFACE_LINEAR,
50 X_Tiled => PLANE_CTL_TILED_SURFACE_X_TILED,
51 Y_Tiled => PLANE_CTL_TILED_SURFACE_Y_TILED);
Nico Huber83693c82016-10-08 22:17:55 +020052
Nico Huber9b479412017-08-27 11:55:56 +020053 PLANE_CTL_PLANE_ROTATION_MASK : constant := 3 * 2 ** 0;
54 PLANE_CTL_PLANE_ROTATION : constant array (Rotation_Type) of Word32 :=
55 (No_Rotation => 0 * 2 ** 0,
56 Rotated_90 => 1 * 2 ** 0,
57 Rotated_180 => 2 * 2 ** 0,
58 Rotated_270 => 3 * 2 ** 0);
59
Nico Huber83693c82016-10-08 22:17:55 +020060 PLANE_WM_ENABLE : constant := 1 * 2 ** 31;
61 PLANE_WM_LINES_SHIFT : constant := 14;
62 PLANE_WM_LINES_MASK : constant := 16#001f# * 2 ** 14;
63 PLANE_WM_BLOCKS_MASK : constant := 16#03ff# * 2 ** 0;
64
Nico Huber33912aa2016-12-06 20:36:23 +010065 VGA_SR_INDEX : constant := 16#03c4#;
66 VGA_SR_DATA : constant := 16#03c5#;
67 VGA_SR01 : constant := 16#01#;
68 VGA_SR01_SCREEN_OFF : constant := 1 * 2 ** 5;
Nico Huber3675db52016-11-04 16:27:29 +010069
70 VGA_CONTROL_VGA_DISPLAY_DISABLE : constant := 1 * 2 ** 31;
71 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK : constant := 16#0003# * 2 ** 6;
72 VGA_CONTROL_BLINK_DUTY_CYCLE_50 : constant := 2 * 2 ** 6;
73 VGA_CONTROL_VSYNC_BLINK_RATE_MASK : constant := 16#003f# * 2 ** 0;
74
75 subtype VGA_Cycle_Count is Pos32 range 2 .. 128;
76 function VGA_CONTROL_VSYNC_BLINK_RATE
77 (Cycles : VGA_Cycle_Count)
78 return Word32
79 is
80 begin
81 return Word32 (Cycles) / 2 - 1;
82 end VGA_CONTROL_VSYNC_BLINK_RATE;
83
Nico Huber7ad2d652016-12-07 15:19:32 +010084 PF_CTRL_ENABLE : constant := 1 * 2 ** 31;
85 PF_CTRL_PIPE_SELECT_MASK : constant := 3 * 2 ** 29;
86 PF_CTRL_FILTER_MED : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +020087
Nico Huber7ad2d652016-12-07 15:19:32 +010088 PS_CTRL_ENABLE_SCALER : constant := 1 * 2 ** 31;
89 PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant := 1 * 2 ** 28;
90 PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant := 1 * 2 ** 23;
Nico Huber83693c82016-10-08 22:17:55 +020091
Arthur Heymansd5198442018-03-28 17:05:12 +020092 GMCH_PFIT_CONTROL_SELECT_MASK : constant := 3 * 2 ** 29;
93 GMCH_PFIT_CONTROL_SELECT_PIPE_A : constant := 0 * 2 ** 29;
94 GMCH_PFIT_CONTROL_SELECT_PIPE_B : constant := 1 * 2 ** 29;
95
Arthur Heymansdfcdd772018-03-28 16:42:50 +020096 VGACNTRL_REG : constant Registers.Registers_Index :=
97 (if Config.Has_GMCH_VGACNTRL then
98 Registers.GMCH_VGACNTRL
99 else Registers.CPU_VGACNTRL);
100
Nico Huber83693c82016-10-08 22:17:55 +0200101 ---------------------------------------------------------------------------
102
Nico Huber83693c82016-10-08 22:17:55 +0200103 function PLANE_WM_LINES (Lines : Natural) return Word32 is
104 begin
105 return Shift_Left (Word32 (Lines), PLANE_WM_LINES_SHIFT)
106 and PLANE_WM_LINES_MASK;
107 end PLANE_WM_LINES;
108
109 function PLANE_WM_BLOCKS (Blocks : Natural) return Word32 is
110 begin
111 return Word32 (Blocks) and PLANE_WM_BLOCKS_MASK;
112 end PLANE_WM_BLOCKS;
113
114 ---------------------------------------------------------------------------
115
116 function Encode (LSW, MSW : Pos16) return Word32 is
117 begin
Nico Huber7ad2d652016-12-07 15:19:32 +0100118 return Shift_Left (Word32 (MSW) - 1, 16) or (Word32 (LSW) - 1);
Nico Huber83693c82016-10-08 22:17:55 +0200119 end Encode;
120
121 ----------------------------------------------------------------------------
122
Nico Huber83693c82016-10-08 22:17:55 +0200123 procedure Clear_Watermarks (Controller : Controller_Type) is
124 begin
125 Registers.Write
126 (Register => Controller.PLANE_BUF_CFG,
127 Value => 16#0000_0000#);
128 for Level in WM_Levels range 0 .. WM_Levels'Last loop
129 Registers.Write
130 (Register => Controller.PLANE_WM (Level),
131 Value => 16#0000_0000#);
132 end loop;
133 Registers.Write
134 (Register => Controller.WM_LINETIME,
135 Value => 16#0000_0000#);
136 end Clear_Watermarks;
137
138 procedure Setup_Watermarks (Controller : Controller_Type)
139 is
Nico Huberf3e23662016-12-05 21:33:03 +0100140 type Per_Plane_Buffer_Range is array (Pipe_Index) of Word32;
141 Buffer_Range : constant Per_Plane_Buffer_Range :=
142 (Primary => Shift_Left (159, 16) or 0,
143 Secondary => Shift_Left (319, 16) or 160,
144 Tertiary => Shift_Left (479, 16) or 320);
Nico Huber83693c82016-10-08 22:17:55 +0200145 begin
146 Registers.Write
147 (Register => Controller.PLANE_BUF_CFG,
Nico Huberf3e23662016-12-05 21:33:03 +0100148 Value => Buffer_Range (Controller.Pipe));
Nico Huber83693c82016-10-08 22:17:55 +0200149 Registers.Write
150 (Register => Controller.PLANE_WM (0),
151 Value => PLANE_WM_ENABLE or
152 PLANE_WM_LINES (2) or
153 PLANE_WM_BLOCKS (160));
154 end Setup_Watermarks;
155
156 ----------------------------------------------------------------------------
157
Nico Huber3675db52016-11-04 16:27:29 +0100158 procedure Setup_Hires_Plane
Nico Huber6a4dfc82016-11-04 15:50:58 +0100159 (Controller : Controller_Type;
Nico Huber0164b022017-08-24 15:12:51 +0200160 FB : HW.GFX.Framebuffer_Type)
Nico Huber83693c82016-10-08 22:17:55 +0200161 with
162 Global => (In_Out => Registers.Register_State),
163 Depends =>
164 (Registers.Register_State
165 =>+
166 (Registers.Register_State,
167 Controller,
Nico Huber9b479412017-08-27 11:55:56 +0200168 FB)),
Nico Huber5ef4d602017-12-13 13:56:47 +0100169 Pre => FB.Height + FB.Start_Y <= FB.V_Stride
Nico Huber83693c82016-10-08 22:17:55 +0200170 is
171 -- FIXME: setup correct format, based on framebuffer RGB format
172 Format : constant Word32 := 6 * 2 ** 26;
173 PRI : Word32 := DSPCNTR_ENABLE or Format;
Nico Huber83693c82016-10-08 22:17:55 +0200174 begin
175 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
176
Nico Huber83693c82016-10-08 22:17:55 +0200177 if Config.Has_Plane_Control then
Nico Huber9b479412017-08-27 11:55:56 +0200178 declare
Nico Huber34be6542017-12-13 09:26:24 +0100179 Stride, Offset : Word32;
Nico Huber9b479412017-08-27 11:55:56 +0200180 Width : constant Pos16 := Rotated_Width (FB);
181 Height : constant Pos16 := Rotated_Height (FB);
182 begin
183 if Rotation_90 (FB) then
Nico Huber5ef4d602017-12-13 13:56:47 +0100184 Stride := Word32 (FB_Pitch (FB.V_Stride, FB));
185 Offset := Shift_Left (Word32 (FB.Start_X), 16) or
186 Word32 (FB.V_Stride - FB.Height - FB.Start_Y);
Nico Huber9b479412017-08-27 11:55:56 +0200187 else
Nico Huber5ef4d602017-12-13 13:56:47 +0100188 Stride := Word32 (FB_Pitch (FB.Stride, FB));
189 Offset := Shift_Left (Word32 (FB.Start_Y), 16) or
190 Word32 (FB.Start_X);
Nico Huber9b479412017-08-27 11:55:56 +0200191 end if;
192 Registers.Write
193 (Register => Controller.PLANE_CTL,
194 Value => PLANE_CTL_PLANE_ENABLE or
195 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 or
196 PLANE_CTL_PLANE_GAMMA_DISABLE or
197 PLANE_CTL_TILED_SURFACE (FB.Tiling) or
198 PLANE_CTL_PLANE_ROTATION (FB.Rotation));
199 Registers.Write (Controller.PLANE_OFFSET, Offset);
200 Registers.Write (Controller.PLANE_SIZE, Encode (Width, Height));
201 Registers.Write (Controller.PLANE_STRIDE, Stride);
202 Registers.Write (Controller.PLANE_POS, 16#0000_0000#);
Nico Huber34be6542017-12-13 09:26:24 +0100203 Registers.Write (Controller.PLANE_SURF, FB.Offset and 16#ffff_f000#);
Nico Huber9b479412017-08-27 11:55:56 +0200204 end;
Nico Huber83693c82016-10-08 22:17:55 +0200205 else
206 if Config.Disable_Trickle_Feed then
207 PRI := PRI or DSPCNTR_DISABLE_TRICKLE_FEED;
208 end if;
209 -- for now, just disable gamma LUT (can't do anything
210 -- useful without colorimetry information from display)
211 Registers.Unset_And_Set_Mask
212 (Register => Controller.DSPCNTR,
213 Mask_Unset => DSPCNTR_MASK,
214 Mask_Set => PRI);
215
Nico Huber0164b022017-08-24 15:12:51 +0200216 Registers.Write
217 (Controller.DSPSTRIDE, Word32 (Pixel_To_Bytes (FB.Stride, FB)));
Nico Huber83693c82016-10-08 22:17:55 +0200218 if Config.Has_DSP_Linoff then
Nico Huber5ef4d602017-12-13 13:56:47 +0100219 Registers.Write
220 (Register => Controller.DSPLINOFF,
221 Value => Word32 (Pixel_To_Bytes
222 (FB.Start_Y * FB.Stride + FB.Start_X, FB)));
223 Registers.Write (Controller.DSPTILEOFF, 0);
224 else
225 Registers.Write
226 (Register => Controller.DSPTILEOFF,
227 Value => Shift_Left (Word32 (FB.Start_Y), 16) or
228 Word32 (FB.Start_X));
Nico Huber83693c82016-10-08 22:17:55 +0200229 end if;
Nico Huber8fd92a12018-01-02 14:02:59 +0100230 Registers.Write (Controller.DSPSURF, FB.Offset and 16#ffff_f000#);
Nico Huber83693c82016-10-08 22:17:55 +0200231 end if;
Nico Huber3675db52016-11-04 16:27:29 +0100232 end Setup_Hires_Plane;
233
234 procedure Setup_Display
Nico Huber113a14b2016-12-06 21:59:15 +0100235 (Controller : Controller_Type;
236 Framebuffer : Framebuffer_Type;
237 Dither_BPC : BPC_Type;
238 Dither : Boolean)
Nico Huber3675db52016-11-04 16:27:29 +0100239 with
240 Global => (In_Out => (Registers.Register_State, Port_IO.State)),
241 Depends =>
242 (Registers.Register_State
243 =>+
244 (Registers.Register_State,
245 Controller,
Nico Huber113a14b2016-12-06 21:59:15 +0100246 Framebuffer,
247 Dither_BPC,
248 Dither),
Nico Huber3675db52016-11-04 16:27:29 +0100249 Port_IO.State
250 =>+
Nico Huber9b479412017-08-27 11:55:56 +0200251 (Framebuffer)),
252 Pre =>
253 Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
Nico Huber5ef4d602017-12-13 13:56:47 +0100254 Framebuffer.Height + Framebuffer.Start_Y <= Framebuffer.V_Stride
Nico Huber3675db52016-11-04 16:27:29 +0100255 is
256 use type Word8;
257
258 Reg8 : Word8;
259 begin
260 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
261
262 if Config.Has_Plane_Control then
263 Setup_Watermarks (Controller);
264 end if;
265
266 if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
Nico Huberfbb42202016-11-07 15:08:26 +0100267 if Config.VGA_Plane_Workaround then
268 Registers.Unset_And_Set_Mask
269 (Register => Registers.ILK_DISPLAY_CHICKEN1,
270 Mask_Unset => ILK_DISPLAY_CHICKEN1_VGA_MASK,
271 Mask_Set => ILK_DISPLAY_CHICKEN1_VGA_ENABLE);
272 Registers.Unset_And_Set_Mask
273 (Register => Registers.ILK_DISPLAY_CHICKEN2,
274 Mask_Unset => ILK_DISPLAY_CHICKEN2_VGA_MASK,
275 Mask_Set => ILK_DISPLAY_CHICKEN2_VGA_ENABLE);
276 end if;
277
Nico Huber3675db52016-11-04 16:27:29 +0100278 Registers.Unset_And_Set_Mask
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200279 (Register => VGACNTRL_REG,
Nico Huber3675db52016-11-04 16:27:29 +0100280 Mask_Unset => VGA_CONTROL_VGA_DISPLAY_DISABLE or
281 VGA_CONTROL_BLINK_DUTY_CYCLE_MASK or
282 VGA_CONTROL_VSYNC_BLINK_RATE_MASK,
283 Mask_Set => VGA_CONTROL_BLINK_DUTY_CYCLE_50 or
284 VGA_CONTROL_VSYNC_BLINK_RATE (30));
285
286 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
287 Port_IO.InB (Reg8, VGA_SR_DATA);
288 Port_IO.OutB (VGA_SR_DATA, Reg8 and not (VGA_SR01_SCREEN_OFF));
289 else
Nico Huber6a4dfc82016-11-04 15:50:58 +0100290 Setup_Hires_Plane (Controller, Framebuffer);
Nico Huber3675db52016-11-04 16:27:29 +0100291 end if;
292
293 Registers.Write
294 (Register => Controller.PIPESRC,
295 Value => Encode
Nico Huber9b479412017-08-27 11:55:56 +0200296 (Rotated_Height (Framebuffer), Rotated_Width (Framebuffer)));
Nico Huber83693c82016-10-08 22:17:55 +0200297
Nico Huber113a14b2016-12-06 21:59:15 +0100298 if Config.Has_Pipeconf_Misc then
299 Registers.Write
300 (Register => Controller.PIPEMISC,
Nico Huber7ad2d652016-12-07 15:19:32 +0100301 Value => Transcoder.BPC_Conf (Dither_BPC, Dither));
Nico Huber113a14b2016-12-06 21:59:15 +0100302 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200303 end Setup_Display;
304
305 ----------------------------------------------------------------------------
306
Nico Huber4916e342016-11-04 14:37:53 +0100307 procedure Scale_Keep_Aspect
308 (Width : out Pos32;
309 Height : out Pos32;
310 Max_Width : in Pos32;
311 Max_Height : in Pos32;
312 Framebuffer : in Framebuffer_Type)
313 with
314 Pre =>
315 Max_Width <= Pos32 (Pos16'Last) and
316 Max_Height <= Pos32 (Pos16'Last) and
Nico Huber9b479412017-08-27 11:55:56 +0200317 Pos32 (Rotated_Width (Framebuffer)) <= Max_Width and
318 Pos32 (Rotated_Height (Framebuffer)) <= Max_Height,
Nico Huber4916e342016-11-04 14:37:53 +0100319 Post =>
320 Width <= Max_Width and Height <= Max_Height
321 is
Nico Huber9b479412017-08-27 11:55:56 +0200322 Src_Width : constant Pos32 := Pos32 (Rotated_Width (Framebuffer));
323 Src_Height : constant Pos32 := Pos32 (Rotated_Height (Framebuffer));
Nico Huber4916e342016-11-04 14:37:53 +0100324 begin
Nico Huber9b479412017-08-27 11:55:56 +0200325 if (Max_Width * Src_Height) / Src_Width <= Max_Height then
Nico Huber4916e342016-11-04 14:37:53 +0100326 Width := Max_Width;
Nico Huber9b479412017-08-27 11:55:56 +0200327 Height := (Max_Width * Src_Height) / Src_Width;
Nico Huber4916e342016-11-04 14:37:53 +0100328 else
329 Height := Max_Height;
330 Width := Pos32'Min (Max_Width, -- could prove, it's <= Max_Width
Nico Huber9b479412017-08-27 11:55:56 +0200331 (Max_Height * Src_Width) / Src_Height);
Nico Huber4916e342016-11-04 14:37:53 +0100332 end if;
333 end Scale_Keep_Aspect;
334
335 procedure Setup_Skylake_Pipe_Scaler
336 (Controller : in Controller_Type;
337 Mode : in HW.GFX.Mode_Type;
338 Framebuffer : in HW.GFX.Framebuffer_Type)
339 with
340 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200341 Rotated_Width (Framebuffer) <= Mode.H_Visible and
342 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100343 is
Nico Huber7ad2d652016-12-07 15:19:32 +0100344 use type Registers.Registers_Invalid_Index;
345
Nico Huber4916e342016-11-04 14:37:53 +0100346 -- Enable 7x5 extended mode where possible:
347 Scaler_Mode : constant Word32 :=
348 (if Controller.PS_CTRL_2 /= Registers.Invalid_Register then
349 PS_CTRL_SCALER_MODE_7X5_EXTENDED else 0);
350
Nico Huber9b479412017-08-27 11:55:56 +0200351 Width_In : constant Pos32 := Pos32 (Rotated_Width (Framebuffer));
352 Height_In : constant Pos32 := Pos32 (Rotated_Height (Framebuffer));
353
Nico Huber4916e342016-11-04 14:37:53 +0100354 -- We can scale up to 2.99x horizontally:
Nico Huber9b479412017-08-27 11:55:56 +0200355 Horizontal_Limit : constant Pos32 := (Width_In * 299) / 100;
Nico Huber4916e342016-11-04 14:37:53 +0100356 -- The third scaler is limited to 1.99x
357 -- vertical scaling for source widths > 2048:
358 Vertical_Limit : constant Pos32 :=
Nico Huber9b479412017-08-27 11:55:56 +0200359 (Height_In *
Nico Huber4916e342016-11-04 14:37:53 +0100360 (if Controller.PS_CTRL_2 = Registers.Invalid_Register and
Nico Huber9b479412017-08-27 11:55:56 +0200361 Width_In > 2048
Nico Huber4916e342016-11-04 14:37:53 +0100362 then
363 199
364 else
365 299)) / 100;
366
367 Width, Height : Pos32;
368 begin
369 -- Writes to WIN_SZ arm the PS registers.
370
371 Scale_Keep_Aspect
372 (Width => Width,
373 Height => Height,
374 Max_Width => Pos32'Min (Horizontal_Limit, Pos32 (Mode.H_Visible)),
375 Max_Height => Pos32'Min (Vertical_Limit, Pos32 (Mode.V_Visible)),
376 Framebuffer => Framebuffer);
377
378 Registers.Write
379 (Register => Controller.PS_CTRL_1,
380 Value => PS_CTRL_ENABLE_SCALER or Scaler_Mode);
381 Registers.Write
382 (Register => Controller.PS_WIN_POS_1,
383 Value =>
384 Shift_Left (Word32 (Pos32 (Mode.H_Visible) - Width) / 2, 16) or
385 Word32 (Pos32 (Mode.V_Visible) - Height) / 2);
386 Registers.Write
387 (Register => Controller.PS_WIN_SZ_1,
388 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
389 end Setup_Skylake_Pipe_Scaler;
390
391 procedure Setup_Ironlake_Panel_Fitter
392 (Controller : in Controller_Type;
393 Mode : in HW.GFX.Mode_Type;
394 Framebuffer : in HW.GFX.Framebuffer_Type)
395 with
396 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200397 Rotated_Width (Framebuffer) <= Mode.H_Visible and
398 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100399 is
400 -- Force 1:1 mapping of panel fitter:pipe
401 PF_Ctrl_Pipe_Sel : constant Word32 :=
402 (if Config.Has_PF_Pipe_Select then
403 (case Controller.PF_CTRL is
404 when Registers.PFA_CTL_1 => 0 * 2 ** 29,
405 when Registers.PFB_CTL_1 => 1 * 2 ** 29,
406 when Registers.PFC_CTL_1 => 2 * 2 ** 29,
407 when others => 0) else 0);
408
409 Width, Height : Pos32;
Nico Huberfdb0df12018-02-07 14:30:34 +0100410 X, Y : Int32;
Nico Huber4916e342016-11-04 14:37:53 +0100411 begin
412 -- Writes to WIN_SZ arm the PF registers.
413
414 Scale_Keep_Aspect
415 (Width => Width,
416 Height => Height,
417 Max_Width => Pos32 (Mode.H_Visible),
418 Max_Height => Pos32 (Mode.V_Visible),
419 Framebuffer => Framebuffer);
420
Nico Huberfdb0df12018-02-07 14:30:34 +0100421 -- Do not scale to odd width (at least Haswell has trouble with this).
422 if Width < Pos32 (Mode.H_Visible) and Width mod 2 = 1 then
423 Width := Width + 1;
424 end if;
425
426 X := (Int32 (Mode.H_Visible) - Width) / 2;
427 Y := (Int32 (Mode.V_Visible) - Height) / 2;
428
429 -- Hardware is picky about minimal horizontal gaps.
430 if Pos32 (Mode.H_Visible) - Width <= 3 then
431 Width := Pos32(Mode.H_Visible);
432 X := 0;
433 end if;
434
Nico Huber4916e342016-11-04 14:37:53 +0100435 Registers.Write
436 (Register => Controller.PF_CTRL,
437 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel or PF_CTRL_FILTER_MED);
438 Registers.Write
439 (Register => Controller.PF_WIN_POS,
Nico Huberfdb0df12018-02-07 14:30:34 +0100440 Value => Shift_Left (Word32 (X), 16) or Word32 (Y));
Nico Huber4916e342016-11-04 14:37:53 +0100441 Registers.Write
442 (Register => Controller.PF_WIN_SZ,
443 Value => Shift_Left (Word32 (Width), 16) or Word32 (Height));
444 end Setup_Ironlake_Panel_Fitter;
445
Arthur Heymansd5198442018-03-28 17:05:12 +0200446 -- TODO the panel fitter can only be set for one pipe
447 -- If this causes problems:
448 -- Check in Enable_Output if panel fitter has already been enabled
449 -- Pass this information to Validate_Config
450 procedure Setup_Gmch_Panel_Fitter
451 (Controller : in Controller_Type)
452 is
453 PF_Ctrl_Pipe_Sel : constant Word32 :=
454 (case Controller.Pipe is
455 when Primary => GMCH_PFIT_CONTROL_SELECT_PIPE_A,
456 when Secondary => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
457 when others => 0);
458 In_Use : Boolean;
459 begin
460 Registers.Is_Set_Mask
461 (Register => Registers.GMCH_PFIT_CONTROL,
462 Mask => PF_CTRL_ENABLE,
463 Result => In_Use);
464
465 if not In_Use then
466 Registers.Write
467 (Register => Registers.GMCH_PFIT_CONTROL,
468 Value => PF_CTRL_ENABLE or PF_Ctrl_Pipe_Sel);
469 else
470 Debug.Put_Line ("GMCH Pannel fitter already in use, skipping...");
471 end if;
472 end Setup_Gmch_Panel_Fitter;
473
Nico Huberb4b72792018-01-02 13:45:41 +0100474 procedure Panel_Fitter_Off (Controller : Controller_Type)
475 is
476 use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
Arthur Heymansd5198442018-03-28 17:05:12 +0200477 Used_For_Secondary : Boolean;
Nico Huberb4b72792018-01-02 13:45:41 +0100478 begin
479 -- Writes to WIN_SZ arm the PS/PF registers.
480 if Config.Has_Plane_Control then
481 Registers.Unset_Mask (Controller.PS_CTRL_1, PS_CTRL_ENABLE_SCALER);
482 Registers.Write (Controller.PS_WIN_SZ_1, 16#0000_0000#);
483 if Controller.PS_CTRL_2 /= Registers.Invalid_Register and
484 Controller.PS_WIN_SZ_2 /= Registers.Invalid_Register
485 then
486 Registers.Unset_Mask (Controller.PS_CTRL_2, PS_CTRL_ENABLE_SCALER);
487 Registers.Write (Controller.PS_WIN_SZ_2, 16#0000_0000#);
488 end if;
Arthur Heymansd5198442018-03-28 17:05:12 +0200489 elsif Config.Has_GMCH_PFIT_CONTROL then
490 Registers.Is_Set_Mask
491 (Register => Registers.GMCH_PFIT_CONTROL,
492 Mask => GMCH_PFIT_CONTROL_SELECT_PIPE_B,
493 Result => Used_For_Secondary);
494 if (Controller.Pipe = Primary and not Used_For_Secondary) or
495 (Controller.Pipe = Secondary and Used_For_Secondary)
496 then
497 Registers.Unset_Mask
498 (Register => Registers.GMCH_PFIT_CONTROL,
499 Mask => PF_CTRL_ENABLE);
500 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100501 else
502 Registers.Unset_Mask (Controller.PF_CTRL, PF_CTRL_ENABLE);
503 Registers.Write (Controller.PF_WIN_SZ, 16#0000_0000#);
504 end if;
505 end Panel_Fitter_Off;
506
Nico Huber4916e342016-11-04 14:37:53 +0100507 procedure Setup_Scaling
508 (Controller : in Controller_Type;
509 Mode : in HW.GFX.Mode_Type;
510 Framebuffer : in HW.GFX.Framebuffer_Type)
511 with
512 Pre =>
Nico Huber9b479412017-08-27 11:55:56 +0200513 Rotated_Width (Framebuffer) <= Mode.H_Visible and
514 Rotated_Height (Framebuffer) <= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100515 is
516 begin
Nico Huber9b479412017-08-27 11:55:56 +0200517 if Rotated_Width (Framebuffer) /= Mode.H_Visible or
518 Rotated_Height (Framebuffer) /= Mode.V_Visible
Nico Huber4916e342016-11-04 14:37:53 +0100519 then
520 if Config.Has_Plane_Control then
521 Setup_Skylake_Pipe_Scaler (Controller, Mode, Framebuffer);
Arthur Heymansd5198442018-03-28 17:05:12 +0200522 elsif Config.Has_GMCH_PFIT_CONTROL then
523 Setup_Gmch_Panel_Fitter (Controller);
Nico Huber4916e342016-11-04 14:37:53 +0100524 else
525 Setup_Ironlake_Panel_Fitter (Controller, Mode, Framebuffer);
526 end if;
Nico Huberb4b72792018-01-02 13:45:41 +0100527 else
528 Panel_Fitter_Off (Controller);
Nico Huber4916e342016-11-04 14:37:53 +0100529 end if;
530 end Setup_Scaling;
531
532 ----------------------------------------------------------------------------
533
Nico Huberf7f537e2018-01-02 14:15:43 +0100534 procedure Setup_FB
535 (Pipe : Pipe_Index;
536 Mode : Mode_Type;
537 Framebuffer : Framebuffer_Type)
538 is
539 -- Enable dithering if framebuffer BPC differs from port BPC,
540 -- as smooth gradients look really bad without.
541 Dither : constant Boolean := Framebuffer.BPC /= Mode.BPC;
542 begin
543 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
544
545 Setup_Display (Controllers (Pipe), Framebuffer, Mode.BPC, Dither);
546 Setup_Scaling (Controllers (Pipe), Mode, Framebuffer);
547 end Setup_FB;
548
Nico Huber83693c82016-10-08 22:17:55 +0200549 procedure On
Nico Huberf3e23662016-12-05 21:33:03 +0100550 (Pipe : Pipe_Index;
Nico Huber83693c82016-10-08 22:17:55 +0200551 Port_Cfg : Port_Config;
552 Framebuffer : Framebuffer_Type)
553 is
554 begin
555 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
556
Nico Huber7ad2d652016-12-07 15:19:32 +0100557 Transcoder.Setup (Pipe, Port_Cfg);
Nico Huber83693c82016-10-08 22:17:55 +0200558
Nico Huberf7f537e2018-01-02 14:15:43 +0100559 Setup_FB (Pipe, Port_Cfg.Mode, Framebuffer);
Nico Huber83693c82016-10-08 22:17:55 +0200560
Nico Huberf7f537e2018-01-02 14:15:43 +0100561 Transcoder.On (Pipe, Port_Cfg, Framebuffer.BPC /= Port_Cfg.Mode.BPC);
Nico Huber83693c82016-10-08 22:17:55 +0200562 end On;
563
564 ----------------------------------------------------------------------------
565
566 procedure Planes_Off (Controller : Controller_Type) is
567 begin
Nico Huber7ad2d652016-12-07 15:19:32 +0100568 Registers.Unset_Mask (Controller.SPCNTR, DSPCNTR_ENABLE);
Nico Huber83693c82016-10-08 22:17:55 +0200569 if Config.Has_Plane_Control then
570 Clear_Watermarks (Controller);
571 Registers.Unset_Mask (Controller.PLANE_CTL, PLANE_CTL_PLANE_ENABLE);
572 Registers.Write (Controller.PLANE_SURF, 16#0000_0000#);
573 else
574 Registers.Unset_Mask (Controller.DSPCNTR, DSPCNTR_ENABLE);
575 end if;
576 end Planes_Off;
577
Nico Huber7ad2d652016-12-07 15:19:32 +0100578 procedure Off (Pipe : Pipe_Index)
Nico Huberf3e23662016-12-05 21:33:03 +0100579 is
Nico Huber83693c82016-10-08 22:17:55 +0200580 begin
581 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
582
Nico Huberf3e23662016-12-05 21:33:03 +0100583 Planes_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100584 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100585 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100586 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200587 end Off;
588
Nico Huber33912aa2016-12-06 20:36:23 +0100589 procedure Legacy_VGA_Off
590 is
591 use type HW.Word8;
592 Reg8 : Word8;
593 begin
594 Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
595 Port_IO.InB (Reg8, VGA_SR_DATA);
596 Port_IO.OutB (VGA_SR_DATA, Reg8 or VGA_SR01_SCREEN_OFF);
597 Time.U_Delay (100); -- PRM says 100us, Linux does 300
Arthur Heymansdfcdd772018-03-28 16:42:50 +0200598 Registers.Set_Mask (VGACNTRL_REG, VGA_CONTROL_VGA_DISPLAY_DISABLE);
Nico Huber33912aa2016-12-06 20:36:23 +0100599 end Legacy_VGA_Off;
600
Nico Huber83693c82016-10-08 22:17:55 +0200601 procedure All_Off
602 is
Nico Huber83693c82016-10-08 22:17:55 +0200603 begin
604 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
605
Nico Huber33912aa2016-12-06 20:36:23 +0100606 Legacy_VGA_Off;
607
Nico Huberf3e23662016-12-05 21:33:03 +0100608 for Pipe in Pipe_Index loop
609 Planes_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100610 Transcoder.Off (Pipe);
Nico Huberf3e23662016-12-05 21:33:03 +0100611 Panel_Fitter_Off (Controllers (Pipe));
Nico Huber7ad2d652016-12-07 15:19:32 +0100612 Transcoder.Clk_Off (Pipe);
Nico Huber83693c82016-10-08 22:17:55 +0200613 end loop;
Nico Huber83693c82016-10-08 22:17:55 +0200614 end All_Off;
615
Nico Huber83693c82016-10-08 22:17:55 +0200616end HW.GFX.GMA.Pipe_Setup;