FILE
dcn314_dio_stream_encoder.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright 2022 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 * Authors: AMD 24 * 25 */ 26 27 28#include "dc_bios_types.h" 29#include "dcn30/dcn30_dio_stream_encoder.h" 30#include "dcn314_dio_stream_encoder.h" 31#include "reg_helper.h" 32#include "hw_shared.h" 33#include "link_service.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 52void enc314_reset_fifo(struct stream_encoder *enc, bool reset) 53{ 54 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 55 uint32_t reset_val = reset ? 1 : 0; 56 uint32_t is_symclk_on; 57 58 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val); 59 REG_GET(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, &is_symclk_on); 60 61 if (is_symclk_on) 62 REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000); 63 else 64 udelay(10); 65} 66 67void enc314_enable_fifo(struct stream_encoder *enc) 68{ 69 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 70 71 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); 72 73 enc314_reset_fifo(enc, true); 74 enc314_reset_fifo(enc, false); 75 76 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1); 77} 78 79void enc314_disable_fifo(struct stream_encoder *enc) 80{ 81 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 82 83 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0); 84} 85 86static bool enc314_is_fifo_enabled(struct stream_encoder *enc) 87{ 88 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 89 uint32_t reset_val; 90 91 REG_GET(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, &reset_val); 92 return (reset_val != 0); 93} 94 95void enc314_dp_set_odm_combine( 96 struct stream_encoder *enc, 97 bool odm_combine) 98{ 99 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 100 101 REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, odm_combine); 102} 103 104/* setup stream encoder in dvi mode */ 105void enc314_stream_encoder_dvi_set_stream_attribute( 106 struct stream_encoder *enc, 107 struct dc_crtc_timing *crtc_timing, 108 bool is_dual_link) 109{ 110 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 111 112 if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { 113 struct bp_encoder_control cntl = {0}; 114 115 cntl.action = ENCODER_CONTROL_SETUP; 116 cntl.engine_id = enc1->base.id; 117 cntl.signal = is_dual_link ? 118 SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; 119 cntl.enable_dp_audio = false; 120 cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; 121 cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; 122 123 if (enc1->base.bp->funcs->encoder_control( 124 enc1->base.bp, &cntl) != BP_RESULT_OK) 125 return; 126 127 } else { 128 129 //Set pattern for clock channel, default vlue 0x63 does not work 130 REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); 131 132 //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup 133 134 //DIG_SOURCE_SELECT is already set in dig_connect_to_otg 135 136 enc314_enable_fifo(enc); 137 } 138 139 ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); 140 ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); 141 enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); 142} 143 144/* setup stream encoder in hdmi mode */ 145void enc314_stream_encoder_hdmi_set_stream_attribute( 146 struct stream_encoder *enc, 147 struct dc_crtc_timing *crtc_timing, 148 int actual_pix_clk_khz, 149 bool enable_audio) 150{ 151 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 152 153 if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { 154 struct bp_encoder_control cntl = {0}; 155 156 cntl.action = ENCODER_CONTROL_SETUP; 157 cntl.engine_id = enc1->base.id; 158 cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; 159 cntl.enable_dp_audio = enable_audio; 160 cntl.pixel_clock = actual_pix_clk_khz; 161 cntl.lanes_number = LANE_COUNT_FOUR; 162 163 if (enc1->base.bp->funcs->encoder_control( 164 enc1->base.bp, &cntl) != BP_RESULT_OK) 165 return; 166 167 } else { 168 169 //Set pattern for clock channel, default vlue 0x63 does not work 170 REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); 171 172 //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup 173 174 //DIG_SOURCE_SELECT is already set in dig_connect_to_otg 175 176 enc314_enable_fifo(enc); 177 } 178 179 /* Configure pixel encoding */ 180 enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); 181 182 /* setup HDMI engine */ 183 REG_UPDATE_6(HDMI_CONTROL, 184 HDMI_PACKET_GEN_VERSION, 1, 185 HDMI_KEEPOUT_MODE, 1, 186 HDMI_DEEP_COLOR_ENABLE, 0, 187 HDMI_DATA_SCRAMBLE_EN, 0, 188 HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, 189 HDMI_CLOCK_CHANNEL_RATE, 0); 190 191 /* Configure color depth */ 192 switch (crtc_timing->display_color_depth) { 193 case COLOR_DEPTH_888: 194 REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); 195 break; 196 case COLOR_DEPTH_101010: 197 if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 198 REG_UPDATE_2(HDMI_CONTROL, 199 HDMI_DEEP_COLOR_DEPTH, 1, 200 HDMI_DEEP_COLOR_ENABLE, 0); 201 } else { 202 REG_UPDATE_2(HDMI_CONTROL, 203 HDMI_DEEP_COLOR_DEPTH, 1, 204 HDMI_DEEP_COLOR_ENABLE, 1); 205 } 206 break; 207 case COLOR_DEPTH_121212: 208 if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 209 REG_UPDATE_2(HDMI_CONTROL, 210 HDMI_DEEP_COLOR_DEPTH, 2, 211 HDMI_DEEP_COLOR_ENABLE, 0); 212 } else { 213 REG_UPDATE_2(HDMI_CONTROL, 214 HDMI_DEEP_COLOR_DEPTH, 2, 215 HDMI_DEEP_COLOR_ENABLE, 1); 216 } 217 break; 218 case COLOR_DEPTH_161616: 219 REG_UPDATE_2(HDMI_CONTROL, 220 HDMI_DEEP_COLOR_DEPTH, 3, 221 HDMI_DEEP_COLOR_ENABLE, 1); 222 break; 223 default: 224 break; 225 } 226 227 if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { 228 /* enable HDMI data scrambler 229 * HDMI_CLOCK_CHANNEL_RATE_MORE_340M 230 * Clock channel frequency is 1/4 of character rate. 231 */ 232 REG_UPDATE_2(HDMI_CONTROL, 233 HDMI_DATA_SCRAMBLE_EN, 1, 234 HDMI_CLOCK_CHANNEL_RATE, 1); 235 } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { 236 237 /* TODO: New feature for DCE11, still need to implement */ 238 239 /* enable HDMI data scrambler 240 * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE 241 * Clock channel frequency is the same 242 * as character rate 243 */ 244 REG_UPDATE_2(HDMI_CONTROL, 245 HDMI_DATA_SCRAMBLE_EN, 1, 246 HDMI_CLOCK_CHANNEL_RATE, 0); 247 } 248 249 250 /* Enable transmission of General Control packet on every frame */ 251 REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, 252 HDMI_GC_CONT, 1, 253 HDMI_GC_SEND, 1, 254 HDMI_NULL_SEND, 1); 255 256 /* Disable Audio Content Protection packet transmission */ 257 REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); 258 259 /* following belongs to audio */ 260 /* Enable Audio InfoFrame packet transmission. */ 261 REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); 262 263 /* update double-buffered AUDIO_INFO registers immediately */ 264 ASSERT(enc->afmt); 265 enc->afmt->funcs->audio_info_immediate_update(enc->afmt); 266 267 /* Select line number on which to send Audio InfoFrame packets */ 268 REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, 269 VBI_LINE_0 + 2); 270 271 /* set HDMI GC AVMUTE */ 272 REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); 273} 274 275 276 277static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 278{ 279 bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 280 281 two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 282 && !timing->dsc_cfg.ycbcr422_simple); 283 return two_pix; 284} 285 286void enc314_stream_encoder_dp_blank( 287 struct dc_link *link, 288 struct stream_encoder *enc) 289{ 290 enc1_stream_encoder_dp_blank(link, enc); 291 292 /* Disable FIFO after the DP vid stream is disabled to avoid corruption. */ 293 if (enc->ctx->dc->debug.dig_fifo_off_in_blank) 294 enc314_disable_fifo(enc); 295} 296 297void enc314_stream_encoder_dp_unblank( 298 struct dc_link *link, 299 struct stream_encoder *enc, 300 const struct encoder_unblank_param *param) 301{ 302 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 303 304 if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { 305 uint32_t n_vid = 0x8000; 306 uint32_t m_vid; 307 uint32_t n_multiply = 0; 308 uint32_t pix_per_cycle = 0; 309 uint64_t m_vid_l = n_vid; 310 311 /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ 312 if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { 313 /*this logic should be the same in get_pixel_clock_parameters() */ 314 n_multiply = 1; 315 pix_per_cycle = 1; 316 } 317 /* M / N = Fstream / Flink 318 * m_vid / n_vid = pixel rate / link rate 319 */ 320 321 m_vid_l *= param->timing.pix_clk_100hz / 10; 322 m_vid_l = div_u64(m_vid_l, 323 param->link_settings.link_rate 324 * LINK_RATE_REF_FREQ_IN_KHZ); 325 326 m_vid = (uint32_t) m_vid_l; 327 328 /* enable auto measurement */ 329 330 REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); 331 332 /* auto measurement need 1 full 0x8000 symbol cycle to kick in, 333 * therefore program initial value for Mvid and Nvid 334 */ 335 336 REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); 337 338 REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); 339 340 REG_UPDATE_2(DP_VID_TIMING, 341 DP_VID_M_N_GEN_EN, 1, 342 DP_VID_N_MUL, n_multiply); 343 344 REG_UPDATE(DP_PIXEL_FORMAT, 345 DP_PIXEL_PER_CYCLE_PROCESSING_MODE, 346 pix_per_cycle); 347 } 348 349 /* make sure stream is disabled before resetting steer fifo */ 350 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); 351 REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); 352 353 /* DIG_START is removed from the register spec */ 354 355 /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen 356 * that it overflows during mode transition, and sometimes doesn't recover. 357 */ 358 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); 359 udelay(10); 360 361 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); 362 363 /* wait 100us for DIG/DP logic to prime 364 * (i.e. a few video lines) 365 */ 366 udelay(100); 367 368 /* the hardware would start sending video at the start of the next DP 369 * frame (i.e. rising edge of the vblank). 370 * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this 371 * register has no effect on enable transition! HW always guarantees 372 * VID_STREAM enable at start of next frame, and this is not 373 * programmable 374 */ 375 376 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); 377 378 /* 379 * DIG Resync FIFO now needs to be explicitly enabled. 380 * This should come after DP_VID_STREAM_ENABLE per HW docs. 381 */ 382 enc314_enable_fifo(enc); 383 384 link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); 385} 386 387/* Set DSC-related configuration. 388 * dsc_mode: 0 disables DSC, other values enable DSC in specified format 389 * sc_bytes_per_pixel: DP_DSC_BYTES_PER_PIXEL removed in DCN32 390 * dsc_slice_width: DP_DSC_SLICE_WIDTH removed in DCN32 391 */ 392void enc314_dp_set_dsc_config(struct stream_encoder *enc, 393 enum optc_dsc_mode dsc_mode, 394 uint32_t dsc_bytes_per_pixel, 395 uint32_t dsc_slice_width) 396{ 397 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 398 399 REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1); 400} 401 402/* this function read dsc related register fields to be logged later in dcn10_log_hw_state 403 * into a dcn_dsc_state struct. 404 */ 405void enc314_read_state(struct stream_encoder *enc, struct enc_state *s) 406{ 407 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 408 409 //if dsc is enabled, continue to read 410 REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); 411 if (s->dsc_mode) { 412 REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); 413 414 REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); 415 REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); 416 417 REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); 418 REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); 419 } 420} 421 422void enc314_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container) 423{ 424 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 425 426 // The naming of this field is confusing, what it means is the output mode of otg, which 427 // is the input mode of the dig 428 REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, pix_per_container == 2 ? 0x1 : 0x0); 429} 430 431 432static const struct stream_encoder_funcs dcn314_str_enc_funcs = { 433 .dp_set_odm_combine = 434 enc314_dp_set_odm_combine, 435 .dp_set_stream_attribute = 436 enc2_stream_encoder_dp_set_stream_attribute, 437 .hdmi_set_stream_attribute = 438 enc314_stream_encoder_hdmi_set_stream_attribute, 439 .dvi_set_stream_attribute = 440 enc314_stream_encoder_dvi_set_stream_attribute, 441 .set_throttled_vcp_size = 442 enc1_stream_encoder_set_throttled_vcp_size, 443 .update_hdmi_info_packets = 444 enc3_stream_encoder_update_hdmi_info_packets, 445 .stop_hdmi_info_packets = 446 enc3_stream_encoder_stop_hdmi_info_packets, 447 .update_dp_info_packets_sdp_line_num = 448 enc3_stream_encoder_update_dp_info_packets_sdp_line_num, 449 .update_dp_info_packets = 450 enc3_stream_encoder_update_dp_info_packets, 451 .stop_dp_info_packets = 452 enc1_stream_encoder_stop_dp_info_packets, 453 .dp_blank = 454 enc314_stream_encoder_dp_blank, 455 .dp_unblank = 456 enc314_stream_encoder_dp_unblank, 457 .audio_mute_control = enc3_audio_mute_control, 458 459 .dp_audio_setup = enc3_se_dp_audio_setup, 460 .dp_audio_enable = enc3_se_dp_audio_enable, 461 .dp_audio_disable = enc1_se_dp_audio_disable, 462 463 .hdmi_audio_setup = enc3_se_hdmi_audio_setup, 464 .hdmi_audio_disable = enc1_se_hdmi_audio_disable, 465 .setup_stereo_sync = enc1_setup_stereo_sync, 466 .set_avmute = enc1_stream_encoder_set_avmute, 467 .dig_connect_to_otg = enc1_dig_connect_to_otg, 468 .dig_source_otg = enc1_dig_source_otg, 469 470 .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, 471 472 .enc_read_state = enc314_read_state, 473 .dp_set_dsc_config = enc314_dp_set_dsc_config, 474 .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, 475 .set_dynamic_metadata = enc2_set_dynamic_metadata, 476 .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, 477 478 .enable_fifo = enc314_enable_fifo, 479 .disable_fifo = enc314_disable_fifo, 480 .is_fifo_enabled = enc314_is_fifo_enabled, 481 .set_input_mode = enc314_set_dig_input_mode, 482}; 483 484void dcn314_dio_stream_encoder_construct( 485 struct dcn10_stream_encoder *enc1, 486 struct dc_context *ctx, 487 struct dc_bios *bp, 488 enum engine_id eng_id, 489 struct vpg *vpg, 490 struct afmt *afmt, 491 const struct dcn10_stream_enc_registers *regs, 492 const struct dcn10_stream_encoder_shift *se_shift, 493 const struct dcn10_stream_encoder_mask *se_mask) 494{ 495 enc1->base.funcs = &dcn314_str_enc_funcs; 496 enc1->base.ctx = ctx; 497 enc1->base.id = eng_id; 498 enc1->base.bp = bp; 499 enc1->base.vpg = vpg; 500 enc1->base.afmt = afmt; 501 enc1->regs = regs; 502 enc1->se_shift = se_shift; 503 enc1->se_mask = se_mask; 504 enc1->base.stream_enc_inst = vpg->inst; 505} 506
~/
Read-only file preview.