1/*
2 * Copyright 2017 Advanced Micro Devices, Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 * Authors: AMD
23 *
24 */
25
26#include "dml1_display_rq_dlg_calc.h"
27#include "display_mode_lib.h"
28
29#include "dml_inline_defs.h"
30
31/*
32 * NOTE:
33 *   This file is gcc-parseable HW gospel, coming straight from HW engineers.
34 *
35 * It doesn't adhere to Linux kernel style and sometimes will do things in odd
36 * ways. Unless there is something clearly wrong with it the code should
37 * remain as-is as it provides us with a guarantee from HW that it is correct.
38 */
39
40static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
41{
42	unsigned int ret_val = 0;
43
44	if (source_format == dm_444_16) {
45		if (!is_chroma)
46			ret_val = 2;
47	} else if (source_format == dm_444_32) {
48		if (!is_chroma)
49			ret_val = 4;
50	} else if (source_format == dm_444_64) {
51		if (!is_chroma)
52			ret_val = 8;
53	} else if (source_format == dm_420_8) {
54		if (is_chroma)
55			ret_val = 2;
56		else
57			ret_val = 1;
58	} else if (source_format == dm_420_10) {
59		if (is_chroma)
60			ret_val = 4;
61		else
62			ret_val = 2;
63	}
64	return ret_val;
65}
66
67static bool is_dual_plane(enum source_format_class source_format)
68{
69	bool ret_val = 0;
70
71	if ((source_format == dm_420_8) || (source_format == dm_420_10))
72		ret_val = 1;
73
74	return ret_val;
75}
76
77static void get_blk256_size(
78		unsigned int *blk256_width,
79		unsigned int *blk256_height,
80		unsigned int bytes_per_element)
81{
82	if (bytes_per_element == 1) {
83		*blk256_width = 16;
84		*blk256_height = 16;
85	} else if (bytes_per_element == 2) {
86		*blk256_width = 16;
87		*blk256_height = 8;
88	} else if (bytes_per_element == 4) {
89		*blk256_width = 8;
90		*blk256_height = 8;
91	} else if (bytes_per_element == 8) {
92		*blk256_width = 8;
93		*blk256_height = 4;
94	}
95}
96
97static double get_refcyc_per_delivery(
98		struct display_mode_lib *mode_lib,
99		double refclk_freq_in_mhz,
100		double pclk_freq_in_mhz,
101		unsigned int recout_width,
102		double vratio,
103		double hscale_pixel_rate,
104		unsigned int delivery_width,
105		unsigned int req_per_swath_ub)
106{
107	double refcyc_per_delivery = 0.0;
108
109	if (vratio <= 1.0) {
110		refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width
111				/ pclk_freq_in_mhz / (double) req_per_swath_ub;
112	} else {
113		refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width
114				/ (double) hscale_pixel_rate / (double) req_per_swath_ub;
115	}
116
117	DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz);
118	DTRACE("DLG: %s: pclk_freq_in_mhz   = %3.2f", __func__, pclk_freq_in_mhz);
119	DTRACE("DLG: %s: recout_width       = %d", __func__, recout_width);
120	DTRACE("DLG: %s: vratio             = %3.2f", __func__, vratio);
121	DTRACE("DLG: %s: req_per_swath_ub   = %d", __func__, req_per_swath_ub);
122	DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery);
123
124	return refcyc_per_delivery;
125
126}
127
128static double get_vratio_pre(
129		struct display_mode_lib *mode_lib,
130		unsigned int max_num_sw,
131		unsigned int max_partial_sw,
132		unsigned int swath_height,
133		double vinit,
134		double l_sw)
135{
136	double prefill = dml_floor(vinit, 1);
137	double vratio_pre = 1.0;
138
139	vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw;
140
141	if (swath_height > 4) {
142		double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0);
143
144		if (tmp0 > vratio_pre)
145			vratio_pre = tmp0;
146	}
147
148	DTRACE("DLG: %s: max_num_sw        = %0d", __func__, max_num_sw);
149	DTRACE("DLG: %s: max_partial_sw    = %0d", __func__, max_partial_sw);
150	DTRACE("DLG: %s: swath_height      = %0d", __func__, swath_height);
151	DTRACE("DLG: %s: vinit             = %3.2f", __func__, vinit);
152	DTRACE("DLG: %s: vratio_pre        = %3.2f", __func__, vratio_pre);
153
154	if (vratio_pre < 1.0) {
155		DTRACE("WARNING_DLG: %s:  vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre);
156		vratio_pre = 1.0;
157	}
158
159	if (vratio_pre > 4.0) {
160		DTRACE(
161				"WARNING_DLG: %s:  vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0",
162				__func__,
163				vratio_pre);
164		vratio_pre = 4.0;
165	}
166
167	return vratio_pre;
168}
169
170static void get_swath_need(
171		struct display_mode_lib *mode_lib,
172		unsigned int *max_num_sw,
173		unsigned int *max_partial_sw,
174		unsigned int swath_height,
175		double vinit)
176{
177	double prefill = dml_floor(vinit, 1);
178	unsigned int max_partial_sw_int;
179
180	DTRACE("DLG: %s: swath_height      = %0d", __func__, swath_height);
181	DTRACE("DLG: %s: vinit             = %3.2f", __func__, vinit);
182
183	ASSERT(prefill > 0.0 && prefill <= 8.0);
184
185	*max_num_sw = (unsigned int) (dml_ceil((prefill - 1.0) / (double) swath_height, 1) + 1.0); /* prefill has to be >= 1 */
186	max_partial_sw_int =
187			(prefill == 1) ?
188					(swath_height - 1) :
189					((unsigned int) (prefill - 2.0) % swath_height);
190	*max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */
191
192	DTRACE("DLG: %s: max_num_sw        = %0d", __func__, *max_num_sw);
193	DTRACE("DLG: %s: max_partial_sw    = %0d", __func__, *max_partial_sw);
194}
195
196static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size)
197{
198	if (tile_size == dm_256k_tile)
199		return (256 * 1024);
200	else if (tile_size == dm_64k_tile)
201		return (64 * 1024);
202	else
203		return (4 * 1024);
204}
205
206static void extract_rq_sizing_regs(
207		struct display_mode_lib *mode_lib,
208		struct _vcs_dpi_display_data_rq_regs_st *rq_regs,
209		const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing)
210{
211	DTRACE("DLG: %s: rq_sizing param", __func__);
212	print__data_rq_sizing_params_st(mode_lib, rq_sizing);
213
214	rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10;
215
216	if (rq_sizing->min_chunk_bytes == 0)
217		rq_regs->min_chunk_size = 0;
218	else
219		rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1;
220
221	rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10;
222	if (rq_sizing->min_meta_chunk_bytes == 0)
223		rq_regs->min_meta_chunk_size = 0;
224	else
225		rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1;
226
227	rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6;
228	rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6;
229}
230
231void dml1_extract_rq_regs(
232		struct display_mode_lib *mode_lib,
233		struct _vcs_dpi_display_rq_regs_st *rq_regs,
234		const struct _vcs_dpi_display_rq_params_st *rq_param)
235{
236	unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024;
237	unsigned int detile_buf_plane1_addr = 0;
238
239	extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l);
240	if (rq_param->yuv420)
241		extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c);
242
243	rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height);
244	rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height);
245
246	/* TODO: take the max between luma, chroma chunk size?
247	 * okay for now, as we are setting chunk_bytes to 8kb anyways
248	 */
249	if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */
250		rq_regs->drq_expansion_mode = 0;
251	} else {
252		rq_regs->drq_expansion_mode = 2;
253	}
254	rq_regs->prq_expansion_mode = 1;
255	rq_regs->mrq_expansion_mode = 1;
256	rq_regs->crq_expansion_mode = 1;
257
258	if (rq_param->yuv420) {
259		if ((double) rq_param->misc.rq_l.stored_swath_bytes
260				/ (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) {
261			detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */
262		} else {
263			detile_buf_plane1_addr = dml_round_to_multiple(
264					(unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0),
265					256,
266					0) / 64.0; /* 2/3 to chroma */
267		}
268	}
269	rq_regs->plane1_base_address = detile_buf_plane1_addr;
270}
271
272static void handle_det_buf_split(
273		struct display_mode_lib *mode_lib,
274		struct _vcs_dpi_display_rq_params_st *rq_param,
275		const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param)
276{
277	unsigned int total_swath_bytes = 0;
278	unsigned int swath_bytes_l = 0;
279	unsigned int swath_bytes_c = 0;
280	unsigned int full_swath_bytes_packed_l = 0;
281	unsigned int full_swath_bytes_packed_c = 0;
282	bool req128_l = 0;
283	bool req128_c = 0;
284	bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear);
285	bool surf_vert = (pipe_src_param->source_scan == dm_vert);
286	unsigned int log2_swath_height_l = 0;
287	unsigned int log2_swath_height_c = 0;
288	unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024;
289
290	full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes;
291	full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes;
292
293	if (rq_param->yuv420_10bpc) {
294		full_swath_bytes_packed_l = dml_round_to_multiple(
295				rq_param->misc.rq_l.full_swath_bytes * 2 / 3,
296				256,
297				1) + 256;
298		full_swath_bytes_packed_c = dml_round_to_multiple(
299				rq_param->misc.rq_c.full_swath_bytes * 2 / 3,
300				256,
301				1) + 256;
302	}
303
304	if (rq_param->yuv420) {
305		total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c;
306
307		if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */
308			req128_l = 0;
309			req128_c = 0;
310			swath_bytes_l = full_swath_bytes_packed_l;
311			swath_bytes_c = full_swath_bytes_packed_c;
312		} else { /*128b request (for luma only for yuv420 8bpc) */
313			req128_l = 1;
314			req128_c = 0;
315			swath_bytes_l = full_swath_bytes_packed_l / 2;
316			swath_bytes_c = full_swath_bytes_packed_c;
317		}
318
319		/* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137)
320		 * TODO: Remove after rtl fix
321		 */
322		if (req128_l == 1) {
323			req128_c = 1;
324			DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__);
325		}
326
327		/* Note: assumption, the config that pass in will fit into
328		 *       the detiled buffer.
329		 */
330	} else {
331		total_swath_bytes = 2 * full_swath_bytes_packed_l;
332
333		if (total_swath_bytes <= detile_buf_size_in_bytes)
334			req128_l = 0;
335		else
336			req128_l = 1;
337
338		swath_bytes_l = total_swath_bytes;
339		swath_bytes_c = 0;
340	}
341	rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l;
342	rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c;
343
344	if (surf_linear) {
345		log2_swath_height_l = 0;
346		log2_swath_height_c = 0;
347	} else {
348		unsigned int swath_height_l;
349		unsigned int swath_height_c;
350
351		if (!surf_vert) {
352			swath_height_l = rq_param->misc.rq_l.blk256_height;
353			swath_height_c = rq_param->misc.rq_c.blk256_height;
354		} else {
355			swath_height_l = rq_param->misc.rq_l.blk256_width;
356			swath_height_c = rq_param->misc.rq_c.blk256_width;
357		}
358
359		if (swath_height_l > 0)
360			log2_swath_height_l = dml_log2(swath_height_l);
361
362		if (req128_l && log2_swath_height_l > 0)
363			log2_swath_height_l -= 1;
364
365		if (swath_height_c > 0)
366			log2_swath_height_c = dml_log2(swath_height_c);
367
368		if (req128_c && log2_swath_height_c > 0)
369			log2_swath_height_c -= 1;
370	}
371
372	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
373	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;
374
375	DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l);
376	DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c);
377	DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l);
378	DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c);
379}
380
381/* Need refactor. */
382static void dml1_rq_dlg_get_row_heights(
383		struct display_mode_lib *mode_lib,
384		unsigned int *o_dpte_row_height,
385		unsigned int *o_meta_row_height,
386		unsigned int vp_width,
387		unsigned int data_pitch,
388		int source_format,
389		int tiling,
390		int macro_tile_size,
391		int source_scan,
392		int is_chroma)
393{
394	bool surf_linear = (tiling == dm_sw_linear);
395	bool surf_vert = (source_scan == dm_vert);
396
397	unsigned int bytes_per_element = get_bytes_per_element(
398			(enum source_format_class) source_format,
399			is_chroma);
400	unsigned int log2_bytes_per_element = dml_log2(bytes_per_element);
401	unsigned int blk256_width = 0;
402	unsigned int blk256_height = 0;
403
404	unsigned int log2_blk256_height;
405	unsigned int blk_bytes;
406	unsigned int log2_blk_bytes;
407	unsigned int log2_blk_height;
408	unsigned int log2_blk_width;
409	unsigned int log2_meta_req_bytes;
410	unsigned int log2_meta_req_height;
411	unsigned int log2_meta_req_width;
412	unsigned int log2_meta_row_height;
413	unsigned int log2_vmpg_bytes;
414	unsigned int dpte_buf_in_pte_reqs;
415	unsigned int log2_vmpg_height;
416	unsigned int log2_vmpg_width;
417	unsigned int log2_dpte_req_height_ptes;
418	unsigned int log2_dpte_req_width_ptes;
419	unsigned int log2_dpte_req_height;
420	unsigned int log2_dpte_req_width;
421	unsigned int log2_dpte_row_height_linear;
422	unsigned int log2_dpte_row_height;
423	unsigned int dpte_req_width;
424
425	if (surf_linear) {
426		blk256_width = 256;
427		blk256_height = 1;
428	} else {
429		get_blk256_size(&blk256_width, &blk256_height, bytes_per_element);
430	}
431
432	log2_blk256_height = dml_log2((double) blk256_height);
433	blk_bytes = surf_linear ?
434			256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size);
435	log2_blk_bytes = dml_log2((double) blk_bytes);
436	log2_blk_height = 0;
437	log2_blk_width = 0;
438
439	/* remember log rule
440	 * "+" in log is multiply
441	 * "-" in log is divide
442	 * "/2" is like square root
443	 * blk is vertical biased
444	 */
445	if (tiling != dm_sw_linear)
446		log2_blk_height = log2_blk256_height
447				+ dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1);
448	else
449		log2_blk_height = 0; /* blk height of 1 */
450
451	log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height;
452
453	/* ------- */
454	/* meta    */
455	/* ------- */
456	log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
457
458	/* each 64b meta request for dcn is 8x8 meta elements and
459	 * a meta element covers one 256b block of the data surface.
460	 */
461	log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */
462	log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
463			- log2_meta_req_height;
464	log2_meta_row_height = 0;
465
466	/* the dimensions of a meta row are meta_row_width x meta_row_height in elements.
467	 * calculate upper bound of the meta_row_width
468	 */
469	if (!surf_vert)
470		log2_meta_row_height = log2_meta_req_height;
471	else
472		log2_meta_row_height = log2_meta_req_width;
473
474	*o_meta_row_height = 1 << log2_meta_row_height;
475
476	/* ------ */
477	/* dpte   */
478	/* ------ */
479	log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes);
480	dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma;
481
482	log2_vmpg_height = 0;
483	log2_vmpg_width = 0;
484	log2_dpte_req_height_ptes = 0;
485	log2_dpte_req_width_ptes = 0;
486	log2_dpte_req_height = 0;
487	log2_dpte_req_width = 0;
488	log2_dpte_row_height_linear = 0;
489	log2_dpte_row_height = 0;
490	dpte_req_width = 0; /* 64b dpte req width in data element */
491
492	if (surf_linear)
493		log2_vmpg_height = 0; /* one line high */
494	else
495		log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height;
496	log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height;
497
498	/* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */
499	if (log2_blk_bytes <= log2_vmpg_bytes)
500		log2_dpte_req_height_ptes = 0;
501	else if (log2_blk_height - log2_vmpg_height >= 2)
502		log2_dpte_req_height_ptes = 2;
503	else
504		log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height;
505	log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes;
506
507	ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */
508			(log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */
509			(log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */
510
511	/* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height
512	 * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent
513	 */
514	log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes;
515	log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes;
516	dpte_req_width = 1 << log2_dpte_req_width;
517
518	/* calculate pitch dpte row buffer can hold
519	 * round the result down to a power of two.
520	 */
521	if (surf_linear) {
522		log2_dpte_row_height_linear = dml_floor(
523				dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch),
524				1);
525
526		ASSERT(log2_dpte_row_height_linear >= 3);
527
528		if (log2_dpte_row_height_linear > 7)
529			log2_dpte_row_height_linear = 7;
530
531		log2_dpte_row_height = log2_dpte_row_height_linear;
532	} else {
533		/* the upper bound of the dpte_row_width without dependency on viewport position follows.  */
534		if (!surf_vert)
535			log2_dpte_row_height = log2_dpte_req_height;
536		else
537			log2_dpte_row_height =
538					(log2_blk_width < log2_dpte_req_width) ?
539							log2_blk_width : log2_dpte_req_width;
540	}
541
542	/* From programming guide:
543	 * There is a special case of saving only half of ptes returned due to buffer space limits.
544	 * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16
545	 * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb).
546	 */
547	if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12
548			&& log2_blk_bytes >= 16)
549		log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */
550
551	*o_dpte_row_height = 1 << log2_dpte_row_height;
552}
553
554static void get_surf_rq_param(
555		struct display_mode_lib *mode_lib,
556		struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param,
557		struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param,
558		struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param,
559		const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param,
560		bool is_chroma)
561{
562	bool mode_422 = 0;
563	unsigned int vp_width = 0;
564	unsigned int vp_height = 0;
565	unsigned int data_pitch = 0;
566	unsigned int meta_pitch = 0;
567	unsigned int ppe = mode_422 ? 2 : 1;
568	bool surf_linear;
569	bool surf_vert;
570	unsigned int bytes_per_element;
571	unsigned int log2_bytes_per_element;
572	unsigned int blk256_width;
573	unsigned int blk256_height;
574	unsigned int log2_blk256_width;
575	unsigned int log2_blk256_height;
576	unsigned int blk_bytes;
577	unsigned int log2_blk_bytes;
578	unsigned int log2_blk_height;
579	unsigned int log2_blk_width;
580	unsigned int log2_meta_req_bytes;
581	unsigned int log2_meta_req_height;
582	unsigned int log2_meta_req_width;
583	unsigned int meta_req_width;
584	unsigned int meta_req_height;
585	unsigned int log2_meta_row_height;
586	unsigned int meta_row_width_ub;
587	unsigned int log2_meta_chunk_bytes;
588	unsigned int log2_meta_chunk_height;
589	unsigned int log2_meta_chunk_width;
590	unsigned int log2_min_meta_chunk_bytes;
591	unsigned int min_meta_chunk_width;
592	unsigned int meta_chunk_width;
593	unsigned int meta_chunk_per_row_int;
594	unsigned int meta_row_remainder;
595	unsigned int meta_chunk_threshold;
596	unsigned int meta_blk_bytes;
597	unsigned int meta_blk_height;
598	unsigned int meta_blk_width;
599	unsigned int meta_surface_bytes;
600	unsigned int vmpg_bytes;
601	unsigned int meta_pte_req_per_frame_ub;
602	unsigned int meta_pte_bytes_per_frame_ub;
603	unsigned int log2_vmpg_bytes;
604	unsigned int dpte_buf_in_pte_reqs;
605	unsigned int log2_vmpg_height;
606	unsigned int log2_vmpg_width;
607	unsigned int log2_dpte_req_height_ptes;
608	unsigned int log2_dpte_req_width_ptes;
609	unsigned int log2_dpte_req_height;
610	unsigned int log2_dpte_req_width;
611	unsigned int log2_dpte_row_height_linear;
612	unsigned int log2_dpte_row_height;
613	unsigned int log2_dpte_group_width;
614	unsigned int dpte_row_width_ub;
615	unsigned int dpte_row_height;
616	unsigned int dpte_req_height;
617	unsigned int dpte_req_width;
618	unsigned int dpte_group_width;
619	unsigned int log2_dpte_group_bytes;
620	unsigned int log2_dpte_group_length;
621	unsigned int func_meta_row_height, func_dpte_row_height;
622
623	/* TODO check if ppe apply for both luma and chroma in 422 case */
624	if (is_chroma) {
625		vp_width = pipe_src_param->viewport_width_c / ppe;
626		vp_height = pipe_src_param->viewport_height_c;
627		data_pitch = pipe_src_param->data_pitch_c;
628		meta_pitch = pipe_src_param->meta_pitch_c;
629	} else {
630		vp_width = pipe_src_param->viewport_width / ppe;
631		vp_height = pipe_src_param->viewport_height;
632		data_pitch = pipe_src_param->data_pitch;
633		meta_pitch = pipe_src_param->meta_pitch;
634	}
635
636	rq_sizing_param->chunk_bytes = 8192;
637
638	if (rq_sizing_param->chunk_bytes == 64 * 1024)
639		rq_sizing_param->min_chunk_bytes = 0;
640	else
641		rq_sizing_param->min_chunk_bytes = 1024;
642
643	rq_sizing_param->meta_chunk_bytes = 2048;
644	rq_sizing_param->min_meta_chunk_bytes = 256;
645
646	rq_sizing_param->mpte_group_bytes = 2048;
647
648	surf_linear = (pipe_src_param->sw_mode == dm_sw_linear);
649	surf_vert = (pipe_src_param->source_scan == dm_vert);
650
651	bytes_per_element = get_bytes_per_element(
652			(enum source_format_class) pipe_src_param->source_format,
653			is_chroma);
654	log2_bytes_per_element = dml_log2(bytes_per_element);
655	blk256_width = 0;
656	blk256_height = 0;
657
658	if (surf_linear) {
659		blk256_width = 256 / bytes_per_element;
660		blk256_height = 1;
661	} else {
662		get_blk256_size(&blk256_width, &blk256_height, bytes_per_element);
663	}
664
665	DTRACE("DLG: %s: surf_linear        = %d", __func__, surf_linear);
666	DTRACE("DLG: %s: surf_vert          = %d", __func__, surf_vert);
667	DTRACE("DLG: %s: blk256_width       = %d", __func__, blk256_width);
668	DTRACE("DLG: %s: blk256_height      = %d", __func__, blk256_height);
669
670	log2_blk256_width = dml_log2((double) blk256_width);
671	log2_blk256_height = dml_log2((double) blk256_height);
672	blk_bytes =
673			surf_linear ? 256 : get_blk_size_bytes(
674							(enum source_macro_tile_size) pipe_src_param->macro_tile_size);
675	log2_blk_bytes = dml_log2((double) blk_bytes);
676	log2_blk_height = 0;
677	log2_blk_width = 0;
678
679	/* remember log rule
680	 * "+" in log is multiply
681	 * "-" in log is divide
682	 * "/2" is like square root
683	 * blk is vertical biased
684	 */
685	if (pipe_src_param->sw_mode != dm_sw_linear)
686		log2_blk_height = log2_blk256_height
687				+ dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1);
688	else
689		log2_blk_height = 0; /* blk height of 1 */
690
691	log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height;
692
693	if (!surf_vert) {
694		rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1)
695				+ blk256_width;
696		rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width;
697	} else {
698		rq_dlg_param->swath_width_ub = dml_round_to_multiple(
699				vp_height - 1,
700				blk256_height,
701				1) + blk256_height;
702		rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height;
703	}
704
705	if (!surf_vert)
706		rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height
707				* bytes_per_element;
708	else
709		rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width
710				* bytes_per_element;
711
712	rq_misc_param->blk256_height = blk256_height;
713	rq_misc_param->blk256_width = blk256_width;
714
715	/* -------  */
716	/* meta     */
717	/* -------  */
718	log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
719
720	/* each 64b meta request for dcn is 8x8 meta elements and
721	 * a meta element covers one 256b block of the data surface.
722	 */
723	log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */
724	log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
725			- log2_meta_req_height;
726	meta_req_width = 1 << log2_meta_req_width;
727	meta_req_height = 1 << log2_meta_req_height;
728	log2_meta_row_height = 0;
729	meta_row_width_ub = 0;
730
731	/* the dimensions of a meta row are meta_row_width x meta_row_height in elements.
732	 * calculate upper bound of the meta_row_width
733	 */
734	if (!surf_vert) {
735		log2_meta_row_height = log2_meta_req_height;
736		meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1)
737				+ meta_req_width;
738		rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width;
739	} else {
740		log2_meta_row_height = log2_meta_req_width;
741		meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1)
742				+ meta_req_height;
743		rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height;
744	}
745	rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64;
746
747	log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes);
748	log2_meta_chunk_height = log2_meta_row_height;
749
750	/*full sized meta chunk width in unit of data elements */
751	log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element
752			- log2_meta_chunk_height;
753	log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes);
754	min_meta_chunk_width = 1
755			<< (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element
756					- log2_meta_chunk_height);
757	meta_chunk_width = 1 << log2_meta_chunk_width;
758	meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width);
759	meta_row_remainder = meta_row_width_ub % meta_chunk_width;
760	meta_chunk_threshold = 0;
761	meta_blk_bytes = 4096;
762	meta_blk_height = blk256_height * 64;
763	meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height;
764	meta_surface_bytes = meta_pitch
765			* (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1)
766					+ meta_blk_height) * bytes_per_element / 256;
767	vmpg_bytes = mode_lib->soc.vmm_page_size_bytes;
768	meta_pte_req_per_frame_ub = (dml_round_to_multiple(
769			meta_surface_bytes - vmpg_bytes,
770			8 * vmpg_bytes,
771			1) + 8 * vmpg_bytes) / (8 * vmpg_bytes);
772	meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */
773	rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub;
774
775	DTRACE("DLG: %s: meta_blk_height             = %d", __func__, meta_blk_height);
776	DTRACE("DLG: %s: meta_blk_width              = %d", __func__, meta_blk_width);
777	DTRACE("DLG: %s: meta_surface_bytes          = %d", __func__, meta_surface_bytes);
778	DTRACE("DLG: %s: meta_pte_req_per_frame_ub   = %d", __func__, meta_pte_req_per_frame_ub);
779	DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub);
780
781	if (!surf_vert)
782		meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width;
783	else
784		meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height;
785
786	if (meta_row_remainder <= meta_chunk_threshold)
787		rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1;
788	else
789		rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2;
790
791	rq_dlg_param->meta_row_height = 1 << log2_meta_row_height;
792
793	/* ------ */
794	/* dpte   */
795	/* ------ */
796	log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes);
797	dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma;
798
799	log2_vmpg_height = 0;
800	log2_vmpg_width = 0;
801	log2_dpte_req_height_ptes = 0;
802	log2_dpte_req_width_ptes = 0;
803	log2_dpte_req_height = 0;
804	log2_dpte_req_width = 0;
805	log2_dpte_row_height_linear = 0;
806	log2_dpte_row_height = 0;
807	log2_dpte_group_width = 0;
808	dpte_row_width_ub = 0;
809	dpte_row_height = 0;
810	dpte_req_height = 0; /* 64b dpte req height in data element */
811	dpte_req_width = 0; /* 64b dpte req width in data element */
812	dpte_group_width = 0;
813	log2_dpte_group_bytes = 0;
814	log2_dpte_group_length = 0;
815
816	if (surf_linear)
817		log2_vmpg_height = 0; /* one line high */
818	else
819		log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height;
820	log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height;
821
822	/* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */
823	if (log2_blk_bytes <= log2_vmpg_bytes)
824		log2_dpte_req_height_ptes = 0;
825	else if (log2_blk_height - log2_vmpg_height >= 2)
826		log2_dpte_req_height_ptes = 2;
827	else
828		log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height;
829	log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes;
830
831	/* Ensure we only have the 3 shapes */
832	ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */
833			(log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */
834			(log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */
835
836	/* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height
837	 * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent
838	 * That depends on the pte shape (i.e. 8x1, 4x2, 2x4)
839	 */
840	log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes;
841	log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes;
842	dpte_req_height = 1 << log2_dpte_req_height;
843	dpte_req_width = 1 << log2_dpte_req_width;
844
845	/* calculate pitch dpte row buffer can hold
846	 * round the result down to a power of two.
847	 */
848	if (surf_linear) {
849		log2_dpte_row_height_linear = dml_floor(
850				dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch),
851				1);
852
853		ASSERT(log2_dpte_row_height_linear >= 3);
854
855		if (log2_dpte_row_height_linear > 7)
856			log2_dpte_row_height_linear = 7;
857
858		log2_dpte_row_height = log2_dpte_row_height_linear;
859		rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height;
860
861		/* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary.
862		 * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering.
863		 */
864		dpte_row_width_ub = dml_round_to_multiple(
865				data_pitch * dpte_row_height - 1,
866				dpte_req_width,
867				1) + dpte_req_width;
868		rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width;
869	} else {
870		/* for tiled mode, row height is the same as req height and row store up to vp size upper bound */
871		if (!surf_vert) {
872			log2_dpte_row_height = log2_dpte_req_height;
873			dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1)
874					+ dpte_req_width;
875			rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width;
876		} else {
877			log2_dpte_row_height =
878					(log2_blk_width < log2_dpte_req_width) ?
879							log2_blk_width : log2_dpte_req_width;
880			dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1)
881					+ dpte_req_height;
882			rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height;
883		}
884		rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height;
885	}
886	rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64;
887
888	/* From programming guide:
889	 * There is a special case of saving only half of ptes returned due to buffer space limits.
890	 * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16
891	 * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb).
892	 */
893	if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12
894			&& log2_blk_bytes >= 16) {
895		log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */
896		rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height;
897	}
898
899	/* the dpte_group_bytes is reduced for the specific case of vertical
900	 * access of a tile surface that has dpte request of 8x1 ptes.
901	 */
902	if (!surf_linear && (log2_dpte_req_height_ptes == 0) && surf_vert) /*reduced, in this case, will have page fault within a group */
903		rq_sizing_param->dpte_group_bytes = 512;
904	else
905		/*full size */
906		rq_sizing_param->dpte_group_bytes = 2048;
907
908	/*since pte request size is 64byte, the number of data pte requests per full sized group is as follows.  */
909	log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes);
910	log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests  */
911
912	/* full sized data pte group width in elements */
913	if (!surf_vert)
914		log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width;
915	else
916		log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height;
917
918	dpte_group_width = 1 << log2_dpte_group_width;
919
920	/* since dpte groups are only aligned to dpte_req_width and not dpte_group_width,
921	 * the upper bound for the dpte groups per row is as follows.
922	 */
923	rq_dlg_param->dpte_groups_per_row_ub = dml_ceil(
924			(double) dpte_row_width_ub / dpte_group_width,
925			1);
926
927	dml1_rq_dlg_get_row_heights(
928			mode_lib,
929			&func_dpte_row_height,
930			&func_meta_row_height,
931			vp_width,
932			data_pitch,
933			pipe_src_param->source_format,
934			pipe_src_param->sw_mode,
935			pipe_src_param->macro_tile_size,
936			pipe_src_param->source_scan,
937			is_chroma);
938
939	/* Just a check to make sure this function and the new one give the same
940	 * result. The standalone get_row_heights() function is based off of the
941	 * code in this function so the same changes need to be made to both.
942	 */
943	if (rq_dlg_param->meta_row_height != func_meta_row_height) {
944		DTRACE(
945				"MISMATCH: rq_dlg_param->meta_row_height = %d",
946				rq_dlg_param->meta_row_height);
947		DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height);
948		ASSERT(0);
949	}
950
951	if (rq_dlg_param->dpte_row_height != func_dpte_row_height) {
952		DTRACE(
953				"MISMATCH: rq_dlg_param->dpte_row_height = %d",
954				rq_dlg_param->dpte_row_height);
955		DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height);
956		ASSERT(0);
957	}
958}
959
960void dml1_rq_dlg_get_rq_params(
961		struct display_mode_lib *mode_lib,
962		struct _vcs_dpi_display_rq_params_st *rq_param,
963		const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param)
964{
965	/* get param for luma surface */
966	rq_param->yuv420 = pipe_src_param->source_format == dm_420_8
967			|| pipe_src_param->source_format == dm_420_10;
968	rq_param->yuv420_10bpc = pipe_src_param->source_format == dm_420_10;
969
970	get_surf_rq_param(
971			mode_lib,
972			&(rq_param->sizing.rq_l),
973			&(rq_param->dlg.rq_l),
974			&(rq_param->misc.rq_l),
975			pipe_src_param,
976			0);
977
978	if (is_dual_plane((enum source_format_class) pipe_src_param->source_format)) {
979		/* get param for chroma surface */
980		get_surf_rq_param(
981				mode_lib,
982				&(rq_param->sizing.rq_c),
983				&(rq_param->dlg.rq_c),
984				&(rq_param->misc.rq_c),
985				pipe_src_param,
986				1);
987	}
988
989	/* calculate how to split the det buffer space between luma and chroma */
990	handle_det_buf_split(mode_lib, rq_param, pipe_src_param);
991	print__rq_params_st(mode_lib, rq_param);
992}
993
994/* Note: currently taken in as is.
995 * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma.
996 */
997void dml1_rq_dlg_get_dlg_params(
998		struct display_mode_lib *mode_lib,
999		struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs,
1000		struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs,
1001		const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param,
1002		const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param,
1003		const struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param,
1004		const bool cstate_en,
1005		const bool pstate_en,
1006		const bool vm_en,
1007		const bool iflip_en)
1008{
1009	/* Timing */
1010	unsigned int htotal = e2e_pipe_param->pipe.dest.htotal;
1011	unsigned int hblank_end = e2e_pipe_param->pipe.dest.hblank_end;
1012	unsigned int vblank_start = e2e_pipe_param->pipe.dest.vblank_start;
1013	unsigned int vblank_end = e2e_pipe_param->pipe.dest.vblank_end;
1014	bool interlaced = e2e_pipe_param->pipe.dest.interlaced;
1015	unsigned int min_vblank = mode_lib->ip.min_vblank_lines;
1016
1017	double pclk_freq_in_mhz = e2e_pipe_param->pipe.dest.pixel_rate_mhz;
1018	double refclk_freq_in_mhz = e2e_pipe_param->clks_cfg.refclk_mhz;
1019	double dppclk_freq_in_mhz = e2e_pipe_param->clks_cfg.dppclk_mhz;
1020	double dispclk_freq_in_mhz = e2e_pipe_param->clks_cfg.dispclk_mhz;
1021
1022	double ref_freq_to_pix_freq;
1023	double prefetch_xy_calc_in_dcfclk;
1024	double min_dcfclk_mhz;
1025	double t_calc_us;
1026	double min_ttu_vblank;
1027	double min_dst_y_ttu_vblank;
1028	unsigned int dlg_vblank_start;
1029	bool dcc_en;
1030	bool dual_plane;
1031	bool mode_422;
1032	unsigned int access_dir;
1033	unsigned int bytes_per_element_l;
1034	unsigned int bytes_per_element_c;
1035	unsigned int vp_height_l;
1036	unsigned int vp_width_l;
1037	unsigned int vp_height_c;
1038	unsigned int vp_width_c;
1039	unsigned int htaps_l;
1040	unsigned int htaps_c;
1041	double hratios_l;
1042	double hratios_c;
1043	double vratio_l;
1044	double vratio_c;
1045	double line_time_in_us;
1046	double vinit_l;
1047	double vinit_c;
1048	double vinit_bot_l;
1049	double vinit_bot_c;
1050	unsigned int swath_height_l;
1051	unsigned int swath_width_ub_l;
1052	unsigned int dpte_bytes_per_row_ub_l;
1053	unsigned int dpte_groups_per_row_ub_l;
1054	unsigned int meta_pte_bytes_per_frame_ub_l;
1055	unsigned int meta_bytes_per_row_ub_l;
1056	unsigned int swath_height_c;
1057	unsigned int swath_width_ub_c;
1058	unsigned int dpte_bytes_per_row_ub_c;
1059	unsigned int dpte_groups_per_row_ub_c;
1060	unsigned int meta_chunks_per_row_ub_l;
1061	unsigned int vupdate_offset;
1062	unsigned int vupdate_width;
1063	unsigned int vready_offset;
1064	unsigned int dppclk_delay_subtotal;
1065	unsigned int dispclk_delay_subtotal;
1066	unsigned int pixel_rate_delay_subtotal;
1067	unsigned int vstartup_start;
1068	unsigned int dst_x_after_scaler;
1069	unsigned int dst_y_after_scaler;
1070	double line_wait;
1071	double line_o;
1072	double line_setup;
1073	double line_calc;
1074	double dst_y_prefetch;
1075	double t_pre_us;
1076	unsigned int vm_bytes;
1077	unsigned int meta_row_bytes;
1078	unsigned int max_num_sw_l;
1079	unsigned int max_num_sw_c;
1080	unsigned int max_partial_sw_l;
1081	unsigned int max_partial_sw_c;
1082	double max_vinit_l;
1083	double max_vinit_c;
1084	unsigned int lsw_l;
1085	unsigned int lsw_c;
1086	unsigned int sw_bytes_ub_l;
1087	unsigned int sw_bytes_ub_c;
1088	unsigned int sw_bytes;
1089	unsigned int dpte_row_bytes;
1090	double prefetch_bw;
1091	double flip_bw;
1092	double t_vm_us;
1093	double t_r0_us;
1094	double dst_y_per_vm_vblank;
1095	double dst_y_per_row_vblank;
1096	double min_dst_y_per_vm_vblank;
1097	double min_dst_y_per_row_vblank;
1098	double lsw;
1099	double vratio_pre_l;
1100	double vratio_pre_c;
1101	unsigned int req_per_swath_ub_l;
1102	unsigned int req_per_swath_ub_c;
1103	unsigned int meta_row_height_l;
1104	unsigned int swath_width_pixels_ub_l;
1105	unsigned int swath_width_pixels_ub_c;
1106	unsigned int scaler_rec_in_width_l;
1107	unsigned int scaler_rec_in_width_c;
1108	unsigned int dpte_row_height_l;
1109	unsigned int dpte_row_height_c;
1110	double hscale_pixel_rate_l;
1111	double hscale_pixel_rate_c;
1112	double min_hratio_fact_l;
1113	double min_hratio_fact_c;
1114	double refcyc_per_line_delivery_pre_l;
1115	double refcyc_per_line_delivery_pre_c;
1116	double refcyc_per_line_delivery_l;
1117	double refcyc_per_line_delivery_c;
1118	double refcyc_per_req_delivery_pre_l;
1119	double refcyc_per_req_delivery_pre_c;
1120	double refcyc_per_req_delivery_l;
1121	double refcyc_per_req_delivery_c;
1122	double refcyc_per_req_delivery_pre_cur0;
1123	double refcyc_per_req_delivery_cur0;
1124	unsigned int full_recout_width;
1125	double hratios_cur0;
1126	unsigned int cur0_src_width;
1127	enum cursor_bpp cur0_bpp;
1128	unsigned int cur0_req_size;
1129	unsigned int cur0_req_width;
1130	double cur0_width_ub;
1131	double cur0_req_per_width;
1132	double hactive_cur0;
1133
1134	memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs));
1135	memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs));
1136
1137	DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en);
1138	DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en);
1139	DTRACE("DLG: %s: vm_en     = %d", __func__, vm_en);
1140	DTRACE("DLG: %s: iflip_en  = %d", __func__, iflip_en);
1141
1142	/* ------------------------- */
1143	/* Section 1.5.2.1: OTG dependent Params */
1144	/* ------------------------- */
1145	DTRACE("DLG: %s: dppclk_freq_in_mhz     = %3.2f", __func__, dppclk_freq_in_mhz);
1146	DTRACE("DLG: %s: dispclk_freq_in_mhz    = %3.2f", __func__, dispclk_freq_in_mhz);
1147	DTRACE("DLG: %s: refclk_freq_in_mhz     = %3.2f", __func__, refclk_freq_in_mhz);
1148	DTRACE("DLG: %s: pclk_freq_in_mhz       = %3.2f", __func__, pclk_freq_in_mhz);
1149	DTRACE("DLG: %s: interlaced             = %d", __func__, interlaced);
1150
1151	ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz;
1152	ASSERT(ref_freq_to_pix_freq < 4.0);
1153	disp_dlg_regs->ref_freq_to_pix_freq =
1154			(unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19));
1155	disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal
1156			* dml_pow(2, 8));
1157	disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end
1158			* (double) ref_freq_to_pix_freq);
1159	ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13));
1160	disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */
1161
1162	prefetch_xy_calc_in_dcfclk = 24.0; /* TODO: ip_param */
1163	min_dcfclk_mhz = dlg_sys_param->deepsleep_dcfclk_mhz;
1164	t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz;
1165	min_ttu_vblank = dlg_sys_param->t_urg_wm_us;
1166	if (cstate_en)
1167		min_ttu_vblank = dml_max(dlg_sys_param->t_sr_wm_us, min_ttu_vblank);
1168	if (pstate_en)
1169		min_ttu_vblank = dml_max(dlg_sys_param->t_mclk_wm_us, min_ttu_vblank);
1170	min_ttu_vblank = min_ttu_vblank + t_calc_us;
1171
1172	min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal;
1173	dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start;
1174
1175	disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start
1176			+ min_dst_y_ttu_vblank) * dml_pow(2, 2));
1177	ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18));
1178
1179	DTRACE("DLG: %s: min_dcfclk_mhz                         = %3.2f", __func__, min_dcfclk_mhz);
1180	DTRACE("DLG: %s: min_ttu_vblank                         = %3.2f", __func__, min_ttu_vblank);
1181	DTRACE(
1182			"DLG: %s: min_dst_y_ttu_vblank                   = %3.2f",
1183			__func__,
1184			min_dst_y_ttu_vblank);
1185	DTRACE("DLG: %s: t_calc_us                              = %3.2f", __func__, t_calc_us);
1186	DTRACE(
1187			"DLG: %s: disp_dlg_regs->min_dst_y_next_start    = 0x%0x",
1188			__func__,
1189			disp_dlg_regs->min_dst_y_next_start);
1190	DTRACE(
1191			"DLG: %s: ref_freq_to_pix_freq                   = %3.2f",
1192			__func__,
1193			ref_freq_to_pix_freq);
1194
1195	/* ------------------------- */
1196	/* Section 1.5.2.2: Prefetch, Active and TTU  */
1197	/* ------------------------- */
1198	/* Prefetch Calc */
1199	/* Source */
1200	dcc_en = e2e_pipe_param->pipe.src.dcc;
1201	dual_plane = is_dual_plane(
1202			(enum source_format_class) e2e_pipe_param->pipe.src.source_format);
1203	mode_422 = 0; /* TODO */
1204	access_dir = (e2e_pipe_param->pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */
1205	bytes_per_element_l = get_bytes_per_element(
1206			(enum source_format_class) e2e_pipe_param->pipe.src.source_format,
1207			0);
1208	bytes_per_element_c = get_bytes_per_element(
1209			(enum source_format_class) e2e_pipe_param->pipe.src.source_format,
1210			1);
1211	vp_height_l = e2e_pipe_param->pipe.src.viewport_height;
1212	vp_width_l = e2e_pipe_param->pipe.src.viewport_width;
1213	vp_height_c = e2e_pipe_param->pipe.src.viewport_height_c;
1214	vp_width_c = e2e_pipe_param->pipe.src.viewport_width_c;
1215
1216	/* Scaling */
1217	htaps_l = e2e_pipe_param->pipe.scale_taps.htaps;
1218	htaps_c = e2e_pipe_param->pipe.scale_taps.htaps_c;
1219	hratios_l = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio;
1220	hratios_c = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio_c;
1221	vratio_l = e2e_pipe_param->pipe.scale_ratio_depth.vscl_ratio;
1222	vratio_c = e2e_pipe_param->pipe.scale_ratio_depth.vscl_ratio_c;
1223
1224	line_time_in_us = (htotal / pclk_freq_in_mhz);
1225	vinit_l = e2e_pipe_param->pipe.scale_ratio_depth.vinit;
1226	vinit_c = e2e_pipe_param->pipe.scale_ratio_depth.vinit_c;
1227	vinit_bot_l = e2e_pipe_param->pipe.scale_ratio_depth.vinit_bot;
1228	vinit_bot_c = e2e_pipe_param->pipe.scale_ratio_depth.vinit_bot_c;
1229
1230	swath_height_l = rq_dlg_param->rq_l.swath_height;
1231	swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub;
1232	dpte_bytes_per_row_ub_l = rq_dlg_param->rq_l.dpte_bytes_per_row_ub;
1233	dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub;
1234	meta_pte_bytes_per_frame_ub_l = rq_dlg_param->rq_l.meta_pte_bytes_per_frame_ub;
1235	meta_bytes_per_row_ub_l = rq_dlg_param->rq_l.meta_bytes_per_row_ub;
1236
1237	swath_height_c = rq_dlg_param->rq_c.swath_height;
1238	swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub;
1239	dpte_bytes_per_row_ub_c = rq_dlg_param->rq_c.dpte_bytes_per_row_ub;
1240	dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub;
1241
1242	meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub;
1243	vupdate_offset = e2e_pipe_param->pipe.dest.vupdate_offset;
1244	vupdate_width = e2e_pipe_param->pipe.dest.vupdate_width;
1245	vready_offset = e2e_pipe_param->pipe.dest.vready_offset;
1246
1247	dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal;
1248	dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal;
1249	pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz
1250			+ dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz;
1251
1252	vstartup_start = e2e_pipe_param->pipe.dest.vstartup_start;
1253
1254	if (interlaced)
1255		vstartup_start = vstartup_start / 2;
1256
1257	if (vstartup_start >= min_vblank) {
1258		DTRACE(
1259				"WARNING_DLG: %s:  vblank_start=%d vblank_end=%d",
1260				__func__,
1261				vblank_start,
1262				vblank_end);
1263		DTRACE(
1264				"WARNING_DLG: %s:  vstartup_start=%d should be less than min_vblank=%d",
1265				__func__,
1266				vstartup_start,
1267				min_vblank);
1268		min_vblank = vstartup_start + 1;
1269		DTRACE(
1270				"WARNING_DLG: %s:  vstartup_start=%d should be less than min_vblank=%d",
1271				__func__,
1272				vstartup_start,
1273				min_vblank);
1274	}
1275
1276	dst_x_after_scaler = 0;
1277	dst_y_after_scaler = 0;
1278
1279	if (e2e_pipe_param->pipe.src.is_hsplit)
1280		dst_x_after_scaler = pixel_rate_delay_subtotal
1281				+ e2e_pipe_param->pipe.dest.recout_width;
1282	else
1283		dst_x_after_scaler = pixel_rate_delay_subtotal;
1284
1285	if (e2e_pipe_param->dout.output_format == dm_420)
1286		dst_y_after_scaler = 1;
1287	else
1288		dst_y_after_scaler = 0;
1289
1290	if (dst_x_after_scaler >= htotal) {
1291		dst_x_after_scaler = dst_x_after_scaler - htotal;
1292		dst_y_after_scaler = dst_y_after_scaler + 1;
1293	}
1294
1295	DTRACE("DLG: %s: htotal                                 = %d", __func__, htotal);
1296	DTRACE(
1297			"DLG: %s: pixel_rate_delay_subtotal              = %d",
1298			__func__,
1299			pixel_rate_delay_subtotal);
1300	DTRACE("DLG: %s: dst_x_after_scaler                     = %d", __func__, dst_x_after_scaler);
1301	DTRACE("DLG: %s: dst_y_after_scaler                     = %d", __func__, dst_y_after_scaler);
1302
1303	line_wait = mode_lib->soc.urgent_latency_us;
1304	if (cstate_en)
1305		line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait);
1306	if (pstate_en)
1307		line_wait = dml_max(
1308				mode_lib->soc.dram_clock_change_latency_us
1309						+ mode_lib->soc.urgent_latency_us,
1310				line_wait);
1311	line_wait = line_wait / line_time_in_us;
1312
1313	line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal;
1314	line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal;
1315	line_calc = t_calc_us / line_time_in_us;
1316
1317	DTRACE(
1318			"DLG: %s: soc.sr_enter_plus_exit_time_us     = %3.2f",
1319			__func__,
1320			(double) mode_lib->soc.sr_enter_plus_exit_time_us);
1321	DTRACE(
1322			"DLG: %s: soc.dram_clock_change_latency_us   = %3.2f",
1323			__func__,
1324			(double) mode_lib->soc.dram_clock_change_latency_us);
1325	DTRACE(
1326			"DLG: %s: soc.urgent_latency_us              = %3.2f",
1327			__func__,
1328			mode_lib->soc.urgent_latency_us);
1329
1330	DTRACE("DLG: %s: swath_height_l     = %d", __func__, swath_height_l);
1331	if (dual_plane)
1332		DTRACE("DLG: %s: swath_height_c     = %d", __func__, swath_height_c);
1333
1334	DTRACE("DLG: %s: line_time_in_us    = %3.2f", __func__, (double) line_time_in_us);
1335	DTRACE("DLG: %s: vupdate_offset     = %d", __func__, vupdate_offset);
1336	DTRACE("DLG: %s: vupdate_width      = %d", __func__, vupdate_width);
1337	DTRACE("DLG: %s: vready_offset      = %d", __func__, vready_offset);
1338	DTRACE("DLG: %s: line_time_in_us    = %3.2f", __func__, line_time_in_us);
1339	DTRACE("DLG: %s: line_wait          = %3.2f", __func__, line_wait);
1340	DTRACE("DLG: %s: line_o             = %3.2f", __func__, line_o);
1341	DTRACE("DLG: %s: line_setup         = %3.2f", __func__, line_setup);
1342	DTRACE("DLG: %s: line_calc          = %3.2f", __func__, line_calc);
1343
1344	dst_y_prefetch = ((double) min_vblank - 1.0)
1345			- (line_setup + line_calc + line_wait + line_o);
1346	DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch);
1347	ASSERT(dst_y_prefetch >= 2.0);
1348
1349	dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125), 1) / 4;
1350	DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch);
1351
1352	t_pre_us = dst_y_prefetch * line_time_in_us;
1353	vm_bytes = 0;
1354	meta_row_bytes = 0;
1355
1356	if (dcc_en && vm_en)
1357		vm_bytes = meta_pte_bytes_per_frame_ub_l;
1358	if (dcc_en)
1359		meta_row_bytes = meta_bytes_per_row_ub_l;
1360
1361	max_num_sw_l = 0;
1362	max_num_sw_c = 0;
1363	max_partial_sw_l = 0;
1364	max_partial_sw_c = 0;
1365
1366	max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l;
1367	max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c;
1368
1369	get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l);
1370	if (dual_plane)
1371		get_swath_need(
1372				mode_lib,
1373				&max_num_sw_c,
1374				&max_partial_sw_c,
1375				swath_height_c,
1376				max_vinit_c);
1377
1378	lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l;
1379	lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c;
1380	sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l;
1381	sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c;
1382	sw_bytes = 0;
1383	dpte_row_bytes = 0;
1384
1385	if (vm_en) {
1386		if (dual_plane)
1387			dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c;
1388		else
1389			dpte_row_bytes = dpte_bytes_per_row_ub_l;
1390	} else {
1391		dpte_row_bytes = 0;
1392	}
1393
1394	if (dual_plane)
1395		sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c;
1396	else
1397		sw_bytes = sw_bytes_ub_l;
1398
1399	DTRACE("DLG: %s: sw_bytes_ub_l           = %d", __func__, sw_bytes_ub_l);
1400	DTRACE("DLG: %s: sw_bytes_ub_c           = %d", __func__, sw_bytes_ub_c);
1401	DTRACE("DLG: %s: sw_bytes                = %d", __func__, sw_bytes);
1402	DTRACE("DLG: %s: vm_bytes                = %d", __func__, vm_bytes);
1403	DTRACE("DLG: %s: meta_row_bytes          = %d", __func__, meta_row_bytes);
1404	DTRACE("DLG: %s: dpte_row_bytes          = %d", __func__, dpte_row_bytes);
1405
1406	prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us;
1407	flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param->total_flip_bw)
1408			/ (double) dlg_sys_param->total_flip_bytes;
1409	t_vm_us = line_time_in_us / 4.0;
1410	if (vm_en && dcc_en) {
1411		t_vm_us = dml_max(
1412				dlg_sys_param->t_extra_us,
1413				dml_max((double) vm_bytes / prefetch_bw, t_vm_us));
1414
1415		if (iflip_en && !dual_plane) {
1416			t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us);
1417			if (flip_bw > 0.)
1418				t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us);
1419		}
1420	}
1421
1422	t_r0_us = dml_max(dlg_sys_param->t_extra_us - t_vm_us, line_time_in_us - t_vm_us);
1423
1424	if (vm_en || dcc_en) {
1425		t_r0_us = dml_max(
1426				(double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw,
1427				dlg_sys_param->t_extra_us);
1428		t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us);
1429
1430		if (iflip_en && !dual_plane) {
1431			t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us);
1432			if (flip_bw > 0.)
1433				t_r0_us = dml_max(
1434						(dpte_row_bytes + meta_row_bytes) / flip_bw,
1435						t_r0_us);
1436		}
1437	}
1438
1439	disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */
1440	disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */
1441	ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13));
1442	DTRACE(
1443			"DLG: %s: disp_dlg_regs->dst_y_after_scaler      = 0x%0x",
1444			__func__,
1445			disp_dlg_regs->dst_y_after_scaler);
1446	DTRACE(
1447			"DLG: %s: disp_dlg_regs->refcyc_x_after_scaler   = 0x%0x",
1448			__func__,
1449			disp_dlg_regs->refcyc_x_after_scaler);
1450
1451	disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2));
1452	DTRACE(
1453			"DLG: %s: disp_dlg_regs->dst_y_prefetch  = %d",
1454			__func__,
1455			disp_dlg_regs->dst_y_prefetch);
1456
1457	dst_y_per_vm_vblank = 0.0;
1458	dst_y_per_row_vblank = 0.0;
1459
1460	dst_y_per_vm_vblank = t_vm_us / line_time_in_us;
1461	dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125), 1) / 4.0;
1462	disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2));
1463
1464	dst_y_per_row_vblank = t_r0_us / line_time_in_us;
1465	dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125), 1) / 4.0;
1466	disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2));
1467
1468	DTRACE("DLG: %s: lsw_l                   = %d", __func__, lsw_l);
1469	DTRACE("DLG: %s: lsw_c                   = %d", __func__, lsw_c);
1470	DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l);
1471	DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c);
1472
1473	DTRACE("DLG: %s: prefetch_bw            = %3.2f", __func__, prefetch_bw);
1474	DTRACE("DLG: %s: flip_bw                = %3.2f", __func__, flip_bw);
1475	DTRACE("DLG: %s: t_pre_us               = %3.2f", __func__, t_pre_us);
1476	DTRACE("DLG: %s: t_vm_us                = %3.2f", __func__, t_vm_us);
1477	DTRACE("DLG: %s: t_r0_us                = %3.2f", __func__, t_r0_us);
1478	DTRACE("DLG: %s: dst_y_per_vm_vblank    = %3.2f", __func__, dst_y_per_vm_vblank);
1479	DTRACE("DLG: %s: dst_y_per_row_vblank   = %3.2f", __func__, dst_y_per_row_vblank);
1480	DTRACE("DLG: %s: dst_y_prefetch         = %3.2f", __func__, dst_y_prefetch);
1481
1482	min_dst_y_per_vm_vblank = 8.0;
1483	min_dst_y_per_row_vblank = 16.0;
1484	if (htotal <= 75) {
1485		min_vblank = 300;
1486		min_dst_y_per_vm_vblank = 100.0;
1487		min_dst_y_per_row_vblank = 100.0;
1488	}
1489
1490	ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank);
1491	ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank);
1492
1493	ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank));
1494	lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank);
1495
1496	DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw);
1497
1498	vratio_pre_l = get_vratio_pre(
1499			mode_lib,
1500			max_num_sw_l,
1501			max_partial_sw_l,
1502			swath_height_l,
1503			max_vinit_l,
1504			lsw);
1505	vratio_pre_c = 1.0;
1506	if (dual_plane)
1507		vratio_pre_c = get_vratio_pre(
1508				mode_lib,
1509				max_num_sw_c,
1510				max_partial_sw_c,
1511				swath_height_c,
1512				max_vinit_c,
1513				lsw);
1514
1515	DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l);
1516	DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c);
1517
1518	ASSERT(vratio_pre_l <= 4.0);
1519	if (vratio_pre_l >= 4.0)
1520		disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1;
1521	else
1522		disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19));
1523
1524	ASSERT(vratio_pre_c <= 4.0);
1525	if (vratio_pre_c >= 4.0)
1526		disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1;
1527	else
1528		disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19));
1529
1530	disp_dlg_regs->refcyc_per_pte_group_vblank_l =
1531			(unsigned int) (dst_y_per_row_vblank * (double) htotal
1532					* ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l);
1533	ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13));
1534
1535	disp_dlg_regs->refcyc_per_pte_group_vblank_c =
1536			(unsigned int) (dst_y_per_row_vblank * (double) htotal
1537					* ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c);
1538	ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13));
1539
1540	disp_dlg_regs->refcyc_per_meta_chunk_vblank_l =
1541			(unsigned int) (dst_y_per_row_vblank * (double) htotal
1542					* ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l);
1543	ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13));
1544
1545	disp_dlg_regs->refcyc_per_meta_chunk_vblank_c =
1546			disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0.  assigned to be the same as _l for now */
1547
1548	/* Active */
1549	req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub;
1550	req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub;
1551	meta_row_height_l = rq_dlg_param->rq_l.meta_row_height;
1552	swath_width_pixels_ub_l = 0;
1553	swath_width_pixels_ub_c = 0;
1554	scaler_rec_in_width_l = 0;
1555	scaler_rec_in_width_c = 0;
1556	dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
1557	dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
1558
1559	disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l
1560			/ (double) vratio_l * dml_pow(2, 2));
1561	ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17));
1562
1563	disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c
1564			/ (double) vratio_c * dml_pow(2, 2));
1565	ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17));
1566
1567	disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l
1568			/ (double) vratio_l * dml_pow(2, 2));
1569	ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17));
1570
1571	disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0.  assigned to be the same as _l for now */
1572
1573	disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l
1574			/ (double) vratio_l * (double) htotal * ref_freq_to_pix_freq
1575			/ (double) dpte_groups_per_row_ub_l);
1576	if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23))
1577		disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1;
1578
1579	disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c
1580			/ (double) vratio_c * (double) htotal * ref_freq_to_pix_freq
1581			/ (double) dpte_groups_per_row_ub_c);
1582	if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23))
1583		disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1;
1584
1585	disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l
1586			/ (double) vratio_l * (double) htotal * ref_freq_to_pix_freq
1587			/ (double) meta_chunks_per_row_ub_l);
1588	if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23))
1589		disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1;
1590
1591	if (mode_422) {
1592		swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */
1593		swath_width_pixels_ub_c = swath_width_ub_c * 2;
1594	} else {
1595		swath_width_pixels_ub_l = swath_width_ub_l * 1;
1596		swath_width_pixels_ub_c = swath_width_ub_c * 1;
1597	}
1598
1599	hscale_pixel_rate_l = 0.;
1600	hscale_pixel_rate_c = 0.;
1601	min_hratio_fact_l = 1.0;
1602	min_hratio_fact_c = 1.0;
1603
1604	if (htaps_l <= 1)
1605		min_hratio_fact_l = 2.0;
1606	else if (htaps_l <= 6) {
1607		if ((hratios_l * 2.0) > 4.0)
1608			min_hratio_fact_l = 4.0;
1609		else
1610			min_hratio_fact_l = hratios_l * 2.0;
1611	} else {
1612		if (hratios_l > 4.0)
1613			min_hratio_fact_l = 4.0;
1614		else
1615			min_hratio_fact_l = hratios_l;
1616	}
1617
1618	hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz;
1619
1620	if (htaps_c <= 1)
1621		min_hratio_fact_c = 2.0;
1622	else if (htaps_c <= 6) {
1623		if ((hratios_c * 2.0) > 4.0)
1624			min_hratio_fact_c = 4.0;
1625		else
1626			min_hratio_fact_c = hratios_c * 2.0;
1627	} else {
1628		if (hratios_c > 4.0)
1629			min_hratio_fact_c = 4.0;
1630		else
1631			min_hratio_fact_c = hratios_c;
1632	}
1633
1634	hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz;
1635
1636	refcyc_per_line_delivery_pre_l = 0.;
1637	refcyc_per_line_delivery_pre_c = 0.;
1638	refcyc_per_line_delivery_l = 0.;
1639	refcyc_per_line_delivery_c = 0.;
1640
1641	refcyc_per_req_delivery_pre_l = 0.;
1642	refcyc_per_req_delivery_pre_c = 0.;
1643	refcyc_per_req_delivery_l = 0.;
1644	refcyc_per_req_delivery_c = 0.;
1645	refcyc_per_req_delivery_pre_cur0 = 0.;
1646	refcyc_per_req_delivery_cur0 = 0.;
1647
1648	full_recout_width = 0;
1649	if (e2e_pipe_param->pipe.src.is_hsplit) {
1650		if (e2e_pipe_param->pipe.dest.full_recout_width == 0) {
1651			DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__);
1652			full_recout_width = e2e_pipe_param->pipe.dest.recout_width * 2; /* assume half split for dcn1 */
1653		} else
1654			full_recout_width = e2e_pipe_param->pipe.dest.full_recout_width;
1655	} else
1656		full_recout_width = e2e_pipe_param->pipe.dest.recout_width;
1657
1658	refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery(
1659			mode_lib,
1660			refclk_freq_in_mhz,
1661			pclk_freq_in_mhz,
1662			full_recout_width,
1663			vratio_pre_l,
1664			hscale_pixel_rate_l,
1665			swath_width_pixels_ub_l,
1666			1); /* per line */
1667
1668	refcyc_per_line_delivery_l = get_refcyc_per_delivery(
1669			mode_lib,
1670			refclk_freq_in_mhz,
1671			pclk_freq_in_mhz,
1672			full_recout_width,
1673			vratio_l,
1674			hscale_pixel_rate_l,
1675			swath_width_pixels_ub_l,
1676			1); /* per line */
1677
1678	DTRACE("DLG: %s: full_recout_width              = %d", __func__, full_recout_width);
1679	DTRACE("DLG: %s: hscale_pixel_rate_l            = %3.2f", __func__, hscale_pixel_rate_l);
1680	DTRACE(
1681			"DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f",
1682			__func__,
1683			refcyc_per_line_delivery_pre_l);
1684	DTRACE(
1685			"DLG: %s: refcyc_per_line_delivery_l     = %3.2f",
1686			__func__,
1687			refcyc_per_line_delivery_l);
1688
1689	disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor(
1690			refcyc_per_line_delivery_pre_l,
1691			1);
1692	disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor(
1693			refcyc_per_line_delivery_l,
1694			1);
1695	ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13));
1696	ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13));
1697
1698	if (dual_plane) {
1699		refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery(
1700				mode_lib,
1701				refclk_freq_in_mhz,
1702				pclk_freq_in_mhz,
1703				full_recout_width,
1704				vratio_pre_c,
1705				hscale_pixel_rate_c,
1706				swath_width_pixels_ub_c,
1707				1); /* per line */
1708
1709		refcyc_per_line_delivery_c = get_refcyc_per_delivery(
1710				mode_lib,
1711				refclk_freq_in_mhz,
1712				pclk_freq_in_mhz,
1713				full_recout_width,
1714				vratio_c,
1715				hscale_pixel_rate_c,
1716				swath_width_pixels_ub_c,
1717				1); /* per line */
1718
1719		DTRACE(
1720				"DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f",
1721				__func__,
1722				refcyc_per_line_delivery_pre_c);
1723		DTRACE(
1724				"DLG: %s: refcyc_per_line_delivery_c     = %3.2f",
1725				__func__,
1726				refcyc_per_line_delivery_c);
1727
1728		disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor(
1729				refcyc_per_line_delivery_pre_c,
1730				1);
1731		disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor(
1732				refcyc_per_line_delivery_c,
1733				1);
1734		ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13));
1735		ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13));
1736	}
1737	disp_dlg_regs->chunk_hdl_adjust_cur0 = 3;
1738
1739	/* TTU - Luma / Chroma */
1740	if (access_dir) { /* vertical access */
1741		scaler_rec_in_width_l = vp_height_l;
1742		scaler_rec_in_width_c = vp_height_c;
1743	} else {
1744		scaler_rec_in_width_l = vp_width_l;
1745		scaler_rec_in_width_c = vp_width_c;
1746	}
1747
1748	refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery(
1749			mode_lib,
1750			refclk_freq_in_mhz,
1751			pclk_freq_in_mhz,
1752			full_recout_width,
1753			vratio_pre_l,
1754			hscale_pixel_rate_l,
1755			scaler_rec_in_width_l,
1756			req_per_swath_ub_l); /* per req */
1757	refcyc_per_req_delivery_l = get_refcyc_per_delivery(
1758			mode_lib,
1759			refclk_freq_in_mhz,
1760			pclk_freq_in_mhz,
1761			full_recout_width,
1762			vratio_l,
1763			hscale_pixel_rate_l,
1764			scaler_rec_in_width_l,
1765			req_per_swath_ub_l); /* per req */
1766
1767	DTRACE(
1768			"DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f",
1769			__func__,
1770			refcyc_per_req_delivery_pre_l);
1771	DTRACE(
1772			"DLG: %s: refcyc_per_req_delivery_l     = %3.2f",
1773			__func__,
1774			refcyc_per_req_delivery_l);
1775
1776	disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l
1777			* dml_pow(2, 10));
1778	disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l
1779			* dml_pow(2, 10));
1780
1781	ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13));
1782	ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13));
1783
1784	if (dual_plane) {
1785		refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery(
1786				mode_lib,
1787				refclk_freq_in_mhz,
1788				pclk_freq_in_mhz,
1789				full_recout_width,
1790				vratio_pre_c,
1791				hscale_pixel_rate_c,
1792				scaler_rec_in_width_c,
1793				req_per_swath_ub_c); /* per req  */
1794		refcyc_per_req_delivery_c = get_refcyc_per_delivery(
1795				mode_lib,
1796				refclk_freq_in_mhz,
1797				pclk_freq_in_mhz,
1798				full_recout_width,
1799				vratio_c,
1800				hscale_pixel_rate_c,
1801				scaler_rec_in_width_c,
1802				req_per_swath_ub_c); /* per req */
1803
1804		DTRACE(
1805				"DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f",
1806				__func__,
1807				refcyc_per_req_delivery_pre_c);
1808		DTRACE(
1809				"DLG: %s: refcyc_per_req_delivery_c     = %3.2f",
1810				__func__,
1811				refcyc_per_req_delivery_c);
1812
1813		disp_ttu_regs->refcyc_per_req_delivery_pre_c =
1814				(unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10));
1815		disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c
1816				* dml_pow(2, 10));
1817
1818		ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13));
1819		ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13));
1820	}
1821
1822	/* TTU - Cursor */
1823	hratios_cur0 = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio;
1824	cur0_src_width = e2e_pipe_param->pipe.src.cur0_src_width; /* cursor source width */
1825	cur0_bpp = (enum cursor_bpp) e2e_pipe_param->pipe.src.cur0_bpp;
1826	cur0_req_size = 0;
1827	cur0_req_width = 0;
1828	cur0_width_ub = 0.0;
1829	cur0_req_per_width = 0.0;
1830	hactive_cur0 = 0.0;
1831
1832	ASSERT(cur0_src_width <= 256);
1833
1834	if (cur0_src_width > 0) {
1835		unsigned int cur0_bit_per_pixel = 0;
1836
1837		if (cur0_bpp == dm_cur_2bit) {
1838			cur0_req_size = 64; /* byte */
1839			cur0_bit_per_pixel = 2;
1840		} else { /* 32bit */
1841			cur0_bit_per_pixel = 32;
1842			if (cur0_src_width >= 1 && cur0_src_width <= 16)
1843				cur0_req_size = 64;
1844			else if (cur0_src_width >= 17 && cur0_src_width <= 31)
1845				cur0_req_size = 128;
1846			else
1847				cur0_req_size = 256;
1848		}
1849
1850		cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0);
1851		cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width, 1)
1852				* (double) cur0_req_width;
1853		cur0_req_per_width = cur0_width_ub / (double) cur0_req_width;
1854		hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* TODO: oswin to think about what to do for cursor */
1855
1856		if (vratio_pre_l <= 1.0) {
1857			refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq
1858					/ (double) cur0_req_per_width;
1859		} else {
1860			refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz
1861					* (double) cur0_src_width / hscale_pixel_rate_l
1862					/ (double) cur0_req_per_width;
1863		}
1864
1865		disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 =
1866				(unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10));
1867		ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13));
1868
1869		if (vratio_l <= 1.0) {
1870			refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq
1871					/ (double) cur0_req_per_width;
1872		} else {
1873			refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz
1874					* (double) cur0_src_width / hscale_pixel_rate_l
1875					/ (double) cur0_req_per_width;
1876		}
1877
1878		DTRACE("DLG: %s: cur0_req_width                     = %d", __func__, cur0_req_width);
1879		DTRACE(
1880				"DLG: %s: cur0_width_ub                      = %3.2f",
1881				__func__,
1882				cur0_width_ub);
1883		DTRACE(
1884				"DLG: %s: cur0_req_per_width                 = %3.2f",
1885				__func__,
1886				cur0_req_per_width);
1887		DTRACE(
1888				"DLG: %s: hactive_cur0                       = %3.2f",
1889				__func__,
1890				hactive_cur0);
1891		DTRACE(
1892				"DLG: %s: refcyc_per_req_delivery_pre_cur0   = %3.2f",
1893				__func__,
1894				refcyc_per_req_delivery_pre_cur0);
1895		DTRACE(
1896				"DLG: %s: refcyc_per_req_delivery_cur0       = %3.2f",
1897				__func__,
1898				refcyc_per_req_delivery_cur0);
1899
1900		disp_ttu_regs->refcyc_per_req_delivery_cur0 =
1901				(unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10));
1902		ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13));
1903	} else {
1904		disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0;
1905		disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0;
1906	}
1907
1908	/* TTU - Misc */
1909	disp_ttu_regs->qos_level_low_wm = 0;
1910	ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14));
1911	disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal
1912			* ref_freq_to_pix_freq);
1913	ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14));
1914
1915	disp_ttu_regs->qos_level_flip = 14;
1916	disp_ttu_regs->qos_level_fixed_l = 8;
1917	disp_ttu_regs->qos_level_fixed_c = 8;
1918	disp_ttu_regs->qos_level_fixed_cur0 = 8;
1919	disp_ttu_regs->qos_ramp_disable_l = 0;
1920	disp_ttu_regs->qos_ramp_disable_c = 0;
1921	disp_ttu_regs->qos_ramp_disable_cur0 = 0;
1922
1923	disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz;
1924	ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24));
1925
1926	print__ttu_regs_st(mode_lib, disp_ttu_regs);
1927	print__dlg_regs_st(mode_lib, disp_dlg_regs);
1928}
1929