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