blob: 2d13a015993c41dbba23d56314f6b28339e7b5fc [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2015-2016 secunet Security Networks AG
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
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;
19with HW.GFX.GMA.DP_Info;
20with HW.GFX.GMA.Registers;
21
22use type HW.Word64;
23use type HW.Pos16;
Nico Huber83693c82016-10-08 22:17:55 +020024use type HW.GFX.GMA.Registers.Registers_Invalid_Index;
25
26package body HW.GFX.GMA.Pipe_Setup is
27
28 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;
32
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;
42
43 PLANE_WM_ENABLE : constant := 1 * 2 ** 31;
44 PLANE_WM_LINES_SHIFT : constant := 14;
45 PLANE_WM_LINES_MASK : constant := 16#001f# * 2 ** 14;
46 PLANE_WM_BLOCKS_MASK : constant := 16#03ff# * 2 ** 0;
47
48 SPCNTR_ENABLE : constant := 1 * 2 ** 31;
49
50 TRANS_CLK_SEL_PORT_NONE : constant := 0 * 2 ** 29;
51
52 type TRANS_CLK_SEL_PORT_Array is
53 array (Digital_Port) of Word32;
54 TRANS_CLK_SEL_PORT : constant TRANS_CLK_SEL_PORT_Array :=
55 TRANS_CLK_SEL_PORT_Array'
56 (DIGI_A => 0 * 2 ** 29, -- DDI A is not selectable
57 DIGI_B => 2 * 2 ** 29,
58 DIGI_C => 3 * 2 ** 29,
59 DIGI_D => 4 * 2 ** 29,
60 DIGI_E => 5 * 2 ** 29);
61
62 PIPECONF_ENABLE : constant := 1 * 2 ** 31;
63 PIPECONF_ENABLED_STATUS : constant := 1 * 2 ** 30;
64 PIPECONF_ENABLE_DITHER : constant := 1 * 2 ** 4;
65 PIPECONF_DITHER_TEMPORAL : constant := 1 * 2 ** 2;
66
67 PF_CTL_1_ENABLE : constant Word32 := 1 * 2 ** 31;
68
69 PS_CTRL_ENABLE_SCALER : constant Word32 := 1 * 2 ** 31;
70 PS_CTRL_SCALER_MODE_7X5_EXTENDED : constant Word32 := 1 * 2 ** 28;
71 PS_CTRL_FILTER_SELECT_MEDIUM_2 : constant Word32 := 1 * 2 ** 23;
72
73 PIPE_DDI_FUNC_CTL_ENABLE : constant := 1 * 2 ** 31;
74 PIPE_DDI_FUNC_CTL_DDI_SELECT_MASK : constant := 7 * 2 ** 28;
75 PIPE_DDI_FUNC_CTL_DDI_SELECT_NONE : constant := 0 * 2 ** 28;
76 PIPE_DDI_FUNC_CTL_DDI_SELECT_B : constant := 1 * 2 ** 28;
77 PIPE_DDI_FUNC_CTL_DDI_SELECT_C : constant := 2 * 2 ** 28;
78 PIPE_DDI_FUNC_CTL_DDI_SELECT_D : constant := 3 * 2 ** 28;
79 PIPE_DDI_FUNC_CTL_DDI_SELECT_E : constant := 4 * 2 ** 28;
80 PIPE_DDI_FUNC_CTL_MODE_SELECT_MASK : constant := 7 * 2 ** 24;
81 PIPE_DDI_FUNC_CTL_MODE_SELECT_HDMI : constant := 0 * 2 ** 24;
82 PIPE_DDI_FUNC_CTL_MODE_SELECT_DVI : constant := 1 * 2 ** 24;
83 PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_SST : constant := 2 * 2 ** 24;
84 PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_MST : constant := 3 * 2 ** 24;
85 PIPE_DDI_FUNC_CTL_MODE_SELECT_FDI : constant := 4 * 2 ** 24;
86 PIPE_DDI_FUNC_CTL_BPC_MASK : constant := 7 * 2 ** 20;
87 PIPE_DDI_FUNC_CTL_BPC_8BITS : constant := 0 * 2 ** 20;
88 PIPE_DDI_FUNC_CTL_BPC_10BITS : constant := 1 * 2 ** 20;
89 PIPE_DDI_FUNC_CTL_BPC_6BITS : constant := 2 * 2 ** 20;
90 PIPE_DDI_FUNC_CTL_BPC_12BITS : constant := 3 * 2 ** 20;
91 PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_LOW : constant := 0 * 2 ** 17;
92 PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 17;
93 PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_LOW : constant := 0 * 2 ** 16;
94 PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_HIGH : constant := 1 * 2 ** 16;
95 PIPE_DDI_FUNC_CTL_EDP_SELECT_MASK : constant := 7 * 2 ** 12;
96 PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON : constant := 0 * 2 ** 12;
97 PIPE_DDI_FUNC_CTL_EDP_SELECT_A : constant := 4 * 2 ** 12;
98 PIPE_DDI_FUNC_CTL_EDP_SELECT_B : constant := 5 * 2 ** 12;
99 PIPE_DDI_FUNC_CTL_EDP_SELECT_C : constant := 6 * 2 ** 12;
100 PIPE_DDI_FUNC_CTL_DP_VC_PAYLOAD_ALLOC : constant := 1 * 2 ** 8;
101 PIPE_DDI_FUNC_CTL_BFI_ENABLE : constant := 1 * 2 ** 4;
102 PIPE_DDI_FUNC_CTL_PORT_WIDTH_MASK : constant := 7 * 2 ** 1;
103 PIPE_DDI_FUNC_CTL_PORT_WIDTH_1_LANE : constant := 0 * 2 ** 1;
104 PIPE_DDI_FUNC_CTL_PORT_WIDTH_2_LANES : constant := 1 * 2 ** 1;
105 PIPE_DDI_FUNC_CTL_PORT_WIDTH_4_LANES : constant := 3 * 2 ** 1;
106
107 type DDI_Select_Array is array (Digital_Port) of Word32;
108 PIPE_DDI_FUNC_CTL_DDI_SELECT : constant DDI_Select_Array :=
109 DDI_Select_Array'
110 (DIGI_A => PIPE_DDI_FUNC_CTL_DDI_SELECT_NONE,
111 DIGI_B => PIPE_DDI_FUNC_CTL_DDI_SELECT_B,
112 DIGI_C => PIPE_DDI_FUNC_CTL_DDI_SELECT_C,
113 DIGI_D => PIPE_DDI_FUNC_CTL_DDI_SELECT_D,
114 DIGI_E => PIPE_DDI_FUNC_CTL_DDI_SELECT_E);
115
116 type DDI_Mode_Array is array (Display_Type) of Word32;
117 PIPE_DDI_FUNC_CTL_MODE_SELECT : constant DDI_Mode_Array :=
118 DDI_Mode_Array'
119 (VGA => PIPE_DDI_FUNC_CTL_MODE_SELECT_FDI,
120 HDMI => PIPE_DDI_FUNC_CTL_MODE_SELECT_DVI,
121 DP => PIPE_DDI_FUNC_CTL_MODE_SELECT_DP_SST,
122 others => 0);
123
124 type HV_Sync_Array is array (Boolean) of Word32;
125 PIPE_DDI_FUNC_CTL_VSYNC : constant HV_Sync_Array := HV_Sync_Array'
126 (False => PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_LOW,
127 True => PIPE_DDI_FUNC_CTL_VSYNC_ACTIVE_HIGH);
128 PIPE_DDI_FUNC_CTL_HSYNC : constant HV_Sync_Array := HV_Sync_Array'
129 (False => PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_LOW,
130 True => PIPE_DDI_FUNC_CTL_HSYNC_ACTIVE_HIGH);
131
132 type EDP_Select_Array is array (Controller_Kind) of Word32;
133 PIPE_DDI_FUNC_CTL_EDP_SELECT : constant EDP_Select_Array :=
134 EDP_Select_Array'
135 (A => PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON, -- we never use panel fitter
136 B => PIPE_DDI_FUNC_CTL_EDP_SELECT_B,
137 C => PIPE_DDI_FUNC_CTL_EDP_SELECT_C);
138 PIPE_DDI_FUNC_CTL_EDP_SELECT_ONOFF : constant EDP_Select_Array :=
139 EDP_Select_Array'
140 (A => PIPE_DDI_FUNC_CTL_EDP_SELECT_A,
141 B => PIPE_DDI_FUNC_CTL_EDP_SELECT_B,
142 C => PIPE_DDI_FUNC_CTL_EDP_SELECT_C);
143
144 type Port_Width_Array is array (HW.GFX.DP_Lane_Count) of Word32;
145 PIPE_DDI_FUNC_CTL_PORT_WIDTH : constant Port_Width_Array :=
146 Port_Width_Array'
147 (HW.GFX.DP_Lane_Count_1 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_1_LANE,
148 HW.GFX.DP_Lane_Count_2 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_2_LANES,
149 HW.GFX.DP_Lane_Count_4 => PIPE_DDI_FUNC_CTL_PORT_WIDTH_4_LANES);
150
151 function PIPE_DDI_FUNC_CTL_BPC (BPC : HW.GFX.BPC_Type) return Word32
152 is
153 Result : Word32;
154 begin
155 case BPC is
156 when 6 => Result := PIPE_DDI_FUNC_CTL_BPC_6BITS;
157 when 8 => Result := PIPE_DDI_FUNC_CTL_BPC_8BITS;
158 when 10 => Result := PIPE_DDI_FUNC_CTL_BPC_10BITS;
159 when 12 => Result := PIPE_DDI_FUNC_CTL_BPC_12BITS;
160 when others => Result := PIPE_DDI_FUNC_CTL_BPC_8BITS;
161 end case;
162 return Result;
163 end PIPE_DDI_FUNC_CTL_BPC;
164
165 function PIPE_DATA_M_TU (Transfer_Unit : Positive) return Word32 is
166 begin
167 return Shift_Left (Word32 (Transfer_Unit - 1), 25);
168 end PIPE_DATA_M_TU;
169
170 PIPE_MSA_MISC_SYNC_CLK : constant := 1 * 2 ** 0;
171 PIPE_MSA_MISC_BPC_6BITS : constant := 0 * 2 ** 5;
172 PIPE_MSA_MISC_BPC_8BITS : constant := 1 * 2 ** 5;
173 PIPE_MSA_MISC_BPC_10BITS : constant := 2 * 2 ** 5;
174 PIPE_MSA_MISC_BPC_12BITS : constant := 3 * 2 ** 5;
175 PIPE_MSA_MISC_BPC_16BITS : constant := 4 * 2 ** 5;
176
177 function PIPE_MSA_MISC_BPC (BPC : HW.GFX.BPC_Type) return Word32 is
178 Result : Word32;
179 begin
180 case BPC is
181 when 6 => Result := PIPE_MSA_MISC_BPC_6BITS;
182 when 8 => Result := PIPE_MSA_MISC_BPC_8BITS;
183 when 10 => Result := PIPE_MSA_MISC_BPC_10BITS;
184 when 12 => Result := PIPE_MSA_MISC_BPC_12BITS;
185 --when 16 => Result := PIPE_MSA_MISC_BPC_16BITS;
186 when others => Result := PIPE_MSA_MISC_BPC_8BITS;
187 end case;
188 return Result;
189 end PIPE_MSA_MISC_BPC;
190
191 ---------------------------------------------------------------------------
192
193 function PIPECONF_BPC_MAP (Bits_Per_Color : HW.GFX.BPC_Type) return Word32
194 is
195 Result : Word32;
196 begin
197 if Bits_Per_Color = 6 then
198 Result := 2 * 2 ** 5;
199 elsif Bits_Per_Color = 10 then
200 Result := 1 * 2 ** 5;
201 elsif Bits_Per_Color = 12 then
202 Result := 3 * 2 ** 5;
203 else
204 Result := 0;
205 end if;
206 return Result;
207 end PIPECONF_BPC_MAP;
208
209 ---------------------------------------------------------------------------
210
211 function PLANE_WM_LINES (Lines : Natural) return Word32 is
212 begin
213 return Shift_Left (Word32 (Lines), PLANE_WM_LINES_SHIFT)
214 and PLANE_WM_LINES_MASK;
215 end PLANE_WM_LINES;
216
217 function PLANE_WM_BLOCKS (Blocks : Natural) return Word32 is
218 begin
219 return Word32 (Blocks) and PLANE_WM_BLOCKS_MASK;
220 end PLANE_WM_BLOCKS;
221
222 ---------------------------------------------------------------------------
223
224 function Encode (LSW, MSW : Pos16) return Word32 is
225 begin
226 return Shift_Left (Word32 (MSW - 1), 16) or Word32 (LSW - 1);
227 end Encode;
228
229 ----------------------------------------------------------------------------
230
231 procedure Setup_Link
232 (Head : Head_Type;
233 Link : DP_Link;
234 Mode : Mode_Type)
235 with
236 Global => (In_Out => Registers.Register_State),
237 Depends => (Registers.Register_State =>+ (Head, Link, Mode))
238 is
239 Data_M, Link_M : DP_Info.M_Type;
240 Data_N, Link_N : DP_Info.N_Type;
241 begin
242 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
243
244 DP_Info.Calculate_M_N
245 (Link => Link,
246 Mode => Mode,
247 Data_M => Data_M,
248 Data_N => Data_N,
249 Link_M => Link_M,
250 Link_N => Link_N);
251
252 Registers.Write
253 (Register => Head.PIPE_DATA_M1,
254 Value => PIPE_DATA_M_TU (64) or
255 Word32 (Data_M));
256 Registers.Write
257 (Register => Head.PIPE_DATA_N1,
258 Value => Word32 (Data_N));
259
260 Registers.Write
261 (Register => Head.PIPE_LINK_M1,
262 Value => Word32 (Link_M));
263 Registers.Write
264 (Register => Head.PIPE_LINK_N1,
265 Value => Word32 (Link_N));
266
267 if Config.Has_Pipe_MSA_Misc then
268 Registers.Write
269 (Register => Head.PIPE_MSA_MISC,
270 Value => PIPE_MSA_MISC_SYNC_CLK or
271 PIPE_MSA_MISC_BPC (Mode.BPC));
272 end if;
273 end Setup_Link;
274
275 ----------------------------------------------------------------------------
276
277 procedure Clear_Watermarks (Controller : Controller_Type) is
278 begin
279 Registers.Write
280 (Register => Controller.PLANE_BUF_CFG,
281 Value => 16#0000_0000#);
282 for Level in WM_Levels range 0 .. WM_Levels'Last loop
283 Registers.Write
284 (Register => Controller.PLANE_WM (Level),
285 Value => 16#0000_0000#);
286 end loop;
287 Registers.Write
288 (Register => Controller.WM_LINETIME,
289 Value => 16#0000_0000#);
290 end Clear_Watermarks;
291
292 procedure Setup_Watermarks (Controller : Controller_Type)
293 is
294 type Per_Plane_Buffer_Range is array (Controller_Kind) of Word32;
295 Buffer_Range : constant Per_Plane_Buffer_Range := Per_Plane_Buffer_Range'
296 (A => Shift_Left (159, 16) or 0,
297 B => Shift_Left (319, 16) or 160,
298 C => Shift_Left (479, 16) or 320);
299 begin
300 Registers.Write
301 (Register => Controller.PLANE_BUF_CFG,
302 Value => Buffer_Range (Controller.Kind));
303 Registers.Write
304 (Register => Controller.PLANE_WM (0),
305 Value => PLANE_WM_ENABLE or
306 PLANE_WM_LINES (2) or
307 PLANE_WM_BLOCKS (160));
308 end Setup_Watermarks;
309
310 ----------------------------------------------------------------------------
311
312 procedure Setup_Display
313 (Controller : in Controller_Type;
314 Head : in Head_Type;
315 Mode : in HW.GFX.Mode_Type;
316 Framebuffer : in HW.GFX.Framebuffer_Type)
317 with
318 Global => (In_Out => Registers.Register_State),
319 Depends =>
320 (Registers.Register_State
321 =>+
322 (Registers.Register_State,
323 Controller,
324 Head,
325 Mode,
326 Framebuffer))
327 is
328 -- FIXME: setup correct format, based on framebuffer RGB format
329 Format : constant Word32 := 6 * 2 ** 26;
330 PRI : Word32 := DSPCNTR_ENABLE or Format;
331
332 function To_Bytes (Pixels : Width_Type) return Word32
333 with
334 Pre => (Word32 (Pixels) <= Word32'Last / 4 / Word32 (BPC_Type'Last) * 8)
335 is
336 begin
337 return Word32 (Pos64 (Pixels) * 4 * Framebuffer.BPC / 8);
338 end To_Bytes;
339 begin
340 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
341
Nico Huber770fe4a2016-11-04 15:50:58 +0100342 Registers.Write
343 (Register => Controller.PIPESRC,
344 Value => Encode
345 (Pos16 (Framebuffer.Height), Pos16 (Framebuffer.Width)));
Nico Huber83693c82016-10-08 22:17:55 +0200346
347 if Config.Has_Plane_Control then
348 Setup_Watermarks (Controller);
349 Registers.Write
350 (Register => Controller.PLANE_CTL,
351 Value => PLANE_CTL_PLANE_ENABLE or
352 PLANE_CTL_SRC_PIX_FMT_RGB_32B_8888 or
353 PLANE_CTL_PLANE_GAMMA_DISABLE);
354 Registers.Write (Controller.PLANE_OFFSET, 16#0000_0000#);
355 Registers.Write (Controller.PLANE_SIZE, Encode (Mode.H_Visible, Mode.V_Visible));
356 Registers.Write (Controller.PLANE_STRIDE, To_Bytes (Framebuffer.Stride) / 64);
357 Registers.Write (Controller.PLANE_POS, 16#0000_0000#);
358 Registers.Write (Controller.PLANE_SURF, Framebuffer.Offset and 16#ffff_f000#);
359 else
360 if Config.Disable_Trickle_Feed then
361 PRI := PRI or DSPCNTR_DISABLE_TRICKLE_FEED;
362 end if;
363 -- for now, just disable gamma LUT (can't do anything
364 -- useful without colorimetry information from display)
365 Registers.Unset_And_Set_Mask
366 (Register => Controller.DSPCNTR,
367 Mask_Unset => DSPCNTR_MASK,
368 Mask_Set => PRI);
369
370 Registers.Write (Controller.DSPSTRIDE, To_Bytes (Framebuffer.Stride));
371 Registers.Write (Controller.DSPSURF, Framebuffer.Offset and 16#ffff_f000#);
372 if Config.Has_DSP_Linoff then
373 Registers.Write (Controller.DSPLINOFF, 0);
374 end if;
375 Registers.Write (Controller.DSPTILEOFF, 0);
376 end if;
377
378 Registers.Write (Head.HTOTAL, Encode (Mode.H_Visible, Mode.H_Total));
379 Registers.Write (Head.HBLANK, Encode (Mode.H_Visible, Mode.H_Total));
380 Registers.Write (Head.HSYNC, Encode (Mode.H_Sync_Begin, Mode.H_Sync_End));
381 Registers.Write (Head.VTOTAL, Encode (Mode.V_Visible, Mode.V_Total));
382 Registers.Write (Head.VBLANK, Encode (Mode.V_Visible, Mode.V_Total));
383 Registers.Write (Head.VSYNC, Encode (Mode.V_Sync_Begin, Mode.V_Sync_End));
384 end Setup_Display;
385
386 ----------------------------------------------------------------------------
387
388 procedure Setup_Head
389 (Controller : Controller_Type;
390 Head : Head_Type;
391 Port_Cfg : Port_Config;
392 Framebuffer : Framebuffer_Type)
393 is
394 PIPECONF_Options : Word32 := 0;
395 begin
396 if Config.Has_Pipe_DDI_Func then
397 Registers.Write
398 (Register => Head.PIPE_DDI_FUNC_CTL,
399 Value => PIPE_DDI_FUNC_CTL_ENABLE or
400 PIPE_DDI_FUNC_CTL_DDI_SELECT (Port_Cfg.Port) or
401 PIPE_DDI_FUNC_CTL_MODE_SELECT (Port_Cfg.Display) or
402 PIPE_DDI_FUNC_CTL_BPC (Port_Cfg.Mode.BPC) or
403 PIPE_DDI_FUNC_CTL_VSYNC (Port_Cfg.Mode.V_Sync_Active_High) or
404 PIPE_DDI_FUNC_CTL_HSYNC (Port_Cfg.Mode.H_Sync_Active_High) or
405 PIPE_DDI_FUNC_CTL_EDP_SELECT (Controller.Kind) or
406 PIPE_DDI_FUNC_CTL_PORT_WIDTH (Port_Cfg.DP.Lane_Count));
407 end if;
408
409 if Config.Has_Pipeconf_BPC then
410 PIPECONF_Options := PIPECONF_BPC_MAP (Port_Cfg.Mode.BPC);
411 end if;
412
413 -- Enable dithering if framebuffer BPC differs from connector BPC,
414 -- as smooth gradients look really bad without
415 if Framebuffer.BPC /= Port_Cfg.Mode.BPC then
416 PIPECONF_Options := PIPECONF_Options or PIPECONF_ENABLE_DITHER;
417 end if;
418
419 if not Config.Has_Pipeconf_Misc then
420 Registers.Write
421 (Register => Head.PIPECONF,
422 Value => PIPECONF_ENABLE or PIPECONF_Options);
423 else
424 Registers.Write
425 (Register => Controller.PIPEMISC,
426 Value => PIPECONF_Options);
427 Registers.Write
428 (Register => Head.PIPECONF,
429 Value => PIPECONF_ENABLE);
430 end if;
431 Registers.Posting_Read (Head.PIPECONF);
432 end Setup_Head;
433
434 ----------------------------------------------------------------------------
435
436 procedure On
437 (Controller : Controller_Type;
438 Head : Head_Type;
439 Port_Cfg : Port_Config;
440 Framebuffer : Framebuffer_Type)
441 is
442 begin
443 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
444
445 if Config.Has_Trans_Clk_Sel then
446 Registers.Write
447 (Register => Controller.TRANS_CLK_SEL,
448 Value => TRANS_CLK_SEL_PORT (Port_Cfg.Port));
449 end if;
450
451 if Port_Cfg.Is_FDI then
452 Setup_Link (Head, Port_Cfg.FDI, Port_Cfg.Mode);
453 elsif Port_Cfg.Display = DP then
454 Setup_Link (Head, Port_Cfg.DP, Port_Cfg.Mode);
455 end if;
456
457 Setup_Display (Controller, Head, Port_Cfg.Mode, Framebuffer);
458
459 Setup_Head (Controller, Head, Port_Cfg, Framebuffer);
460 end On;
461
462 ----------------------------------------------------------------------------
463
464 procedure Planes_Off (Controller : Controller_Type) is
465 begin
466 Registers.Unset_Mask (Controller.SPCNTR, SPCNTR_ENABLE);
467 if Config.Has_Plane_Control then
468 Clear_Watermarks (Controller);
469 Registers.Unset_Mask (Controller.PLANE_CTL, PLANE_CTL_PLANE_ENABLE);
470 Registers.Write (Controller.PLANE_SURF, 16#0000_0000#);
471 else
472 Registers.Unset_Mask (Controller.DSPCNTR, DSPCNTR_ENABLE);
473 end if;
474 end Planes_Off;
475
476 procedure Head_Off (Head : Head_Type)
477 is
478 Enabled : Boolean;
479 begin
480 Registers.Is_Set_Mask (Head.PIPECONF, PIPECONF_ENABLE, Enabled);
481
482 if Enabled then
483 Registers.Unset_Mask (Head.PIPECONF, PIPECONF_ENABLE);
484 end if;
485
486 -- Workaround for Broadwell:
487 -- Status may be wrong if pipe hasn't been enabled since reset.
488 if not Config.Pipe_Enabled_Workaround or else Enabled then
489 -- synchronously wait until pipe is truly off
490 Registers.Wait_Unset_Mask
491 (Register => Head.PIPECONF,
492 Mask => PIPECONF_ENABLED_STATUS,
493 TOut_MS => 40);
494 end if;
495
496 if Config.Has_Pipe_DDI_Func then
497 Registers.Write (Head.PIPE_DDI_FUNC_CTL, 0);
498 end if;
499 end Head_Off;
500
501 procedure Panel_Fitter_Off (Controller : Controller_Type) is
502 begin
503 -- Writes to WIN_SZ arm the PS/PF registers.
504 if Config.Has_Plane_Control then
505 Registers.Unset_Mask (Controller.PS_CTRL_1, PS_CTRL_ENABLE_SCALER);
506 Registers.Write (Controller.PS_WIN_SZ_1, 16#0000_0000#);
507 if Controller.PS_CTRL_2 /= Registers.Invalid_Register and
508 Controller.PS_WIN_SZ_2 /= Registers.Invalid_Register
509 then
510 Registers.Unset_Mask (Controller.PS_CTRL_2, PS_CTRL_ENABLE_SCALER);
511 Registers.Write (Controller.PS_WIN_SZ_2, 16#0000_0000#);
512 end if;
513 else
514 Registers.Unset_Mask (Controller.PF_CTL_1, PF_CTL_1_ENABLE);
515 Registers.Write (Controller.PF_WIN_SZ, 16#0000_0000#);
516 end if;
517 end Panel_Fitter_Off;
518
519 procedure Trans_Clk_Off (Controller : Controller_Type) is
520 begin
521 if Config.Has_Trans_Clk_Sel then
522 Registers.Write (Controller.TRANS_CLK_SEL, TRANS_CLK_SEL_PORT_NONE);
523 end if;
524 end Trans_Clk_Off;
525
526 procedure Off (Controller : Controller_Type; Head : Head_Type) is
527 begin
528 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
529
530 Planes_Off (Controller);
531 Head_Off (Head);
532 Panel_Fitter_Off (Controller);
533 Trans_Clk_Off (Controller);
534 end Off;
535
536 procedure All_Off
537 is
538 EDP_Enabled, EDP_Piped : Boolean;
539
540 procedure EDP_Piped_To (Kind : Controller_Kind; Piped_To : out Boolean)
541 is
542 Pipe_DDI_Func_Ctl : Word32;
543 begin
544 Registers.Read (Registers.PIPE_EDP_DDI_FUNC_CTL, Pipe_DDI_Func_Ctl);
545 Pipe_DDI_Func_Ctl :=
546 Pipe_DDI_Func_Ctl and PIPE_DDI_FUNC_CTL_EDP_SELECT_MASK;
547
548 Piped_To := (Kind = A and Pipe_DDI_Func_Ctl = PIPE_DDI_FUNC_CTL_EDP_SELECT_ALWAYS_ON) or
549 Pipe_DDI_Func_Ctl = PIPE_DDI_FUNC_CTL_EDP_SELECT_ONOFF (Kind);
550 end EDP_Piped_To;
551 begin
552 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
553
554 if Config.Has_EDP_Pipe then
555 Registers.Is_Set_Mask
556 (Registers.PIPE_EDP_CONF, PIPECONF_ENABLE, EDP_Enabled);
557 else
558 EDP_Enabled := False;
559 end if;
560
561 for Kind in Controller_Kind loop
562 Planes_Off (Controllers (Kind));
563 if EDP_Enabled then
564 EDP_Piped_To (Kind, EDP_Piped);
565 if EDP_Piped then
566 Head_Off (Heads (Head_EDP));
567 EDP_Enabled := False;
568 end if;
569 end if;
570 Head_Off (Default_Pipe_Head (Kind));
571 Panel_Fitter_Off (Controllers (Kind));
572 Trans_Clk_Off (Controllers (Kind));
573 end loop;
574
575 if EDP_Enabled then
576 Head_Off (Heads (Head_EDP));
577 end if;
578 end All_Off;
579
580 ----------------------------------------------------------------------------
581
582 procedure Update_Offset
583 (Controller : Controller_Type;
584 Framebuffer : HW.GFX.Framebuffer_Type) is
585 begin
586 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
587
588 Registers.Write (Controller.DSPSURF, Framebuffer.Offset and 16#ffff_f000#);
589 end Update_Offset;
590
591 ----------------------------------------------------------------------------
592
593 function Get_Pipe_Hint (Head : Head_Type) return Word32
594 is
595 type Pipe_Hint_Array is array (Pipe_Head) of Word32;
596 Pipe_Hint : constant Pipe_Hint_Array := Pipe_Hint_Array'
597 (Head_EDP => 0, Head_A => 0, Head_B => 1, Head_C => 2);
598 begin
599 return Pipe_Hint (Head.Head);
600 end Get_Pipe_Hint;
601
602 ----------------------------------------------------------------------------
603
604 function Default_Pipe_Head (Kind : Controller_Kind) return Head_Type
605 is
606 type Default_Head_Array is array (Controller_Kind) of Head_Type;
607 Default_Head : constant Default_Head_Array := Default_Head_Array'
608 (A => Heads (Head_A), B => Heads (Head_B), C => Heads (Head_C));
609 begin
610 return Default_Head (Kind);
611 end Default_Pipe_Head;
612
613end HW.GFX.GMA.Pipe_Setup;