brintos

brintos / linux-shallow public Read only

0
0
Text · 28.1 KiB · f5e1d9c Raw
983 lines · c
1/*2 * Copyright 2016 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *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.ctx32#define REG(reg)\33	dce_mi->regs->reg34 35#undef FN36#define FN(reg_name, field_name) \37	dce_mi->shifts->field_name, dce_mi->masks->field_name38 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	else97		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#endif192 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#endif230 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#endif276 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	else291		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	else308		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#endif365 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 info444		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#endif555 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_VIDEO_BEGIN)646		program_grph_pixel_format(dce_mi, format);647}648 649#if defined(CONFIG_DRM_AMD_DC_SI)650static void dce60_mi_program_surface_config(651	struct mem_input *mi,652	enum surface_pixel_format format,653	union dc_tiling_info *tiling_info,654	struct plane_size *plane_size,655	enum dc_rotation_angle rotation, /* not used in DCE6 */656	struct dc_plane_dcc_param *dcc,657	bool horizontal_mirror)658{659	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);660	REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);661 662	program_tiling(dce_mi, tiling_info);663	dce60_program_size(dce_mi, rotation, plane_size);664 665	if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)666		program_grph_pixel_format(dce_mi, format);667}668#endif669 670static uint32_t get_dmif_switch_time_us(671	uint32_t h_total,672	uint32_t v_total,673	uint32_t pix_clk_khz)674{675	uint32_t frame_time;676	uint32_t pixels_per_second;677	uint32_t pixels_per_frame;678	uint32_t refresh_rate;679	const uint32_t us_in_sec = 1000000;680	const uint32_t min_single_frame_time_us = 30000;681	/*return double of frame time*/682	const uint32_t single_frame_time_multiplier = 2;683 684	if (!h_total || v_total || !pix_clk_khz)685		return single_frame_time_multiplier * min_single_frame_time_us;686 687	/*TODO: should we use pixel format normalized pixel clock here?*/688	pixels_per_second = pix_clk_khz * 1000;689	pixels_per_frame = h_total * v_total;690 691	if (!pixels_per_second || !pixels_per_frame) {692		/* avoid division by zero */693		ASSERT(pixels_per_frame);694		ASSERT(pixels_per_second);695		return single_frame_time_multiplier * min_single_frame_time_us;696	}697 698	refresh_rate = pixels_per_second / pixels_per_frame;699 700	if (!refresh_rate) {701		/* avoid division by zero*/702		ASSERT(refresh_rate);703		return single_frame_time_multiplier * min_single_frame_time_us;704	}705 706	frame_time = us_in_sec / refresh_rate;707 708	if (frame_time < min_single_frame_time_us)709		frame_time = min_single_frame_time_us;710 711	frame_time *= single_frame_time_multiplier;712 713	return frame_time;714}715 716static void dce_mi_allocate_dmif(717	struct mem_input *mi,718	uint32_t h_total,719	uint32_t v_total,720	uint32_t pix_clk_khz,721	uint32_t total_stream_num)722{723	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);724	const uint32_t retry_delay = 10;725	uint32_t retry_count = get_dmif_switch_time_us(726			h_total,727			v_total,728			pix_clk_khz) / retry_delay;729 730	uint32_t pix_dur;731	uint32_t buffers_allocated;732	uint32_t dmif_buffer_control;733 734	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,735			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);736 737	if (buffers_allocated == 2)738		return;739 740	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,741			DMIF_BUFFERS_ALLOCATED, 2);742 743	REG_WAIT(DMIF_BUFFER_CONTROL,744			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,745			retry_delay, retry_count);746 747	if (pix_clk_khz != 0) {748		pix_dur = 1000000000ULL / pix_clk_khz;749 750		REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,751			PIXEL_DURATION, pix_dur);752	}753 754	if (dce_mi->wa.single_head_rdreq_dmif_limit) {755		uint32_t enable =  (total_stream_num > 1) ? 0 :756				dce_mi->wa.single_head_rdreq_dmif_limit;757 758		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,759				ENABLE, enable);760	}761}762 763static void dce_mi_free_dmif(764		struct mem_input *mi,765		uint32_t total_stream_num)766{767	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);768	uint32_t buffers_allocated;769	uint32_t dmif_buffer_control;770 771	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,772			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);773 774	if (buffers_allocated == 0)775		return;776 777	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,778			DMIF_BUFFERS_ALLOCATED, 0);779 780	REG_WAIT(DMIF_BUFFER_CONTROL,781			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,782			10, 3500);783 784	if (dce_mi->wa.single_head_rdreq_dmif_limit) {785		uint32_t enable =  (total_stream_num > 1) ? 0 :786				dce_mi->wa.single_head_rdreq_dmif_limit;787 788		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,789				ENABLE, enable);790	}791}792 793 794static void program_sec_addr(795	struct dce_mem_input *dce_mi,796	PHYSICAL_ADDRESS_LOC address)797{798	/*high register MUST be programmed first*/799	REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,800		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,801		address.high_part);802 803	REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,804		GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,805		GRPH_SECONDARY_DFQ_ENABLE, 0);806}807 808static void program_pri_addr(809	struct dce_mem_input *dce_mi,810	PHYSICAL_ADDRESS_LOC address)811{812	/*high register MUST be programmed first*/813	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,814		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,815		address.high_part);816 817	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,818		GRPH_PRIMARY_SURFACE_ADDRESS,819		address.low_part >> 8);820}821 822 823static bool dce_mi_is_flip_pending(struct mem_input *mem_input)824{825	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);826	uint32_t update_pending;827 828	REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);829	if (update_pending)830		return true;831 832	mem_input->current_address = mem_input->request_address;833	return false;834}835 836static bool dce_mi_program_surface_flip_and_addr(837	struct mem_input *mem_input,838	const struct dc_plane_address *address,839	bool flip_immediate)840{841	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);842 843	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);844 845	REG_UPDATE(846		GRPH_FLIP_CONTROL,847		GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);848 849	switch (address->type) {850	case PLN_ADDR_TYPE_GRAPHICS:851		if (address->grph.addr.quad_part == 0)852			break;853		program_pri_addr(dce_mi, address->grph.addr);854		break;855	case PLN_ADDR_TYPE_GRPH_STEREO:856		if (address->grph_stereo.left_addr.quad_part == 0 ||857		    address->grph_stereo.right_addr.quad_part == 0)858			break;859		program_pri_addr(dce_mi, address->grph_stereo.left_addr);860		program_sec_addr(dce_mi, address->grph_stereo.right_addr);861		break;862	default:863		/* not supported */864		BREAK_TO_DEBUGGER();865		break;866	}867 868	mem_input->request_address = *address;869 870	if (flip_immediate)871		mem_input->current_address = *address;872 873	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);874 875	return true;876}877 878static const struct mem_input_funcs dce_mi_funcs = {879	.mem_input_program_display_marks = dce_mi_program_display_marks,880	.allocate_mem_input = dce_mi_allocate_dmif,881	.free_mem_input = dce_mi_free_dmif,882	.mem_input_program_surface_flip_and_addr =883			dce_mi_program_surface_flip_and_addr,884	.mem_input_program_pte_vm = dce_mi_program_pte_vm,885	.mem_input_program_surface_config =886			dce_mi_program_surface_config,887	.mem_input_is_flip_pending = dce_mi_is_flip_pending888};889 890#if defined(CONFIG_DRM_AMD_DC_SI)891static const struct mem_input_funcs dce60_mi_funcs = {892	.mem_input_program_display_marks = dce60_mi_program_display_marks,893	.allocate_mem_input = dce_mi_allocate_dmif,894	.free_mem_input = dce_mi_free_dmif,895	.mem_input_program_surface_flip_and_addr =896			dce_mi_program_surface_flip_and_addr,897	.mem_input_program_pte_vm = dce_mi_program_pte_vm,898	.mem_input_program_surface_config =899			dce60_mi_program_surface_config,900	.mem_input_is_flip_pending = dce_mi_is_flip_pending901};902#endif903 904static const struct mem_input_funcs dce112_mi_funcs = {905	.mem_input_program_display_marks = dce112_mi_program_display_marks,906	.allocate_mem_input = dce_mi_allocate_dmif,907	.free_mem_input = dce_mi_free_dmif,908	.mem_input_program_surface_flip_and_addr =909			dce_mi_program_surface_flip_and_addr,910	.mem_input_program_pte_vm = dce_mi_program_pte_vm,911	.mem_input_program_surface_config =912			dce_mi_program_surface_config,913	.mem_input_is_flip_pending = dce_mi_is_flip_pending914};915 916static const struct mem_input_funcs dce120_mi_funcs = {917	.mem_input_program_display_marks = dce120_mi_program_display_marks,918	.allocate_mem_input = dce_mi_allocate_dmif,919	.free_mem_input = dce_mi_free_dmif,920	.mem_input_program_surface_flip_and_addr =921			dce_mi_program_surface_flip_and_addr,922	.mem_input_program_pte_vm = dce_mi_program_pte_vm,923	.mem_input_program_surface_config =924			dce_mi_program_surface_config,925	.mem_input_is_flip_pending = dce_mi_is_flip_pending926};927 928void dce_mem_input_construct(929	struct dce_mem_input *dce_mi,930	struct dc_context *ctx,931	int inst,932	const struct dce_mem_input_registers *regs,933	const struct dce_mem_input_shift *mi_shift,934	const struct dce_mem_input_mask *mi_mask)935{936	dce_mi->base.ctx = ctx;937 938	dce_mi->base.inst = inst;939	dce_mi->base.funcs = &dce_mi_funcs;940 941	dce_mi->regs = regs;942	dce_mi->shifts = mi_shift;943	dce_mi->masks = mi_mask;944}945 946#if defined(CONFIG_DRM_AMD_DC_SI)947void dce60_mem_input_construct(948	struct dce_mem_input *dce_mi,949	struct dc_context *ctx,950	int inst,951	const struct dce_mem_input_registers *regs,952	const struct dce_mem_input_shift *mi_shift,953	const struct dce_mem_input_mask *mi_mask)954{955	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);956	dce_mi->base.funcs = &dce60_mi_funcs;957}958#endif959 960void dce112_mem_input_construct(961	struct dce_mem_input *dce_mi,962	struct dc_context *ctx,963	int inst,964	const struct dce_mem_input_registers *regs,965	const struct dce_mem_input_shift *mi_shift,966	const struct dce_mem_input_mask *mi_mask)967{968	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);969	dce_mi->base.funcs = &dce112_mi_funcs;970}971 972void dce120_mem_input_construct(973	struct dce_mem_input *dce_mi,974	struct dc_context *ctx,975	int inst,976	const struct dce_mem_input_registers *regs,977	const struct dce_mem_input_shift *mi_shift,978	const struct dce_mem_input_mask *mi_mask)979{980	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);981	dce_mi->base.funcs = &dce120_mi_funcs;982}983