1 /*
2  * Copyright 2016 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 "dce_mem_input.h"
27 #include "reg_helper.h"
28 #include "basics/conversion.h"
29 
30 #define CTX \
31 	dce_mi->base.ctx
32 #define REG(reg)\
33 	dce_mi->regs->reg
34 
35 #undef FN
36 #define FN(reg_name, field_name) \
37 	dce_mi->shifts->field_name, dce_mi->masks->field_name
38 
39 struct pte_setting {
40 	unsigned int bpp;
41 	unsigned int page_width;
42 	unsigned int page_height;
43 	unsigned char min_pte_before_flip_horiz_scan;
44 	unsigned char min_pte_before_flip_vert_scan;
45 	unsigned char pte_req_per_chunk;
46 	unsigned char param_6;
47 	unsigned char param_7;
48 	unsigned char param_8;
49 };
50 
51 enum mi_bits_per_pixel {
52 	mi_bpp_8 = 0,
53 	mi_bpp_16,
54 	mi_bpp_32,
55 	mi_bpp_64,
56 	mi_bpp_count,
57 };
58 
59 enum mi_tiling_format {
60 	mi_tiling_linear = 0,
61 	mi_tiling_1D,
62 	mi_tiling_2D,
63 	mi_tiling_count,
64 };
65 
66 static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = {
67 	[mi_tiling_linear] = {
68 		{  8, 4096, 1, 8, 0, 1, 0, 0, 0},
69 		{ 16, 2048, 1, 8, 0, 1, 0, 0, 0},
70 		{ 32, 1024, 1, 8, 0, 1, 0, 0, 0},
71 		{ 64,  512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
72 	},
73 	[mi_tiling_1D] = {
74 		{  8, 512, 8, 1, 0, 1, 0, 0, 0},  /* 0 for invalid */
75 		{ 16, 256, 8, 2, 0, 1, 0, 0, 0},
76 		{ 32, 128, 8, 4, 0, 1, 0, 0, 0},
77 		{ 64,  64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
78 	},
79 	[mi_tiling_2D] = {
80 		{  8, 64, 64,  8,  8, 1, 4, 0, 0},
81 		{ 16, 64, 32,  8, 16, 1, 8, 0, 0},
82 		{ 32, 32, 32, 16, 16, 1, 8, 0, 0},
83 		{ 64,  8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
84 	},
85 };
86 
87 static enum mi_bits_per_pixel get_mi_bpp(
88 		enum surface_pixel_format format)
89 {
90 	if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
91 		return mi_bpp_64;
92 	else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
93 		return mi_bpp_32;
94 	else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
95 		return mi_bpp_16;
96 	else
97 		return mi_bpp_8;
98 }
99 
100 static enum mi_tiling_format get_mi_tiling(
101 		union dc_tiling_info *tiling_info)
102 {
103 	switch (tiling_info->gfx8.array_mode) {
104 	case DC_ARRAY_1D_TILED_THIN1:
105 	case DC_ARRAY_1D_TILED_THICK:
106 	case DC_ARRAY_PRT_TILED_THIN1:
107 		return mi_tiling_1D;
108 	case DC_ARRAY_2D_TILED_THIN1:
109 	case DC_ARRAY_2D_TILED_THICK:
110 	case DC_ARRAY_2D_TILED_X_THICK:
111 	case DC_ARRAY_PRT_2D_TILED_THIN1:
112 	case DC_ARRAY_PRT_2D_TILED_THICK:
113 		return mi_tiling_2D;
114 	case DC_ARRAY_LINEAR_GENERAL:
115 	case DC_ARRAY_LINEAR_ALLIGNED:
116 		return mi_tiling_linear;
117 	default:
118 		return mi_tiling_2D;
119 	}
120 }
121 
122 static bool is_vert_scan(enum dc_rotation_angle rotation)
123 {
124 	switch (rotation) {
125 	case ROTATION_ANGLE_90:
126 	case ROTATION_ANGLE_270:
127 		return true;
128 	default:
129 		return false;
130 	}
131 }
132 
133 static void dce_mi_program_pte_vm(
134 		struct mem_input *mi,
135 		enum surface_pixel_format format,
136 		union dc_tiling_info *tiling_info,
137 		enum dc_rotation_angle rotation)
138 {
139 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
140 	enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
141 	enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
142 	const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
143 
144 	unsigned int page_width = log_2(pte->page_width);
145 	unsigned int page_height = log_2(pte->page_height);
146 	unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
147 			pte->min_pte_before_flip_vert_scan :
148 			pte->min_pte_before_flip_horiz_scan;
149 
150 	REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
151 			GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0xff);
152 
153 	REG_UPDATE_3(DVMM_PTE_CONTROL,
154 			DVMM_PAGE_WIDTH, page_width,
155 			DVMM_PAGE_HEIGHT, page_height,
156 			DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip);
157 
158 	REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
159 			DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
160 			DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff);
161 }
162 
163 static void program_urgency_watermark(
164 	struct dce_mem_input *dce_mi,
165 	uint32_t wm_select,
166 	uint32_t urgency_low_wm,
167 	uint32_t urgency_high_wm)
168 {
169 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
170 		URGENCY_WATERMARK_MASK, wm_select);
171 
172 	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
173 		URGENCY_LOW_WATERMARK, urgency_low_wm,
174 		URGENCY_HIGH_WATERMARK, urgency_high_wm);
175 }
176 
177 static void dce120_program_urgency_watermark(
178 	struct dce_mem_input *dce_mi,
179 	uint32_t wm_select,
180 	uint32_t urgency_low_wm,
181 	uint32_t urgency_high_wm)
182 {
183 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
184 		URGENCY_WATERMARK_MASK, wm_select);
185 
186 	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
187 		URGENCY_LOW_WATERMARK, urgency_low_wm,
188 		URGENCY_HIGH_WATERMARK, urgency_high_wm);
189 
190 	REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
191 		URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
192 		URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
193 
194 }
195 
196 static void program_nbp_watermark(
197 	struct dce_mem_input *dce_mi,
198 	uint32_t wm_select,
199 	uint32_t nbp_wm)
200 {
201 	if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
202 		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
203 				NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
204 
205 		REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
206 				NB_PSTATE_CHANGE_ENABLE, 1,
207 				NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
208 				NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
209 
210 		REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
211 				NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
212 	}
213 
214 	if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
215 		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
216 				PSTATE_CHANGE_WATERMARK_MASK, wm_select);
217 
218 		REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
219 				PSTATE_CHANGE_ENABLE, 1,
220 				PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
221 				PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
222 
223 		REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
224 				PSTATE_CHANGE_WATERMARK, nbp_wm);
225 	}
226 }
227 
228 static void dce120_program_stutter_watermark(
229 	struct dce_mem_input *dce_mi,
230 	uint32_t wm_select,
231 	uint32_t stutter_mark,
232 	uint32_t stutter_entry)
233 {
234 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
235 		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
236 
237 	if (REG(DPG_PIPE_STUTTER_CONTROL2))
238 		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
239 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
240 				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
241 	else
242 		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
243 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
244 				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
245 }
246 
247 static void program_stutter_watermark(
248 	struct dce_mem_input *dce_mi,
249 	uint32_t wm_select,
250 	uint32_t stutter_mark)
251 {
252 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
253 		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
254 
255 	if (REG(DPG_PIPE_STUTTER_CONTROL2))
256 		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
257 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
258 	else
259 		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
260 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
261 }
262 
263 static void dce_mi_program_display_marks(
264 	struct mem_input *mi,
265 	struct dce_watermarks nbp,
266 	struct dce_watermarks stutter_exit,
267 	struct dce_watermarks stutter_enter,
268 	struct dce_watermarks urgent,
269 	uint32_t total_dest_line_time_ns)
270 {
271 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
272 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
273 
274 	program_urgency_watermark(dce_mi, 2, /* set a */
275 			urgent.a_mark, total_dest_line_time_ns);
276 	program_urgency_watermark(dce_mi, 1, /* set d */
277 			urgent.d_mark, total_dest_line_time_ns);
278 
279 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
280 		STUTTER_ENABLE, stutter_en,
281 		STUTTER_IGNORE_FBC, 1);
282 	program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
283 	program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
284 
285 	program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
286 	program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
287 }
288 
289 static void dce112_mi_program_display_marks(struct mem_input *mi,
290 	struct dce_watermarks nbp,
291 	struct dce_watermarks stutter_exit,
292 	struct dce_watermarks stutter_entry,
293 	struct dce_watermarks urgent,
294 	uint32_t total_dest_line_time_ns)
295 {
296 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
297 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
298 
299 	program_urgency_watermark(dce_mi, 0, /* set a */
300 			urgent.a_mark, total_dest_line_time_ns);
301 	program_urgency_watermark(dce_mi, 1, /* set b */
302 			urgent.b_mark, total_dest_line_time_ns);
303 	program_urgency_watermark(dce_mi, 2, /* set c */
304 			urgent.c_mark, total_dest_line_time_ns);
305 	program_urgency_watermark(dce_mi, 3, /* set d */
306 			urgent.d_mark, total_dest_line_time_ns);
307 
308 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
309 		STUTTER_ENABLE, stutter_en,
310 		STUTTER_IGNORE_FBC, 1);
311 	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
312 	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
313 	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
314 	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
315 
316 	program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
317 	program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
318 	program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
319 	program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
320 }
321 
322 static void dce120_mi_program_display_marks(struct mem_input *mi,
323 	struct dce_watermarks nbp,
324 	struct dce_watermarks stutter_exit,
325 	struct dce_watermarks stutter_entry,
326 	struct dce_watermarks urgent,
327 	uint32_t total_dest_line_time_ns)
328 {
329 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
330 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
331 
332 	dce120_program_urgency_watermark(dce_mi, 0, /* set a */
333 			urgent.a_mark, total_dest_line_time_ns);
334 	dce120_program_urgency_watermark(dce_mi, 1, /* set b */
335 			urgent.b_mark, total_dest_line_time_ns);
336 	dce120_program_urgency_watermark(dce_mi, 2, /* set c */
337 			urgent.c_mark, total_dest_line_time_ns);
338 	dce120_program_urgency_watermark(dce_mi, 3, /* set d */
339 			urgent.d_mark, total_dest_line_time_ns);
340 
341 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
342 		STUTTER_ENABLE, stutter_en,
343 		STUTTER_IGNORE_FBC, 1);
344 	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
345 	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
346 	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
347 	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
348 
349 	dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
350 	dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
351 	dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
352 	dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
353 }
354 
355 static void program_tiling(
356 	struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
357 {
358 	if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
359 		REG_UPDATE_6(GRPH_CONTROL,
360 				GRPH_SW_MODE, info->gfx9.swizzle,
361 				GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
362 				GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
363 				GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
364 				GRPH_COLOR_EXPANSION_MODE, 1,
365 				GRPH_SE_ENABLE, info->gfx9.shaderEnable);
366 		/* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
367 		GRPH_SE_ENABLE, 1,
368 		GRPH_Z, 0);
369 		 */
370 	}
371 
372 	if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
373 		REG_UPDATE_9(GRPH_CONTROL,
374 				GRPH_NUM_BANKS, info->gfx8.num_banks,
375 				GRPH_BANK_WIDTH, info->gfx8.bank_width,
376 				GRPH_BANK_HEIGHT, info->gfx8.bank_height,
377 				GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
378 				GRPH_TILE_SPLIT, info->gfx8.tile_split,
379 				GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
380 				GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
381 				GRPH_ARRAY_MODE, info->gfx8.array_mode,
382 				GRPH_COLOR_EXPANSION_MODE, 1);
383 		/* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
384 		/*
385 				GRPH_Z, 0);
386 				*/
387 	}
388 }
389 
390 
391 static void program_size_and_rotation(
392 	struct dce_mem_input *dce_mi,
393 	enum dc_rotation_angle rotation,
394 	const union plane_size *plane_size)
395 {
396 	const struct rect *in_rect = &plane_size->grph.surface_size;
397 	struct rect hw_rect = plane_size->grph.surface_size;
398 	const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
399 			[ROTATION_ANGLE_0] = 0,
400 			[ROTATION_ANGLE_90] = 1,
401 			[ROTATION_ANGLE_180] = 2,
402 			[ROTATION_ANGLE_270] = 3,
403 	};
404 
405 	if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
406 		hw_rect.x = in_rect->y;
407 		hw_rect.y = in_rect->x;
408 
409 		hw_rect.height = in_rect->width;
410 		hw_rect.width = in_rect->height;
411 	}
412 
413 	REG_SET(GRPH_X_START, 0,
414 			GRPH_X_START, hw_rect.x);
415 
416 	REG_SET(GRPH_Y_START, 0,
417 			GRPH_Y_START, hw_rect.y);
418 
419 	REG_SET(GRPH_X_END, 0,
420 			GRPH_X_END, hw_rect.width);
421 
422 	REG_SET(GRPH_Y_END, 0,
423 			GRPH_Y_END, hw_rect.height);
424 
425 	REG_SET(GRPH_PITCH, 0,
426 			GRPH_PITCH, plane_size->grph.surface_pitch);
427 
428 	REG_SET(HW_ROTATION, 0,
429 			GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
430 }
431 
432 static void program_grph_pixel_format(
433 	struct dce_mem_input *dce_mi,
434 	enum surface_pixel_format format)
435 {
436 	uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
437 	uint32_t grph_depth = 0, grph_format = 0;
438 	uint32_t sign = 0, floating = 0;
439 
440 	if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
441 			/*todo: doesn't look like we handle BGRA here,
442 			 *  should problem swap endian*/
443 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
444 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
445 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
446 		/* ABGR formats */
447 		red_xbar = 2;
448 		blue_xbar = 2;
449 	}
450 
451 	REG_SET_2(GRPH_SWAP_CNTL, 0,
452 			GRPH_RED_CROSSBAR, red_xbar,
453 			GRPH_BLUE_CROSSBAR, blue_xbar);
454 
455 	switch (format) {
456 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
457 		grph_depth = 0;
458 		grph_format = 0;
459 		break;
460 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
461 		grph_depth = 1;
462 		grph_format = 0;
463 		break;
464 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
465 		grph_depth = 1;
466 		grph_format = 1;
467 		break;
468 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
469 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
470 		grph_depth = 2;
471 		grph_format = 0;
472 		break;
473 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
474 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
475 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
476 		grph_depth = 2;
477 		grph_format = 1;
478 		break;
479 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
480 		sign = 1;
481 		floating = 1;
482 		/* no break */
483 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
484 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
485 		grph_depth = 3;
486 		grph_format = 0;
487 		break;
488 	default:
489 		DC_ERR("unsupported grph pixel format");
490 		break;
491 	}
492 
493 	REG_UPDATE_2(GRPH_CONTROL,
494 			GRPH_DEPTH, grph_depth,
495 			GRPH_FORMAT, grph_format);
496 
497 	REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
498 			GRPH_PRESCALE_SELECT, floating,
499 			GRPH_PRESCALE_R_SIGN, sign,
500 			GRPH_PRESCALE_G_SIGN, sign,
501 			GRPH_PRESCALE_B_SIGN, sign);
502 }
503 
504 static void dce_mi_program_surface_config(
505 	struct mem_input *mi,
506 	enum surface_pixel_format format,
507 	union dc_tiling_info *tiling_info,
508 	union plane_size *plane_size,
509 	enum dc_rotation_angle rotation,
510 	struct dc_plane_dcc_param *dcc,
511 	bool horizontal_mirror)
512 {
513 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
514 	REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
515 
516 	program_tiling(dce_mi, tiling_info);
517 	program_size_and_rotation(dce_mi, rotation, plane_size);
518 
519 	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
520 		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
521 		program_grph_pixel_format(dce_mi, format);
522 }
523 
524 static uint32_t get_dmif_switch_time_us(
525 	uint32_t h_total,
526 	uint32_t v_total,
527 	uint32_t pix_clk_khz)
528 {
529 	uint32_t frame_time;
530 	uint32_t pixels_per_second;
531 	uint32_t pixels_per_frame;
532 	uint32_t refresh_rate;
533 	const uint32_t us_in_sec = 1000000;
534 	const uint32_t min_single_frame_time_us = 30000;
535 	/*return double of frame time*/
536 	const uint32_t single_frame_time_multiplier = 2;
537 
538 	if (!h_total || v_total || !pix_clk_khz)
539 		return single_frame_time_multiplier * min_single_frame_time_us;
540 
541 	/*TODO: should we use pixel format normalized pixel clock here?*/
542 	pixels_per_second = pix_clk_khz * 1000;
543 	pixels_per_frame = h_total * v_total;
544 
545 	if (!pixels_per_second || !pixels_per_frame) {
546 		/* avoid division by zero */
547 		ASSERT(pixels_per_frame);
548 		ASSERT(pixels_per_second);
549 		return single_frame_time_multiplier * min_single_frame_time_us;
550 	}
551 
552 	refresh_rate = pixels_per_second / pixels_per_frame;
553 
554 	if (!refresh_rate) {
555 		/* avoid division by zero*/
556 		ASSERT(refresh_rate);
557 		return single_frame_time_multiplier * min_single_frame_time_us;
558 	}
559 
560 	frame_time = us_in_sec / refresh_rate;
561 
562 	if (frame_time < min_single_frame_time_us)
563 		frame_time = min_single_frame_time_us;
564 
565 	frame_time *= single_frame_time_multiplier;
566 
567 	return frame_time;
568 }
569 
570 static void dce_mi_allocate_dmif(
571 	struct mem_input *mi,
572 	uint32_t h_total,
573 	uint32_t v_total,
574 	uint32_t pix_clk_khz,
575 	uint32_t total_stream_num)
576 {
577 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
578 	const uint32_t retry_delay = 10;
579 	uint32_t retry_count = get_dmif_switch_time_us(
580 			h_total,
581 			v_total,
582 			pix_clk_khz) / retry_delay;
583 
584 	uint32_t pix_dur;
585 	uint32_t buffers_allocated;
586 	uint32_t dmif_buffer_control;
587 
588 	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
589 			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
590 
591 	if (buffers_allocated == 2)
592 		return;
593 
594 	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
595 			DMIF_BUFFERS_ALLOCATED, 2);
596 
597 	REG_WAIT(DMIF_BUFFER_CONTROL,
598 			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
599 			retry_delay, retry_count);
600 
601 	if (pix_clk_khz != 0) {
602 		pix_dur = 1000000000ULL / pix_clk_khz;
603 
604 		REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
605 			PIXEL_DURATION, pix_dur);
606 	}
607 
608 	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
609 		uint32_t eanble =  (total_stream_num > 1) ? 0 :
610 				dce_mi->wa.single_head_rdreq_dmif_limit;
611 
612 		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
613 				ENABLE, eanble);
614 	}
615 }
616 
617 static void dce_mi_free_dmif(
618 		struct mem_input *mi,
619 		uint32_t total_stream_num)
620 {
621 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
622 	uint32_t buffers_allocated;
623 	uint32_t dmif_buffer_control;
624 
625 	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
626 			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
627 
628 	if (buffers_allocated == 0)
629 		return;
630 
631 	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
632 			DMIF_BUFFERS_ALLOCATED, 0);
633 
634 	REG_WAIT(DMIF_BUFFER_CONTROL,
635 			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
636 			10, 3500);
637 
638 	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
639 		uint32_t eanble =  (total_stream_num > 1) ? 0 :
640 				dce_mi->wa.single_head_rdreq_dmif_limit;
641 
642 		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
643 				ENABLE, eanble);
644 	}
645 }
646 
647 
648 static void program_sec_addr(
649 	struct dce_mem_input *dce_mi,
650 	PHYSICAL_ADDRESS_LOC address)
651 {
652 	/*high register MUST be programmed first*/
653 	REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
654 		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
655 		address.high_part);
656 
657 	REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
658 		GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
659 		GRPH_SECONDARY_DFQ_ENABLE, 0);
660 }
661 
662 static void program_pri_addr(
663 	struct dce_mem_input *dce_mi,
664 	PHYSICAL_ADDRESS_LOC address)
665 {
666 	/*high register MUST be programmed first*/
667 	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
668 		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
669 		address.high_part);
670 
671 	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
672 		GRPH_PRIMARY_SURFACE_ADDRESS,
673 		address.low_part >> 8);
674 }
675 
676 
677 static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
678 {
679 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
680 	uint32_t update_pending;
681 
682 	REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
683 	if (update_pending)
684 		return true;
685 
686 	mem_input->current_address = mem_input->request_address;
687 	return false;
688 }
689 
690 static bool dce_mi_program_surface_flip_and_addr(
691 	struct mem_input *mem_input,
692 	const struct dc_plane_address *address,
693 	bool flip_immediate)
694 {
695 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
696 
697 	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
698 
699 	REG_UPDATE(
700 		GRPH_FLIP_CONTROL,
701 		GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
702 
703 	switch (address->type) {
704 	case PLN_ADDR_TYPE_GRAPHICS:
705 		if (address->grph.addr.quad_part == 0)
706 			break;
707 		program_pri_addr(dce_mi, address->grph.addr);
708 		break;
709 	case PLN_ADDR_TYPE_GRPH_STEREO:
710 		if (address->grph_stereo.left_addr.quad_part == 0 ||
711 		    address->grph_stereo.right_addr.quad_part == 0)
712 			break;
713 		program_pri_addr(dce_mi, address->grph_stereo.left_addr);
714 		program_sec_addr(dce_mi, address->grph_stereo.right_addr);
715 		break;
716 	default:
717 		/* not supported */
718 		BREAK_TO_DEBUGGER();
719 		break;
720 	}
721 
722 	mem_input->request_address = *address;
723 
724 	if (flip_immediate)
725 		mem_input->current_address = *address;
726 
727 	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
728 
729 	return true;
730 }
731 
732 static const struct mem_input_funcs dce_mi_funcs = {
733 	.mem_input_program_display_marks = dce_mi_program_display_marks,
734 	.allocate_mem_input = dce_mi_allocate_dmif,
735 	.free_mem_input = dce_mi_free_dmif,
736 	.mem_input_program_surface_flip_and_addr =
737 			dce_mi_program_surface_flip_and_addr,
738 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
739 	.mem_input_program_surface_config =
740 			dce_mi_program_surface_config,
741 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
742 };
743 
744 static const struct mem_input_funcs dce112_mi_funcs = {
745 	.mem_input_program_display_marks = dce112_mi_program_display_marks,
746 	.allocate_mem_input = dce_mi_allocate_dmif,
747 	.free_mem_input = dce_mi_free_dmif,
748 	.mem_input_program_surface_flip_and_addr =
749 			dce_mi_program_surface_flip_and_addr,
750 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
751 	.mem_input_program_surface_config =
752 			dce_mi_program_surface_config,
753 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
754 };
755 
756 static const struct mem_input_funcs dce120_mi_funcs = {
757 	.mem_input_program_display_marks = dce120_mi_program_display_marks,
758 	.allocate_mem_input = dce_mi_allocate_dmif,
759 	.free_mem_input = dce_mi_free_dmif,
760 	.mem_input_program_surface_flip_and_addr =
761 			dce_mi_program_surface_flip_and_addr,
762 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
763 	.mem_input_program_surface_config =
764 			dce_mi_program_surface_config,
765 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
766 };
767 
768 void dce_mem_input_construct(
769 	struct dce_mem_input *dce_mi,
770 	struct dc_context *ctx,
771 	int inst,
772 	const struct dce_mem_input_registers *regs,
773 	const struct dce_mem_input_shift *mi_shift,
774 	const struct dce_mem_input_mask *mi_mask)
775 {
776 	dce_mi->base.ctx = ctx;
777 
778 	dce_mi->base.inst = inst;
779 	dce_mi->base.funcs = &dce_mi_funcs;
780 
781 	dce_mi->regs = regs;
782 	dce_mi->shifts = mi_shift;
783 	dce_mi->masks = mi_mask;
784 }
785 
786 void dce112_mem_input_construct(
787 	struct dce_mem_input *dce_mi,
788 	struct dc_context *ctx,
789 	int inst,
790 	const struct dce_mem_input_registers *regs,
791 	const struct dce_mem_input_shift *mi_shift,
792 	const struct dce_mem_input_mask *mi_mask)
793 {
794 	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
795 	dce_mi->base.funcs = &dce112_mi_funcs;
796 }
797 
798 void dce120_mem_input_construct(
799 	struct dce_mem_input *dce_mi,
800 	struct dc_context *ctx,
801 	int inst,
802 	const struct dce_mem_input_registers *regs,
803 	const struct dce_mem_input_shift *mi_shift,
804 	const struct dce_mem_input_mask *mi_mask)
805 {
806 	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
807 	dce_mi->base.funcs = &dce120_mi_funcs;
808 }
809