1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright 2023 Advanced Micro Devices, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#include "dml_display_rq_dlg_calc.h"
26#include "display_mode_core.h"
27#include "display_mode_util.h"
28
29static dml_bool_t is_dual_plane(enum dml_source_format_class source_format)
30{
31 dml_bool_t ret_val = 0;
32
33 if ((source_format == dml_420_12) || (source_format == dml_420_8) || (source_format == dml_420_10) || (source_format == dml_rgbe_alpha))
34 ret_val = 1;
35
36 return ret_val;
37}
38
39void dml_rq_dlg_get_rq_reg(dml_display_rq_regs_st *rq_regs,
40 struct display_mode_lib_st *mode_lib,
41 const dml_uint_t pipe_idx)
42{
43 dml_uint_t plane_idx = dml_get_plane_idx(mode_lib, pipe_idx);
44 enum dml_source_format_class source_format = mode_lib->ms.cache_display_cfg.surface.SourcePixelFormat[plane_idx];
45 enum dml_swizzle_mode sw_mode = mode_lib->ms.cache_display_cfg.surface.SurfaceTiling[plane_idx];
46 dml_bool_t dual_plane = is_dual_plane(source_format: (enum dml_source_format_class)(source_format));
47
48 uint32 pixel_chunk_bytes = 0;
49 uint32 min_pixel_chunk_bytes = 0;
50 uint32 meta_chunk_bytes = 0;
51 uint32 min_meta_chunk_bytes = 0;
52 uint32 dpte_group_bytes = 0;
53 uint32 mpte_group_bytes = 0;
54
55 uint32 p1_pixel_chunk_bytes = 0;
56 uint32 p1_min_pixel_chunk_bytes = 0;
57 uint32 p1_meta_chunk_bytes = 0;
58 uint32 p1_min_meta_chunk_bytes = 0;
59 uint32 p1_dpte_group_bytes = 0;
60 uint32 p1_mpte_group_bytes = 0;
61
62 dml_uint_t detile_buf_size_in_bytes;
63 dml_uint_t detile_buf_plane1_addr = 0;
64
65 dml_float_t stored_swath_l_bytes;
66 dml_float_t stored_swath_c_bytes;
67 dml_bool_t is_phantom_pipe;
68
69 dml_uint_t pte_row_height_linear;
70
71 dml_print("DML_DLG::%s: Calculation for pipe[%d] start\n", __func__, pipe_idx);
72
73 memset(rq_regs, 0, sizeof(*rq_regs));
74
75 pixel_chunk_bytes = (dml_uint_t)(dml_get_pixel_chunk_size_in_kbyte(mode_lib) * 1024);
76 min_pixel_chunk_bytes = (dml_uint_t)(dml_get_min_pixel_chunk_size_in_byte(mode_lib));
77
78 if (pixel_chunk_bytes == 64 * 1024)
79 min_pixel_chunk_bytes = 0;
80
81 meta_chunk_bytes = (dml_uint_t)(dml_get_meta_chunk_size_in_kbyte(mode_lib) * 1024);
82 min_meta_chunk_bytes = (dml_uint_t)(dml_get_min_meta_chunk_size_in_byte(mode_lib));
83
84 dpte_group_bytes = (dml_uint_t)(dml_get_dpte_group_size_in_bytes(mode_lib, surface_idx: pipe_idx));
85 mpte_group_bytes = (dml_uint_t)(dml_get_vm_group_size_in_bytes(mode_lib, surface_idx: pipe_idx));
86
87 p1_pixel_chunk_bytes = pixel_chunk_bytes;
88 p1_min_pixel_chunk_bytes = min_pixel_chunk_bytes;
89 p1_meta_chunk_bytes = meta_chunk_bytes;
90 p1_min_meta_chunk_bytes = min_meta_chunk_bytes;
91 p1_dpte_group_bytes = dpte_group_bytes;
92 p1_mpte_group_bytes = mpte_group_bytes;
93
94 if (source_format == dml_rgbe_alpha)
95 p1_pixel_chunk_bytes = (dml_uint_t)(dml_get_alpha_pixel_chunk_size_in_kbyte(mode_lib) * 1024);
96
97 rq_regs->rq_regs_l.chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) pixel_chunk_bytes) - 10);
98 rq_regs->rq_regs_c.chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_pixel_chunk_bytes) - 10);
99
100 if (min_pixel_chunk_bytes == 0)
101 rq_regs->rq_regs_l.min_chunk_size = 0;
102 else
103 rq_regs->rq_regs_l.min_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) min_pixel_chunk_bytes) - 8 + 1);
104
105 if (p1_min_pixel_chunk_bytes == 0)
106 rq_regs->rq_regs_c.min_chunk_size = 0;
107 else
108 rq_regs->rq_regs_c.min_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_min_pixel_chunk_bytes) - 8 + 1);
109
110 rq_regs->rq_regs_l.meta_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) meta_chunk_bytes) - 10);
111 rq_regs->rq_regs_c.meta_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_meta_chunk_bytes) - 10);
112
113 if (min_meta_chunk_bytes == 0)
114 rq_regs->rq_regs_l.min_meta_chunk_size = 0;
115 else
116 rq_regs->rq_regs_l.min_meta_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) min_meta_chunk_bytes) - 6 + 1);
117
118 if (min_meta_chunk_bytes == 0)
119 rq_regs->rq_regs_c.min_meta_chunk_size = 0;
120 else
121 rq_regs->rq_regs_c.min_meta_chunk_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_min_meta_chunk_bytes) - 6 + 1);
122
123 rq_regs->rq_regs_l.dpte_group_size = (dml_uint_t)(dml_log2(x: (dml_float_t) dpte_group_bytes) - 6);
124 rq_regs->rq_regs_l.mpte_group_size = (dml_uint_t)(dml_log2(x: (dml_float_t) mpte_group_bytes) - 6);
125 rq_regs->rq_regs_c.dpte_group_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_dpte_group_bytes) - 6);
126 rq_regs->rq_regs_c.mpte_group_size = (dml_uint_t)(dml_log2(x: (dml_float_t) p1_mpte_group_bytes) - 6);
127
128 detile_buf_size_in_bytes = (dml_uint_t)(dml_get_det_buffer_size_kbytes(mode_lib, surface_idx: pipe_idx) * 1024);
129
130 pte_row_height_linear = (dml_uint_t)(dml_get_dpte_row_height_linear_l(mode_lib, surface_idx: pipe_idx));
131
132 if (sw_mode == dml_sw_linear)
133 ASSERT(pte_row_height_linear >= 8);
134
135 rq_regs->rq_regs_l.pte_row_height_linear = (dml_uint_t)(dml_floor(x: dml_log2(x: (dml_float_t) pte_row_height_linear), granularity: 1) - 3);
136
137 if (dual_plane) {
138 dml_uint_t p1_pte_row_height_linear = (dml_uint_t)(dml_get_dpte_row_height_linear_c(mode_lib, surface_idx: pipe_idx));
139 if (sw_mode == dml_sw_linear)
140 ASSERT(p1_pte_row_height_linear >= 8);
141
142 rq_regs->rq_regs_c.pte_row_height_linear = (dml_uint_t)(dml_floor(x: dml_log2(x: (dml_float_t) p1_pte_row_height_linear), granularity: 1) - 3);
143 }
144
145 rq_regs->rq_regs_l.swath_height = (dml_uint_t)(dml_log2(x: (dml_float_t) dml_get_swath_height_l(mode_lib, surface_idx: pipe_idx)));
146 rq_regs->rq_regs_c.swath_height = (dml_uint_t)(dml_log2(x: (dml_float_t) dml_get_swath_height_c(mode_lib, surface_idx: pipe_idx)));
147
148 if (pixel_chunk_bytes >= 32 * 1024 || (dual_plane && p1_pixel_chunk_bytes >= 32 * 1024)) { //32kb
149 rq_regs->drq_expansion_mode = 0;
150 } else {
151 rq_regs->drq_expansion_mode = 2;
152 }
153 rq_regs->prq_expansion_mode = 1;
154 rq_regs->mrq_expansion_mode = 1;
155 rq_regs->crq_expansion_mode = 1;
156
157 stored_swath_l_bytes = dml_get_det_stored_buffer_size_l_bytes(mode_lib, surface_idx: pipe_idx);
158 stored_swath_c_bytes = dml_get_det_stored_buffer_size_c_bytes(mode_lib, surface_idx: pipe_idx);
159 is_phantom_pipe = dml_get_is_phantom_pipe(mode_lib, pipe_idx);
160
161 // Note: detile_buf_plane1_addr is in unit of 1KB
162 if (dual_plane) {
163 if (is_phantom_pipe) {
164 detile_buf_plane1_addr = (dml_uint_t)((1024.0*1024.0) / 2.0 / 1024.0); // half to chroma
165 } else {
166 if (stored_swath_l_bytes / stored_swath_c_bytes <= 1.5) {
167 detile_buf_plane1_addr = (dml_uint_t)(detile_buf_size_in_bytes / 2.0 / 1024.0); // half to chroma
168#ifdef __DML_VBA_DEBUG__
169 dml_print("DML_DLG: %s: detile_buf_plane1_addr = %d (1/2 to chroma)\n", __func__, detile_buf_plane1_addr);
170#endif
171 } else {
172 detile_buf_plane1_addr = (dml_uint_t)(dml_round_to_multiple(num: (dml_uint_t)((2.0 * detile_buf_size_in_bytes) / 3.0), multiple: 1024, up: 0) / 1024.0); // 2/3 to luma
173#ifdef __DML_VBA_DEBUG__
174 dml_print("DML_DLG: %s: detile_buf_plane1_addr = %d (1/3 chroma)\n", __func__, detile_buf_plane1_addr);
175#endif
176 }
177 }
178 }
179 rq_regs->plane1_base_address = detile_buf_plane1_addr;
180
181#ifdef __DML_VBA_DEBUG__
182 dml_print("DML_DLG: %s: is_phantom_pipe = %d\n", __func__, is_phantom_pipe);
183 dml_print("DML_DLG: %s: stored_swath_l_bytes = %f\n", __func__, stored_swath_l_bytes);
184 dml_print("DML_DLG: %s: stored_swath_c_bytes = %f\n", __func__, stored_swath_c_bytes);
185 dml_print("DML_DLG: %s: detile_buf_size_in_bytes = %d\n", __func__, detile_buf_size_in_bytes);
186 dml_print("DML_DLG: %s: detile_buf_plane1_addr = %d\n", __func__, detile_buf_plane1_addr);
187 dml_print("DML_DLG: %s: plane1_base_address = %d\n", __func__, rq_regs->plane1_base_address);
188#endif
189 dml_print_rq_regs_st(rq_regs);
190 dml_print("DML_DLG::%s: Calculation for pipe[%d] done\n", __func__, pipe_idx);
191}
192
193// Note: currently taken in as is.
194// Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma.
195
196
197void dml_rq_dlg_get_dlg_reg(dml_display_dlg_regs_st *disp_dlg_regs,
198 dml_display_ttu_regs_st *disp_ttu_regs,
199 struct display_mode_lib_st *mode_lib,
200 const dml_uint_t pipe_idx)
201{
202 dml_uint_t plane_idx = dml_get_plane_idx(mode_lib, pipe_idx);
203 enum dml_source_format_class source_format = mode_lib->ms.cache_display_cfg.surface.SourcePixelFormat[plane_idx];
204 struct dml_timing_cfg_st *timing = &mode_lib->ms.cache_display_cfg.timing;
205 struct dml_plane_cfg_st *plane = &mode_lib->ms.cache_display_cfg.plane;
206 struct dml_hw_resource_st *hw = &mode_lib->ms.cache_display_cfg.hw;
207 dml_bool_t dual_plane = is_dual_plane(source_format);
208 dml_uint_t num_cursors = plane->NumberOfCursors[plane_idx];
209 enum dml_odm_mode odm_mode = hw->ODMMode[plane_idx];
210
211 dml_uint_t htotal = timing->HTotal[plane_idx];
212 dml_uint_t hactive = timing->HActive[plane_idx];
213 dml_uint_t hblank_end = timing->HBlankEnd[plane_idx];
214 dml_uint_t vblank_end = timing->VBlankEnd[plane_idx];
215 dml_bool_t interlaced = timing->Interlace[plane_idx];
216 dml_float_t pclk_freq_in_mhz = (dml_float_t) timing->PixelClock[plane_idx];
217 dml_float_t refclk_freq_in_mhz = (hw->DLGRefClkFreqMHz > 0) ? (dml_float_t) hw->DLGRefClkFreqMHz : mode_lib->soc.refclk_mhz;
218 dml_float_t ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz;
219
220 dml_uint_t vready_after_vcount0;
221
222 dml_uint_t dst_x_after_scaler;
223 dml_uint_t dst_y_after_scaler;
224
225 dml_float_t dst_y_prefetch;
226 dml_float_t dst_y_per_vm_vblank;
227 dml_float_t dst_y_per_row_vblank;
228 dml_float_t dst_y_per_vm_flip;
229 dml_float_t dst_y_per_row_flip;
230
231 dml_float_t max_dst_y_per_vm_vblank = 32.0; //U5.2
232 dml_float_t max_dst_y_per_row_vblank = 16.0; //U4.2
233
234 dml_float_t vratio_pre_l;
235 dml_float_t vratio_pre_c;
236
237 dml_float_t refcyc_per_line_delivery_pre_l;
238 dml_float_t refcyc_per_line_delivery_l;
239 dml_float_t refcyc_per_line_delivery_pre_c = 0.;
240 dml_float_t refcyc_per_line_delivery_c = 0.;
241 dml_float_t refcyc_per_req_delivery_pre_l;
242 dml_float_t refcyc_per_req_delivery_l;
243 dml_float_t refcyc_per_req_delivery_pre_c = 0.;
244 dml_float_t refcyc_per_req_delivery_c = 0.;
245 dml_float_t refcyc_per_req_delivery_pre_cur0 = 0.;
246 dml_float_t refcyc_per_req_delivery_cur0 = 0.;
247
248 dml_float_t dst_y_per_pte_row_nom_l;
249 dml_float_t dst_y_per_pte_row_nom_c;
250 dml_float_t dst_y_per_meta_row_nom_l;
251 dml_float_t dst_y_per_meta_row_nom_c;
252 dml_float_t refcyc_per_pte_group_nom_l;
253 dml_float_t refcyc_per_pte_group_nom_c;
254 dml_float_t refcyc_per_pte_group_vblank_l;
255 dml_float_t refcyc_per_pte_group_vblank_c;
256 dml_float_t refcyc_per_pte_group_flip_l;
257 dml_float_t refcyc_per_pte_group_flip_c;
258 dml_float_t refcyc_per_meta_chunk_nom_l;
259 dml_float_t refcyc_per_meta_chunk_nom_c;
260 dml_float_t refcyc_per_meta_chunk_vblank_l;
261 dml_float_t refcyc_per_meta_chunk_vblank_c;
262 dml_float_t refcyc_per_meta_chunk_flip_l;
263 dml_float_t refcyc_per_meta_chunk_flip_c;
264
265 dml_float_t temp;
266 dml_float_t min_ttu_vblank;
267 dml_uint_t min_dst_y_next_start;
268
269 dml_print("DML_DLG::%s: Calculation for pipe_idx=%d\n", __func__, pipe_idx);
270 dml_print("DML_DLG::%s: plane_idx = %d\n", __func__, plane_idx);
271 dml_print("DML_DLG: %s: htotal = %d\n", __func__, htotal);
272 dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz);
273 dml_print("DML_DLG: %s: hw->DLGRefClkFreqMHz = %3.2f\n", __func__, hw->DLGRefClkFreqMHz);
274 dml_print("DML_DLG: %s: soc.refclk_mhz = %3.2f\n", __func__, mode_lib->soc.refclk_mhz);
275 dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz);
276 dml_print("DML_DLG: %s: ref_freq_to_pix_freq = %3.2f\n", __func__, ref_freq_to_pix_freq);
277 dml_print("DML_DLG: %s: interlaced = %d\n", __func__, interlaced);
278
279 memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs));
280 memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs));
281
282 ASSERT(refclk_freq_in_mhz != 0);
283 ASSERT(pclk_freq_in_mhz != 0);
284 ASSERT(ref_freq_to_pix_freq < 4.0);
285
286 // Need to figure out which side of odm combine we're in
287 // Assume the pipe instance under the same plane is in order
288
289 if (odm_mode == dml_odm_mode_bypass) {
290 disp_dlg_regs->refcyc_h_blank_end = (dml_uint_t)((dml_float_t) hblank_end * ref_freq_to_pix_freq);
291 } else if (odm_mode == dml_odm_mode_combine_2to1 || odm_mode == dml_odm_mode_combine_4to1) {
292 // find out how many pipe are in this plane
293 dml_uint_t num_active_pipes = dml_get_num_active_pipes(display_cfg: &mode_lib->ms.cache_display_cfg);
294 dml_uint_t first_pipe_idx_in_plane = __DML_NUM_PLANES__;
295 dml_uint_t pipe_idx_in_combine = 0; // pipe index within the plane
296 dml_uint_t odm_combine_factor = (odm_mode == dml_odm_mode_combine_2to1 ? 2 : 4);
297
298 for (dml_uint_t i = 0; i < num_active_pipes; i++) {
299 if (dml_get_plane_idx(mode_lib, pipe_idx: i) == plane_idx) {
300 if (i < first_pipe_idx_in_plane) {
301 first_pipe_idx_in_plane = i;
302 }
303 }
304 }
305 pipe_idx_in_combine = pipe_idx - first_pipe_idx_in_plane; // DML assumes the pipes in the same plane will have continuous indexing (i.e. plane 0 use pipe 0, 1, and plane 1 uses pipe 2, 3, etc.)
306
307 disp_dlg_regs->refcyc_h_blank_end = (dml_uint_t)(((dml_float_t) hblank_end + (dml_float_t) pipe_idx_in_combine * (dml_float_t) hactive / (dml_float_t) odm_combine_factor) * ref_freq_to_pix_freq);
308 dml_print("DML_DLG: %s: pipe_idx = %d\n", __func__, pipe_idx);
309 dml_print("DML_DLG: %s: first_pipe_idx_in_plane = %d\n", __func__, first_pipe_idx_in_plane);
310 dml_print("DML_DLG: %s: pipe_idx_in_combine = %d\n", __func__, pipe_idx_in_combine);
311 dml_print("DML_DLG: %s: odm_combine_factor = %d\n", __func__, odm_combine_factor);
312 }
313 dml_print("DML_DLG: %s: refcyc_h_blank_end = %d\n", __func__, disp_dlg_regs->refcyc_h_blank_end);
314
315 ASSERT(disp_dlg_regs->refcyc_h_blank_end < (dml_uint_t)dml_pow(2, 13));
316
317 disp_dlg_regs->ref_freq_to_pix_freq = (dml_uint_t)(ref_freq_to_pix_freq * dml_pow(base: 2, exp: 19));
318 temp = dml_pow(base: 2, exp: 8);
319 disp_dlg_regs->refcyc_per_htotal = (dml_uint_t)(ref_freq_to_pix_freq * (dml_float_t)htotal * temp);
320 disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; // 15 bits
321
322 min_ttu_vblank = dml_get_min_ttu_vblank_in_us(mode_lib, surface_idx: pipe_idx);
323 min_dst_y_next_start = (dml_uint_t)(dml_get_min_dst_y_next_start(mode_lib, surface_idx: pipe_idx));
324
325 dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank);
326 dml_print("DML_DLG: %s: min_dst_y_next_start = %d\n", __func__, min_dst_y_next_start);
327 dml_print("DML_DLG: %s: ref_freq_to_pix_freq = %3.2f\n", __func__, ref_freq_to_pix_freq);
328
329 vready_after_vcount0 = (dml_uint_t)(dml_get_vready_at_or_after_vsync(mode_lib, surface_idx: pipe_idx));
330 disp_dlg_regs->vready_after_vcount0 = vready_after_vcount0;
331
332 dml_print("DML_DLG: %s: vready_after_vcount0 = %d\n", __func__, disp_dlg_regs->vready_after_vcount0);
333
334 dst_x_after_scaler = (dml_uint_t)(dml_get_dst_x_after_scaler(mode_lib, surface_idx: pipe_idx));
335 dst_y_after_scaler = (dml_uint_t)(dml_get_dst_y_after_scaler(mode_lib, surface_idx: pipe_idx));
336
337 dml_print("DML_DLG: %s: dst_x_after_scaler = %d\n", __func__, dst_x_after_scaler);
338 dml_print("DML_DLG: %s: dst_y_after_scaler = %d\n", __func__, dst_y_after_scaler);
339
340 dst_y_prefetch = dml_get_dst_y_prefetch(mode_lib, surface_idx: pipe_idx);
341 dst_y_per_vm_vblank = dml_get_dst_y_per_vm_vblank(mode_lib, surface_idx: pipe_idx);
342 dst_y_per_row_vblank = dml_get_dst_y_per_row_vblank(mode_lib, surface_idx: pipe_idx);
343 dst_y_per_vm_flip = dml_get_dst_y_per_vm_flip(mode_lib, surface_idx: pipe_idx);
344 dst_y_per_row_flip = dml_get_dst_y_per_row_flip(mode_lib, surface_idx: pipe_idx);
345
346 // magic!
347 if (htotal <= 75) {
348 max_dst_y_per_vm_vblank = 100.0;
349 max_dst_y_per_row_vblank = 100.0;
350 }
351
352 dml_print("DML_DLG: %s: dst_y_prefetch (after rnd) = %3.2f\n", __func__, dst_y_prefetch);
353 dml_print("DML_DLG: %s: dst_y_per_vm_flip = %3.2f\n", __func__, dst_y_per_vm_flip);
354 dml_print("DML_DLG: %s: dst_y_per_row_flip = %3.2f\n", __func__, dst_y_per_row_flip);
355 dml_print("DML_DLG: %s: dst_y_per_vm_vblank = %3.2f\n", __func__, dst_y_per_vm_vblank);
356 dml_print("DML_DLG: %s: dst_y_per_row_vblank = %3.2f\n", __func__, dst_y_per_row_vblank);
357
358 ASSERT(dst_y_per_vm_vblank < max_dst_y_per_vm_vblank);
359 ASSERT(dst_y_per_row_vblank < max_dst_y_per_row_vblank);
360 ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank));
361
362 vratio_pre_l = dml_get_vratio_prefetch_l(mode_lib, surface_idx: pipe_idx);
363 vratio_pre_c = dml_get_vratio_prefetch_c(mode_lib, surface_idx: pipe_idx);
364
365 dml_print("DML_DLG: %s: vratio_pre_l = %3.2f\n", __func__, vratio_pre_l);
366 dml_print("DML_DLG: %s: vratio_pre_c = %3.2f\n", __func__, vratio_pre_c);
367
368 // Active
369 refcyc_per_line_delivery_pre_l = dml_get_refcyc_per_line_delivery_pre_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
370 refcyc_per_line_delivery_l = dml_get_refcyc_per_line_delivery_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
371
372 dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f\n", __func__, refcyc_per_line_delivery_pre_l);
373 dml_print("DML_DLG: %s: refcyc_per_line_delivery_l = %3.2f\n", __func__, refcyc_per_line_delivery_l);
374
375 if (dual_plane) {
376 refcyc_per_line_delivery_pre_c = dml_get_refcyc_per_line_delivery_pre_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
377 refcyc_per_line_delivery_c = dml_get_refcyc_per_line_delivery_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
378
379 dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f\n", __func__, refcyc_per_line_delivery_pre_c);
380 dml_print("DML_DLG: %s: refcyc_per_line_delivery_c = %3.2f\n", __func__, refcyc_per_line_delivery_c);
381 }
382
383 disp_dlg_regs->refcyc_per_vm_dmdata = (dml_uint_t)(dml_get_refcyc_per_vm_dmdata_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz);
384 disp_dlg_regs->dmdata_dl_delta = (dml_uint_t)(dml_get_dmdata_dl_delta_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz);
385
386 refcyc_per_req_delivery_pre_l = dml_get_refcyc_per_req_delivery_pre_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
387 refcyc_per_req_delivery_l = dml_get_refcyc_per_req_delivery_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
388
389 dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f\n", __func__, refcyc_per_req_delivery_pre_l);
390 dml_print("DML_DLG: %s: refcyc_per_req_delivery_l = %3.2f\n", __func__, refcyc_per_req_delivery_l);
391
392 if (dual_plane) {
393 refcyc_per_req_delivery_pre_c = dml_get_refcyc_per_req_delivery_pre_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
394 refcyc_per_req_delivery_c = dml_get_refcyc_per_req_delivery_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
395
396 dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f\n", __func__, refcyc_per_req_delivery_pre_c);
397 dml_print("DML_DLG: %s: refcyc_per_req_delivery_c = %3.2f\n", __func__, refcyc_per_req_delivery_c);
398 }
399
400 // TTU - Cursor
401 ASSERT(num_cursors <= 1);
402 if (num_cursors > 0) {
403 refcyc_per_req_delivery_pre_cur0 = dml_get_refcyc_per_cursor_req_delivery_pre_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
404 refcyc_per_req_delivery_cur0 = dml_get_refcyc_per_cursor_req_delivery_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
405
406 dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f\n", __func__, refcyc_per_req_delivery_pre_cur0);
407 dml_print("DML_DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f\n", __func__, refcyc_per_req_delivery_cur0);
408 }
409
410 // Assign to register structures
411 disp_dlg_regs->min_dst_y_next_start = (dml_uint_t)((dml_float_t) min_dst_y_next_start * dml_pow(base: 2, exp: 2));
412 ASSERT(disp_dlg_regs->min_dst_y_next_start < (dml_uint_t)dml_pow(2, 18));
413
414 disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; // in terms of line
415 disp_dlg_regs->refcyc_x_after_scaler = (dml_uint_t)((dml_float_t) dst_x_after_scaler * ref_freq_to_pix_freq); // in terms of refclk
416 disp_dlg_regs->dst_y_prefetch = (dml_uint_t)(dst_y_prefetch * dml_pow(base: 2, exp: 2));
417 disp_dlg_regs->dst_y_per_vm_vblank = (dml_uint_t)(dst_y_per_vm_vblank * dml_pow(base: 2, exp: 2));
418 disp_dlg_regs->dst_y_per_row_vblank = (dml_uint_t)(dst_y_per_row_vblank * dml_pow(base: 2, exp: 2));
419 disp_dlg_regs->dst_y_per_vm_flip = (dml_uint_t)(dst_y_per_vm_flip * dml_pow(base: 2, exp: 2));
420 disp_dlg_regs->dst_y_per_row_flip = (dml_uint_t)(dst_y_per_row_flip * dml_pow(base: 2, exp: 2));
421
422 disp_dlg_regs->vratio_prefetch = (dml_uint_t)(vratio_pre_l * dml_pow(base: 2, exp: 19));
423 disp_dlg_regs->vratio_prefetch_c = (dml_uint_t)(vratio_pre_c * dml_pow(base: 2, exp: 19));
424
425 dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_vm_vblank = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_vm_vblank);
426 dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_row_vblank = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_row_vblank);
427 dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_vm_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_vm_flip);
428 dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_row_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_row_flip);
429
430 // hack for FPGA
431 /* NOTE: We dont have getenv defined in driver and it does not make any sense in the driver */
432 /*char* fpga_env = getenv("FPGA_FPDIV");
433 if(fpga_env !=NULL)
434 {
435 if(disp_dlg_regs->vratio_prefetch >= (dml_uint_t)dml_pow(2, 22))
436 {
437 disp_dlg_regs->vratio_prefetch = (dml_uint_t)dml_pow(2, 22)-1;
438 dml_print("FPGA msg: vratio_prefetch exceed the max value, the register field is [21:0]\n");
439 }
440 }*/
441
442 disp_dlg_regs->refcyc_per_vm_group_vblank = (dml_uint_t)(dml_get_refcyc_per_vm_group_vblank_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz);
443 disp_dlg_regs->refcyc_per_vm_group_flip = (dml_uint_t)(dml_get_refcyc_per_vm_group_flip_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz);
444 disp_dlg_regs->refcyc_per_vm_req_vblank = (dml_uint_t)(dml_get_refcyc_per_vm_req_vblank_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz * dml_pow(base: 2, exp: 10));
445 disp_dlg_regs->refcyc_per_vm_req_flip = (dml_uint_t)(dml_get_refcyc_per_vm_req_flip_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz * dml_pow(base: 2, exp: 10));
446
447 dst_y_per_pte_row_nom_l = dml_get_dst_y_per_pte_row_nom_l(mode_lib, surface_idx: pipe_idx);
448 dst_y_per_pte_row_nom_c = dml_get_dst_y_per_pte_row_nom_c(mode_lib, surface_idx: pipe_idx);
449 dst_y_per_meta_row_nom_l = dml_get_dst_y_per_meta_row_nom_l(mode_lib, surface_idx: pipe_idx);
450 dst_y_per_meta_row_nom_c = dml_get_dst_y_per_meta_row_nom_c(mode_lib, surface_idx: pipe_idx);
451
452 refcyc_per_pte_group_nom_l = dml_get_refcyc_per_pte_group_nom_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
453 refcyc_per_pte_group_nom_c = dml_get_refcyc_per_pte_group_nom_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
454 refcyc_per_pte_group_vblank_l = dml_get_refcyc_per_pte_group_vblank_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
455 refcyc_per_pte_group_vblank_c = dml_get_refcyc_per_pte_group_vblank_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
456 refcyc_per_pte_group_flip_l = dml_get_refcyc_per_pte_group_flip_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
457 refcyc_per_pte_group_flip_c = dml_get_refcyc_per_pte_group_flip_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
458
459 refcyc_per_meta_chunk_nom_l = dml_get_refcyc_per_meta_chunk_nom_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
460 refcyc_per_meta_chunk_nom_c = dml_get_refcyc_per_meta_chunk_nom_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
461 refcyc_per_meta_chunk_vblank_l = dml_get_refcyc_per_meta_chunk_vblank_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
462 refcyc_per_meta_chunk_vblank_c = dml_get_refcyc_per_meta_chunk_vblank_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
463 refcyc_per_meta_chunk_flip_l = dml_get_refcyc_per_meta_chunk_flip_l_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
464 refcyc_per_meta_chunk_flip_c = dml_get_refcyc_per_meta_chunk_flip_c_in_us(mode_lib, surface_idx: pipe_idx) * refclk_freq_in_mhz;
465
466 disp_dlg_regs->dst_y_per_pte_row_nom_l = (dml_uint_t)(dst_y_per_pte_row_nom_l * dml_pow(base: 2, exp: 2));
467 disp_dlg_regs->dst_y_per_pte_row_nom_c = (dml_uint_t)(dst_y_per_pte_row_nom_c * dml_pow(base: 2, exp: 2));
468 disp_dlg_regs->dst_y_per_meta_row_nom_l = (dml_uint_t)(dst_y_per_meta_row_nom_l * dml_pow(base: 2, exp: 2));
469 disp_dlg_regs->dst_y_per_meta_row_nom_c = (dml_uint_t)(dst_y_per_meta_row_nom_c * dml_pow(base: 2, exp: 2));
470 disp_dlg_regs->refcyc_per_pte_group_nom_l = (dml_uint_t)(refcyc_per_pte_group_nom_l);
471 disp_dlg_regs->refcyc_per_pte_group_nom_c = (dml_uint_t)(refcyc_per_pte_group_nom_c);
472 disp_dlg_regs->refcyc_per_pte_group_vblank_l = (dml_uint_t)(refcyc_per_pte_group_vblank_l);
473 disp_dlg_regs->refcyc_per_pte_group_vblank_c = (dml_uint_t)(refcyc_per_pte_group_vblank_c);
474 disp_dlg_regs->refcyc_per_pte_group_flip_l = (dml_uint_t)(refcyc_per_pte_group_flip_l);
475 disp_dlg_regs->refcyc_per_pte_group_flip_c = (dml_uint_t)(refcyc_per_pte_group_flip_c);
476 disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (dml_uint_t)(refcyc_per_meta_chunk_nom_l);
477 disp_dlg_regs->refcyc_per_meta_chunk_nom_c = (dml_uint_t)(refcyc_per_meta_chunk_nom_c);
478 disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = (dml_uint_t)(refcyc_per_meta_chunk_vblank_l);
479 disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = (dml_uint_t)(refcyc_per_meta_chunk_vblank_c);
480 disp_dlg_regs->refcyc_per_meta_chunk_flip_l = (dml_uint_t)(refcyc_per_meta_chunk_flip_l);
481 disp_dlg_regs->refcyc_per_meta_chunk_flip_c = (dml_uint_t)(refcyc_per_meta_chunk_flip_c);
482 disp_dlg_regs->refcyc_per_line_delivery_pre_l = (dml_uint_t)dml_floor(x: refcyc_per_line_delivery_pre_l, granularity: 1);
483 disp_dlg_regs->refcyc_per_line_delivery_l = (dml_uint_t)dml_floor(x: refcyc_per_line_delivery_l, granularity: 1);
484 disp_dlg_regs->refcyc_per_line_delivery_pre_c = (dml_uint_t)dml_floor(x: refcyc_per_line_delivery_pre_c, granularity: 1);
485 disp_dlg_regs->refcyc_per_line_delivery_c = (dml_uint_t)dml_floor(x: refcyc_per_line_delivery_c, granularity: 1);
486
487 disp_dlg_regs->chunk_hdl_adjust_cur0 = 3;
488 disp_dlg_regs->dst_y_offset_cur0 = 0;
489 disp_dlg_regs->chunk_hdl_adjust_cur1 = 3;
490 disp_dlg_regs->dst_y_offset_cur1 = 0;
491
492 disp_dlg_regs->dst_y_delta_drq_limit = 0x7fff; // off
493
494 disp_ttu_regs->refcyc_per_req_delivery_pre_l = (dml_uint_t)(refcyc_per_req_delivery_pre_l * dml_pow(base: 2, exp: 10));
495 disp_ttu_regs->refcyc_per_req_delivery_l = (dml_uint_t)(refcyc_per_req_delivery_l * dml_pow(base: 2, exp: 10));
496 disp_ttu_regs->refcyc_per_req_delivery_pre_c = (dml_uint_t)(refcyc_per_req_delivery_pre_c * dml_pow(base: 2, exp: 10));
497 disp_ttu_regs->refcyc_per_req_delivery_c = (dml_uint_t)(refcyc_per_req_delivery_c * dml_pow(base: 2, exp: 10));
498 disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = (dml_uint_t)(refcyc_per_req_delivery_pre_cur0 * dml_pow(base: 2, exp: 10));
499 disp_ttu_regs->refcyc_per_req_delivery_cur0 = (dml_uint_t)(refcyc_per_req_delivery_cur0 * dml_pow(base: 2, exp: 10));
500 disp_ttu_regs->refcyc_per_req_delivery_pre_cur1 = 0;
501 disp_ttu_regs->refcyc_per_req_delivery_cur1 = 0;
502 disp_ttu_regs->qos_level_low_wm = 0;
503
504 disp_ttu_regs->qos_level_high_wm = (dml_uint_t)(4.0 * (dml_float_t)htotal * ref_freq_to_pix_freq);
505
506 disp_ttu_regs->qos_level_flip = 14;
507 disp_ttu_regs->qos_level_fixed_l = 8;
508 disp_ttu_regs->qos_level_fixed_c = 8;
509 disp_ttu_regs->qos_level_fixed_cur0 = 8;
510 disp_ttu_regs->qos_ramp_disable_l = 0;
511 disp_ttu_regs->qos_ramp_disable_c = 0;
512 disp_ttu_regs->qos_ramp_disable_cur0 = 0;
513 disp_ttu_regs->min_ttu_vblank = (dml_uint_t)(min_ttu_vblank * refclk_freq_in_mhz);
514
515 // CHECK for HW registers' range, assert or clamp
516 ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13));
517 ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13));
518 ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13));
519 ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13));
520 if (disp_dlg_regs->refcyc_per_vm_group_vblank >= (dml_uint_t)dml_pow(base: 2, exp: 23))
521 disp_dlg_regs->refcyc_per_vm_group_vblank = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
522
523 if (disp_dlg_regs->refcyc_per_vm_group_flip >= (dml_uint_t)dml_pow(base: 2, exp: 23))
524 disp_dlg_regs->refcyc_per_vm_group_flip = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
525
526 if (disp_dlg_regs->refcyc_per_vm_req_vblank >= (dml_uint_t)dml_pow(base: 2, exp: 23))
527 disp_dlg_regs->refcyc_per_vm_req_vblank = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
528
529 if (disp_dlg_regs->refcyc_per_vm_req_flip >= (dml_uint_t)dml_pow(base: 2, exp: 23))
530 disp_dlg_regs->refcyc_per_vm_req_flip = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
531
532
533 ASSERT(disp_dlg_regs->dst_y_after_scaler < (dml_uint_t)8);
534 ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (dml_uint_t)dml_pow(2, 13));
535 ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (dml_uint_t)dml_pow(2, 17));
536 if (dual_plane) {
537 if (disp_dlg_regs->dst_y_per_pte_row_nom_c >= (dml_uint_t)dml_pow(base: 2, exp: 17)) { // FIXME what so special about chroma, can we just assert?
538 dml_print("DML_DLG: %s: Warning dst_y_per_pte_row_nom_c %u > register max U15.2 %u\n", __func__, disp_dlg_regs->dst_y_per_pte_row_nom_c, (dml_uint_t)dml_pow(2, 17) - 1);
539 }
540 }
541 ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (dml_uint_t)dml_pow(2, 17));
542 ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_c < (dml_uint_t)dml_pow(2, 17));
543
544 if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (dml_uint_t)dml_pow(base: 2, exp: 23))
545 disp_dlg_regs->refcyc_per_pte_group_nom_l = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
546 if (dual_plane) {
547 if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (dml_uint_t)dml_pow(base: 2, exp: 23))
548 disp_dlg_regs->refcyc_per_pte_group_nom_c = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
549 }
550 ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (dml_uint_t)dml_pow(2, 13));
551 if (dual_plane) {
552 ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (dml_uint_t)dml_pow(2, 13));
553 }
554
555 if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (dml_uint_t)dml_pow(base: 2, exp: 23))
556 disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
557 if (dual_plane) {
558 if (disp_dlg_regs->refcyc_per_meta_chunk_nom_c >= (dml_uint_t)dml_pow(base: 2, exp: 23))
559 disp_dlg_regs->refcyc_per_meta_chunk_nom_c = (dml_uint_t)(dml_pow(base: 2, exp: 23) - 1);
560 }
561 ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (dml_uint_t)dml_pow(2, 13));
562 ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_c < (dml_uint_t)dml_pow(2, 13));
563 ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (dml_uint_t)dml_pow(2, 13));
564 ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (dml_uint_t)dml_pow(2, 13));
565 ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (dml_uint_t)dml_pow(2, 13));
566 ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (dml_uint_t)dml_pow(2, 13));
567 ASSERT(disp_ttu_regs->qos_level_low_wm < (dml_uint_t) dml_pow(2, 14));
568 ASSERT(disp_ttu_regs->qos_level_high_wm < (dml_uint_t) dml_pow(2, 14));
569 ASSERT(disp_ttu_regs->min_ttu_vblank < (dml_uint_t) dml_pow(2, 24));
570
571 dml_print_ttu_regs_st(ttu_regs: disp_ttu_regs);
572 dml_print_dlg_regs_st(dlg_regs: disp_dlg_regs);
573 dml_print("DML_DLG::%s: Calculation for pipe[%d] done\n", __func__, pipe_idx);
574}
575
576void dml_rq_dlg_get_arb_params(struct display_mode_lib_st *mode_lib, dml_display_arb_params_st *arb_param)
577{
578 memset(arb_param, 0, sizeof(*arb_param));
579 arb_param->max_req_outstanding = 256;
580 arb_param->min_req_outstanding = 256; // turn off the sat level feature if this set to max
581 arb_param->sat_level_us = 60;
582 arb_param->hvm_max_qos_commit_threshold = 0xf;
583 arb_param->hvm_min_req_outstand_commit_threshold = 0xa;
584 arb_param->compbuf_reserved_space_kbytes = 2 * 8; // assume max data chunk size of 8K
585}
586

source code of linux/drivers/gpu/drm/amd/display/dc/dml2/dml_display_rq_dlg_calc.c