1/* SPDX-License-Identifier: MIT */ 2/* 3 * Copyright 2023 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25 26#include "dc_bios_types.h" 27#include "dcn30/dcn30_dio_stream_encoder.h" 28#include "dcn314/dcn314_dio_stream_encoder.h" 29#include "dcn32/dcn32_dio_stream_encoder.h" 30#include "dcn35_dio_stream_encoder.h" 31#include "reg_helper.h" 32#include "hw_shared.h" 33#include "link.h" 34#include "dpcd_defs.h" 35 36#define DC_LOGGER \ 37 enc1->base.ctx->logger 38 39#define REG(reg)\ 40 (enc1->regs->reg) 41 42#undef FN 43#define FN(reg_name, field_name) \ 44 enc1->se_shift->field_name, enc1->se_mask->field_name 45 46#define VBI_LINE_0 0 47#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 48 49#define CTX \ 50 enc1->base.ctx 51/* setup stream encoder in dvi mode */ 52static void enc35_stream_encoder_dvi_set_stream_attribute( 53 struct stream_encoder *enc, 54 struct dc_crtc_timing *crtc_timing, 55 bool is_dual_link) 56{ 57 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 58 59 if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { 60 struct bp_encoder_control cntl = {0}; 61 62 cntl.action = ENCODER_CONTROL_SETUP; 63 cntl.engine_id = enc1->base.id; 64 cntl.signal = is_dual_link ? 65 SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; 66 cntl.enable_dp_audio = false; 67 cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; 68 cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; 69 70 if (enc1->base.bp->funcs->encoder_control( 71 enc1->base.bp, &cntl) != BP_RESULT_OK) 72 return; 73 74 } else { 75 76 //Set pattern for clock channel, default vlue 0x63 does not work 77 REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); 78 79 //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup 80 81 //DIG_SOURCE_SELECT is already set in dig_connect_to_otg 82 83 /* DIG_START is removed from the register spec */ 84 } 85 86 ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); 87 ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); 88 enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); 89} 90/* setup stream encoder in hdmi mode */ 91static void enc35_stream_encoder_hdmi_set_stream_attribute( 92 struct stream_encoder *enc, 93 struct dc_crtc_timing *crtc_timing, 94 int actual_pix_clk_khz, 95 bool enable_audio) 96{ 97 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 98 99 if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { 100 struct bp_encoder_control cntl = {0}; 101 102 cntl.action = ENCODER_CONTROL_SETUP; 103 cntl.engine_id = enc1->base.id; 104 cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; 105 cntl.enable_dp_audio = enable_audio; 106 cntl.pixel_clock = actual_pix_clk_khz; 107 cntl.lanes_number = LANE_COUNT_FOUR; 108 109 if (enc1->base.bp->funcs->encoder_control( 110 enc1->base.bp, &cntl) != BP_RESULT_OK) 111 return; 112 113 } else { 114 115 //Set pattern for clock channel, default vlue 0x63 does not work 116 REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); 117 118 //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup 119 120 //DIG_SOURCE_SELECT is already set in dig_connect_to_otg 121 122 /* DIG_START is removed from the register spec */ 123 enc314_enable_fifo(enc); 124 } 125 126 /* Configure pixel encoding */ 127 enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); 128 129 /* setup HDMI engine */ 130 REG_UPDATE_6(HDMI_CONTROL, 131 HDMI_PACKET_GEN_VERSION, 1, 132 HDMI_KEEPOUT_MODE, 1, 133 HDMI_DEEP_COLOR_ENABLE, 0, 134 HDMI_DATA_SCRAMBLE_EN, 0, 135 HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, 136 HDMI_CLOCK_CHANNEL_RATE, 0); 137 138 /* Configure color depth */ 139 switch (crtc_timing->display_color_depth) { 140 case COLOR_DEPTH_888: 141 REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); 142 break; 143 case COLOR_DEPTH_101010: 144 if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 145 REG_UPDATE_2(HDMI_CONTROL, 146 HDMI_DEEP_COLOR_DEPTH, 1, 147 HDMI_DEEP_COLOR_ENABLE, 0); 148 } else { 149 REG_UPDATE_2(HDMI_CONTROL, 150 HDMI_DEEP_COLOR_DEPTH, 1, 151 HDMI_DEEP_COLOR_ENABLE, 1); 152 } 153 break; 154 case COLOR_DEPTH_121212: 155 if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 156 REG_UPDATE_2(HDMI_CONTROL, 157 HDMI_DEEP_COLOR_DEPTH, 2, 158 HDMI_DEEP_COLOR_ENABLE, 0); 159 } else { 160 REG_UPDATE_2(HDMI_CONTROL, 161 HDMI_DEEP_COLOR_DEPTH, 2, 162 HDMI_DEEP_COLOR_ENABLE, 1); 163 } 164 break; 165 case COLOR_DEPTH_161616: 166 REG_UPDATE_2(HDMI_CONTROL, 167 HDMI_DEEP_COLOR_DEPTH, 3, 168 HDMI_DEEP_COLOR_ENABLE, 1); 169 break; 170 default: 171 break; 172 } 173 174 if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { 175 /* enable HDMI data scrambler 176 * HDMI_CLOCK_CHANNEL_RATE_MORE_340M 177 * Clock channel frequency is 1/4 of character rate. 178 */ 179 REG_UPDATE_2(HDMI_CONTROL, 180 HDMI_DATA_SCRAMBLE_EN, 1, 181 HDMI_CLOCK_CHANNEL_RATE, 1); 182 } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { 183 184 /* TODO: New feature for DCE11, still need to implement */ 185 186 /* enable HDMI data scrambler 187 * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE 188 * Clock channel frequency is the same 189 * as character rate 190 */ 191 REG_UPDATE_2(HDMI_CONTROL, 192 HDMI_DATA_SCRAMBLE_EN, 1, 193 HDMI_CLOCK_CHANNEL_RATE, 0); 194 } 195 196 197 /* Enable transmission of General Control packet on every frame */ 198 REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, 199 HDMI_GC_CONT, 1, 200 HDMI_GC_SEND, 1, 201 HDMI_NULL_SEND, 1); 202 203 /* Disable Audio Content Protection packet transmission */ 204 REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); 205 206 /* following belongs to audio */ 207 /* Enable Audio InfoFrame packet transmission. */ 208 REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); 209 210 /* update double-buffered AUDIO_INFO registers immediately */ 211 ASSERT(enc->afmt); 212 enc->afmt->funcs->audio_info_immediate_update(enc->afmt); 213 214 /* Select line number on which to send Audio InfoFrame packets */ 215 REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, 216 VBI_LINE_0 + 2); 217 218 /* set HDMI GC AVMUTE */ 219 REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); 220 switch (crtc_timing->pixel_encoding) { 221 case PIXEL_ENCODING_YCBCR422: 222 REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 1); 223 break; 224 default: 225 REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 0); 226 break; 227 } 228 REG_UPDATE(HDMI_CONTROL, TMDS_COLOR_FORMAT, 0); 229} 230 231 232 233static void enc35_stream_encoder_enable( 234 struct stream_encoder *enc, 235 enum signal_type signal, 236 bool enable) 237{ 238 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 239 240 if (enable) { 241 switch (signal) { 242 case SIGNAL_TYPE_DVI_SINGLE_LINK: 243 case SIGNAL_TYPE_DVI_DUAL_LINK: 244 /* TMDS-DVI */ 245 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 2); 246 break; 247 case SIGNAL_TYPE_HDMI_TYPE_A: 248 /* TMDS-HDMI */ 249 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 3); 250 break; 251 case SIGNAL_TYPE_DISPLAY_PORT_MST: 252 /* DP MST */ 253 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 5); 254 break; 255 case SIGNAL_TYPE_EDP: 256 case SIGNAL_TYPE_DISPLAY_PORT: 257 /* DP SST */ 258 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 0); 259 break; 260 default: 261 /* invalid mode ! */ 262 ASSERT_CRITICAL(false); 263 } 264 } 265} 266 267static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 268{ 269 bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 270 271 two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 272 && !timing->dsc_cfg.ycbcr422_simple); 273 return two_pix; 274} 275 276static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing) 277{ 278 /* math borrowed from function of same name in inc/resource 279 * checks if h_timing is divisible by 2 280 */ 281 282 bool divisible = false; 283 uint16_t h_blank_start = 0; 284 uint16_t h_blank_end = 0; 285 286 if (timing) { 287 h_blank_start = timing->h_total - timing->h_front_porch; 288 h_blank_end = h_blank_start - timing->h_addressable; 289 290 /* HTOTAL, Hblank start/end, and Hsync start/end all must be 291 * divisible by 2 in order for the horizontal timing params 292 * to be considered divisible by 2. Hsync start is always 0. 293 */ 294 divisible = (timing->h_total % 2 == 0) && 295 (h_blank_start % 2 == 0) && 296 (h_blank_end % 2 == 0) && 297 (timing->h_sync_width % 2 == 0); 298 } 299 return divisible; 300} 301 302static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing) 303{ 304 /* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/ 305 return is_h_timing_divisible_by_2(timing) && 306 dc->debug.enable_dp_dig_pixel_rate_div_policy; 307} 308 309static void enc35_stream_encoder_dp_unblank( 310 struct dc_link *link, 311 struct stream_encoder *enc, 312 const struct encoder_unblank_param *param) 313{ 314 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 315 struct dc *dc = enc->ctx->dc; 316 317 if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { 318 uint32_t n_vid = 0x8000; 319 uint32_t m_vid; 320 uint32_t n_multiply = 0; 321 uint32_t pix_per_cycle = 0; 322 uint64_t m_vid_l = n_vid; 323 324 /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ 325 if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1 326 || is_dp_dig_pixel_rate_div_policy(dc, ¶m->timing)) { 327 /*this logic should be the same in get_pixel_clock_parameters() */ 328 n_multiply = 1; 329 pix_per_cycle = 1; 330 } 331 /* M / N = Fstream / Flink 332 * m_vid / n_vid = pixel rate / link rate 333 */ 334 335 m_vid_l *= param->timing.pix_clk_100hz / 10; 336 m_vid_l = div_u64(m_vid_l, 337 param->link_settings.link_rate 338 * LINK_RATE_REF_FREQ_IN_KHZ); 339 340 m_vid = (uint32_t) m_vid_l; 341 342 /* enable auto measurement */ 343 344 REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); 345 346 /* auto measurement need 1 full 0x8000 symbol cycle to kick in, 347 * therefore program initial value for Mvid and Nvid 348 */ 349 350 REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); 351 352 REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); 353 354 REG_UPDATE_2(DP_VID_TIMING, 355 DP_VID_M_N_GEN_EN, 1, 356 DP_VID_N_MUL, n_multiply); 357 358 REG_UPDATE(DP_PIXEL_FORMAT, 359 DP_PIXEL_PER_CYCLE_PROCESSING_MODE, 360 pix_per_cycle); 361 } 362 363 /* make sure stream is disabled before resetting steer fifo */ 364 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); 365 REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); 366 367 /* DIG_START is removed from the register spec */ 368 369 /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen 370 * that it overflows during mode transition, and sometimes doesn't recover. 371 */ 372 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); 373 udelay(10); 374 375 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); 376 377 /* wait 100us for DIG/DP logic to prime 378 * (i.e. a few video lines) 379 */ 380 udelay(100); 381 382 /* the hardware would start sending video at the start of the next DP 383 * frame (i.e. rising edge of the vblank). 384 * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this 385 * register has no effect on enable transition! HW always makes sure 386 * VID_STREAM enable at start of next frame, and this is not 387 * programmable 388 */ 389 390 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); 391 392 /* 393 * DIG Resync FIFO now needs to be explicitly enabled. 394 * This should come after DP_VID_STREAM_ENABLE per HW docs. 395 */ 396 enc314_enable_fifo(enc); 397 398 link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); 399} 400 401static void enc35_stream_encoder_map_to_link( 402 struct stream_encoder *enc, 403 uint32_t stream_enc_inst, 404 uint32_t link_enc_inst) 405{ 406 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 407 408 ASSERT(stream_enc_inst < 5 && link_enc_inst < 5); 409 REG_UPDATE(STREAM_MAPPER_CONTROL, 410 DIG_STREAM_LINK_TARGET, link_enc_inst); 411} 412 413static void enc35_reset_fifo(struct stream_encoder *enc, bool reset) 414{ 415 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 416 uint32_t reset_val = reset ? 1 : 0; 417 uint32_t is_symclk_on; 418 419 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val); 420 REG_GET(DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_CLOCK_ON, &is_symclk_on); 421 422 if (is_symclk_on) 423 REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000); 424 else 425 udelay(10); 426} 427 428static void enc35_disable_fifo(struct stream_encoder *enc) 429{ 430 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 431 432 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0); 433 REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 0); 434 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0); 435} 436 437static void enc35_enable_fifo(struct stream_encoder *enc) 438{ 439 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 440 441 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); 442 REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 1); 443 REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 1); 444 445 enc35_reset_fifo(enc, true); 446 enc35_reset_fifo(enc, false); 447 448 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1); 449} 450 451static const struct stream_encoder_funcs dcn35_str_enc_funcs = { 452 .dp_set_odm_combine = 453 enc314_dp_set_odm_combine, 454 .dp_set_stream_attribute = 455 enc2_stream_encoder_dp_set_stream_attribute, 456 .hdmi_set_stream_attribute = 457 enc35_stream_encoder_hdmi_set_stream_attribute, 458 .dvi_set_stream_attribute = 459 enc35_stream_encoder_dvi_set_stream_attribute, 460 .set_throttled_vcp_size = 461 enc1_stream_encoder_set_throttled_vcp_size, 462 .update_hdmi_info_packets = 463 enc3_stream_encoder_update_hdmi_info_packets, 464 .stop_hdmi_info_packets = 465 enc3_stream_encoder_stop_hdmi_info_packets, 466 .update_dp_info_packets_sdp_line_num = 467 enc3_stream_encoder_update_dp_info_packets_sdp_line_num, 468 .update_dp_info_packets = 469 enc3_stream_encoder_update_dp_info_packets, 470 .stop_dp_info_packets = 471 enc1_stream_encoder_stop_dp_info_packets, 472 .dp_blank = 473 enc314_stream_encoder_dp_blank, 474 .dp_unblank = 475 enc35_stream_encoder_dp_unblank, 476 .audio_mute_control = enc3_audio_mute_control, 477 478 .dp_audio_setup = enc3_se_dp_audio_setup, 479 .dp_audio_enable = enc3_se_dp_audio_enable, 480 .dp_audio_disable = enc1_se_dp_audio_disable, 481 482 .hdmi_audio_setup = enc3_se_hdmi_audio_setup, 483 .hdmi_audio_disable = enc1_se_hdmi_audio_disable, 484 .setup_stereo_sync = enc1_setup_stereo_sync, 485 .set_avmute = enc1_stream_encoder_set_avmute, 486 .dig_connect_to_otg = enc1_dig_connect_to_otg, 487 .dig_source_otg = enc1_dig_source_otg, 488 489 .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, 490 491 .enc_read_state = enc314_read_state, 492 .dp_set_dsc_config = enc314_dp_set_dsc_config, 493 .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, 494 .set_dynamic_metadata = enc2_set_dynamic_metadata, 495 .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, 496 .dig_stream_enable = enc35_stream_encoder_enable, 497 498 .set_input_mode = enc314_set_dig_input_mode, 499 .enable_fifo = enc35_enable_fifo, 500 .disable_fifo = enc35_disable_fifo, 501 .map_stream_to_link = enc35_stream_encoder_map_to_link, 502}; 503 504void dcn35_dio_stream_encoder_construct( 505 struct dcn10_stream_encoder *enc1, 506 struct dc_context *ctx, 507 struct dc_bios *bp, 508 enum engine_id eng_id, 509 struct vpg *vpg, 510 struct afmt *afmt, 511 const struct dcn10_stream_enc_registers *regs, 512 const struct dcn10_stream_encoder_shift *se_shift, 513 const struct dcn10_stream_encoder_mask *se_mask) 514{ 515 enc1->base.funcs = &dcn35_str_enc_funcs; 516 enc1->base.ctx = ctx; 517 enc1->base.id = eng_id; 518 enc1->base.bp = bp; 519 enc1->base.vpg = vpg; 520 enc1->base.afmt = afmt; 521 enc1->regs = regs; 522 enc1->se_shift = se_shift; 523 enc1->se_mask = se_mask; 524 enc1->base.stream_enc_inst = vpg->inst; 525} 526 527