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