Linux Audio

Check our new training course

Loading...
v6.9.4
  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
 39struct 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
 51enum 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
 59enum mi_tiling_format {
 60	mi_tiling_linear = 0,
 61	mi_tiling_1D,
 62	mi_tiling_2D,
 63	mi_tiling_count,
 64};
 65
 66static 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
 87static 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
100static 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
122static 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
133static 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, 0x7f);
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, 0x7f);
161}
162
163static 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#if defined(CONFIG_DRM_AMD_DC_SI)
178static void dce60_program_urgency_watermark(
179	struct dce_mem_input *dce_mi,
180	uint32_t wm_select,
181	uint32_t urgency_low_wm,
182	uint32_t urgency_high_wm)
183{
184	REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL3,
185		URGENCY_WATERMARK_MASK, wm_select);
186
187	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
188		URGENCY_LOW_WATERMARK, urgency_low_wm,
189		URGENCY_HIGH_WATERMARK, urgency_high_wm);
190}
191#endif
192
193static void dce120_program_urgency_watermark(
194	struct dce_mem_input *dce_mi,
195	uint32_t wm_select,
196	uint32_t urgency_low_wm,
197	uint32_t urgency_high_wm)
198{
199	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
200		URGENCY_WATERMARK_MASK, wm_select);
201
202	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
203		URGENCY_LOW_WATERMARK, urgency_low_wm,
204		URGENCY_HIGH_WATERMARK, urgency_high_wm);
205
206	REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
207		URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
208		URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
209
210}
211
212#if defined(CONFIG_DRM_AMD_DC_SI)
213static void dce60_program_nbp_watermark(
214	struct dce_mem_input *dce_mi,
215	uint32_t wm_select,
216	uint32_t nbp_wm)
217{
218	REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
219		NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
220
221	REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
222		NB_PSTATE_CHANGE_ENABLE, 1,
223		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
224		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
225
226	REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
227		NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
228}
229#endif
230
231static void program_nbp_watermark(
232	struct dce_mem_input *dce_mi,
233	uint32_t wm_select,
234	uint32_t nbp_wm)
235{
236	if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
237		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
238				NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
239
240		REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
241				NB_PSTATE_CHANGE_ENABLE, 1,
242				NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
243				NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
244
245		REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
246				NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
247	}
248
249	if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
250		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
251				PSTATE_CHANGE_WATERMARK_MASK, wm_select);
252
253		REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
254				PSTATE_CHANGE_ENABLE, 1,
255				PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
256				PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
257
258		REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
259				PSTATE_CHANGE_WATERMARK, nbp_wm);
260	}
261}
262
263#if defined(CONFIG_DRM_AMD_DC_SI)
264static void dce60_program_stutter_watermark(
265	struct dce_mem_input *dce_mi,
266	uint32_t wm_select,
267	uint32_t stutter_mark)
268{
269	REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
270		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
271
272	REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
273		STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
274}
275#endif
276
277static void dce120_program_stutter_watermark(
278	struct dce_mem_input *dce_mi,
279	uint32_t wm_select,
280	uint32_t stutter_mark,
281	uint32_t stutter_entry)
282{
283	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
284		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
285
286	if (REG(DPG_PIPE_STUTTER_CONTROL2))
287		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
288				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
289				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
290	else
291		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
292				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
293				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
294}
295
296static void program_stutter_watermark(
297	struct dce_mem_input *dce_mi,
298	uint32_t wm_select,
299	uint32_t stutter_mark)
300{
301	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
302		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
303
304	if (REG(DPG_PIPE_STUTTER_CONTROL2))
305		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
306				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
307	else
308		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
309				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
310}
311
312static void dce_mi_program_display_marks(
313	struct mem_input *mi,
314	struct dce_watermarks nbp,
315	struct dce_watermarks stutter_exit,
316	struct dce_watermarks stutter_enter,
317	struct dce_watermarks urgent,
318	uint32_t total_dest_line_time_ns)
319{
320	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
321	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
322
323	program_urgency_watermark(dce_mi, 2, /* set a */
324			urgent.a_mark, total_dest_line_time_ns);
325	program_urgency_watermark(dce_mi, 1, /* set d */
326			urgent.d_mark, total_dest_line_time_ns);
327
328	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
329		STUTTER_ENABLE, stutter_en,
330		STUTTER_IGNORE_FBC, 1);
331	program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
332	program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
333
334	program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
335	program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
336}
337
338#if defined(CONFIG_DRM_AMD_DC_SI)
339static void dce60_mi_program_display_marks(
340	struct mem_input *mi,
341	struct dce_watermarks nbp,
342	struct dce_watermarks stutter_exit,
343	struct dce_watermarks stutter_enter,
344	struct dce_watermarks urgent,
345	uint32_t total_dest_line_time_ns)
346{
347	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
348	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
349
350	dce60_program_urgency_watermark(dce_mi, 2, /* set a */
351			urgent.a_mark, total_dest_line_time_ns);
352	dce60_program_urgency_watermark(dce_mi, 1, /* set d */
353			urgent.d_mark, total_dest_line_time_ns);
354
355	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
356		STUTTER_ENABLE, stutter_en,
357		STUTTER_IGNORE_FBC, 1);
358	dce60_program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
359	dce60_program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
360
361	dce60_program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
362	dce60_program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
363}
364#endif
365
366static void dce112_mi_program_display_marks(struct mem_input *mi,
367	struct dce_watermarks nbp,
368	struct dce_watermarks stutter_exit,
369	struct dce_watermarks stutter_entry,
370	struct dce_watermarks urgent,
371	uint32_t total_dest_line_time_ns)
372{
373	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
374	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
375
376	program_urgency_watermark(dce_mi, 0, /* set a */
377			urgent.a_mark, total_dest_line_time_ns);
378	program_urgency_watermark(dce_mi, 1, /* set b */
379			urgent.b_mark, total_dest_line_time_ns);
380	program_urgency_watermark(dce_mi, 2, /* set c */
381			urgent.c_mark, total_dest_line_time_ns);
382	program_urgency_watermark(dce_mi, 3, /* set d */
383			urgent.d_mark, total_dest_line_time_ns);
384
385	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
386		STUTTER_ENABLE, stutter_en,
387		STUTTER_IGNORE_FBC, 1);
388	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
389	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
390	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
391	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
392
393	program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
394	program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
395	program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
396	program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
397}
398
399static void dce120_mi_program_display_marks(struct mem_input *mi,
400	struct dce_watermarks nbp,
401	struct dce_watermarks stutter_exit,
402	struct dce_watermarks stutter_entry,
403	struct dce_watermarks urgent,
404	uint32_t total_dest_line_time_ns)
405{
406	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
407	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
408
409	dce120_program_urgency_watermark(dce_mi, 0, /* set a */
410			urgent.a_mark, total_dest_line_time_ns);
411	dce120_program_urgency_watermark(dce_mi, 1, /* set b */
412			urgent.b_mark, total_dest_line_time_ns);
413	dce120_program_urgency_watermark(dce_mi, 2, /* set c */
414			urgent.c_mark, total_dest_line_time_ns);
415	dce120_program_urgency_watermark(dce_mi, 3, /* set d */
416			urgent.d_mark, total_dest_line_time_ns);
417
418	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
419		STUTTER_ENABLE, stutter_en,
420		STUTTER_IGNORE_FBC, 1);
421	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
422	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
423	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
424	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
425
426	dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
427	dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
428	dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
429	dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
430}
431
432static void program_tiling(
433	struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
434{
435	if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
436		REG_UPDATE_6(GRPH_CONTROL,
437				GRPH_SW_MODE, info->gfx9.swizzle,
438				GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
439				GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
440				GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
441				GRPH_COLOR_EXPANSION_MODE, 1,
442				GRPH_SE_ENABLE, info->gfx9.shaderEnable);
443		/* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
444		GRPH_SE_ENABLE, 1,
445		GRPH_Z, 0);
446		 */
447	}
448
449	if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */
450		REG_UPDATE_9(GRPH_CONTROL,
451				GRPH_NUM_BANKS, info->gfx8.num_banks,
452				GRPH_BANK_WIDTH, info->gfx8.bank_width,
453				GRPH_BANK_HEIGHT, info->gfx8.bank_height,
454				GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
455				GRPH_TILE_SPLIT, info->gfx8.tile_split,
456				GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
457				GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
458				GRPH_ARRAY_MODE, info->gfx8.array_mode,
459				GRPH_COLOR_EXPANSION_MODE, 1);
460		/* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
461		/*
462				GRPH_Z, 0);
463				*/
464	}
465
466	if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */
467		REG_UPDATE_8(GRPH_CONTROL,
468				GRPH_NUM_BANKS, info->gfx8.num_banks,
469				GRPH_BANK_WIDTH, info->gfx8.bank_width,
470				GRPH_BANK_HEIGHT, info->gfx8.bank_height,
471				GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
472				GRPH_TILE_SPLIT, info->gfx8.tile_split,
473				/* DCE6 has no GRPH_MICRO_TILE_MODE mask */
474				GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
475				GRPH_ARRAY_MODE, info->gfx8.array_mode,
476				GRPH_COLOR_EXPANSION_MODE, 1);
477		/* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
478		/*
479				GRPH_Z, 0);
480				*/
481	}
482}
483
484
485static void program_size_and_rotation(
486	struct dce_mem_input *dce_mi,
487	enum dc_rotation_angle rotation,
488	const struct plane_size *plane_size)
489{
490	const struct rect *in_rect = &plane_size->surface_size;
491	struct rect hw_rect = plane_size->surface_size;
492	const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
493			[ROTATION_ANGLE_0] = 0,
494			[ROTATION_ANGLE_90] = 1,
495			[ROTATION_ANGLE_180] = 2,
496			[ROTATION_ANGLE_270] = 3,
497	};
498
499	if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
500		hw_rect.x = in_rect->y;
501		hw_rect.y = in_rect->x;
502
503		hw_rect.height = in_rect->width;
504		hw_rect.width = in_rect->height;
505	}
506
507	REG_SET(GRPH_X_START, 0,
508			GRPH_X_START, hw_rect.x);
509
510	REG_SET(GRPH_Y_START, 0,
511			GRPH_Y_START, hw_rect.y);
512
513	REG_SET(GRPH_X_END, 0,
514			GRPH_X_END, hw_rect.width);
515
516	REG_SET(GRPH_Y_END, 0,
517			GRPH_Y_END, hw_rect.height);
518
519	REG_SET(GRPH_PITCH, 0,
520			GRPH_PITCH, plane_size->surface_pitch);
521
522	REG_SET(HW_ROTATION, 0,
523			GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
524}
525
526#if defined(CONFIG_DRM_AMD_DC_SI)
527static void dce60_program_size(
528	struct dce_mem_input *dce_mi,
529	enum dc_rotation_angle rotation, /* not used in DCE6 */
530	const struct plane_size *plane_size)
531{
532	struct rect hw_rect = plane_size->surface_size;
533	/* DCE6 has no HW rotation, skip rotation_angles declaration */
534
535	/* DCE6 has no HW rotation, skip ROTATION_ANGLE_* processing */
536
537	REG_SET(GRPH_X_START, 0,
538			GRPH_X_START, hw_rect.x);
539
540	REG_SET(GRPH_Y_START, 0,
541			GRPH_Y_START, hw_rect.y);
542
543	REG_SET(GRPH_X_END, 0,
544			GRPH_X_END, hw_rect.width);
545
546	REG_SET(GRPH_Y_END, 0,
547			GRPH_Y_END, hw_rect.height);
548
549	REG_SET(GRPH_PITCH, 0,
550			GRPH_PITCH, plane_size->surface_pitch);
551
552	/* DCE6 has no HW_ROTATION register, skip setting rotation_angles */
553}
554#endif
555
556static void program_grph_pixel_format(
557	struct dce_mem_input *dce_mi,
558	enum surface_pixel_format format)
559{
560	uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
561	uint32_t grph_depth = 0, grph_format = 0;
562	uint32_t sign = 0, floating = 0;
563
564	if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
565			/*todo: doesn't look like we handle BGRA here,
566			 *  should problem swap endian*/
567		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
568		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
569		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 ||
570		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
571		/* ABGR formats */
572		red_xbar = 2;
573		blue_xbar = 2;
574	}
575
576	REG_SET_2(GRPH_SWAP_CNTL, 0,
577			GRPH_RED_CROSSBAR, red_xbar,
578			GRPH_BLUE_CROSSBAR, blue_xbar);
579
580	switch (format) {
581	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
582		grph_depth = 0;
583		grph_format = 0;
584		break;
585	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
586		grph_depth = 1;
587		grph_format = 0;
588		break;
589	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
590		grph_depth = 1;
591		grph_format = 1;
592		break;
593	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
594	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
595		grph_depth = 2;
596		grph_format = 0;
597		break;
598	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
599	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
600	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
601		grph_depth = 2;
602		grph_format = 1;
603		break;
604	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
605		sign = 1;
606		floating = 1;
607		fallthrough;
608	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
609	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
610	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
611		grph_depth = 3;
612		grph_format = 0;
613		break;
614	default:
615		DC_ERR("unsupported grph pixel format");
616		break;
617	}
618
619	REG_UPDATE_2(GRPH_CONTROL,
620			GRPH_DEPTH, grph_depth,
621			GRPH_FORMAT, grph_format);
622
623	REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
624			GRPH_PRESCALE_SELECT, floating,
625			GRPH_PRESCALE_R_SIGN, sign,
626			GRPH_PRESCALE_G_SIGN, sign,
627			GRPH_PRESCALE_B_SIGN, sign);
628}
629
630static void dce_mi_program_surface_config(
631	struct mem_input *mi,
632	enum surface_pixel_format format,
633	union dc_tiling_info *tiling_info,
634	struct plane_size *plane_size,
635	enum dc_rotation_angle rotation,
636	struct dc_plane_dcc_param *dcc,
637	bool horizontal_mirror)
638{
639	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
640	REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
641
642	program_tiling(dce_mi, tiling_info);
643	program_size_and_rotation(dce_mi, rotation, plane_size);
644
645	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
646		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
647		program_grph_pixel_format(dce_mi, format);
648}
649
650#if defined(CONFIG_DRM_AMD_DC_SI)
651static void dce60_mi_program_surface_config(
652	struct mem_input *mi,
653	enum surface_pixel_format format,
654	union dc_tiling_info *tiling_info,
655	struct plane_size *plane_size,
656	enum dc_rotation_angle rotation, /* not used in DCE6 */
657	struct dc_plane_dcc_param *dcc,
658	bool horizontal_mirror)
659{
660	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
661	REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
662
663	program_tiling(dce_mi, tiling_info);
664	dce60_program_size(dce_mi, rotation, plane_size);
665
666	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
667		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
668		program_grph_pixel_format(dce_mi, format);
669}
670#endif
671
672static uint32_t get_dmif_switch_time_us(
673	uint32_t h_total,
674	uint32_t v_total,
675	uint32_t pix_clk_khz)
676{
677	uint32_t frame_time;
678	uint32_t pixels_per_second;
679	uint32_t pixels_per_frame;
680	uint32_t refresh_rate;
681	const uint32_t us_in_sec = 1000000;
682	const uint32_t min_single_frame_time_us = 30000;
683	/*return double of frame time*/
684	const uint32_t single_frame_time_multiplier = 2;
685
686	if (!h_total || v_total || !pix_clk_khz)
687		return single_frame_time_multiplier * min_single_frame_time_us;
688
689	/*TODO: should we use pixel format normalized pixel clock here?*/
690	pixels_per_second = pix_clk_khz * 1000;
691	pixels_per_frame = h_total * v_total;
692
693	if (!pixels_per_second || !pixels_per_frame) {
694		/* avoid division by zero */
695		ASSERT(pixels_per_frame);
696		ASSERT(pixels_per_second);
697		return single_frame_time_multiplier * min_single_frame_time_us;
698	}
699
700	refresh_rate = pixels_per_second / pixels_per_frame;
701
702	if (!refresh_rate) {
703		/* avoid division by zero*/
704		ASSERT(refresh_rate);
705		return single_frame_time_multiplier * min_single_frame_time_us;
706	}
707
708	frame_time = us_in_sec / refresh_rate;
709
710	if (frame_time < min_single_frame_time_us)
711		frame_time = min_single_frame_time_us;
712
713	frame_time *= single_frame_time_multiplier;
714
715	return frame_time;
716}
717
718static void dce_mi_allocate_dmif(
719	struct mem_input *mi,
720	uint32_t h_total,
721	uint32_t v_total,
722	uint32_t pix_clk_khz,
723	uint32_t total_stream_num)
724{
725	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
726	const uint32_t retry_delay = 10;
727	uint32_t retry_count = get_dmif_switch_time_us(
728			h_total,
729			v_total,
730			pix_clk_khz) / retry_delay;
731
732	uint32_t pix_dur;
733	uint32_t buffers_allocated;
734	uint32_t dmif_buffer_control;
735
736	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
737			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
738
739	if (buffers_allocated == 2)
740		return;
741
742	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
743			DMIF_BUFFERS_ALLOCATED, 2);
744
745	REG_WAIT(DMIF_BUFFER_CONTROL,
746			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
747			retry_delay, retry_count);
748
749	if (pix_clk_khz != 0) {
750		pix_dur = 1000000000ULL / pix_clk_khz;
751
752		REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
753			PIXEL_DURATION, pix_dur);
754	}
755
756	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
757		uint32_t enable =  (total_stream_num > 1) ? 0 :
758				dce_mi->wa.single_head_rdreq_dmif_limit;
759
760		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
761				ENABLE, enable);
762	}
763}
764
765static void dce_mi_free_dmif(
766		struct mem_input *mi,
767		uint32_t total_stream_num)
768{
769	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
770	uint32_t buffers_allocated;
771	uint32_t dmif_buffer_control;
772
773	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
774			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
775
776	if (buffers_allocated == 0)
777		return;
778
779	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
780			DMIF_BUFFERS_ALLOCATED, 0);
781
782	REG_WAIT(DMIF_BUFFER_CONTROL,
783			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
784			10, 3500);
785
786	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
787		uint32_t enable =  (total_stream_num > 1) ? 0 :
788				dce_mi->wa.single_head_rdreq_dmif_limit;
789
790		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
791				ENABLE, enable);
792	}
793}
794
795
796static void program_sec_addr(
797	struct dce_mem_input *dce_mi,
798	PHYSICAL_ADDRESS_LOC address)
799{
800	/*high register MUST be programmed first*/
801	REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
802		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
803		address.high_part);
804
805	REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
806		GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
807		GRPH_SECONDARY_DFQ_ENABLE, 0);
808}
809
810static void program_pri_addr(
811	struct dce_mem_input *dce_mi,
812	PHYSICAL_ADDRESS_LOC address)
813{
814	/*high register MUST be programmed first*/
815	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
816		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
817		address.high_part);
818
819	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
820		GRPH_PRIMARY_SURFACE_ADDRESS,
821		address.low_part >> 8);
822}
823
824
825static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
826{
827	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
828	uint32_t update_pending;
829
830	REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
831	if (update_pending)
832		return true;
833
834	mem_input->current_address = mem_input->request_address;
835	return false;
836}
837
838static bool dce_mi_program_surface_flip_and_addr(
839	struct mem_input *mem_input,
840	const struct dc_plane_address *address,
841	bool flip_immediate)
842{
843	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
844
845	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
846
847	REG_UPDATE(
848		GRPH_FLIP_CONTROL,
849		GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
850
851	switch (address->type) {
852	case PLN_ADDR_TYPE_GRAPHICS:
853		if (address->grph.addr.quad_part == 0)
854			break;
855		program_pri_addr(dce_mi, address->grph.addr);
856		break;
857	case PLN_ADDR_TYPE_GRPH_STEREO:
858		if (address->grph_stereo.left_addr.quad_part == 0 ||
859		    address->grph_stereo.right_addr.quad_part == 0)
860			break;
861		program_pri_addr(dce_mi, address->grph_stereo.left_addr);
862		program_sec_addr(dce_mi, address->grph_stereo.right_addr);
863		break;
864	default:
865		/* not supported */
866		BREAK_TO_DEBUGGER();
867		break;
868	}
869
870	mem_input->request_address = *address;
871
872	if (flip_immediate)
873		mem_input->current_address = *address;
874
875	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
876
877	return true;
878}
879
880static const struct mem_input_funcs dce_mi_funcs = {
881	.mem_input_program_display_marks = dce_mi_program_display_marks,
882	.allocate_mem_input = dce_mi_allocate_dmif,
883	.free_mem_input = dce_mi_free_dmif,
884	.mem_input_program_surface_flip_and_addr =
885			dce_mi_program_surface_flip_and_addr,
886	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
887	.mem_input_program_surface_config =
888			dce_mi_program_surface_config,
889	.mem_input_is_flip_pending = dce_mi_is_flip_pending
890};
891
892#if defined(CONFIG_DRM_AMD_DC_SI)
893static const struct mem_input_funcs dce60_mi_funcs = {
894	.mem_input_program_display_marks = dce60_mi_program_display_marks,
895	.allocate_mem_input = dce_mi_allocate_dmif,
896	.free_mem_input = dce_mi_free_dmif,
897	.mem_input_program_surface_flip_and_addr =
898			dce_mi_program_surface_flip_and_addr,
899	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
900	.mem_input_program_surface_config =
901			dce60_mi_program_surface_config,
902	.mem_input_is_flip_pending = dce_mi_is_flip_pending
903};
904#endif
905
906static const struct mem_input_funcs dce112_mi_funcs = {
907	.mem_input_program_display_marks = dce112_mi_program_display_marks,
908	.allocate_mem_input = dce_mi_allocate_dmif,
909	.free_mem_input = dce_mi_free_dmif,
910	.mem_input_program_surface_flip_and_addr =
911			dce_mi_program_surface_flip_and_addr,
912	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
913	.mem_input_program_surface_config =
914			dce_mi_program_surface_config,
915	.mem_input_is_flip_pending = dce_mi_is_flip_pending
916};
917
918static const struct mem_input_funcs dce120_mi_funcs = {
919	.mem_input_program_display_marks = dce120_mi_program_display_marks,
920	.allocate_mem_input = dce_mi_allocate_dmif,
921	.free_mem_input = dce_mi_free_dmif,
922	.mem_input_program_surface_flip_and_addr =
923			dce_mi_program_surface_flip_and_addr,
924	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
925	.mem_input_program_surface_config =
926			dce_mi_program_surface_config,
927	.mem_input_is_flip_pending = dce_mi_is_flip_pending
928};
929
930void dce_mem_input_construct(
931	struct dce_mem_input *dce_mi,
932	struct dc_context *ctx,
933	int inst,
934	const struct dce_mem_input_registers *regs,
935	const struct dce_mem_input_shift *mi_shift,
936	const struct dce_mem_input_mask *mi_mask)
937{
938	dce_mi->base.ctx = ctx;
939
940	dce_mi->base.inst = inst;
941	dce_mi->base.funcs = &dce_mi_funcs;
942
943	dce_mi->regs = regs;
944	dce_mi->shifts = mi_shift;
945	dce_mi->masks = mi_mask;
946}
947
948#if defined(CONFIG_DRM_AMD_DC_SI)
949void dce60_mem_input_construct(
950	struct dce_mem_input *dce_mi,
951	struct dc_context *ctx,
952	int inst,
953	const struct dce_mem_input_registers *regs,
954	const struct dce_mem_input_shift *mi_shift,
955	const struct dce_mem_input_mask *mi_mask)
956{
957	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
958	dce_mi->base.funcs = &dce60_mi_funcs;
959}
960#endif
961
962void dce112_mem_input_construct(
963	struct dce_mem_input *dce_mi,
964	struct dc_context *ctx,
965	int inst,
966	const struct dce_mem_input_registers *regs,
967	const struct dce_mem_input_shift *mi_shift,
968	const struct dce_mem_input_mask *mi_mask)
969{
970	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
971	dce_mi->base.funcs = &dce112_mi_funcs;
972}
973
974void dce120_mem_input_construct(
975	struct dce_mem_input *dce_mi,
976	struct dc_context *ctx,
977	int inst,
978	const struct dce_mem_input_registers *regs,
979	const struct dce_mem_input_shift *mi_shift,
980	const struct dce_mem_input_mask *mi_mask)
981{
982	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
983	dce_mi->base.funcs = &dce120_mi_funcs;
984}
v5.9
  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
 39struct 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
 51enum 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
 59enum mi_tiling_format {
 60	mi_tiling_linear = 0,
 61	mi_tiling_1D,
 62	mi_tiling_2D,
 63	mi_tiling_count,
 64};
 65
 66static 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
 87static 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
100static 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
122static 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
133static 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, 0x7f);
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, 0x7f);
161}
162
163static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228static 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
247static 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
263static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289static 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
322static 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
355static 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
391static void program_size_and_rotation(
392	struct dce_mem_input *dce_mi,
393	enum dc_rotation_angle rotation,
394	const struct plane_size *plane_size)
395{
396	const struct rect *in_rect = &plane_size->surface_size;
397	struct rect hw_rect = plane_size->surface_size;
398	const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
399			[ROTATION_ANGLE_0] = 0,
400			[ROTATION_ANGLE_90] = 1,
401			[ROTATION_ANGLE_180] = 2,
402			[ROTATION_ANGLE_270] = 3,
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->surface_pitch);
427
428	REG_SET(HW_ROTATION, 0,
429			GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
430}
431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432static 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		fallthrough;
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
504static void dce_mi_program_surface_config(
505	struct mem_input *mi,
506	enum surface_pixel_format format,
507	union dc_tiling_info *tiling_info,
508	struct plane_size *plane_size,
509	enum dc_rotation_angle rotation,
510	struct dc_plane_dcc_param *dcc,
511	bool horizontal_mirror)
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524static 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
570static 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 enable =  (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, enable);
614	}
615}
616
617static 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 enable =  (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, enable);
644	}
645}
646
647
648static 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
662static 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
677static 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
690static 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
732static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744static 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
756static 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
768void 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
786void 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
798void 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}