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