1 /* 2 * Copyright 2012-17 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 "dcn20_hubp.h" 27 28 #include "dm_services.h" 29 #include "dce_calcs.h" 30 #include "reg_helper.h" 31 #include "basics/conversion.h" 32 33 #define REG(reg)\ 34 hubp2->hubp_regs->reg 35 36 #define CTX \ 37 hubp2->base.ctx 38 39 #undef FN 40 #define FN(reg_name, field_name) \ 41 hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name 42 43 void hubp2_update_dchub( 44 struct hubp *hubp, 45 struct dchub_init_data *dh_data) 46 { 47 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 48 if (REG(DCN_VM_FB_LOCATION_TOP) == 0) 49 return; 50 51 switch (dh_data->fb_mode) { 52 case FRAME_BUFFER_MODE_ZFB_ONLY: 53 /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ 54 REG_UPDATE(DCN_VM_FB_LOCATION_TOP, 55 FB_TOP, 0); 56 57 REG_UPDATE(DCN_VM_FB_LOCATION_BASE, 58 FB_BASE, 0xFFFFFF); 59 60 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/ 61 REG_UPDATE(DCN_VM_AGP_BASE, 62 AGP_BASE, dh_data->zfb_phys_addr_base >> 24); 63 64 /*This field defines the bottom range of the AGP aperture and represents the 24*/ 65 /*MSBs, bits [47:24] of the 48 address bits*/ 66 REG_UPDATE(DCN_VM_AGP_BOT, 67 AGP_BOT, dh_data->zfb_mc_base_addr >> 24); 68 69 /*This field defines the top range of the AGP aperture and represents the 24*/ 70 /*MSBs, bits [47:24] of the 48 address bits*/ 71 REG_UPDATE(DCN_VM_AGP_TOP, 72 AGP_TOP, (dh_data->zfb_mc_base_addr + 73 dh_data->zfb_size_in_byte - 1) >> 24); 74 break; 75 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: 76 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ 77 78 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/ 79 REG_UPDATE(DCN_VM_AGP_BASE, 80 AGP_BASE, dh_data->zfb_phys_addr_base >> 24); 81 82 /*This field defines the bottom range of the AGP aperture and represents the 24*/ 83 /*MSBs, bits [47:24] of the 48 address bits*/ 84 REG_UPDATE(DCN_VM_AGP_BOT, 85 AGP_BOT, dh_data->zfb_mc_base_addr >> 24); 86 87 /*This field defines the top range of the AGP aperture and represents the 24*/ 88 /*MSBs, bits [47:24] of the 48 address bits*/ 89 REG_UPDATE(DCN_VM_AGP_TOP, 90 AGP_TOP, (dh_data->zfb_mc_base_addr + 91 dh_data->zfb_size_in_byte - 1) >> 24); 92 break; 93 case FRAME_BUFFER_MODE_LOCAL_ONLY: 94 /*Should not touch FB LOCATION (should be done by VBIOS)*/ 95 96 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/ 97 REG_UPDATE(DCN_VM_AGP_BASE, 98 AGP_BASE, 0); 99 100 /*This field defines the bottom range of the AGP aperture and represents the 24*/ 101 /*MSBs, bits [47:24] of the 48 address bits*/ 102 REG_UPDATE(DCN_VM_AGP_BOT, 103 AGP_BOT, 0xFFFFFF); 104 105 /*This field defines the top range of the AGP aperture and represents the 24*/ 106 /*MSBs, bits [47:24] of the 48 address bits*/ 107 REG_UPDATE(DCN_VM_AGP_TOP, 108 AGP_TOP, 0); 109 break; 110 default: 111 break; 112 } 113 114 dh_data->dchub_initialzied = true; 115 dh_data->dchub_info_valid = false; 116 } 117 118 void hubp2_set_vm_system_aperture_settings(struct hubp *hubp, 119 struct vm_system_aperture_param *apt) 120 { 121 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 122 123 PHYSICAL_ADDRESS_LOC mc_vm_apt_default; 124 PHYSICAL_ADDRESS_LOC mc_vm_apt_low; 125 PHYSICAL_ADDRESS_LOC mc_vm_apt_high; 126 127 // The format of default addr is 48:12 of the 48 bit addr 128 mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; 129 130 // The format of high/low are 48:18 of the 48 bit addr 131 mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 18; 132 mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 18; 133 134 REG_UPDATE_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 135 DCN_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ 136 DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); 137 138 REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 139 DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); 140 141 REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR, 0, 142 MC_VM_SYSTEM_APERTURE_LOW_ADDR, mc_vm_apt_low.quad_part); 143 144 REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, 0, 145 MC_VM_SYSTEM_APERTURE_HIGH_ADDR, mc_vm_apt_high.quad_part); 146 147 REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, 148 ENABLE_L1_TLB, 1, 149 SYSTEM_ACCESS_MODE, 0x3); 150 } 151 152 void hubp2_program_deadline( 153 struct hubp *hubp, 154 struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 155 struct _vcs_dpi_display_ttu_regs_st *ttu_attr) 156 { 157 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 158 159 hubp1_program_deadline(hubp, dlg_attr, ttu_attr); 160 161 REG_SET(FLIP_PARAMETERS_1, 0, 162 REFCYC_PER_PTE_GROUP_FLIP_L, dlg_attr->refcyc_per_pte_group_flip_l); 163 } 164 165 void hubp2_vready_at_or_After_vsync(struct hubp *hubp, 166 struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) 167 { 168 uint32_t value = 0; 169 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 170 /* disable_dlg_test_mode Set 9th bit to 1 to disable "dv" mode */ 171 REG_WRITE(HUBPREQ_DEBUG_DB, 1 << 8); 172 /* 173 if (VSTARTUP_START - (VREADY_OFFSET+VUPDATE_WIDTH+VUPDATE_OFFSET)/htotal) 174 <= OTG_V_BLANK_END 175 Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 1 176 else 177 Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0 178 */ 179 if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width 180 + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { 181 value = 1; 182 } else 183 value = 0; 184 REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value); 185 } 186 187 static void hubp2_setup( 188 struct hubp *hubp, 189 struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 190 struct _vcs_dpi_display_ttu_regs_st *ttu_attr, 191 struct _vcs_dpi_display_rq_regs_st *rq_regs, 192 struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) 193 { 194 /* otg is locked when this func is called. Register are double buffered. 195 * disable the requestors is not needed 196 */ 197 198 hubp2_vready_at_or_After_vsync(hubp, pipe_dest); 199 hubp1_program_requestor(hubp, rq_regs); 200 hubp2_program_deadline(hubp, dlg_attr, ttu_attr); 201 202 } 203 204 void hubp2_setup_interdependent( 205 struct hubp *hubp, 206 struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 207 struct _vcs_dpi_display_ttu_regs_st *ttu_attr) 208 { 209 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 210 211 REG_SET_2(PREFETCH_SETTINGS, 0, 212 DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 213 VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 214 215 REG_SET(PREFETCH_SETTINGS_C, 0, 216 VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 217 218 REG_SET_2(VBLANK_PARAMETERS_0, 0, 219 DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, 220 DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); 221 222 REG_SET_2(FLIP_PARAMETERS_0, 0, 223 DST_Y_PER_VM_FLIP, dlg_attr->dst_y_per_vm_flip, 224 DST_Y_PER_ROW_FLIP, dlg_attr->dst_y_per_row_flip); 225 226 REG_SET(VBLANK_PARAMETERS_3, 0, 227 REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); 228 229 REG_SET(VBLANK_PARAMETERS_4, 0, 230 REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); 231 232 REG_SET(FLIP_PARAMETERS_2, 0, 233 REFCYC_PER_META_CHUNK_FLIP_L, dlg_attr->refcyc_per_meta_chunk_flip_l); 234 235 REG_SET_2(PER_LINE_DELIVERY_PRE, 0, 236 REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, 237 REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); 238 239 REG_SET(DCN_SURF0_TTU_CNTL1, 0, 240 REFCYC_PER_REQ_DELIVERY_PRE, 241 ttu_attr->refcyc_per_req_delivery_pre_l); 242 REG_SET(DCN_SURF1_TTU_CNTL1, 0, 243 REFCYC_PER_REQ_DELIVERY_PRE, 244 ttu_attr->refcyc_per_req_delivery_pre_c); 245 REG_SET(DCN_CUR0_TTU_CNTL1, 0, 246 REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0); 247 REG_SET(DCN_CUR1_TTU_CNTL1, 0, 248 REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur1); 249 250 REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, 251 MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, 252 QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); 253 } 254 255 /* DCN2 (GFX10), the following GFX fields are deprecated. They can be set but they will not be used: 256 * NUM_BANKS 257 * NUM_SE 258 * NUM_RB_PER_SE 259 * RB_ALIGNED 260 * Other things can be defaulted, since they never change: 261 * PIPE_ALIGNED = 0 262 * META_LINEAR = 0 263 * In GFX10, only these apply: 264 * PIPE_INTERLEAVE 265 * NUM_PIPES 266 * MAX_COMPRESSED_FRAGS 267 * SW_MODE 268 */ 269 static void hubp2_program_tiling( 270 struct dcn20_hubp *hubp2, 271 const union dc_tiling_info *info, 272 const enum surface_pixel_format pixel_format) 273 { 274 REG_UPDATE_3(DCSURF_ADDR_CONFIG, 275 NUM_PIPES, log_2(info->gfx9.num_pipes), 276 PIPE_INTERLEAVE, info->gfx9.pipe_interleave, 277 MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); 278 279 REG_UPDATE_4(DCSURF_TILING_CONFIG, 280 SW_MODE, info->gfx9.swizzle, 281 META_LINEAR, 0, 282 RB_ALIGNED, 0, 283 PIPE_ALIGNED, 0); 284 } 285 286 void hubp2_program_surface_config( 287 struct hubp *hubp, 288 enum surface_pixel_format format, 289 union dc_tiling_info *tiling_info, 290 union plane_size *plane_size, 291 enum dc_rotation_angle rotation, 292 struct dc_plane_dcc_param *dcc, 293 bool horizontal_mirror, 294 unsigned int compat_level) 295 { 296 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 297 298 hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); 299 hubp2_program_tiling(hubp2, tiling_info, format); 300 hubp1_program_size(hubp, format, plane_size, dcc); 301 hubp1_program_rotation(hubp, rotation, horizontal_mirror); 302 hubp1_program_pixel_format(hubp, format); 303 } 304 305 enum cursor_lines_per_chunk hubp2_get_lines_per_chunk( 306 unsigned int cursor_width, 307 enum dc_cursor_color_format cursor_mode) 308 { 309 enum cursor_lines_per_chunk line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 310 311 if (cursor_mode == CURSOR_MODE_MONO) 312 line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 313 else if (cursor_mode == CURSOR_MODE_COLOR_1BIT_AND || 314 cursor_mode == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || 315 cursor_mode == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { 316 if (cursor_width >= 1 && cursor_width <= 32) 317 line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 318 else if (cursor_width >= 33 && cursor_width <= 64) 319 line_per_chunk = CURSOR_LINE_PER_CHUNK_8; 320 else if (cursor_width >= 65 && cursor_width <= 128) 321 line_per_chunk = CURSOR_LINE_PER_CHUNK_4; 322 else if (cursor_width >= 129 && cursor_width <= 256) 323 line_per_chunk = CURSOR_LINE_PER_CHUNK_2; 324 } else if (cursor_mode == CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED || 325 cursor_mode == CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED) { 326 if (cursor_width >= 1 && cursor_width <= 16) 327 line_per_chunk = CURSOR_LINE_PER_CHUNK_16; 328 else if (cursor_width >= 17 && cursor_width <= 32) 329 line_per_chunk = CURSOR_LINE_PER_CHUNK_8; 330 else if (cursor_width >= 33 && cursor_width <= 64) 331 line_per_chunk = CURSOR_LINE_PER_CHUNK_4; 332 else if (cursor_width >= 65 && cursor_width <= 128) 333 line_per_chunk = CURSOR_LINE_PER_CHUNK_2; 334 else if (cursor_width >= 129 && cursor_width <= 256) 335 line_per_chunk = CURSOR_LINE_PER_CHUNK_1; 336 } 337 338 return line_per_chunk; 339 } 340 341 void hubp2_cursor_set_attributes( 342 struct hubp *hubp, 343 const struct dc_cursor_attributes *attr) 344 { 345 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 346 enum cursor_pitch hw_pitch = hubp1_get_cursor_pitch(attr->pitch); 347 enum cursor_lines_per_chunk lpc = hubp2_get_lines_per_chunk( 348 attr->width, attr->color_format); 349 350 hubp->curs_attr = *attr; 351 352 REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, 353 CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); 354 REG_UPDATE(CURSOR_SURFACE_ADDRESS, 355 CURSOR_SURFACE_ADDRESS, attr->address.low_part); 356 357 REG_UPDATE_2(CURSOR_SIZE, 358 CURSOR_WIDTH, attr->width, 359 CURSOR_HEIGHT, attr->height); 360 361 REG_UPDATE_4(CURSOR_CONTROL, 362 CURSOR_MODE, attr->color_format, 363 CURSOR_2X_MAGNIFY, attr->attribute_flags.bits.ENABLE_MAGNIFICATION, 364 CURSOR_PITCH, hw_pitch, 365 CURSOR_LINES_PER_CHUNK, lpc); 366 367 REG_SET_2(CURSOR_SETTINGS, 0, 368 /* no shift of the cursor HDL schedule */ 369 CURSOR0_DST_Y_OFFSET, 0, 370 /* used to shift the cursor chunk request deadline */ 371 CURSOR0_CHUNK_HDL_ADJUST, 3); 372 } 373 374 void hubp2_dmdata_set_attributes( 375 struct hubp *hubp, 376 const struct dc_dmdata_attributes *attr) 377 { 378 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 379 380 if (attr->dmdata_mode == DMDATA_HW_MODE) { 381 /* set to HW mode */ 382 REG_UPDATE(DMDATA_CNTL, 383 DMDATA_MODE, 1); 384 385 /* for DMDATA flip, need to use SURFACE_UPDATE_LOCK */ 386 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); 387 388 /* toggle DMDATA_UPDATED and set repeat and size */ 389 REG_UPDATE(DMDATA_CNTL, 390 DMDATA_UPDATED, 0); 391 REG_UPDATE_3(DMDATA_CNTL, 392 DMDATA_UPDATED, 1, 393 DMDATA_REPEAT, attr->dmdata_repeat, 394 DMDATA_SIZE, attr->dmdata_size); 395 396 /* set DMDATA address */ 397 REG_WRITE(DMDATA_ADDRESS_LOW, attr->address.low_part); 398 REG_UPDATE(DMDATA_ADDRESS_HIGH, 399 DMDATA_ADDRESS_HIGH, attr->address.high_part); 400 401 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); 402 403 } else { 404 /* set to SW mode before loading data */ 405 REG_SET(DMDATA_CNTL, 0, 406 DMDATA_MODE, 0); 407 /* toggle DMDATA_SW_UPDATED to start loading sequence */ 408 REG_UPDATE(DMDATA_SW_CNTL, 409 DMDATA_SW_UPDATED, 0); 410 REG_UPDATE_3(DMDATA_SW_CNTL, 411 DMDATA_SW_UPDATED, 1, 412 DMDATA_SW_REPEAT, attr->dmdata_repeat, 413 DMDATA_SW_SIZE, attr->dmdata_size); 414 /* load data into hubp dmdata buffer */ 415 hubp2_dmdata_load(hubp, attr->dmdata_size, attr->dmdata_sw_data); 416 } 417 418 /* Note that DL_DELTA must be programmed if we want to use TTU mode */ 419 REG_SET_3(DMDATA_QOS_CNTL, 0, 420 DMDATA_QOS_MODE, attr->dmdata_qos_mode, 421 DMDATA_QOS_LEVEL, attr->dmdata_qos_level, 422 DMDATA_DL_DELTA, attr->dmdata_dl_delta); 423 } 424 425 void hubp2_dmdata_load( 426 struct hubp *hubp, 427 uint32_t dmdata_sw_size, 428 const uint32_t *dmdata_sw_data) 429 { 430 int i; 431 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 432 433 /* load dmdata into HUBP buffer in SW mode */ 434 for (i = 0; i < dmdata_sw_size / 4; i++) 435 REG_WRITE(DMDATA_SW_DATA, dmdata_sw_data[i]); 436 } 437 438 bool hubp2_dmdata_status_done(struct hubp *hubp) 439 { 440 uint32_t status; 441 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 442 443 REG_GET(DMDATA_STATUS, DMDATA_DONE, &status); 444 return (status == 1); 445 } 446 447 bool hubp2_program_surface_flip_and_addr( 448 struct hubp *hubp, 449 const struct dc_plane_address *address, 450 bool flip_immediate) 451 { 452 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 453 454 //program flip type 455 REG_UPDATE(DCSURF_FLIP_CONTROL, 456 SURFACE_FLIP_TYPE, flip_immediate); 457 458 // Program VMID reg 459 REG_UPDATE(VMID_SETTINGS_0, 460 VMID, address->vmid); 461 462 if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { 463 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x1); 464 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); 465 466 } else { 467 // turn off stereo if not in stereo 468 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0); 469 REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0); 470 } 471 472 473 474 /* HW automatically latch rest of address register on write to 475 * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used 476 * 477 * program high first and then the low addr, order matters! 478 */ 479 switch (address->type) { 480 case PLN_ADDR_TYPE_GRAPHICS: 481 /* DCN1.0 does not support const color 482 * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 483 * base on address->grph.dcc_const_color 484 * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma 485 * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma 486 */ 487 488 if (address->grph.addr.quad_part == 0) 489 break; 490 491 REG_UPDATE_2(DCSURF_SURFACE_CONTROL, 492 PRIMARY_SURFACE_TMZ, address->tmz_surface, 493 PRIMARY_META_SURFACE_TMZ, address->tmz_surface); 494 495 if (address->grph.meta_addr.quad_part != 0) { 496 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 497 PRIMARY_META_SURFACE_ADDRESS_HIGH, 498 address->grph.meta_addr.high_part); 499 500 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 501 PRIMARY_META_SURFACE_ADDRESS, 502 address->grph.meta_addr.low_part); 503 } 504 505 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 506 PRIMARY_SURFACE_ADDRESS_HIGH, 507 address->grph.addr.high_part); 508 509 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 510 PRIMARY_SURFACE_ADDRESS, 511 address->grph.addr.low_part); 512 break; 513 case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: 514 if (address->video_progressive.luma_addr.quad_part == 0 515 || address->video_progressive.chroma_addr.quad_part == 0) 516 break; 517 518 REG_UPDATE_4(DCSURF_SURFACE_CONTROL, 519 PRIMARY_SURFACE_TMZ, address->tmz_surface, 520 PRIMARY_SURFACE_TMZ_C, address->tmz_surface, 521 PRIMARY_META_SURFACE_TMZ, address->tmz_surface, 522 PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); 523 524 if (address->video_progressive.luma_meta_addr.quad_part != 0) { 525 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, 526 PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 527 address->video_progressive.chroma_meta_addr.high_part); 528 529 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, 530 PRIMARY_META_SURFACE_ADDRESS_C, 531 address->video_progressive.chroma_meta_addr.low_part); 532 533 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 534 PRIMARY_META_SURFACE_ADDRESS_HIGH, 535 address->video_progressive.luma_meta_addr.high_part); 536 537 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 538 PRIMARY_META_SURFACE_ADDRESS, 539 address->video_progressive.luma_meta_addr.low_part); 540 } 541 542 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, 543 PRIMARY_SURFACE_ADDRESS_HIGH_C, 544 address->video_progressive.chroma_addr.high_part); 545 546 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, 547 PRIMARY_SURFACE_ADDRESS_C, 548 address->video_progressive.chroma_addr.low_part); 549 550 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 551 PRIMARY_SURFACE_ADDRESS_HIGH, 552 address->video_progressive.luma_addr.high_part); 553 554 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 555 PRIMARY_SURFACE_ADDRESS, 556 address->video_progressive.luma_addr.low_part); 557 break; 558 case PLN_ADDR_TYPE_GRPH_STEREO: 559 if (address->grph_stereo.left_addr.quad_part == 0) 560 break; 561 if (address->grph_stereo.right_addr.quad_part == 0) 562 break; 563 564 REG_UPDATE_8(DCSURF_SURFACE_CONTROL, 565 PRIMARY_SURFACE_TMZ, address->tmz_surface, 566 PRIMARY_SURFACE_TMZ_C, address->tmz_surface, 567 PRIMARY_META_SURFACE_TMZ, address->tmz_surface, 568 PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface, 569 SECONDARY_SURFACE_TMZ, address->tmz_surface, 570 SECONDARY_SURFACE_TMZ_C, address->tmz_surface, 571 SECONDARY_META_SURFACE_TMZ, address->tmz_surface, 572 SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface); 573 574 if (address->grph_stereo.right_meta_addr.quad_part != 0) { 575 576 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, 577 SECONDARY_META_SURFACE_ADDRESS_HIGH, 578 address->grph_stereo.right_meta_addr.high_part); 579 580 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, 581 SECONDARY_META_SURFACE_ADDRESS, 582 address->grph_stereo.right_meta_addr.low_part); 583 } 584 if (address->grph_stereo.left_meta_addr.quad_part != 0) { 585 586 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, 587 PRIMARY_META_SURFACE_ADDRESS_HIGH, 588 address->grph_stereo.left_meta_addr.high_part); 589 590 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, 591 PRIMARY_META_SURFACE_ADDRESS, 592 address->grph_stereo.left_meta_addr.low_part); 593 } 594 595 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, 596 SECONDARY_SURFACE_ADDRESS_HIGH, 597 address->grph_stereo.right_addr.high_part); 598 599 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, 600 SECONDARY_SURFACE_ADDRESS, 601 address->grph_stereo.right_addr.low_part); 602 603 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, 604 PRIMARY_SURFACE_ADDRESS_HIGH, 605 address->grph_stereo.left_addr.high_part); 606 607 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, 608 PRIMARY_SURFACE_ADDRESS, 609 address->grph_stereo.left_addr.low_part); 610 break; 611 default: 612 BREAK_TO_DEBUGGER(); 613 break; 614 } 615 616 hubp->request_address = *address; 617 618 return true; 619 } 620 621 void hubp2_enable_triplebuffer( 622 struct hubp *hubp, 623 bool enable) 624 { 625 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 626 uint32_t triple_buffer_en = 0; 627 bool tri_buffer_en; 628 629 REG_GET(DCSURF_FLIP_CONTROL2, SURFACE_TRIPLE_BUFFER_ENABLE, &triple_buffer_en); 630 tri_buffer_en = (triple_buffer_en == 1); 631 if (tri_buffer_en != enable) { 632 REG_UPDATE(DCSURF_FLIP_CONTROL2, 633 SURFACE_TRIPLE_BUFFER_ENABLE, enable ? DC_TRIPLEBUFFER_ENABLE : DC_TRIPLEBUFFER_DISABLE); 634 } 635 } 636 637 bool hubp2_is_triplebuffer_enabled( 638 struct hubp *hubp) 639 { 640 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 641 uint32_t triple_buffer_en = 0; 642 643 REG_GET(DCSURF_FLIP_CONTROL2, SURFACE_TRIPLE_BUFFER_ENABLE, &triple_buffer_en); 644 645 return (bool)triple_buffer_en; 646 } 647 648 void hubp2_set_flip_control_surface_gsl(struct hubp *hubp, bool enable) 649 { 650 struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 651 652 REG_UPDATE(DCSURF_FLIP_CONTROL2, SURFACE_GSL_ENABLE, enable ? 1 : 0); 653 } 654 655 static struct hubp_funcs dcn20_hubp_funcs = { 656 .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, 657 .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled, 658 .hubp_program_surface_flip_and_addr = hubp2_program_surface_flip_and_addr, 659 .hubp_program_surface_config = hubp2_program_surface_config, 660 .hubp_is_flip_pending = hubp1_is_flip_pending, 661 .hubp_setup = hubp2_setup, 662 .hubp_setup_interdependent = hubp2_setup_interdependent, 663 .hubp_set_vm_system_aperture_settings = hubp2_set_vm_system_aperture_settings, 664 .set_blank = hubp1_set_blank, 665 .dcc_control = hubp1_dcc_control, 666 .hubp_update_dchub = hubp2_update_dchub, 667 .mem_program_viewport = min_set_viewport, 668 .set_cursor_attributes = hubp2_cursor_set_attributes, 669 .set_cursor_position = hubp1_cursor_set_position, 670 .hubp_clk_cntl = hubp1_clk_cntl, 671 .hubp_vtg_sel = hubp1_vtg_sel, 672 .dmdata_set_attributes = hubp2_dmdata_set_attributes, 673 .dmdata_load = hubp2_dmdata_load, 674 .dmdata_status_done = hubp2_dmdata_status_done, 675 .hubp_read_state = hubp1_read_state, 676 .hubp_clear_underflow = hubp1_clear_underflow, 677 .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl, 678 .hubp_init = hubp1_init, 679 }; 680 681 682 bool hubp2_construct( 683 struct dcn20_hubp *hubp2, 684 struct dc_context *ctx, 685 uint32_t inst, 686 const struct dcn_hubp2_registers *hubp_regs, 687 const struct dcn_hubp2_shift *hubp_shift, 688 const struct dcn_hubp2_mask *hubp_mask) 689 { 690 hubp2->base.funcs = &dcn20_hubp_funcs; 691 hubp2->base.ctx = ctx; 692 hubp2->hubp_regs = hubp_regs; 693 hubp2->hubp_shift = hubp_shift; 694 hubp2->hubp_mask = hubp_mask; 695 hubp2->base.inst = inst; 696 hubp2->base.opp_id = OPP_ID_INVALID; 697 hubp2->base.mpcc_id = 0xf; 698 699 return true; 700 } 701