1/* $NetBSD: amdgpu_dcn20_stream_encoder.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $ */ 2 3/* 4 * Copyright 2012-15 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: amdgpu_dcn20_stream_encoder.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $"); 30 31#include <linux/delay.h> 32 33#include "dc_bios_types.h" 34#include "dcn20_stream_encoder.h" 35#include "reg_helper.h" 36#include "hw_shared.h" 37 38#define DC_LOGGER \ 39 enc1->base.ctx->logger 40 41 42#define REG(reg)\ 43 (enc1->regs->reg) 44 45#undef FN 46#define FN(reg_name, field_name) \ 47 enc1->se_shift->field_name, enc1->se_mask->field_name 48 49 50#define CTX \ 51 enc1->base.ctx 52 53 54static void enc2_update_hdmi_info_packet( 55 struct dcn10_stream_encoder *enc1, 56 uint32_t packet_index, 57 const struct dc_info_packet *info_packet) 58{ 59 uint32_t cont, send, line; 60 61 if (info_packet->valid) { 62 enc1_update_generic_info_packet( 63 enc1, 64 packet_index, 65 info_packet); 66 67 /* enable transmission of packet(s) - 68 * packet transmission begins on the next frame */ 69 cont = 1; 70 /* send packet(s) every frame */ 71 send = 1; 72 /* select line number to send packets on */ 73 line = 2; 74 } else { 75 cont = 0; 76 send = 0; 77 line = 0; 78 } 79 80 /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ 81 82 /* choose which generic packet control to use */ 83 switch (packet_index) { 84 case 0: 85 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 86 HDMI_GENERIC0_CONT, cont, 87 HDMI_GENERIC0_SEND, send); 88 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, 89 HDMI_GENERIC0_LINE, line); 90 break; 91 case 1: 92 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 93 HDMI_GENERIC1_CONT, cont, 94 HDMI_GENERIC1_SEND, send); 95 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, 96 HDMI_GENERIC1_LINE, line); 97 break; 98 case 2: 99 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 100 HDMI_GENERIC2_CONT, cont, 101 HDMI_GENERIC2_SEND, send); 102 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, 103 HDMI_GENERIC2_LINE, line); 104 break; 105 case 3: 106 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 107 HDMI_GENERIC3_CONT, cont, 108 HDMI_GENERIC3_SEND, send); 109 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, 110 HDMI_GENERIC3_LINE, line); 111 break; 112 case 4: 113 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 114 HDMI_GENERIC4_CONT, cont, 115 HDMI_GENERIC4_SEND, send); 116 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, 117 HDMI_GENERIC4_LINE, line); 118 break; 119 case 5: 120 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 121 HDMI_GENERIC5_CONT, cont, 122 HDMI_GENERIC5_SEND, send); 123 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, 124 HDMI_GENERIC5_LINE, line); 125 break; 126 case 6: 127 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 128 HDMI_GENERIC6_CONT, cont, 129 HDMI_GENERIC6_SEND, send); 130 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, 131 HDMI_GENERIC6_LINE, line); 132 break; 133 case 7: 134 REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, 135 HDMI_GENERIC7_CONT, cont, 136 HDMI_GENERIC7_SEND, send); 137 REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, 138 HDMI_GENERIC7_LINE, line); 139 break; 140 default: 141 /* invalid HW packet index */ 142 DC_LOG_WARNING( 143 "Invalid HW packet index: %s()\n", 144 __func__); 145 return; 146 } 147} 148 149static void enc2_stream_encoder_update_hdmi_info_packets( 150 struct stream_encoder *enc, 151 const struct encoder_info_frame *info_frame) 152{ 153 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 154 155 /* for bring up, disable dp double TODO */ 156 REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); 157 158 /*Always add mandatory packets first followed by optional ones*/ 159 enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi); 160 enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); 161 enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); 162 enc2_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); 163 enc2_update_hdmi_info_packet(enc1, 3, &info_frame->spd); 164 enc2_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); 165} 166 167static void enc2_stream_encoder_stop_hdmi_info_packets( 168 struct stream_encoder *enc) 169{ 170 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 171 172 /* stop generic packets 0,1 on HDMI */ 173 REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, 174 HDMI_GENERIC0_CONT, 0, 175 HDMI_GENERIC0_SEND, 0, 176 HDMI_GENERIC1_CONT, 0, 177 HDMI_GENERIC1_SEND, 0); 178 REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, 179 HDMI_GENERIC0_LINE, 0, 180 HDMI_GENERIC1_LINE, 0); 181 182 /* stop generic packets 2,3 on HDMI */ 183 REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, 184 HDMI_GENERIC2_CONT, 0, 185 HDMI_GENERIC2_SEND, 0, 186 HDMI_GENERIC3_CONT, 0, 187 HDMI_GENERIC3_SEND, 0); 188 REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, 189 HDMI_GENERIC2_LINE, 0, 190 HDMI_GENERIC3_LINE, 0); 191 192 /* stop generic packets 4,5 on HDMI */ 193 REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, 194 HDMI_GENERIC4_CONT, 0, 195 HDMI_GENERIC4_SEND, 0, 196 HDMI_GENERIC5_CONT, 0, 197 HDMI_GENERIC5_SEND, 0); 198 REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, 199 HDMI_GENERIC4_LINE, 0, 200 HDMI_GENERIC5_LINE, 0); 201 202 /* stop generic packets 6,7 on HDMI */ 203 REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, 204 HDMI_GENERIC6_CONT, 0, 205 HDMI_GENERIC6_SEND, 0, 206 HDMI_GENERIC7_CONT, 0, 207 HDMI_GENERIC7_SEND, 0); 208 REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, 209 HDMI_GENERIC6_LINE, 0, 210 HDMI_GENERIC7_LINE, 0); 211} 212 213 214/* Update GSP7 SDP 128 byte long */ 215static void enc2_update_gsp7_128_info_packet( 216 struct dcn10_stream_encoder *enc1, 217 const struct dc_info_packet_128 *info_packet) 218{ 219 uint32_t i; 220 221 /* TODOFPGA Figure out a proper number for max_retries polling for lock 222 * use 50 for now. 223 */ 224 uint32_t max_retries = 50; 225 const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; 226 227 ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS); 228 229 /* Configure for PPS packet size (128 bytes) */ 230 REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1); 231 232 /* We need turn on clock before programming AFMT block*/ 233 REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); 234 235 /* Poll dig_update_lock is not locked -> asic internal signal 236 * assumes otg master lock will unlock it 237 */ 238 /*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/ 239 240 /* Wait for HW/SW GSP memory access conflict to go away */ 241 REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, 242 0, 10, max_retries); 243 244 /* Clear HW/SW memory access conflict flag */ 245 REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); 246 247 /* write generic packet header */ 248 REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7); 249 REG_SET_4(AFMT_GENERIC_HDR, 0, 250 AFMT_GENERIC_HB0, info_packet->hb0, 251 AFMT_GENERIC_HB1, info_packet->hb1, 252 AFMT_GENERIC_HB2, info_packet->hb2, 253 AFMT_GENERIC_HB3, info_packet->hb3); 254 255 /* Write generic packet content 128 bytes long. Four sets are used (indexes 7 256 * through 10) to fit 128 bytes. 257 */ 258 for (i = 0; i < 4; i++) { 259 uint32_t packet_index = 7 + i; 260 REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index); 261 262 REG_WRITE(AFMT_GENERIC_0, *content++); 263 REG_WRITE(AFMT_GENERIC_1, *content++); 264 REG_WRITE(AFMT_GENERIC_2, *content++); 265 REG_WRITE(AFMT_GENERIC_3, *content++); 266 REG_WRITE(AFMT_GENERIC_4, *content++); 267 REG_WRITE(AFMT_GENERIC_5, *content++); 268 REG_WRITE(AFMT_GENERIC_6, *content++); 269 REG_WRITE(AFMT_GENERIC_7, *content++); 270 } 271 272 REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, 1); 273} 274 275/* Set DSC-related configuration. 276 * dsc_mode: 0 disables DSC, other values enable DSC in specified format 277 * sc_bytes_per_pixel: Bytes per pixel in u3.28 format 278 * dsc_slice_width: Slice width in pixels 279 */ 280static void enc2_dp_set_dsc_config(struct stream_encoder *enc, 281 enum optc_dsc_mode dsc_mode, 282 uint32_t dsc_bytes_per_pixel, 283 uint32_t dsc_slice_width) 284{ 285 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 286 287 REG_UPDATE_2(DP_DSC_CNTL, 288 DP_DSC_MODE, dsc_mode, 289 DP_DSC_SLICE_WIDTH, dsc_slice_width); 290 291 REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, 292 DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); 293} 294 295 296static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, 297 bool enable, 298 uint8_t *dsc_packed_pps) 299{ 300 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 301 302 if (enable) { 303 struct dc_info_packet_128 pps_sdp; 304 305 ASSERT(dsc_packed_pps); 306 307 /* Load PPS into infoframe (SDP) registers */ 308 pps_sdp.valid = true; 309 pps_sdp.hb0 = 0; 310 pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; 311 pps_sdp.hb2 = 127; 312 pps_sdp.hb3 = 0; 313 memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); 314 enc2_update_gsp7_128_info_packet(enc1, &pps_sdp); 315 316 /* Enable Generic Stream Packet 7 (GSP) transmission */ 317 //REG_UPDATE(DP_SEC_CNTL, 318 // DP_SEC_GSP7_ENABLE, 1); 319 320 /* SW should make sure VBID[6] update line number is bigger 321 * than PPS transmit line number 322 */ 323 REG_UPDATE(DP_SEC_CNTL6, 324 DP_SEC_GSP7_LINE_NUM, 2); 325 REG_UPDATE_2(DP_MSA_VBID_MISC, 326 DP_VBID6_LINE_REFERENCE, 0, 327 DP_VBID6_LINE_NUM, 3); 328 329 /* Send PPS data at the line number specified above. 330 * DP spec requires PPS to be sent only when it changes, however since 331 * decoder has to be able to handle its change on every frame, we're 332 * sending it always (i.e. on every frame) to reduce the chance it'd be 333 * missed by decoder. If it turns out required to send PPS only when it 334 * changes, we can use DP_SEC_GSP7_SEND register. 335 */ 336 REG_UPDATE_2(DP_SEC_CNTL, 337 DP_SEC_GSP7_ENABLE, 1, 338 DP_SEC_STREAM_ENABLE, 1); 339 } else { 340 /* Disable Generic Stream Packet 7 (GSP) transmission */ 341 REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0); 342 REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); 343 } 344} 345 346 347/* this function read dsc related register fields to be logged later in dcn10_log_hw_state 348 * into a dcn_dsc_state struct. 349 */ 350static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s) 351{ 352 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 353 354 //if dsc is enabled, continue to read 355 REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); 356 if (s->dsc_mode) { 357 REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); 358 REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num); 359 360 REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); 361 REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); 362 363 REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable); 364 REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); 365 } 366} 367 368/* Set Dynamic Metadata-configuration. 369 * enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME 370 * hubp_requestor_id: HUBP physical instance that is the source of dynamic metadata 371 * only needs to be set when enable_dme is TRUE 372 * dmdata_mode: dynamic metadata packet type: DP, HDMI, or Dolby Vision 373 * 374 * Ensure the OTG master update lock is set when changing DME configuration. 375 */ 376void enc2_set_dynamic_metadata(struct stream_encoder *enc, 377 bool enable_dme, 378 uint32_t hubp_requestor_id, 379 enum dynamic_metadata_mode dmdata_mode) 380{ 381 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 382 383 if (enable_dme) { 384 REG_UPDATE_2(DME_CONTROL, 385 METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id, 386 METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0); 387 388 /* Use default line reference DP_SOF for bringup. 389 * Should use OTG_SOF for DRR cases 390 */ 391 if (dmdata_mode == dmdata_dp) 392 REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION, 393 DP_SEC_METADATA_PACKET_ENABLE, 1, 394 DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0, 395 DP_SEC_METADATA_PACKET_LINE, 20); 396 else { 397 REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL, 398 HDMI_METADATA_PACKET_ENABLE, 1, 399 HDMI_METADATA_PACKET_LINE_REFERENCE, 0, 400 HDMI_METADATA_PACKET_LINE, 2); 401 402 if (dmdata_mode == dmdata_dolby_vision) 403 REG_UPDATE(DIG_FE_CNTL, 404 DOLBY_VISION_EN, 1); 405 } 406 407 REG_UPDATE(DME_CONTROL, 408 METADATA_ENGINE_EN, 1); 409 } else { 410 REG_UPDATE(DME_CONTROL, 411 METADATA_ENGINE_EN, 0); 412 413 if (dmdata_mode == dmdata_dp) 414 REG_UPDATE(DP_SEC_METADATA_TRANSMISSION, 415 DP_SEC_METADATA_PACKET_ENABLE, 0); 416 else { 417 REG_UPDATE(HDMI_METADATA_PACKET_CONTROL, 418 HDMI_METADATA_PACKET_ENABLE, 0); 419 REG_UPDATE(DIG_FE_CNTL, 420 DOLBY_VISION_EN, 0); 421 } 422 } 423} 424 425static void enc2_stream_encoder_update_dp_info_packets( 426 struct stream_encoder *enc, 427 const struct encoder_info_frame *info_frame) 428{ 429 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 430 uint32_t dmdata_packet_enabled = 0; 431 432 enc1_stream_encoder_update_dp_info_packets(enc, info_frame); 433 434 /* check if dynamic metadata packet transmission is enabled */ 435 REG_GET(DP_SEC_METADATA_TRANSMISSION, 436 DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); 437 438 if (dmdata_packet_enabled) 439 REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); 440} 441 442static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 443{ 444 bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 445 446 two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 447 && !timing->dsc_cfg.ycbcr422_simple); 448 return two_pix; 449} 450 451void enc2_stream_encoder_dp_unblank( 452 struct stream_encoder *enc, 453 const struct encoder_unblank_param *param) 454{ 455 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 456 457 if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { 458 uint32_t n_vid = 0x8000; 459 uint32_t m_vid; 460 uint32_t n_multiply = 0; 461 uint64_t m_vid_l = n_vid; 462 463 /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ 464 if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { 465 /*this logic should be the same in get_pixel_clock_parameters() */ 466 n_multiply = 1; 467 } 468 /* M / N = Fstream / Flink 469 * m_vid / n_vid = pixel rate / link rate 470 */ 471 472 m_vid_l *= param->timing.pix_clk_100hz / 10; 473 m_vid_l = div_u64(m_vid_l, 474 param->link_settings.link_rate 475 * LINK_RATE_REF_FREQ_IN_KHZ); 476 477 m_vid = (uint32_t) m_vid_l; 478 479 /* enable auto measurement */ 480 481 REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); 482 483 /* auto measurement need 1 full 0x8000 symbol cycle to kick in, 484 * therefore program initial value for Mvid and Nvid 485 */ 486 487 REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); 488 489 REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); 490 491 REG_UPDATE_2(DP_VID_TIMING, 492 DP_VID_M_N_GEN_EN, 1, 493 DP_VID_N_MUL, n_multiply); 494 } 495 496 /* make sure stream is disabled before resetting steer fifo */ 497 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); 498 REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); 499 500 /* set DIG_START to 0x1 to reset FIFO */ 501 REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); 502 udelay(1); 503 504 /* write 0 to take the FIFO out of reset */ 505 506 REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); 507 508 /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen 509 * that it overflows during mode transition, and sometimes doesn't recover. 510 */ 511 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); 512 udelay(10); 513 514 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); 515 516 /* wait 100us for DIG/DP logic to prime 517 * (i.e. a few video lines) 518 */ 519 udelay(100); 520 521 /* the hardware would start sending video at the start of the next DP 522 * frame (i.e. rising edge of the vblank). 523 * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this 524 * register has no effect on enable transition! HW always guarantees 525 * VID_STREAM enable at start of next frame, and this is not 526 * programmable 527 */ 528 529 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); 530} 531 532static void enc2_dp_set_odm_combine( 533 struct stream_encoder *enc, 534 bool odm_combine) 535{ 536 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 537 538 REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); 539} 540 541void enc2_stream_encoder_dp_set_stream_attribute( 542 struct stream_encoder *enc, 543 struct dc_crtc_timing *crtc_timing, 544 enum dc_color_space output_color_space, 545 bool use_vsc_sdp_for_colorimetry, 546 uint32_t enable_sdp_splitting) 547{ 548 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 549 550 enc1_stream_encoder_dp_set_stream_attribute(enc, 551 crtc_timing, 552 output_color_space, 553 use_vsc_sdp_for_colorimetry, 554 enable_sdp_splitting); 555 556 REG_UPDATE(DP_SEC_FRAMING4, 557 DP_SST_SDP_SPLITTING, enable_sdp_splitting); 558} 559 560static const struct stream_encoder_funcs dcn20_str_enc_funcs = { 561 .dp_set_odm_combine = 562 enc2_dp_set_odm_combine, 563 .dp_set_stream_attribute = 564 enc2_stream_encoder_dp_set_stream_attribute, 565 .hdmi_set_stream_attribute = 566 enc1_stream_encoder_hdmi_set_stream_attribute, 567 .dvi_set_stream_attribute = 568 enc1_stream_encoder_dvi_set_stream_attribute, 569 .set_mst_bandwidth = 570 enc1_stream_encoder_set_mst_bandwidth, 571 .update_hdmi_info_packets = 572 enc2_stream_encoder_update_hdmi_info_packets, 573 .stop_hdmi_info_packets = 574 enc2_stream_encoder_stop_hdmi_info_packets, 575 .update_dp_info_packets = 576 enc2_stream_encoder_update_dp_info_packets, 577 .send_immediate_sdp_message = 578 enc1_stream_encoder_send_immediate_sdp_message, 579 .stop_dp_info_packets = 580 enc1_stream_encoder_stop_dp_info_packets, 581 .dp_blank = 582 enc1_stream_encoder_dp_blank, 583 .dp_unblank = 584 enc2_stream_encoder_dp_unblank, 585 .audio_mute_control = enc1_se_audio_mute_control, 586 587 .dp_audio_setup = enc1_se_dp_audio_setup, 588 .dp_audio_enable = enc1_se_dp_audio_enable, 589 .dp_audio_disable = enc1_se_dp_audio_disable, 590 591 .hdmi_audio_setup = enc1_se_hdmi_audio_setup, 592 .hdmi_audio_disable = enc1_se_hdmi_audio_disable, 593 .setup_stereo_sync = enc1_setup_stereo_sync, 594 .set_avmute = enc1_stream_encoder_set_avmute, 595 .dig_connect_to_otg = enc1_dig_connect_to_otg, 596 .dig_source_otg = enc1_dig_source_otg, 597 598 .dp_get_pixel_format = 599 enc1_stream_encoder_dp_get_pixel_format, 600 601 .enc_read_state = enc2_read_state, 602 .dp_set_dsc_config = enc2_dp_set_dsc_config, 603 .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, 604 .set_dynamic_metadata = enc2_set_dynamic_metadata, 605 .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, 606}; 607 608void dcn20_stream_encoder_construct( 609 struct dcn10_stream_encoder *enc1, 610 struct dc_context *ctx, 611 struct dc_bios *bp, 612 enum engine_id eng_id, 613 const struct dcn10_stream_enc_registers *regs, 614 const struct dcn10_stream_encoder_shift *se_shift, 615 const struct dcn10_stream_encoder_mask *se_mask) 616{ 617 enc1->base.funcs = &dcn20_str_enc_funcs; 618 enc1->base.ctx = ctx; 619 enc1->base.id = eng_id; 620 enc1->base.bp = bp; 621 enc1->regs = regs; 622 enc1->se_shift = se_shift; 623 enc1->se_mask = se_mask; 624} 625 626