Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.16-rc4 1006 lines 30 kB view raw
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 struct 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 struct 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 struct 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 484static void program_size_and_rotation( 485 struct dce_mem_input *dce_mi, 486 enum dc_rotation_angle rotation, 487 const struct plane_size *plane_size) 488{ 489 const struct rect *in_rect = &plane_size->surface_size; 490 struct rect hw_rect = plane_size->surface_size; 491 const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = { 492 [ROTATION_ANGLE_0] = 0, 493 [ROTATION_ANGLE_90] = 1, 494 [ROTATION_ANGLE_180] = 2, 495 [ROTATION_ANGLE_270] = 3, 496 }; 497 498 if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { 499 hw_rect.x = in_rect->y; 500 hw_rect.y = in_rect->x; 501 502 hw_rect.height = in_rect->width; 503 hw_rect.width = in_rect->height; 504 } 505 506 REG_SET(GRPH_X_START, 0, 507 GRPH_X_START, hw_rect.x); 508 509 REG_SET(GRPH_Y_START, 0, 510 GRPH_Y_START, hw_rect.y); 511 512 REG_SET(GRPH_X_END, 0, 513 GRPH_X_END, hw_rect.width); 514 515 REG_SET(GRPH_Y_END, 0, 516 GRPH_Y_END, hw_rect.height); 517 518 REG_SET(GRPH_PITCH, 0, 519 GRPH_PITCH, plane_size->surface_pitch); 520 521 REG_SET(HW_ROTATION, 0, 522 GRPH_ROTATION_ANGLE, rotation_angles[rotation]); 523} 524 525#if defined(CONFIG_DRM_AMD_DC_SI) 526static void dce60_program_size( 527 struct dce_mem_input *dce_mi, 528 enum dc_rotation_angle rotation, /* not used in DCE6 */ 529 const struct plane_size *plane_size) 530{ 531 struct rect hw_rect = plane_size->surface_size; 532 /* DCE6 has no HW rotation, skip rotation_angles declaration */ 533 534 /* DCE6 has no HW rotation, skip ROTATION_ANGLE_* processing */ 535 536 REG_SET(GRPH_X_START, 0, 537 GRPH_X_START, hw_rect.x); 538 539 REG_SET(GRPH_Y_START, 0, 540 GRPH_Y_START, hw_rect.y); 541 542 REG_SET(GRPH_X_END, 0, 543 GRPH_X_END, hw_rect.width); 544 545 REG_SET(GRPH_Y_END, 0, 546 GRPH_Y_END, hw_rect.height); 547 548 REG_SET(GRPH_PITCH, 0, 549 GRPH_PITCH, plane_size->surface_pitch); 550 551 /* DCE6 has no HW_ROTATION register, skip setting rotation_angles */ 552} 553#endif 554 555static void program_grph_pixel_format( 556 struct dce_mem_input *dce_mi, 557 enum surface_pixel_format format) 558{ 559 uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ 560 uint32_t grph_depth = 0, grph_format = 0; 561 uint32_t sign = 0, floating = 0; 562 563 if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || 564 /*todo: doesn't look like we handle BGRA here, 565 * should problem swap endian*/ 566 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || 567 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || 568 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 || 569 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { 570 /* ABGR formats */ 571 red_xbar = 2; 572 blue_xbar = 2; 573 } 574 575 REG_SET_2(GRPH_SWAP_CNTL, 0, 576 GRPH_RED_CROSSBAR, red_xbar, 577 GRPH_BLUE_CROSSBAR, blue_xbar); 578 579 switch (format) { 580 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 581 grph_depth = 0; 582 grph_format = 0; 583 break; 584 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 585 grph_depth = 1; 586 grph_format = 0; 587 break; 588 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 589 grph_depth = 1; 590 grph_format = 1; 591 break; 592 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 593 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 594 grph_depth = 2; 595 grph_format = 0; 596 break; 597 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 598 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 599 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 600 grph_depth = 2; 601 grph_format = 1; 602 break; 603 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 604 sign = 1; 605 floating = 1; 606 fallthrough; 607 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */ 608 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 609 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 610 grph_depth = 3; 611 grph_format = 0; 612 break; 613 default: 614 DC_ERR("unsupported grph pixel format"); 615 break; 616 } 617 618 REG_UPDATE_2(GRPH_CONTROL, 619 GRPH_DEPTH, grph_depth, 620 GRPH_FORMAT, grph_format); 621 622 REG_UPDATE_4(PRESCALE_GRPH_CONTROL, 623 GRPH_PRESCALE_SELECT, floating, 624 GRPH_PRESCALE_R_SIGN, sign, 625 GRPH_PRESCALE_G_SIGN, sign, 626 GRPH_PRESCALE_B_SIGN, sign); 627} 628 629static void dce_mi_clear_tiling( 630 struct mem_input *mi) 631{ 632 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 633 634 if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */ 635 REG_UPDATE(GRPH_CONTROL, 636 GRPH_SW_MODE, DC_SW_LINEAR); 637 } 638 639 if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */ 640 REG_UPDATE(GRPH_CONTROL, 641 GRPH_ARRAY_MODE, DC_SW_LINEAR); 642 } 643 644 if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */ 645 REG_UPDATE(GRPH_CONTROL, 646 GRPH_ARRAY_MODE, DC_SW_LINEAR); 647 } 648} 649 650static void dce_mi_program_surface_config( 651 struct mem_input *mi, 652 enum surface_pixel_format format, 653 struct dc_tiling_info *tiling_info, 654 struct plane_size *plane_size, 655 enum dc_rotation_angle rotation, 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 program_size_and_rotation(dce_mi, rotation, plane_size); 664 665 if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 666 program_grph_pixel_format(dce_mi, format); 667} 668 669#if defined(CONFIG_DRM_AMD_DC_SI) 670static void dce60_mi_program_surface_config( 671 struct mem_input *mi, 672 enum surface_pixel_format format, 673 struct dc_tiling_info *tiling_info, 674 struct plane_size *plane_size, 675 enum dc_rotation_angle rotation, /* not used in DCE6 */ 676 struct dc_plane_dcc_param *dcc, 677 bool horizontal_mirror) 678{ 679 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 680 REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); 681 682 program_tiling(dce_mi, tiling_info); 683 dce60_program_size(dce_mi, rotation, plane_size); 684 685 if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 686 program_grph_pixel_format(dce_mi, format); 687} 688#endif 689 690static uint32_t get_dmif_switch_time_us( 691 uint32_t h_total, 692 uint32_t v_total, 693 uint32_t pix_clk_khz) 694{ 695 uint32_t frame_time; 696 uint32_t pixels_per_second; 697 uint32_t pixels_per_frame; 698 uint32_t refresh_rate; 699 const uint32_t us_in_sec = 1000000; 700 const uint32_t min_single_frame_time_us = 30000; 701 /*return double of frame time*/ 702 const uint32_t single_frame_time_multiplier = 2; 703 704 if (!h_total || v_total || !pix_clk_khz) 705 return single_frame_time_multiplier * min_single_frame_time_us; 706 707 /*TODO: should we use pixel format normalized pixel clock here?*/ 708 pixels_per_second = pix_clk_khz * 1000; 709 pixels_per_frame = h_total * v_total; 710 711 if (!pixels_per_second || !pixels_per_frame) { 712 /* avoid division by zero */ 713 ASSERT(pixels_per_frame); 714 ASSERT(pixels_per_second); 715 return single_frame_time_multiplier * min_single_frame_time_us; 716 } 717 718 refresh_rate = pixels_per_second / pixels_per_frame; 719 720 if (!refresh_rate) { 721 /* avoid division by zero*/ 722 ASSERT(refresh_rate); 723 return single_frame_time_multiplier * min_single_frame_time_us; 724 } 725 726 frame_time = us_in_sec / refresh_rate; 727 728 if (frame_time < min_single_frame_time_us) 729 frame_time = min_single_frame_time_us; 730 731 frame_time *= single_frame_time_multiplier; 732 733 return frame_time; 734} 735 736static void dce_mi_allocate_dmif( 737 struct mem_input *mi, 738 uint32_t h_total, 739 uint32_t v_total, 740 uint32_t pix_clk_khz, 741 uint32_t total_stream_num) 742{ 743 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 744 const uint32_t retry_delay = 10; 745 uint32_t retry_count = get_dmif_switch_time_us( 746 h_total, 747 v_total, 748 pix_clk_khz) / retry_delay; 749 750 uint32_t pix_dur; 751 uint32_t buffers_allocated; 752 uint32_t dmif_buffer_control; 753 754 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, 755 DMIF_BUFFERS_ALLOCATED, &buffers_allocated); 756 757 if (buffers_allocated == 2) 758 return; 759 760 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, 761 DMIF_BUFFERS_ALLOCATED, 2); 762 763 REG_WAIT(DMIF_BUFFER_CONTROL, 764 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 765 retry_delay, retry_count); 766 767 if (pix_clk_khz != 0) { 768 pix_dur = 1000000000ULL / pix_clk_khz; 769 770 REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, 771 PIXEL_DURATION, pix_dur); 772 } 773 774 if (dce_mi->wa.single_head_rdreq_dmif_limit) { 775 uint32_t enable = (total_stream_num > 1) ? 0 : 776 dce_mi->wa.single_head_rdreq_dmif_limit; 777 778 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, 779 ENABLE, enable); 780 } 781} 782 783static void dce_mi_free_dmif( 784 struct mem_input *mi, 785 uint32_t total_stream_num) 786{ 787 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 788 uint32_t buffers_allocated; 789 uint32_t dmif_buffer_control; 790 791 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, 792 DMIF_BUFFERS_ALLOCATED, &buffers_allocated); 793 794 if (buffers_allocated == 0) 795 return; 796 797 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, 798 DMIF_BUFFERS_ALLOCATED, 0); 799 800 REG_WAIT(DMIF_BUFFER_CONTROL, 801 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 802 10, 3500); 803 804 if (dce_mi->wa.single_head_rdreq_dmif_limit) { 805 uint32_t enable = (total_stream_num > 1) ? 0 : 806 dce_mi->wa.single_head_rdreq_dmif_limit; 807 808 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, 809 ENABLE, enable); 810 } 811} 812 813 814static void program_sec_addr( 815 struct dce_mem_input *dce_mi, 816 PHYSICAL_ADDRESS_LOC address) 817{ 818 /*high register MUST be programmed first*/ 819 REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0, 820 GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 821 address.high_part); 822 823 REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0, 824 GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8, 825 GRPH_SECONDARY_DFQ_ENABLE, 0); 826} 827 828static void program_pri_addr( 829 struct dce_mem_input *dce_mi, 830 PHYSICAL_ADDRESS_LOC address) 831{ 832 /*high register MUST be programmed first*/ 833 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 834 GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 835 address.high_part); 836 837 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0, 838 GRPH_PRIMARY_SURFACE_ADDRESS, 839 address.low_part >> 8); 840} 841 842 843static bool dce_mi_is_flip_pending(struct mem_input *mem_input) 844{ 845 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); 846 uint32_t update_pending; 847 848 REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending); 849 if (update_pending) 850 return true; 851 852 mem_input->current_address = mem_input->request_address; 853 return false; 854} 855 856static bool dce_mi_program_surface_flip_and_addr( 857 struct mem_input *mem_input, 858 const struct dc_plane_address *address, 859 bool flip_immediate) 860{ 861 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); 862 863 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); 864 865 REG_UPDATE( 866 GRPH_FLIP_CONTROL, 867 GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); 868 869 switch (address->type) { 870 case PLN_ADDR_TYPE_GRAPHICS: 871 if (address->grph.addr.quad_part == 0) 872 break; 873 program_pri_addr(dce_mi, address->grph.addr); 874 break; 875 case PLN_ADDR_TYPE_GRPH_STEREO: 876 if (address->grph_stereo.left_addr.quad_part == 0 || 877 address->grph_stereo.right_addr.quad_part == 0) 878 break; 879 program_pri_addr(dce_mi, address->grph_stereo.left_addr); 880 program_sec_addr(dce_mi, address->grph_stereo.right_addr); 881 break; 882 default: 883 /* not supported */ 884 BREAK_TO_DEBUGGER(); 885 break; 886 } 887 888 mem_input->request_address = *address; 889 890 if (flip_immediate) 891 mem_input->current_address = *address; 892 893 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); 894 895 return true; 896} 897 898static const struct mem_input_funcs dce_mi_funcs = { 899 .mem_input_program_display_marks = dce_mi_program_display_marks, 900 .allocate_mem_input = dce_mi_allocate_dmif, 901 .free_mem_input = dce_mi_free_dmif, 902 .mem_input_program_surface_flip_and_addr = 903 dce_mi_program_surface_flip_and_addr, 904 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 905 .mem_input_program_surface_config = 906 dce_mi_program_surface_config, 907 .mem_input_is_flip_pending = dce_mi_is_flip_pending, 908 .mem_input_clear_tiling = dce_mi_clear_tiling, 909}; 910 911#if defined(CONFIG_DRM_AMD_DC_SI) 912static const struct mem_input_funcs dce60_mi_funcs = { 913 .mem_input_program_display_marks = dce60_mi_program_display_marks, 914 .allocate_mem_input = dce_mi_allocate_dmif, 915 .free_mem_input = dce_mi_free_dmif, 916 .mem_input_program_surface_flip_and_addr = 917 dce_mi_program_surface_flip_and_addr, 918 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 919 .mem_input_program_surface_config = 920 dce60_mi_program_surface_config, 921 .mem_input_is_flip_pending = dce_mi_is_flip_pending, 922 .mem_input_clear_tiling = dce_mi_clear_tiling, 923}; 924#endif 925 926static const struct mem_input_funcs dce112_mi_funcs = { 927 .mem_input_program_display_marks = dce112_mi_program_display_marks, 928 .allocate_mem_input = dce_mi_allocate_dmif, 929 .free_mem_input = dce_mi_free_dmif, 930 .mem_input_program_surface_flip_and_addr = 931 dce_mi_program_surface_flip_and_addr, 932 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 933 .mem_input_program_surface_config = 934 dce_mi_program_surface_config, 935 .mem_input_is_flip_pending = dce_mi_is_flip_pending, 936 .mem_input_clear_tiling = dce_mi_clear_tiling, 937}; 938 939static const struct mem_input_funcs dce120_mi_funcs = { 940 .mem_input_program_display_marks = dce120_mi_program_display_marks, 941 .allocate_mem_input = dce_mi_allocate_dmif, 942 .free_mem_input = dce_mi_free_dmif, 943 .mem_input_program_surface_flip_and_addr = 944 dce_mi_program_surface_flip_and_addr, 945 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 946 .mem_input_program_surface_config = 947 dce_mi_program_surface_config, 948 .mem_input_is_flip_pending = dce_mi_is_flip_pending, 949 .mem_input_clear_tiling = dce_mi_clear_tiling, 950}; 951 952void dce_mem_input_construct( 953 struct dce_mem_input *dce_mi, 954 struct dc_context *ctx, 955 int inst, 956 const struct dce_mem_input_registers *regs, 957 const struct dce_mem_input_shift *mi_shift, 958 const struct dce_mem_input_mask *mi_mask) 959{ 960 dce_mi->base.ctx = ctx; 961 962 dce_mi->base.inst = inst; 963 dce_mi->base.funcs = &dce_mi_funcs; 964 965 dce_mi->regs = regs; 966 dce_mi->shifts = mi_shift; 967 dce_mi->masks = mi_mask; 968} 969 970#if defined(CONFIG_DRM_AMD_DC_SI) 971void dce60_mem_input_construct( 972 struct dce_mem_input *dce_mi, 973 struct dc_context *ctx, 974 int inst, 975 const struct dce_mem_input_registers *regs, 976 const struct dce_mem_input_shift *mi_shift, 977 const struct dce_mem_input_mask *mi_mask) 978{ 979 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); 980 dce_mi->base.funcs = &dce60_mi_funcs; 981} 982#endif 983 984void dce112_mem_input_construct( 985 struct dce_mem_input *dce_mi, 986 struct dc_context *ctx, 987 int inst, 988 const struct dce_mem_input_registers *regs, 989 const struct dce_mem_input_shift *mi_shift, 990 const struct dce_mem_input_mask *mi_mask) 991{ 992 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); 993 dce_mi->base.funcs = &dce112_mi_funcs; 994} 995 996void dce120_mem_input_construct( 997 struct dce_mem_input *dce_mi, 998 struct dc_context *ctx, 999 int inst, 1000 const struct dce_mem_input_registers *regs, 1001 const struct dce_mem_input_shift *mi_shift, 1002 const struct dce_mem_input_mask *mi_mask) 1003{ 1004 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); 1005 dce_mi->base.funcs = &dce120_mi_funcs; 1006}