cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dce_mem_input.c (28862B)


      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}