2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "dce_mem_input.h"
27 #include "reg_helper.h"
28 #include "basics/conversion.h"
36 #define FN(reg_name, field_name) \
37 dce_mi->shifts->field_name, dce_mi->masks->field_name
41 unsigned int page_width
;
42 unsigned int page_height
;
43 unsigned char min_pte_before_flip_horiz_scan
;
44 unsigned char min_pte_before_flip_vert_scan
;
45 unsigned char pte_req_per_chunk
;
46 unsigned char param_6
;
47 unsigned char param_7
;
48 unsigned char param_8
;
51 enum mi_bits_per_pixel
{
59 enum mi_tiling_format
{
66 static const struct pte_setting pte_settings
[mi_tiling_count
][mi_bpp_count
] = {
67 [mi_tiling_linear
] = {
68 { 8, 4096, 1, 8, 0, 1, 0, 0, 0},
69 { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
70 { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
71 { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
74 { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */
75 { 16, 256, 8, 2, 0, 1, 0, 0, 0},
76 { 32, 128, 8, 4, 0, 1, 0, 0, 0},
77 { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
80 { 8, 64, 64, 8, 8, 1, 4, 0, 0},
81 { 16, 64, 32, 8, 16, 1, 8, 0, 0},
82 { 32, 32, 32, 16, 16, 1, 8, 0, 0},
83 { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
87 static enum mi_bits_per_pixel
get_mi_bpp(
88 enum surface_pixel_format format
)
90 if (format
>= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
)
92 else if (format
>= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
)
94 else if (format
>= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
)
100 static enum mi_tiling_format
get_mi_tiling(
101 union dc_tiling_info
*tiling_info
)
103 switch (tiling_info
->gfx8
.array_mode
) {
104 case DC_ARRAY_1D_TILED_THIN1
:
105 case DC_ARRAY_1D_TILED_THICK
:
106 case DC_ARRAY_PRT_TILED_THIN1
:
108 case DC_ARRAY_2D_TILED_THIN1
:
109 case DC_ARRAY_2D_TILED_THICK
:
110 case DC_ARRAY_2D_TILED_X_THICK
:
111 case DC_ARRAY_PRT_2D_TILED_THIN1
:
112 case DC_ARRAY_PRT_2D_TILED_THICK
:
114 case DC_ARRAY_LINEAR_GENERAL
:
115 case DC_ARRAY_LINEAR_ALLIGNED
:
116 return mi_tiling_linear
;
122 static bool is_vert_scan(enum dc_rotation_angle rotation
)
125 case ROTATION_ANGLE_90
:
126 case ROTATION_ANGLE_270
:
133 static void dce_mi_program_pte_vm(
134 struct mem_input
*mi
,
135 enum surface_pixel_format format
,
136 union dc_tiling_info
*tiling_info
,
137 enum dc_rotation_angle rotation
)
139 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
140 enum mi_bits_per_pixel mi_bpp
= get_mi_bpp(format
);
141 enum mi_tiling_format mi_tiling
= get_mi_tiling(tiling_info
);
142 const struct pte_setting
*pte
= &pte_settings
[mi_tiling
][mi_bpp
];
144 unsigned int page_width
= log_2(pte
->page_width
);
145 unsigned int page_height
= log_2(pte
->page_height
);
146 unsigned int min_pte_before_flip
= is_vert_scan(rotation
) ?
147 pte
->min_pte_before_flip_vert_scan
:
148 pte
->min_pte_before_flip_horiz_scan
;
150 REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT
,
151 GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT
, 0x7f);
153 REG_UPDATE_3(DVMM_PTE_CONTROL
,
154 DVMM_PAGE_WIDTH
, page_width
,
155 DVMM_PAGE_HEIGHT
, page_height
,
156 DVMM_MIN_PTE_BEFORE_FLIP
, min_pte_before_flip
);
158 REG_UPDATE_2(DVMM_PTE_ARB_CONTROL
,
159 DVMM_PTE_REQ_PER_CHUNK
, pte
->pte_req_per_chunk
,
160 DVMM_MAX_PTE_REQ_OUTSTANDING
, 0x7f);
163 static void program_urgency_watermark(
164 struct dce_mem_input
*dce_mi
,
166 uint32_t urgency_low_wm
,
167 uint32_t urgency_high_wm
)
169 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
170 URGENCY_WATERMARK_MASK
, wm_select
);
172 REG_SET_2(DPG_PIPE_URGENCY_CONTROL
, 0,
173 URGENCY_LOW_WATERMARK
, urgency_low_wm
,
174 URGENCY_HIGH_WATERMARK
, urgency_high_wm
);
177 static void dce120_program_urgency_watermark(
178 struct dce_mem_input
*dce_mi
,
180 uint32_t urgency_low_wm
,
181 uint32_t urgency_high_wm
)
183 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
184 URGENCY_WATERMARK_MASK
, wm_select
);
186 REG_SET_2(DPG_PIPE_URGENCY_CONTROL
, 0,
187 URGENCY_LOW_WATERMARK
, urgency_low_wm
,
188 URGENCY_HIGH_WATERMARK
, urgency_high_wm
);
190 REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL
, 0,
191 URGENT_LEVEL_LOW_WATERMARK
, urgency_low_wm
,
192 URGENT_LEVEL_HIGH_WATERMARK
, urgency_high_wm
);
196 static void program_nbp_watermark(
197 struct dce_mem_input
*dce_mi
,
201 if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL
)) {
202 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
203 NB_PSTATE_CHANGE_WATERMARK_MASK
, wm_select
);
205 REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL
,
206 NB_PSTATE_CHANGE_ENABLE
, 1,
207 NB_PSTATE_CHANGE_URGENT_DURING_REQUEST
, 1,
208 NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST
, 1);
210 REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL
,
211 NB_PSTATE_CHANGE_WATERMARK
, nbp_wm
);
214 if (REG(DPG_PIPE_LOW_POWER_CONTROL
)) {
215 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
216 PSTATE_CHANGE_WATERMARK_MASK
, wm_select
);
218 REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL
,
219 PSTATE_CHANGE_ENABLE
, 1,
220 PSTATE_CHANGE_URGENT_DURING_REQUEST
, 1,
221 PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST
, 1);
223 REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL
,
224 PSTATE_CHANGE_WATERMARK
, nbp_wm
);
228 static void dce120_program_stutter_watermark(
229 struct dce_mem_input
*dce_mi
,
231 uint32_t stutter_mark
,
232 uint32_t stutter_entry
)
234 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
235 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK
, wm_select
);
237 if (REG(DPG_PIPE_STUTTER_CONTROL2
))
238 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2
,
239 STUTTER_EXIT_SELF_REFRESH_WATERMARK
, stutter_mark
,
240 STUTTER_ENTER_SELF_REFRESH_WATERMARK
, stutter_entry
);
242 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL
,
243 STUTTER_EXIT_SELF_REFRESH_WATERMARK
, stutter_mark
,
244 STUTTER_ENTER_SELF_REFRESH_WATERMARK
, stutter_entry
);
247 static void program_stutter_watermark(
248 struct dce_mem_input
*dce_mi
,
250 uint32_t stutter_mark
)
252 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL
,
253 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK
, wm_select
);
255 if (REG(DPG_PIPE_STUTTER_CONTROL2
))
256 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2
,
257 STUTTER_EXIT_SELF_REFRESH_WATERMARK
, stutter_mark
);
259 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL
,
260 STUTTER_EXIT_SELF_REFRESH_WATERMARK
, stutter_mark
);
263 static void dce_mi_program_display_marks(
264 struct mem_input
*mi
,
265 struct dce_watermarks nbp
,
266 struct dce_watermarks stutter_exit
,
267 struct dce_watermarks stutter_enter
,
268 struct dce_watermarks urgent
,
269 uint32_t total_dest_line_time_ns
)
271 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
272 uint32_t stutter_en
= mi
->ctx
->dc
->debug
.disable_stutter
? 0 : 1;
274 program_urgency_watermark(dce_mi
, 2, /* set a */
275 urgent
.a_mark
, total_dest_line_time_ns
);
276 program_urgency_watermark(dce_mi
, 1, /* set d */
277 urgent
.d_mark
, total_dest_line_time_ns
);
279 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL
,
280 STUTTER_ENABLE
, stutter_en
,
281 STUTTER_IGNORE_FBC
, 1);
282 program_nbp_watermark(dce_mi
, 2, nbp
.a_mark
); /* set a */
283 program_nbp_watermark(dce_mi
, 1, nbp
.d_mark
); /* set d */
285 program_stutter_watermark(dce_mi
, 2, stutter_exit
.a_mark
); /* set a */
286 program_stutter_watermark(dce_mi
, 1, stutter_exit
.d_mark
); /* set d */
289 static void dce112_mi_program_display_marks(struct mem_input
*mi
,
290 struct dce_watermarks nbp
,
291 struct dce_watermarks stutter_exit
,
292 struct dce_watermarks stutter_entry
,
293 struct dce_watermarks urgent
,
294 uint32_t total_dest_line_time_ns
)
296 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
297 uint32_t stutter_en
= mi
->ctx
->dc
->debug
.disable_stutter
? 0 : 1;
299 program_urgency_watermark(dce_mi
, 0, /* set a */
300 urgent
.a_mark
, total_dest_line_time_ns
);
301 program_urgency_watermark(dce_mi
, 1, /* set b */
302 urgent
.b_mark
, total_dest_line_time_ns
);
303 program_urgency_watermark(dce_mi
, 2, /* set c */
304 urgent
.c_mark
, total_dest_line_time_ns
);
305 program_urgency_watermark(dce_mi
, 3, /* set d */
306 urgent
.d_mark
, total_dest_line_time_ns
);
308 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL
,
309 STUTTER_ENABLE
, stutter_en
,
310 STUTTER_IGNORE_FBC
, 1);
311 program_nbp_watermark(dce_mi
, 0, nbp
.a_mark
); /* set a */
312 program_nbp_watermark(dce_mi
, 1, nbp
.b_mark
); /* set b */
313 program_nbp_watermark(dce_mi
, 2, nbp
.c_mark
); /* set c */
314 program_nbp_watermark(dce_mi
, 3, nbp
.d_mark
); /* set d */
316 program_stutter_watermark(dce_mi
, 0, stutter_exit
.a_mark
); /* set a */
317 program_stutter_watermark(dce_mi
, 1, stutter_exit
.b_mark
); /* set b */
318 program_stutter_watermark(dce_mi
, 2, stutter_exit
.c_mark
); /* set c */
319 program_stutter_watermark(dce_mi
, 3, stutter_exit
.d_mark
); /* set d */
322 static void dce120_mi_program_display_marks(struct mem_input
*mi
,
323 struct dce_watermarks nbp
,
324 struct dce_watermarks stutter_exit
,
325 struct dce_watermarks stutter_entry
,
326 struct dce_watermarks urgent
,
327 uint32_t total_dest_line_time_ns
)
329 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
330 uint32_t stutter_en
= mi
->ctx
->dc
->debug
.disable_stutter
? 0 : 1;
332 dce120_program_urgency_watermark(dce_mi
, 0, /* set a */
333 urgent
.a_mark
, total_dest_line_time_ns
);
334 dce120_program_urgency_watermark(dce_mi
, 1, /* set b */
335 urgent
.b_mark
, total_dest_line_time_ns
);
336 dce120_program_urgency_watermark(dce_mi
, 2, /* set c */
337 urgent
.c_mark
, total_dest_line_time_ns
);
338 dce120_program_urgency_watermark(dce_mi
, 3, /* set d */
339 urgent
.d_mark
, total_dest_line_time_ns
);
341 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL
,
342 STUTTER_ENABLE
, stutter_en
,
343 STUTTER_IGNORE_FBC
, 1);
344 program_nbp_watermark(dce_mi
, 0, nbp
.a_mark
); /* set a */
345 program_nbp_watermark(dce_mi
, 1, nbp
.b_mark
); /* set b */
346 program_nbp_watermark(dce_mi
, 2, nbp
.c_mark
); /* set c */
347 program_nbp_watermark(dce_mi
, 3, nbp
.d_mark
); /* set d */
349 dce120_program_stutter_watermark(dce_mi
, 0, stutter_exit
.a_mark
, stutter_entry
.a_mark
); /* set a */
350 dce120_program_stutter_watermark(dce_mi
, 1, stutter_exit
.b_mark
, stutter_entry
.b_mark
); /* set b */
351 dce120_program_stutter_watermark(dce_mi
, 2, stutter_exit
.c_mark
, stutter_entry
.c_mark
); /* set c */
352 dce120_program_stutter_watermark(dce_mi
, 3, stutter_exit
.d_mark
, stutter_entry
.d_mark
); /* set d */
355 static void program_tiling(
356 struct dce_mem_input
*dce_mi
, const union dc_tiling_info
*info
)
358 if (dce_mi
->masks
->GRPH_SW_MODE
) { /* GFX9 */
359 REG_UPDATE_6(GRPH_CONTROL
,
360 GRPH_SW_MODE
, info
->gfx9
.swizzle
,
361 GRPH_NUM_BANKS
, log_2(info
->gfx9
.num_banks
),
362 GRPH_NUM_SHADER_ENGINES
, log_2(info
->gfx9
.num_shader_engines
),
363 GRPH_NUM_PIPES
, log_2(info
->gfx9
.num_pipes
),
364 GRPH_COLOR_EXPANSION_MODE
, 1,
365 GRPH_SE_ENABLE
, info
->gfx9
.shaderEnable
);
366 /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
372 if (dce_mi
->masks
->GRPH_ARRAY_MODE
) { /* GFX8 */
373 REG_UPDATE_9(GRPH_CONTROL
,
374 GRPH_NUM_BANKS
, info
->gfx8
.num_banks
,
375 GRPH_BANK_WIDTH
, info
->gfx8
.bank_width
,
376 GRPH_BANK_HEIGHT
, info
->gfx8
.bank_height
,
377 GRPH_MACRO_TILE_ASPECT
, info
->gfx8
.tile_aspect
,
378 GRPH_TILE_SPLIT
, info
->gfx8
.tile_split
,
379 GRPH_MICRO_TILE_MODE
, info
->gfx8
.tile_mode
,
380 GRPH_PIPE_CONFIG
, info
->gfx8
.pipe_config
,
381 GRPH_ARRAY_MODE
, info
->gfx8
.array_mode
,
382 GRPH_COLOR_EXPANSION_MODE
, 1);
383 /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
391 static void program_size_and_rotation(
392 struct dce_mem_input
*dce_mi
,
393 enum dc_rotation_angle rotation
,
394 const struct plane_size
*plane_size
)
396 const struct rect
*in_rect
= &plane_size
->surface_size
;
397 struct rect hw_rect
= plane_size
->surface_size
;
398 const uint32_t rotation_angles
[ROTATION_ANGLE_COUNT
] = {
399 [ROTATION_ANGLE_0
] = 0,
400 [ROTATION_ANGLE_90
] = 1,
401 [ROTATION_ANGLE_180
] = 2,
402 [ROTATION_ANGLE_270
] = 3,
405 if (rotation
== ROTATION_ANGLE_90
|| rotation
== ROTATION_ANGLE_270
) {
406 hw_rect
.x
= in_rect
->y
;
407 hw_rect
.y
= in_rect
->x
;
409 hw_rect
.height
= in_rect
->width
;
410 hw_rect
.width
= in_rect
->height
;
413 REG_SET(GRPH_X_START
, 0,
414 GRPH_X_START
, hw_rect
.x
);
416 REG_SET(GRPH_Y_START
, 0,
417 GRPH_Y_START
, hw_rect
.y
);
419 REG_SET(GRPH_X_END
, 0,
420 GRPH_X_END
, hw_rect
.width
);
422 REG_SET(GRPH_Y_END
, 0,
423 GRPH_Y_END
, hw_rect
.height
);
425 REG_SET(GRPH_PITCH
, 0,
426 GRPH_PITCH
, plane_size
->surface_pitch
);
428 REG_SET(HW_ROTATION
, 0,
429 GRPH_ROTATION_ANGLE
, rotation_angles
[rotation
]);
432 static void program_grph_pixel_format(
433 struct dce_mem_input
*dce_mi
,
434 enum surface_pixel_format format
)
436 uint32_t red_xbar
= 0, blue_xbar
= 0; /* no swap */
437 uint32_t grph_depth
= 0, grph_format
= 0;
438 uint32_t sign
= 0, floating
= 0;
440 if (format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
||
441 /*todo: doesn't look like we handle BGRA here,
442 * should problem swap endian*/
443 format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
||
444 format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
||
445 format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
) {
451 REG_SET_2(GRPH_SWAP_CNTL
, 0,
452 GRPH_RED_CROSSBAR
, red_xbar
,
453 GRPH_BLUE_CROSSBAR
, blue_xbar
);
456 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS
:
460 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
464 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
468 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
469 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
473 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
474 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
475 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
:
479 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
483 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
: /* shouldn't this get float too? */
484 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
489 DC_ERR("unsupported grph pixel format");
493 REG_UPDATE_2(GRPH_CONTROL
,
494 GRPH_DEPTH
, grph_depth
,
495 GRPH_FORMAT
, grph_format
);
497 REG_UPDATE_4(PRESCALE_GRPH_CONTROL
,
498 GRPH_PRESCALE_SELECT
, floating
,
499 GRPH_PRESCALE_R_SIGN
, sign
,
500 GRPH_PRESCALE_G_SIGN
, sign
,
501 GRPH_PRESCALE_B_SIGN
, sign
);
504 static void dce_mi_program_surface_config(
505 struct mem_input
*mi
,
506 enum surface_pixel_format format
,
507 union dc_tiling_info
*tiling_info
,
508 struct plane_size
*plane_size
,
509 enum dc_rotation_angle rotation
,
510 struct dc_plane_dcc_param
*dcc
,
511 bool horizontal_mirror
)
513 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
514 REG_UPDATE(GRPH_ENABLE
, GRPH_ENABLE
, 1);
516 program_tiling(dce_mi
, tiling_info
);
517 program_size_and_rotation(dce_mi
, rotation
, plane_size
);
519 if (format
>= SURFACE_PIXEL_FORMAT_GRPH_BEGIN
&&
520 format
< SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
)
521 program_grph_pixel_format(dce_mi
, format
);
524 static uint32_t get_dmif_switch_time_us(
527 uint32_t pix_clk_khz
)
530 uint32_t pixels_per_second
;
531 uint32_t pixels_per_frame
;
532 uint32_t refresh_rate
;
533 const uint32_t us_in_sec
= 1000000;
534 const uint32_t min_single_frame_time_us
= 30000;
535 /*return double of frame time*/
536 const uint32_t single_frame_time_multiplier
= 2;
538 if (!h_total
|| v_total
|| !pix_clk_khz
)
539 return single_frame_time_multiplier
* min_single_frame_time_us
;
541 /*TODO: should we use pixel format normalized pixel clock here?*/
542 pixels_per_second
= pix_clk_khz
* 1000;
543 pixels_per_frame
= h_total
* v_total
;
545 if (!pixels_per_second
|| !pixels_per_frame
) {
546 /* avoid division by zero */
547 ASSERT(pixels_per_frame
);
548 ASSERT(pixels_per_second
);
549 return single_frame_time_multiplier
* min_single_frame_time_us
;
552 refresh_rate
= pixels_per_second
/ pixels_per_frame
;
555 /* avoid division by zero*/
556 ASSERT(refresh_rate
);
557 return single_frame_time_multiplier
* min_single_frame_time_us
;
560 frame_time
= us_in_sec
/ refresh_rate
;
562 if (frame_time
< min_single_frame_time_us
)
563 frame_time
= min_single_frame_time_us
;
565 frame_time
*= single_frame_time_multiplier
;
570 static void dce_mi_allocate_dmif(
571 struct mem_input
*mi
,
574 uint32_t pix_clk_khz
,
575 uint32_t total_stream_num
)
577 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
578 const uint32_t retry_delay
= 10;
579 uint32_t retry_count
= get_dmif_switch_time_us(
582 pix_clk_khz
) / retry_delay
;
585 uint32_t buffers_allocated
;
586 uint32_t dmif_buffer_control
;
588 dmif_buffer_control
= REG_GET(DMIF_BUFFER_CONTROL
,
589 DMIF_BUFFERS_ALLOCATED
, &buffers_allocated
);
591 if (buffers_allocated
== 2)
594 REG_SET(DMIF_BUFFER_CONTROL
, dmif_buffer_control
,
595 DMIF_BUFFERS_ALLOCATED
, 2);
597 REG_WAIT(DMIF_BUFFER_CONTROL
,
598 DMIF_BUFFERS_ALLOCATION_COMPLETED
, 1,
599 retry_delay
, retry_count
);
601 if (pix_clk_khz
!= 0) {
602 pix_dur
= 1000000000ULL / pix_clk_khz
;
604 REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1
,
605 PIXEL_DURATION
, pix_dur
);
608 if (dce_mi
->wa
.single_head_rdreq_dmif_limit
) {
609 uint32_t enable
= (total_stream_num
> 1) ? 0 :
610 dce_mi
->wa
.single_head_rdreq_dmif_limit
;
612 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT
,
617 static void dce_mi_free_dmif(
618 struct mem_input
*mi
,
619 uint32_t total_stream_num
)
621 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mi
);
622 uint32_t buffers_allocated
;
623 uint32_t dmif_buffer_control
;
625 dmif_buffer_control
= REG_GET(DMIF_BUFFER_CONTROL
,
626 DMIF_BUFFERS_ALLOCATED
, &buffers_allocated
);
628 if (buffers_allocated
== 0)
631 REG_SET(DMIF_BUFFER_CONTROL
, dmif_buffer_control
,
632 DMIF_BUFFERS_ALLOCATED
, 0);
634 REG_WAIT(DMIF_BUFFER_CONTROL
,
635 DMIF_BUFFERS_ALLOCATION_COMPLETED
, 1,
638 if (dce_mi
->wa
.single_head_rdreq_dmif_limit
) {
639 uint32_t enable
= (total_stream_num
> 1) ? 0 :
640 dce_mi
->wa
.single_head_rdreq_dmif_limit
;
642 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT
,
648 static void program_sec_addr(
649 struct dce_mem_input
*dce_mi
,
650 PHYSICAL_ADDRESS_LOC address
)
652 /*high register MUST be programmed first*/
653 REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH
, 0,
654 GRPH_SECONDARY_SURFACE_ADDRESS_HIGH
,
657 REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS
, 0,
658 GRPH_SECONDARY_SURFACE_ADDRESS
, address
.low_part
>> 8,
659 GRPH_SECONDARY_DFQ_ENABLE
, 0);
662 static void program_pri_addr(
663 struct dce_mem_input
*dce_mi
,
664 PHYSICAL_ADDRESS_LOC address
)
666 /*high register MUST be programmed first*/
667 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH
, 0,
668 GRPH_PRIMARY_SURFACE_ADDRESS_HIGH
,
671 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS
, 0,
672 GRPH_PRIMARY_SURFACE_ADDRESS
,
673 address
.low_part
>> 8);
677 static bool dce_mi_is_flip_pending(struct mem_input
*mem_input
)
679 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mem_input
);
680 uint32_t update_pending
;
682 REG_GET(GRPH_UPDATE
, GRPH_SURFACE_UPDATE_PENDING
, &update_pending
);
686 mem_input
->current_address
= mem_input
->request_address
;
690 static bool dce_mi_program_surface_flip_and_addr(
691 struct mem_input
*mem_input
,
692 const struct dc_plane_address
*address
,
695 struct dce_mem_input
*dce_mi
= TO_DCE_MEM_INPUT(mem_input
);
697 REG_UPDATE(GRPH_UPDATE
, GRPH_UPDATE_LOCK
, 1);
701 GRPH_SURFACE_UPDATE_H_RETRACE_EN
, flip_immediate
? 1 : 0);
703 switch (address
->type
) {
704 case PLN_ADDR_TYPE_GRAPHICS
:
705 if (address
->grph
.addr
.quad_part
== 0)
707 program_pri_addr(dce_mi
, address
->grph
.addr
);
709 case PLN_ADDR_TYPE_GRPH_STEREO
:
710 if (address
->grph_stereo
.left_addr
.quad_part
== 0 ||
711 address
->grph_stereo
.right_addr
.quad_part
== 0)
713 program_pri_addr(dce_mi
, address
->grph_stereo
.left_addr
);
714 program_sec_addr(dce_mi
, address
->grph_stereo
.right_addr
);
722 mem_input
->request_address
= *address
;
725 mem_input
->current_address
= *address
;
727 REG_UPDATE(GRPH_UPDATE
, GRPH_UPDATE_LOCK
, 0);
732 static const struct mem_input_funcs dce_mi_funcs
= {
733 .mem_input_program_display_marks
= dce_mi_program_display_marks
,
734 .allocate_mem_input
= dce_mi_allocate_dmif
,
735 .free_mem_input
= dce_mi_free_dmif
,
736 .mem_input_program_surface_flip_and_addr
=
737 dce_mi_program_surface_flip_and_addr
,
738 .mem_input_program_pte_vm
= dce_mi_program_pte_vm
,
739 .mem_input_program_surface_config
=
740 dce_mi_program_surface_config
,
741 .mem_input_is_flip_pending
= dce_mi_is_flip_pending
744 static const struct mem_input_funcs dce112_mi_funcs
= {
745 .mem_input_program_display_marks
= dce112_mi_program_display_marks
,
746 .allocate_mem_input
= dce_mi_allocate_dmif
,
747 .free_mem_input
= dce_mi_free_dmif
,
748 .mem_input_program_surface_flip_and_addr
=
749 dce_mi_program_surface_flip_and_addr
,
750 .mem_input_program_pte_vm
= dce_mi_program_pte_vm
,
751 .mem_input_program_surface_config
=
752 dce_mi_program_surface_config
,
753 .mem_input_is_flip_pending
= dce_mi_is_flip_pending
756 static const struct mem_input_funcs dce120_mi_funcs
= {
757 .mem_input_program_display_marks
= dce120_mi_program_display_marks
,
758 .allocate_mem_input
= dce_mi_allocate_dmif
,
759 .free_mem_input
= dce_mi_free_dmif
,
760 .mem_input_program_surface_flip_and_addr
=
761 dce_mi_program_surface_flip_and_addr
,
762 .mem_input_program_pte_vm
= dce_mi_program_pte_vm
,
763 .mem_input_program_surface_config
=
764 dce_mi_program_surface_config
,
765 .mem_input_is_flip_pending
= dce_mi_is_flip_pending
768 void dce_mem_input_construct(
769 struct dce_mem_input
*dce_mi
,
770 struct dc_context
*ctx
,
772 const struct dce_mem_input_registers
*regs
,
773 const struct dce_mem_input_shift
*mi_shift
,
774 const struct dce_mem_input_mask
*mi_mask
)
776 dce_mi
->base
.ctx
= ctx
;
778 dce_mi
->base
.inst
= inst
;
779 dce_mi
->base
.funcs
= &dce_mi_funcs
;
782 dce_mi
->shifts
= mi_shift
;
783 dce_mi
->masks
= mi_mask
;
786 void dce112_mem_input_construct(
787 struct dce_mem_input
*dce_mi
,
788 struct dc_context
*ctx
,
790 const struct dce_mem_input_registers
*regs
,
791 const struct dce_mem_input_shift
*mi_shift
,
792 const struct dce_mem_input_mask
*mi_mask
)
794 dce_mem_input_construct(dce_mi
, ctx
, inst
, regs
, mi_shift
, mi_mask
);
795 dce_mi
->base
.funcs
= &dce112_mi_funcs
;
798 void dce120_mem_input_construct(
799 struct dce_mem_input
*dce_mi
,
800 struct dc_context
*ctx
,
802 const struct dce_mem_input_registers
*regs
,
803 const struct dce_mem_input_shift
*mi_shift
,
804 const struct dce_mem_input_mask
*mi_mask
)
806 dce_mem_input_construct(dce_mi
, ctx
, inst
, regs
, mi_shift
, mi_mask
);
807 dce_mi
->base
.funcs
= &dce120_mi_funcs
;