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}