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 39 struct 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 51 enum 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 59 enum mi_tiling_format { 60 mi_tiling_linear = 0, 61 mi_tiling_1D, 62 mi_tiling_2D, 63 mi_tiling_count, 64 }; 65 66 static 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 87 static 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 100 static 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 122 static 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 133 static 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, 0xff); 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, 0xff); 161 } 162 163 static 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 static void dce120_program_urgency_watermark( 178 struct dce_mem_input *dce_mi, 179 uint32_t wm_select, 180 uint32_t urgency_low_wm, 181 uint32_t urgency_high_wm) 182 { 183 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, 184 URGENCY_WATERMARK_MASK, wm_select); 185 186 REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, 187 URGENCY_LOW_WATERMARK, urgency_low_wm, 188 URGENCY_HIGH_WATERMARK, urgency_high_wm); 189 190 REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0, 191 URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm, 192 URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm); 193 194 } 195 196 static void program_nbp_watermark( 197 struct dce_mem_input *dce_mi, 198 uint32_t wm_select, 199 uint32_t nbp_wm) 200 { 201 if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) { 202 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, 203 NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); 204 205 REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, 206 NB_PSTATE_CHANGE_ENABLE, 1, 207 NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, 208 NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); 209 210 REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, 211 NB_PSTATE_CHANGE_WATERMARK, nbp_wm); 212 } 213 214 if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { 215 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, 216 PSTATE_CHANGE_WATERMARK_MASK, wm_select); 217 218 REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL, 219 PSTATE_CHANGE_ENABLE, 1, 220 PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, 221 PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); 222 223 REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, 224 PSTATE_CHANGE_WATERMARK, nbp_wm); 225 } 226 } 227 228 static void dce120_program_stutter_watermark( 229 struct dce_mem_input *dce_mi, 230 uint32_t wm_select, 231 uint32_t stutter_mark, 232 uint32_t stutter_entry) 233 { 234 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, 235 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); 236 237 if (REG(DPG_PIPE_STUTTER_CONTROL2)) 238 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2, 239 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark, 240 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry); 241 else 242 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, 243 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark, 244 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry); 245 } 246 247 static void program_stutter_watermark( 248 struct dce_mem_input *dce_mi, 249 uint32_t wm_select, 250 uint32_t stutter_mark) 251 { 252 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, 253 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); 254 255 if (REG(DPG_PIPE_STUTTER_CONTROL2)) 256 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, 257 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); 258 else 259 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, 260 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); 261 } 262 263 static void dce_mi_program_display_marks( 264 struct mem_input *mi, 265 struct dce_watermarks nbp, 266 struct dce_watermarks stutter_exit, 267 struct dce_watermarks stutter_enter, 268 struct dce_watermarks urgent, 269 uint32_t total_dest_line_time_ns) 270 { 271 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 272 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; 273 274 program_urgency_watermark(dce_mi, 2, /* set a */ 275 urgent.a_mark, total_dest_line_time_ns); 276 program_urgency_watermark(dce_mi, 1, /* set d */ 277 urgent.d_mark, total_dest_line_time_ns); 278 279 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, 280 STUTTER_ENABLE, stutter_en, 281 STUTTER_IGNORE_FBC, 1); 282 program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */ 283 program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */ 284 285 program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */ 286 program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */ 287 } 288 289 static void dce112_mi_program_display_marks(struct mem_input *mi, 290 struct dce_watermarks nbp, 291 struct dce_watermarks stutter_exit, 292 struct dce_watermarks stutter_entry, 293 struct dce_watermarks urgent, 294 uint32_t total_dest_line_time_ns) 295 { 296 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 297 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; 298 299 program_urgency_watermark(dce_mi, 0, /* set a */ 300 urgent.a_mark, total_dest_line_time_ns); 301 program_urgency_watermark(dce_mi, 1, /* set b */ 302 urgent.b_mark, total_dest_line_time_ns); 303 program_urgency_watermark(dce_mi, 2, /* set c */ 304 urgent.c_mark, total_dest_line_time_ns); 305 program_urgency_watermark(dce_mi, 3, /* set d */ 306 urgent.d_mark, total_dest_line_time_ns); 307 308 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, 309 STUTTER_ENABLE, stutter_en, 310 STUTTER_IGNORE_FBC, 1); 311 program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */ 312 program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */ 313 program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */ 314 program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */ 315 316 program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */ 317 program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */ 318 program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */ 319 program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */ 320 } 321 322 static void dce120_mi_program_display_marks(struct mem_input *mi, 323 struct dce_watermarks nbp, 324 struct dce_watermarks stutter_exit, 325 struct dce_watermarks stutter_entry, 326 struct dce_watermarks urgent, 327 uint32_t total_dest_line_time_ns) 328 { 329 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 330 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; 331 332 dce120_program_urgency_watermark(dce_mi, 0, /* set a */ 333 urgent.a_mark, total_dest_line_time_ns); 334 dce120_program_urgency_watermark(dce_mi, 1, /* set b */ 335 urgent.b_mark, total_dest_line_time_ns); 336 dce120_program_urgency_watermark(dce_mi, 2, /* set c */ 337 urgent.c_mark, total_dest_line_time_ns); 338 dce120_program_urgency_watermark(dce_mi, 3, /* set d */ 339 urgent.d_mark, total_dest_line_time_ns); 340 341 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, 342 STUTTER_ENABLE, stutter_en, 343 STUTTER_IGNORE_FBC, 1); 344 program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */ 345 program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */ 346 program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */ 347 program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */ 348 349 dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */ 350 dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */ 351 dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */ 352 dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */ 353 } 354 355 static void program_tiling( 356 struct dce_mem_input *dce_mi, const union dc_tiling_info *info) 357 { 358 if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */ 359 REG_UPDATE_6(GRPH_CONTROL, 360 GRPH_SW_MODE, info->gfx9.swizzle, 361 GRPH_NUM_BANKS, log_2(info->gfx9.num_banks), 362 GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines), 363 GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes), 364 GRPH_COLOR_EXPANSION_MODE, 1, 365 GRPH_SE_ENABLE, info->gfx9.shaderEnable); 366 /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info 367 GRPH_SE_ENABLE, 1, 368 GRPH_Z, 0); 369 */ 370 } 371 372 if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ 373 REG_UPDATE_9(GRPH_CONTROL, 374 GRPH_NUM_BANKS, info->gfx8.num_banks, 375 GRPH_BANK_WIDTH, info->gfx8.bank_width, 376 GRPH_BANK_HEIGHT, info->gfx8.bank_height, 377 GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect, 378 GRPH_TILE_SPLIT, info->gfx8.tile_split, 379 GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode, 380 GRPH_PIPE_CONFIG, info->gfx8.pipe_config, 381 GRPH_ARRAY_MODE, info->gfx8.array_mode, 382 GRPH_COLOR_EXPANSION_MODE, 1); 383 /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */ 384 /* 385 GRPH_Z, 0); 386 */ 387 } 388 } 389 390 391 static void program_size_and_rotation( 392 struct dce_mem_input *dce_mi, 393 enum dc_rotation_angle rotation, 394 const union plane_size *plane_size) 395 { 396 const struct rect *in_rect = &plane_size->grph.surface_size; 397 struct rect hw_rect = plane_size->grph.surface_size; 398 const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = { 399 [ROTATION_ANGLE_0] = 0, 400 [ROTATION_ANGLE_90] = 1, 401 [ROTATION_ANGLE_180] = 2, 402 [ROTATION_ANGLE_270] = 3, 403 }; 404 405 if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { 406 hw_rect.x = in_rect->y; 407 hw_rect.y = in_rect->x; 408 409 hw_rect.height = in_rect->width; 410 hw_rect.width = in_rect->height; 411 } 412 413 REG_SET(GRPH_X_START, 0, 414 GRPH_X_START, hw_rect.x); 415 416 REG_SET(GRPH_Y_START, 0, 417 GRPH_Y_START, hw_rect.y); 418 419 REG_SET(GRPH_X_END, 0, 420 GRPH_X_END, hw_rect.width); 421 422 REG_SET(GRPH_Y_END, 0, 423 GRPH_Y_END, hw_rect.height); 424 425 REG_SET(GRPH_PITCH, 0, 426 GRPH_PITCH, plane_size->grph.surface_pitch); 427 428 REG_SET(HW_ROTATION, 0, 429 GRPH_ROTATION_ANGLE, rotation_angles[rotation]); 430 } 431 432 static void program_grph_pixel_format( 433 struct dce_mem_input *dce_mi, 434 enum surface_pixel_format format) 435 { 436 uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ 437 uint32_t grph_depth = 0, grph_format = 0; 438 uint32_t sign = 0, floating = 0; 439 440 if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || 441 /*todo: doesn't look like we handle BGRA here, 442 * should problem swap endian*/ 443 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || 444 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || 445 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { 446 /* ABGR formats */ 447 red_xbar = 2; 448 blue_xbar = 2; 449 } 450 451 REG_SET_2(GRPH_SWAP_CNTL, 0, 452 GRPH_RED_CROSSBAR, red_xbar, 453 GRPH_BLUE_CROSSBAR, blue_xbar); 454 455 switch (format) { 456 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 457 grph_depth = 0; 458 grph_format = 0; 459 break; 460 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 461 grph_depth = 1; 462 grph_format = 0; 463 break; 464 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 465 grph_depth = 1; 466 grph_format = 1; 467 break; 468 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 469 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 470 grph_depth = 2; 471 grph_format = 0; 472 break; 473 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 474 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 475 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 476 grph_depth = 2; 477 grph_format = 1; 478 break; 479 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 480 sign = 1; 481 floating = 1; 482 /* no break */ 483 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */ 484 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 485 grph_depth = 3; 486 grph_format = 0; 487 break; 488 default: 489 DC_ERR("unsupported grph pixel format"); 490 break; 491 } 492 493 REG_UPDATE_2(GRPH_CONTROL, 494 GRPH_DEPTH, grph_depth, 495 GRPH_FORMAT, grph_format); 496 497 REG_UPDATE_4(PRESCALE_GRPH_CONTROL, 498 GRPH_PRESCALE_SELECT, floating, 499 GRPH_PRESCALE_R_SIGN, sign, 500 GRPH_PRESCALE_G_SIGN, sign, 501 GRPH_PRESCALE_B_SIGN, sign); 502 } 503 504 static void dce_mi_program_surface_config( 505 struct mem_input *mi, 506 enum surface_pixel_format format, 507 union dc_tiling_info *tiling_info, 508 union plane_size *plane_size, 509 enum dc_rotation_angle rotation, 510 struct dc_plane_dcc_param *dcc, 511 bool horizontal_mirror) 512 { 513 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 514 REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); 515 516 program_tiling(dce_mi, tiling_info); 517 program_size_and_rotation(dce_mi, rotation, plane_size); 518 519 if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && 520 format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 521 program_grph_pixel_format(dce_mi, format); 522 } 523 524 static uint32_t get_dmif_switch_time_us( 525 uint32_t h_total, 526 uint32_t v_total, 527 uint32_t pix_clk_khz) 528 { 529 uint32_t frame_time; 530 uint32_t pixels_per_second; 531 uint32_t pixels_per_frame; 532 uint32_t refresh_rate; 533 const uint32_t us_in_sec = 1000000; 534 const uint32_t min_single_frame_time_us = 30000; 535 /*return double of frame time*/ 536 const uint32_t single_frame_time_multiplier = 2; 537 538 if (!h_total || v_total || !pix_clk_khz) 539 return single_frame_time_multiplier * min_single_frame_time_us; 540 541 /*TODO: should we use pixel format normalized pixel clock here?*/ 542 pixels_per_second = pix_clk_khz * 1000; 543 pixels_per_frame = h_total * v_total; 544 545 if (!pixels_per_second || !pixels_per_frame) { 546 /* avoid division by zero */ 547 ASSERT(pixels_per_frame); 548 ASSERT(pixels_per_second); 549 return single_frame_time_multiplier * min_single_frame_time_us; 550 } 551 552 refresh_rate = pixels_per_second / pixels_per_frame; 553 554 if (!refresh_rate) { 555 /* avoid division by zero*/ 556 ASSERT(refresh_rate); 557 return single_frame_time_multiplier * min_single_frame_time_us; 558 } 559 560 frame_time = us_in_sec / refresh_rate; 561 562 if (frame_time < min_single_frame_time_us) 563 frame_time = min_single_frame_time_us; 564 565 frame_time *= single_frame_time_multiplier; 566 567 return frame_time; 568 } 569 570 static void dce_mi_allocate_dmif( 571 struct mem_input *mi, 572 uint32_t h_total, 573 uint32_t v_total, 574 uint32_t pix_clk_khz, 575 uint32_t total_stream_num) 576 { 577 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 578 const uint32_t retry_delay = 10; 579 uint32_t retry_count = get_dmif_switch_time_us( 580 h_total, 581 v_total, 582 pix_clk_khz) / retry_delay; 583 584 uint32_t pix_dur; 585 uint32_t buffers_allocated; 586 uint32_t dmif_buffer_control; 587 588 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, 589 DMIF_BUFFERS_ALLOCATED, &buffers_allocated); 590 591 if (buffers_allocated == 2) 592 return; 593 594 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, 595 DMIF_BUFFERS_ALLOCATED, 2); 596 597 REG_WAIT(DMIF_BUFFER_CONTROL, 598 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 599 retry_delay, retry_count); 600 601 if (pix_clk_khz != 0) { 602 pix_dur = 1000000000ULL / pix_clk_khz; 603 604 REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, 605 PIXEL_DURATION, pix_dur); 606 } 607 608 if (dce_mi->wa.single_head_rdreq_dmif_limit) { 609 uint32_t eanble = (total_stream_num > 1) ? 0 : 610 dce_mi->wa.single_head_rdreq_dmif_limit; 611 612 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, 613 ENABLE, eanble); 614 } 615 } 616 617 static void dce_mi_free_dmif( 618 struct mem_input *mi, 619 uint32_t total_stream_num) 620 { 621 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); 622 uint32_t buffers_allocated; 623 uint32_t dmif_buffer_control; 624 625 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, 626 DMIF_BUFFERS_ALLOCATED, &buffers_allocated); 627 628 if (buffers_allocated == 0) 629 return; 630 631 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, 632 DMIF_BUFFERS_ALLOCATED, 0); 633 634 REG_WAIT(DMIF_BUFFER_CONTROL, 635 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 636 10, 3500); 637 638 if (dce_mi->wa.single_head_rdreq_dmif_limit) { 639 uint32_t eanble = (total_stream_num > 1) ? 0 : 640 dce_mi->wa.single_head_rdreq_dmif_limit; 641 642 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, 643 ENABLE, eanble); 644 } 645 } 646 647 648 static void program_sec_addr( 649 struct dce_mem_input *dce_mi, 650 PHYSICAL_ADDRESS_LOC address) 651 { 652 /*high register MUST be programmed first*/ 653 REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0, 654 GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 655 address.high_part); 656 657 REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0, 658 GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8, 659 GRPH_SECONDARY_DFQ_ENABLE, 0); 660 } 661 662 static void program_pri_addr( 663 struct dce_mem_input *dce_mi, 664 PHYSICAL_ADDRESS_LOC address) 665 { 666 /*high register MUST be programmed first*/ 667 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 668 GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 669 address.high_part); 670 671 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0, 672 GRPH_PRIMARY_SURFACE_ADDRESS, 673 address.low_part >> 8); 674 } 675 676 677 static bool dce_mi_is_flip_pending(struct mem_input *mem_input) 678 { 679 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); 680 uint32_t update_pending; 681 682 REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending); 683 if (update_pending) 684 return true; 685 686 mem_input->current_address = mem_input->request_address; 687 return false; 688 } 689 690 static bool dce_mi_program_surface_flip_and_addr( 691 struct mem_input *mem_input, 692 const struct dc_plane_address *address, 693 bool flip_immediate) 694 { 695 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); 696 697 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); 698 699 REG_UPDATE( 700 GRPH_FLIP_CONTROL, 701 GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); 702 703 switch (address->type) { 704 case PLN_ADDR_TYPE_GRAPHICS: 705 if (address->grph.addr.quad_part == 0) 706 break; 707 program_pri_addr(dce_mi, address->grph.addr); 708 break; 709 case PLN_ADDR_TYPE_GRPH_STEREO: 710 if (address->grph_stereo.left_addr.quad_part == 0 || 711 address->grph_stereo.right_addr.quad_part == 0) 712 break; 713 program_pri_addr(dce_mi, address->grph_stereo.left_addr); 714 program_sec_addr(dce_mi, address->grph_stereo.right_addr); 715 break; 716 default: 717 /* not supported */ 718 BREAK_TO_DEBUGGER(); 719 break; 720 } 721 722 mem_input->request_address = *address; 723 724 if (flip_immediate) 725 mem_input->current_address = *address; 726 727 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); 728 729 return true; 730 } 731 732 static const struct mem_input_funcs dce_mi_funcs = { 733 .mem_input_program_display_marks = dce_mi_program_display_marks, 734 .allocate_mem_input = dce_mi_allocate_dmif, 735 .free_mem_input = dce_mi_free_dmif, 736 .mem_input_program_surface_flip_and_addr = 737 dce_mi_program_surface_flip_and_addr, 738 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 739 .mem_input_program_surface_config = 740 dce_mi_program_surface_config, 741 .mem_input_is_flip_pending = dce_mi_is_flip_pending 742 }; 743 744 static const struct mem_input_funcs dce112_mi_funcs = { 745 .mem_input_program_display_marks = dce112_mi_program_display_marks, 746 .allocate_mem_input = dce_mi_allocate_dmif, 747 .free_mem_input = dce_mi_free_dmif, 748 .mem_input_program_surface_flip_and_addr = 749 dce_mi_program_surface_flip_and_addr, 750 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 751 .mem_input_program_surface_config = 752 dce_mi_program_surface_config, 753 .mem_input_is_flip_pending = dce_mi_is_flip_pending 754 }; 755 756 static const struct mem_input_funcs dce120_mi_funcs = { 757 .mem_input_program_display_marks = dce120_mi_program_display_marks, 758 .allocate_mem_input = dce_mi_allocate_dmif, 759 .free_mem_input = dce_mi_free_dmif, 760 .mem_input_program_surface_flip_and_addr = 761 dce_mi_program_surface_flip_and_addr, 762 .mem_input_program_pte_vm = dce_mi_program_pte_vm, 763 .mem_input_program_surface_config = 764 dce_mi_program_surface_config, 765 .mem_input_is_flip_pending = dce_mi_is_flip_pending 766 }; 767 768 void dce_mem_input_construct( 769 struct dce_mem_input *dce_mi, 770 struct dc_context *ctx, 771 int inst, 772 const struct dce_mem_input_registers *regs, 773 const struct dce_mem_input_shift *mi_shift, 774 const struct dce_mem_input_mask *mi_mask) 775 { 776 dce_mi->base.ctx = ctx; 777 778 dce_mi->base.inst = inst; 779 dce_mi->base.funcs = &dce_mi_funcs; 780 781 dce_mi->regs = regs; 782 dce_mi->shifts = mi_shift; 783 dce_mi->masks = mi_mask; 784 } 785 786 void dce112_mem_input_construct( 787 struct dce_mem_input *dce_mi, 788 struct dc_context *ctx, 789 int inst, 790 const struct dce_mem_input_registers *regs, 791 const struct dce_mem_input_shift *mi_shift, 792 const struct dce_mem_input_mask *mi_mask) 793 { 794 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); 795 dce_mi->base.funcs = &dce112_mi_funcs; 796 } 797 798 void dce120_mem_input_construct( 799 struct dce_mem_input *dce_mi, 800 struct dc_context *ctx, 801 int inst, 802 const struct dce_mem_input_registers *regs, 803 const struct dce_mem_input_shift *mi_shift, 804 const struct dce_mem_input_mask *mi_mask) 805 { 806 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); 807 dce_mi->base.funcs = &dce120_mi_funcs; 808 } 809