1 /* 2 * Copyright 2012-15 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 #include "dm_services.h" 26 #include "dce_calcs.h" 27 #include "reg_helper.h" 28 #include "basics/conversion.h" 29 #include "dcn10_hubp.h" 30 31 #define REG(reg)\ 32 hubp1->hubp_regs->reg 33 34 #define CTX \ 35 hubp1->base.ctx 36 37 #undef FN 38 #define FN(reg_name, field_name) \ 39 hubp1->hubp_shift->field_name, hubp1->hubp_mask->field_name 40 41 void hubp1_set_blank(struct hubp *hubp, bool blank) 42 { 43 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 44 uint32_t blank_en = blank ? 1 : 0; 45 46 REG_UPDATE_2(DCHUBP_CNTL, 47 HUBP_BLANK_EN, blank_en, 48 HUBP_TTU_DISABLE, blank_en); 49 50 if (blank) { 51 REG_WAIT(DCHUBP_CNTL, 52 HUBP_NO_OUTSTANDING_REQ, 1, 53 1, 200); 54 hubp->mpcc_id = 0xf; 55 hubp->opp_id = 0xf; 56 } 57 } 58 59 static void hubp1_disconnect(struct hubp *hubp) 60 { 61 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 62 63 REG_UPDATE(DCHUBP_CNTL, 64 HUBP_TTU_DISABLE, 1); 65 } 66 67 static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) 68 { 69 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 70 uint32_t blank_en = blank ? 1 : 0; 71 72 REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); 73 } 74 75 static void hubp1_vready_workaround(struct hubp *hubp, 76 struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) 77 { 78 uint32_t value = 0; 79 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 80 81 /* set HBUBREQ_DEBUG_DB[12] = 1 */ 82 value = REG_READ(HUBPREQ_DEBUG_DB); 83 84 /* hack mode disable */ 85 value |= 0x100; 86 value &= ~0x1000; 87 88 if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width 89 + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { 90 /* if (eco_fix_needed(otg_global_sync_timing) 91 * set HBUBREQ_DEBUG_DB[12] = 1 */ 92 value |= 0x1000; 93 } 94 95 REG_WRITE(HUBPREQ_DEBUG_DB, value); 96 } 97 98 void hubp1_program_tiling( 99 struct dcn10_hubp *hubp1, 100 const union dc_tiling_info *info, 101 const enum surface_pixel_format pixel_format) 102 { 103 REG_UPDATE_6(DCSURF_ADDR_CONFIG, 104 NUM_PIPES, log_2(info->gfx9.num_pipes), 105 NUM_BANKS, log_2(info->gfx9.num_banks), 106 PIPE_INTERLEAVE, info->gfx9.pipe_interleave, 107 NUM_SE, log_2(info->gfx9.num_shader_engines), 108 NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), 109 MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); 110 111 REG_UPDATE_4(DCSURF_TILING_CONFIG, 112 SW_MODE, info->gfx9.swizzle, 113 META_LINEAR, info->gfx9.meta_linear, 114 RB_ALIGNED, info->gfx9.rb_aligned, 115 PIPE_ALIGNED, info->gfx9.pipe_aligned); 116 } 117 118 void hubp1_program_size_and_rotation( 119 struct dcn10_hubp *hubp1, 120 enum dc_rotation_angle rotation, 121 enum surface_pixel_format format, 122 const union plane_size *plane_size, 123 struct dc_plane_dcc_param *dcc, 124 bool horizontal_mirror) 125 { 126 uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; 127 128 /* Program data and meta surface pitch (calculation from addrlib) 129 * 444 or 420 luma 130 */ 131 if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { 132 pitch = plane_size->video.luma_pitch - 1; 133 meta_pitch = dcc->video.meta_pitch_l - 1; 134 pitch_c = plane_size->video.chroma_pitch - 1; 135 meta_pitch_c = dcc->video.meta_pitch_c - 1; 136 } else { 137 pitch = plane_size->grph.surface_pitch - 1; 138 meta_pitch = dcc->grph.meta_pitch - 1; 139 pitch_c = 0; 140 meta_pitch_c = 0; 141 } 142 143 if (!dcc->enable) { 144 meta_pitch = 0; 145 meta_pitch_c = 0; 146 } 147 148 REG_UPDATE_2(DCSURF_SURFACE_PITCH, 149 PITCH, pitch, META_PITCH, meta_pitch); 150 151 if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 152 REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, 153 PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); 154 155 if (horizontal_mirror) 156 mirror = 1; 157 else 158 mirror = 0; 159 160 161 /* Program rotation angle and horz mirror - no mirror */ 162 if (rotation == ROTATION_ANGLE_0) 163 REG_UPDATE_2(DCSURF_SURFACE_CONFIG, 164 ROTATION_ANGLE, 0, 165 H_MIRROR_EN, mirror); 166 else if (rotation == ROTATION_ANGLE_90) 167 REG_UPDATE_2(DCSURF_SURFACE_CONFIG, 168 ROTATION_ANGLE, 1, 169 H_MIRROR_EN, mirror); 170 else if (rotation == ROTATION_ANGLE_180) 171 REG_UPDATE_2(DCSURF_SURFACE_CONFIG, 172 ROTATION_ANGLE, 2, 173 H_MIRROR_EN, mirror); 174 else if (rotation == ROTATION_ANGLE_270) 175 REG_UPDATE_2(DCSURF_SURFACE_CONFIG, 176 ROTATION_ANGLE, 3, 177 H_MIRROR_EN, mirror); 178 } 179 180 void hubp1_program_pixel_format( 181 struct dcn10_hubp *hubp1, 182 enum surface_pixel_format format) 183 { 184 uint32_t red_bar = 3; 185 uint32_t blue_bar = 2; 186 187 /* swap for ABGR format */ 188 if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 189 || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 190 || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS 191 || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { 192 red_bar = 2; 193 blue_bar = 3; 194 } 195 196 REG_UPDATE_2(HUBPRET_CONTROL, 197 CROSSBAR_SRC_CB_B, blue_bar, 198 CROSSBAR_SRC_CR_R, red_bar); 199 200 /* Mapping is same as ipp programming (cnvc) */ 201 202 switch (format) { 203 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 204 REG_UPDATE(DCSURF_SURFACE_CONFIG, 205 SURFACE_PIXEL_FORMAT, 1); 206 break; 207 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 208 REG_UPDATE(DCSURF_SURFACE_CONFIG, 209 SURFACE_PIXEL_FORMAT, 3); 210 break; 211 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 212 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 213 REG_UPDATE(DCSURF_SURFACE_CONFIG, 214 SURFACE_PIXEL_FORMAT, 8); 215 break; 216 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 217 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 218 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 219 REG_UPDATE(DCSURF_SURFACE_CONFIG, 220 SURFACE_PIXEL_FORMAT, 10); 221 break; 222 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 223 REG_UPDATE(DCSURF_SURFACE_CONFIG, 224 SURFACE_PIXEL_FORMAT, 22); 225 break; 226 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 227 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ 228 REG_UPDATE(DCSURF_SURFACE_CONFIG, 229 SURFACE_PIXEL_FORMAT, 24); 230 break; 231 232 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 233 REG_UPDATE(DCSURF_SURFACE_CONFIG, 234 SURFACE_PIXEL_FORMAT, 65); 235 break; 236 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 237 REG_UPDATE(DCSURF_SURFACE_CONFIG, 238 SURFACE_PIXEL_FORMAT, 64); 239 break; 240 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 241 REG_UPDATE(DCSURF_SURFACE_CONFIG, 242 SURFACE_PIXEL_FORMAT, 67); 243 break; 244 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 245 REG_UPDATE(DCSURF_SURFACE_CONFIG, 246 SURFACE_PIXEL_FORMAT, 66); 247 break; 248 default: 249 BREAK_TO_DEBUGGER(); 250 break; 251 } 252 253 /* don't see the need of program the xbar in DCN 1.0 */ 254 } 255 256 bool hubp1_program_surface_flip_and_addr( 257 struct hubp *hubp, 258 const struct dc_plane_address *address, 259 bool flip_immediate) 260 { 261 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 262 263 /* program flip type */ 264 REG_SET(DCSURF_FLIP_CONTROL, 0, 265 SURFACE_FLIP_TYPE, flip_immediate); 266 267 /* HW automatically latch rest of address register on write to 268 * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used 269 * 270 * program high first and then the low addr, order matters! 271 */ 272 switch (address->type) { 273 case PLN_ADDR_TYPE_GRAPHICS: 274 /* DCN1.0 does not support const color 275 * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 276 * base on address->grph.dcc_const_color 277 * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma 278 * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma 279 */ 280 281 if (address->grph.addr.quad_part == 0) 282 break; 283 284 REG_UPDATE(DCSURF_SURFACE_CONTROL, 285 PRIMARY_SURFACE_TMZ, address->tmz_surface); 286 287 if (address->grph.meta_addr.quad_part != 0) { 288 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 289 PRIMARY_META_SURFACE_ADDRESS_HIGH, 290 address->grph.meta_addr.high_part); 291 292 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 293 PRIMARY_META_SURFACE_ADDRESS, 294 address->grph.meta_addr.low_part); 295 } 296 297 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 298 PRIMARY_SURFACE_ADDRESS_HIGH, 299 address->grph.addr.high_part); 300 301 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 302 PRIMARY_SURFACE_ADDRESS, 303 address->grph.addr.low_part); 304 break; 305 case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: 306 if (address->video_progressive.luma_addr.quad_part == 0 307 || address->video_progressive.chroma_addr.quad_part == 0) 308 break; 309 310 REG_UPDATE(DCSURF_SURFACE_CONTROL, 311 PRIMARY_SURFACE_TMZ, address->tmz_surface); 312 313 if (address->video_progressive.luma_meta_addr.quad_part != 0) { 314 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, 315 PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 316 address->video_progressive.chroma_meta_addr.high_part); 317 318 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, 319 PRIMARY_META_SURFACE_ADDRESS_C, 320 address->video_progressive.chroma_meta_addr.low_part); 321 322 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 323 PRIMARY_META_SURFACE_ADDRESS_HIGH, 324 address->video_progressive.luma_meta_addr.high_part); 325 326 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 327 PRIMARY_META_SURFACE_ADDRESS, 328 address->video_progressive.luma_meta_addr.low_part); 329 } 330 331 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, 332 PRIMARY_SURFACE_ADDRESS_HIGH_C, 333 address->video_progressive.chroma_addr.high_part); 334 335 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, 336 PRIMARY_SURFACE_ADDRESS_C, 337 address->video_progressive.chroma_addr.low_part); 338 339 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 340 PRIMARY_SURFACE_ADDRESS_HIGH, 341 address->video_progressive.luma_addr.high_part); 342 343 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 344 PRIMARY_SURFACE_ADDRESS, 345 address->video_progressive.luma_addr.low_part); 346 break; 347 case PLN_ADDR_TYPE_GRPH_STEREO: 348 if (address->grph_stereo.left_addr.quad_part == 0) 349 break; 350 if (address->grph_stereo.right_addr.quad_part == 0) 351 break; 352 353 REG_UPDATE(DCSURF_SURFACE_CONTROL, 354 PRIMARY_SURFACE_TMZ, address->tmz_surface); 355 356 if (address->grph_stereo.right_meta_addr.quad_part != 0) { 357 358 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, 359 SECONDARY_META_SURFACE_ADDRESS_HIGH, 360 address->grph_stereo.right_meta_addr.high_part); 361 362 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, 363 SECONDARY_META_SURFACE_ADDRESS, 364 address->grph_stereo.right_meta_addr.low_part); 365 } 366 if (address->grph_stereo.left_meta_addr.quad_part != 0) { 367 368 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 369 PRIMARY_META_SURFACE_ADDRESS_HIGH, 370 address->grph_stereo.left_meta_addr.high_part); 371 372 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 373 PRIMARY_META_SURFACE_ADDRESS, 374 address->grph_stereo.left_meta_addr.low_part); 375 } 376 377 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, 378 SECONDARY_SURFACE_ADDRESS_HIGH, 379 address->grph_stereo.right_addr.high_part); 380 381 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, 382 SECONDARY_SURFACE_ADDRESS, 383 address->grph_stereo.right_addr.low_part); 384 385 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 386 PRIMARY_SURFACE_ADDRESS_HIGH, 387 address->grph_stereo.left_addr.high_part); 388 389 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 390 PRIMARY_SURFACE_ADDRESS, 391 address->grph_stereo.left_addr.low_part); 392 break; 393 default: 394 BREAK_TO_DEBUGGER(); 395 break; 396 } 397 398 hubp->request_address = *address; 399 400 if (flip_immediate) 401 hubp->current_address = *address; 402 403 return true; 404 } 405 406 void hubp1_dcc_control(struct hubp *hubp, bool enable, 407 bool independent_64b_blks) 408 { 409 uint32_t dcc_en = enable ? 1 : 0; 410 uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; 411 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 412 413 REG_UPDATE_2(DCSURF_SURFACE_CONTROL, 414 PRIMARY_SURFACE_DCC_EN, dcc_en, 415 PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); 416 } 417 418 void hubp1_program_surface_config( 419 struct hubp *hubp, 420 enum surface_pixel_format format, 421 union dc_tiling_info *tiling_info, 422 union plane_size *plane_size, 423 enum dc_rotation_angle rotation, 424 struct dc_plane_dcc_param *dcc, 425 bool horizontal_mirror) 426 { 427 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 428 429 hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); 430 hubp1_program_tiling(hubp1, tiling_info, format); 431 hubp1_program_size_and_rotation( 432 hubp1, rotation, format, plane_size, dcc, horizontal_mirror); 433 hubp1_program_pixel_format(hubp1, format); 434 } 435 436 void hubp1_program_requestor( 437 struct hubp *hubp, 438 struct _vcs_dpi_display_rq_regs_st *rq_regs) 439 { 440 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 441 442 REG_UPDATE(HUBPRET_CONTROL, 443 DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); 444 REG_SET_4(DCN_EXPANSION_MODE, 0, 445 DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, 446 PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, 447 MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, 448 CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); 449 REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, 450 CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, 451 MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, 452 META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, 453 MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, 454 DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, 455 MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, 456 SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, 457 PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); 458 REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, 459 CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, 460 MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, 461 META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, 462 MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, 463 DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, 464 MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, 465 SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, 466 PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); 467 } 468 469 470 void hubp1_program_deadline( 471 struct hubp *hubp, 472 struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 473 struct _vcs_dpi_display_ttu_regs_st *ttu_attr) 474 { 475 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 476 477 /* DLG - Per hubp */ 478 REG_SET_2(BLANK_OFFSET_0, 0, 479 REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, 480 DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); 481 482 REG_SET(BLANK_OFFSET_1, 0, 483 MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); 484 485 REG_SET(DST_DIMENSIONS, 0, 486 REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); 487 488 REG_SET_2(DST_AFTER_SCALER, 0, 489 REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, 490 DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); 491 492 if (REG(PREFETCH_SETTINS)) 493 REG_SET_2(PREFETCH_SETTINS, 0, 494 DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 495 VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 496 else 497 REG_SET_2(PREFETCH_SETTINGS, 0, 498 DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 499 VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 500 501 REG_SET_2(VBLANK_PARAMETERS_0, 0, 502 DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, 503 DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); 504 505 REG_SET(REF_FREQ_TO_PIX_FREQ, 0, 506 REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); 507 508 /* DLG - Per luma/chroma */ 509 REG_SET(VBLANK_PARAMETERS_1, 0, 510 REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); 511 512 REG_SET(VBLANK_PARAMETERS_3, 0, 513 REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); 514 515 REG_SET(NOM_PARAMETERS_0, 0, 516 DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); 517 518 REG_SET(NOM_PARAMETERS_1, 0, 519 REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); 520 521 REG_SET(NOM_PARAMETERS_4, 0, 522 DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); 523 524 REG_SET(NOM_PARAMETERS_5, 0, 525 REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); 526 527 REG_SET_2(PER_LINE_DELIVERY_PRE, 0, 528 REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, 529 REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); 530 531 REG_SET_2(PER_LINE_DELIVERY, 0, 532 REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, 533 REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); 534 535 if (REG(PREFETCH_SETTINS_C)) 536 REG_SET(PREFETCH_SETTINS_C, 0, 537 VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 538 else 539 REG_SET(PREFETCH_SETTINGS_C, 0, 540 VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 541 542 REG_SET(VBLANK_PARAMETERS_2, 0, 543 REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); 544 545 REG_SET(VBLANK_PARAMETERS_4, 0, 546 REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); 547 548 REG_SET(NOM_PARAMETERS_2, 0, 549 DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); 550 551 REG_SET(NOM_PARAMETERS_3, 0, 552 REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); 553 554 REG_SET(NOM_PARAMETERS_6, 0, 555 DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); 556 557 REG_SET(NOM_PARAMETERS_7, 0, 558 REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); 559 560 /* TTU - per hubp */ 561 REG_SET_2(DCN_TTU_QOS_WM, 0, 562 QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, 563 QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); 564 565 REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, 566 MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, 567 QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); 568 569 /* TTU - per luma/chroma */ 570 /* Assumed surf0 is luma and 1 is chroma */ 571 572 REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, 573 REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, 574 QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, 575 QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); 576 577 REG_SET(DCN_SURF0_TTU_CNTL1, 0, 578 REFCYC_PER_REQ_DELIVERY_PRE, 579 ttu_attr->refcyc_per_req_delivery_pre_l); 580 581 REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, 582 REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, 583 QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, 584 QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); 585 586 REG_SET(DCN_SURF1_TTU_CNTL1, 0, 587 REFCYC_PER_REQ_DELIVERY_PRE, 588 ttu_attr->refcyc_per_req_delivery_pre_c); 589 } 590 591 static void hubp1_setup( 592 struct hubp *hubp, 593 struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 594 struct _vcs_dpi_display_ttu_regs_st *ttu_attr, 595 struct _vcs_dpi_display_rq_regs_st *rq_regs, 596 struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) 597 { 598 /* otg is locked when this func is called. Register are double buffered. 599 * disable the requestors is not needed 600 */ 601 hubp1_program_requestor(hubp, rq_regs); 602 hubp1_program_deadline(hubp, dlg_attr, ttu_attr); 603 hubp1_vready_workaround(hubp, pipe_dest); 604 } 605 606 bool hubp1_is_flip_pending(struct hubp *hubp) 607 { 608 uint32_t flip_pending = 0; 609 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 610 struct dc_plane_address earliest_inuse_address; 611 612 REG_GET(DCSURF_FLIP_CONTROL, 613 SURFACE_FLIP_PENDING, &flip_pending); 614 615 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, 616 SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); 617 618 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, 619 SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); 620 621 if (flip_pending) 622 return true; 623 624 if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) 625 return true; 626 627 hubp->current_address = hubp->request_address; 628 return false; 629 } 630 631 uint32_t aperture_default_system = 1; 632 uint32_t context0_default_system; /* = 0;*/ 633 634 static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, 635 struct vm_system_aperture_param *apt) 636 { 637 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 638 PHYSICAL_ADDRESS_LOC mc_vm_apt_default; 639 PHYSICAL_ADDRESS_LOC mc_vm_apt_low; 640 PHYSICAL_ADDRESS_LOC mc_vm_apt_high; 641 642 mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; 643 mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; 644 mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; 645 646 REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 647 MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ 648 MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); 649 REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 650 MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); 651 652 REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 653 MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); 654 REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 655 MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); 656 657 REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 658 MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); 659 REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 660 MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); 661 } 662 663 static void hubp1_set_vm_context0_settings(struct hubp *hubp, 664 const struct vm_context0_param *vm0) 665 { 666 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 667 /* pte base */ 668 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, 669 VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); 670 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, 671 VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); 672 673 /* pte start */ 674 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, 675 VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); 676 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, 677 VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); 678 679 /* pte end */ 680 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, 681 VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); 682 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, 683 VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); 684 685 /* fault handling */ 686 REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, 687 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, 688 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); 689 REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, 690 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); 691 692 /* control: enable VM PTE*/ 693 REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, 694 ENABLE_L1_TLB, 1, 695 SYSTEM_ACCESS_MODE, 3); 696 } 697 698 void min_set_viewport( 699 struct hubp *hubp, 700 const struct rect *viewport, 701 const struct rect *viewport_c) 702 { 703 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 704 705 REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, 706 PRI_VIEWPORT_WIDTH, viewport->width, 707 PRI_VIEWPORT_HEIGHT, viewport->height); 708 709 REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, 710 PRI_VIEWPORT_X_START, viewport->x, 711 PRI_VIEWPORT_Y_START, viewport->y); 712 713 /*for stereo*/ 714 REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, 715 SEC_VIEWPORT_WIDTH, viewport->width, 716 SEC_VIEWPORT_HEIGHT, viewport->height); 717 718 REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, 719 SEC_VIEWPORT_X_START, viewport->x, 720 SEC_VIEWPORT_Y_START, viewport->y); 721 722 /* DC supports NV12 only at the moment */ 723 REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, 724 PRI_VIEWPORT_WIDTH_C, viewport_c->width, 725 PRI_VIEWPORT_HEIGHT_C, viewport_c->height); 726 727 REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, 728 PRI_VIEWPORT_X_START_C, viewport_c->x, 729 PRI_VIEWPORT_Y_START_C, viewport_c->y); 730 } 731 732 void hubp1_read_state(struct dcn10_hubp *hubp1, 733 struct dcn_hubp_state *s) 734 { 735 REG_GET(DCSURF_SURFACE_CONFIG, 736 SURFACE_PIXEL_FORMAT, &s->pixel_format); 737 738 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, 739 SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); 740 741 REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 742 PRI_VIEWPORT_WIDTH, &s->viewport_width, 743 PRI_VIEWPORT_HEIGHT, &s->viewport_height); 744 745 REG_GET_2(DCSURF_SURFACE_CONFIG, 746 ROTATION_ANGLE, &s->rotation_angle, 747 H_MIRROR_EN, &s->h_mirror_en); 748 749 REG_GET(DCSURF_TILING_CONFIG, 750 SW_MODE, &s->sw_mode); 751 752 REG_GET(DCSURF_SURFACE_CONTROL, 753 PRIMARY_SURFACE_DCC_EN, &s->dcc_en); 754 755 REG_GET_3(DCHUBP_CNTL, 756 HUBP_BLANK_EN, &s->blank_en, 757 HUBP_TTU_DISABLE, &s->ttu_disable, 758 HUBP_UNDERFLOW_STATUS, &s->underflow_status); 759 760 REG_GET(DCN_GLOBAL_TTU_CNTL, 761 MIN_TTU_VBLANK, &s->min_ttu_vblank); 762 763 REG_GET_2(DCN_TTU_QOS_WM, 764 QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, 765 QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); 766 } 767 768 enum cursor_pitch { 769 CURSOR_PITCH_64_PIXELS = 0, 770 CURSOR_PITCH_128_PIXELS, 771 CURSOR_PITCH_256_PIXELS 772 }; 773 774 enum cursor_lines_per_chunk { 775 CURSOR_LINE_PER_CHUNK_2 = 1, 776 CURSOR_LINE_PER_CHUNK_4, 777 CURSOR_LINE_PER_CHUNK_8, 778 CURSOR_LINE_PER_CHUNK_16 779 }; 780 781 static bool ippn10_cursor_program_control( 782 struct dcn10_hubp *hubp1, 783 bool pixel_data_invert, 784 enum dc_cursor_color_format color_format) 785 { 786 if (REG(CURSOR_SETTINS)) 787 REG_SET_2(CURSOR_SETTINS, 0, 788 /* no shift of the cursor HDL schedule */ 789 CURSOR0_DST_Y_OFFSET, 0, 790 /* used to shift the cursor chunk request deadline */ 791 CURSOR0_CHUNK_HDL_ADJUST, 3); 792 else 793 REG_SET_2(CURSOR_SETTINGS, 0, 794 /* no shift of the cursor HDL schedule */ 795 CURSOR0_DST_Y_OFFSET, 0, 796 /* used to shift the cursor chunk request deadline */ 797 CURSOR0_CHUNK_HDL_ADJUST, 3); 798 799 return true; 800 } 801 802 static enum cursor_pitch ippn10_get_cursor_pitch( 803 unsigned int pitch) 804 { 805 enum cursor_pitch hw_pitch; 806 807 switch (pitch) { 808 case 64: 809 hw_pitch = CURSOR_PITCH_64_PIXELS; 810 break; 811 case 128: 812 hw_pitch = CURSOR_PITCH_128_PIXELS; 813 break; 814 case 256: 815 hw_pitch = CURSOR_PITCH_256_PIXELS; 816 break; 817 default: 818 DC_ERR("Invalid cursor pitch of %d. " 819 "Only 64/128/256 is supported on DCN.\n", pitch); 820 hw_pitch = CURSOR_PITCH_64_PIXELS; 821 break; 822 } 823 return hw_pitch; 824 } 825 826 static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( 827 unsigned int cur_width, 828 enum dc_cursor_color_format format) 829 { 830 enum cursor_lines_per_chunk line_per_chunk; 831 832 if (format == CURSOR_MODE_MONO) 833 /* impl B. expansion in CUR Buffer reader */ 834 line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 835 else if (cur_width <= 32) 836 line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 837 else if (cur_width <= 64) 838 line_per_chunk = CURSOR_LINE_PER_CHUNK_8; 839 else if (cur_width <= 128) 840 line_per_chunk = CURSOR_LINE_PER_CHUNK_4; 841 else 842 line_per_chunk = CURSOR_LINE_PER_CHUNK_2; 843 844 return line_per_chunk; 845 } 846 847 void hubp1_cursor_set_attributes( 848 struct hubp *hubp, 849 const struct dc_cursor_attributes *attr) 850 { 851 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 852 enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); 853 enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( 854 attr->width, attr->color_format); 855 856 hubp->curs_attr = *attr; 857 858 REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, 859 CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); 860 REG_UPDATE(CURSOR_SURFACE_ADDRESS, 861 CURSOR_SURFACE_ADDRESS, attr->address.low_part); 862 863 REG_UPDATE_2(CURSOR_SIZE, 864 CURSOR_WIDTH, attr->width, 865 CURSOR_HEIGHT, attr->height); 866 REG_UPDATE_3(CURSOR_CONTROL, 867 CURSOR_MODE, attr->color_format, 868 CURSOR_PITCH, hw_pitch, 869 CURSOR_LINES_PER_CHUNK, lpc); 870 ippn10_cursor_program_control(hubp1, 871 attr->attribute_flags.bits.INVERT_PIXEL_DATA, 872 attr->color_format); 873 } 874 875 void hubp1_cursor_set_position( 876 struct hubp *hubp, 877 const struct dc_cursor_position *pos, 878 const struct dc_cursor_mi_param *param) 879 { 880 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 881 int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; 882 uint32_t cur_en = pos->enable ? 1 : 0; 883 uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; 884 885 /* 886 * Guard aganst cursor_set_position() from being called with invalid 887 * attributes 888 * 889 * TODO: Look at combining cursor_set_position() and 890 * cursor_set_attributes() into cursor_update() 891 */ 892 if (hubp->curs_attr.address.quad_part == 0) 893 return; 894 895 dst_x_offset *= param->ref_clk_khz; 896 dst_x_offset /= param->pixel_clk_khz; 897 898 ASSERT(param->h_scale_ratio.value); 899 900 if (param->h_scale_ratio.value) 901 dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( 902 dal_fixed31_32_from_int(dst_x_offset), 903 param->h_scale_ratio)); 904 905 if (src_x_offset >= (int)param->viewport_width) 906 cur_en = 0; /* not visible beyond right edge*/ 907 908 if (src_x_offset + (int)hubp->curs_attr.width < 0) 909 cur_en = 0; /* not visible beyond left edge*/ 910 911 if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) 912 hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); 913 REG_UPDATE(CURSOR_CONTROL, 914 CURSOR_ENABLE, cur_en); 915 916 REG_SET_2(CURSOR_POSITION, 0, 917 CURSOR_X_POSITION, pos->x, 918 CURSOR_Y_POSITION, pos->y); 919 920 REG_SET_2(CURSOR_HOT_SPOT, 0, 921 CURSOR_HOT_SPOT_X, pos->x_hotspot, 922 CURSOR_HOT_SPOT_Y, pos->y_hotspot); 923 924 REG_SET(CURSOR_DST_OFFSET, 0, 925 CURSOR_DST_X_OFFSET, dst_x_offset); 926 /* TODO Handle surface pixel formats other than 4:4:4 */ 927 } 928 929 static struct hubp_funcs dcn10_hubp_funcs = { 930 .hubp_program_surface_flip_and_addr = 931 hubp1_program_surface_flip_and_addr, 932 .hubp_program_surface_config = 933 hubp1_program_surface_config, 934 .hubp_is_flip_pending = hubp1_is_flip_pending, 935 .hubp_setup = hubp1_setup, 936 .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, 937 .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, 938 .set_blank = hubp1_set_blank, 939 .dcc_control = hubp1_dcc_control, 940 .mem_program_viewport = min_set_viewport, 941 .set_hubp_blank_en = hubp1_set_hubp_blank_en, 942 .set_cursor_attributes = hubp1_cursor_set_attributes, 943 .set_cursor_position = hubp1_cursor_set_position, 944 .hubp_disconnect = hubp1_disconnect, 945 }; 946 947 /*****************************************/ 948 /* Constructor, Destructor */ 949 /*****************************************/ 950 951 void dcn10_hubp_construct( 952 struct dcn10_hubp *hubp1, 953 struct dc_context *ctx, 954 uint32_t inst, 955 const struct dcn_mi_registers *hubp_regs, 956 const struct dcn_mi_shift *hubp_shift, 957 const struct dcn_mi_mask *hubp_mask) 958 { 959 hubp1->base.funcs = &dcn10_hubp_funcs; 960 hubp1->base.ctx = ctx; 961 hubp1->hubp_regs = hubp_regs; 962 hubp1->hubp_shift = hubp_shift; 963 hubp1->hubp_mask = hubp_mask; 964 hubp1->base.inst = inst; 965 hubp1->base.opp_id = 0xf; 966 hubp1->base.mpcc_id = 0xf; 967 } 968 969 970