Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright 2022 Advanced Micro Devices, Inc.
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining a
0006  * copy of this software and associated documentation files (the "Software"),
0007  * to deal in the Software without restriction, including without limitation
0008  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0009  *  and/or sell copies of the Software, and to permit persons to whom the
0010  * Software is furnished to do so, subject to the following conditions:
0011  *
0012  * The above copyright notice and this permission notice shall be included in
0013  * all copies or substantial portions of the Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0019  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0020  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0021  * OTHER DEALINGS IN THE SOFTWARE.
0022  *
0023  * Authors: AMD
0024  *
0025  */
0026 
0027 
0028 #include "dc_bios_types.h"
0029 #include "dcn30/dcn30_dio_stream_encoder.h"
0030 #include "dcn314_dio_stream_encoder.h"
0031 #include "reg_helper.h"
0032 #include "hw_shared.h"
0033 #include "inc/link_dpcd.h"
0034 #include "dpcd_defs.h"
0035 
0036 #define DC_LOGGER \
0037         enc1->base.ctx->logger
0038 
0039 #define REG(reg)\
0040     (enc1->regs->reg)
0041 
0042 #undef FN
0043 #define FN(reg_name, field_name) \
0044     enc1->se_shift->field_name, enc1->se_mask->field_name
0045 
0046 #define VBI_LINE_0 0
0047 #define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
0048 
0049 #define CTX \
0050     enc1->base.ctx
0051 
0052 
0053 static void enc314_enable_fifo(struct stream_encoder *enc)
0054 {
0055     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0056 
0057     /* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */
0058     REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000);
0059     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
0060     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
0061     REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000);
0062     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
0063     REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000);
0064     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1);
0065 }
0066 
0067 static void enc314_disable_fifo(struct stream_encoder *enc)
0068 {
0069     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0070 
0071     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0);
0072 }
0073 
0074 static void enc314_dp_set_odm_combine(
0075     struct stream_encoder *enc,
0076     bool odm_combine)
0077 {
0078     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0079 
0080     REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, odm_combine);
0081 }
0082 
0083 /* setup stream encoder in dvi mode */
0084 void enc314_stream_encoder_dvi_set_stream_attribute(
0085     struct stream_encoder *enc,
0086     struct dc_crtc_timing *crtc_timing,
0087     bool is_dual_link)
0088 {
0089     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0090 
0091     if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
0092         struct bp_encoder_control cntl = {0};
0093 
0094         cntl.action = ENCODER_CONTROL_SETUP;
0095         cntl.engine_id = enc1->base.id;
0096         cntl.signal = is_dual_link ?
0097             SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK;
0098         cntl.enable_dp_audio = false;
0099         cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
0100         cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
0101 
0102         if (enc1->base.bp->funcs->encoder_control(
0103                 enc1->base.bp, &cntl) != BP_RESULT_OK)
0104             return;
0105 
0106     } else {
0107 
0108         //Set pattern for clock channel, default vlue 0x63 does not work
0109         REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
0110 
0111         //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup
0112 
0113         //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
0114 
0115         enc314_enable_fifo(enc);
0116     }
0117 
0118     ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB);
0119     ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888);
0120     enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
0121 }
0122 
0123 /* setup stream encoder in hdmi mode */
0124 static void enc314_stream_encoder_hdmi_set_stream_attribute(
0125     struct stream_encoder *enc,
0126     struct dc_crtc_timing *crtc_timing,
0127     int actual_pix_clk_khz,
0128     bool enable_audio)
0129 {
0130     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0131 
0132     if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
0133         struct bp_encoder_control cntl = {0};
0134 
0135         cntl.action = ENCODER_CONTROL_SETUP;
0136         cntl.engine_id = enc1->base.id;
0137         cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
0138         cntl.enable_dp_audio = enable_audio;
0139         cntl.pixel_clock = actual_pix_clk_khz;
0140         cntl.lanes_number = LANE_COUNT_FOUR;
0141 
0142         if (enc1->base.bp->funcs->encoder_control(
0143                 enc1->base.bp, &cntl) != BP_RESULT_OK)
0144             return;
0145 
0146     } else {
0147 
0148         //Set pattern for clock channel, default vlue 0x63 does not work
0149         REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
0150 
0151         //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup
0152 
0153         //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
0154 
0155         enc314_enable_fifo(enc);
0156     }
0157 
0158     /* Configure pixel encoding */
0159     enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
0160 
0161     /* setup HDMI engine */
0162     REG_UPDATE_6(HDMI_CONTROL,
0163         HDMI_PACKET_GEN_VERSION, 1,
0164         HDMI_KEEPOUT_MODE, 1,
0165         HDMI_DEEP_COLOR_ENABLE, 0,
0166         HDMI_DATA_SCRAMBLE_EN, 0,
0167         HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1,
0168         HDMI_CLOCK_CHANNEL_RATE, 0);
0169 
0170     /* Configure color depth */
0171     switch (crtc_timing->display_color_depth) {
0172     case COLOR_DEPTH_888:
0173         REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
0174         break;
0175     case COLOR_DEPTH_101010:
0176         if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0177             REG_UPDATE_2(HDMI_CONTROL,
0178                     HDMI_DEEP_COLOR_DEPTH, 1,
0179                     HDMI_DEEP_COLOR_ENABLE, 0);
0180         } else {
0181             REG_UPDATE_2(HDMI_CONTROL,
0182                     HDMI_DEEP_COLOR_DEPTH, 1,
0183                     HDMI_DEEP_COLOR_ENABLE, 1);
0184             }
0185         break;
0186     case COLOR_DEPTH_121212:
0187         if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
0188             REG_UPDATE_2(HDMI_CONTROL,
0189                     HDMI_DEEP_COLOR_DEPTH, 2,
0190                     HDMI_DEEP_COLOR_ENABLE, 0);
0191         } else {
0192             REG_UPDATE_2(HDMI_CONTROL,
0193                     HDMI_DEEP_COLOR_DEPTH, 2,
0194                     HDMI_DEEP_COLOR_ENABLE, 1);
0195             }
0196         break;
0197     case COLOR_DEPTH_161616:
0198         REG_UPDATE_2(HDMI_CONTROL,
0199                 HDMI_DEEP_COLOR_DEPTH, 3,
0200                 HDMI_DEEP_COLOR_ENABLE, 1);
0201         break;
0202     default:
0203         break;
0204     }
0205 
0206     if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
0207         /* enable HDMI data scrambler
0208          * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
0209          * Clock channel frequency is 1/4 of character rate.
0210          */
0211         REG_UPDATE_2(HDMI_CONTROL,
0212             HDMI_DATA_SCRAMBLE_EN, 1,
0213             HDMI_CLOCK_CHANNEL_RATE, 1);
0214     } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
0215 
0216         /* TODO: New feature for DCE11, still need to implement */
0217 
0218         /* enable HDMI data scrambler
0219          * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
0220          * Clock channel frequency is the same
0221          * as character rate
0222          */
0223         REG_UPDATE_2(HDMI_CONTROL,
0224             HDMI_DATA_SCRAMBLE_EN, 1,
0225             HDMI_CLOCK_CHANNEL_RATE, 0);
0226     }
0227 
0228 
0229     /* Enable transmission of General Control packet on every frame */
0230     REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
0231         HDMI_GC_CONT, 1,
0232         HDMI_GC_SEND, 1,
0233         HDMI_NULL_SEND, 1);
0234 
0235     /* Disable Audio Content Protection packet transmission */
0236     REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
0237 
0238     /* following belongs to audio */
0239     /* Enable Audio InfoFrame packet transmission. */
0240     REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
0241 
0242     /* update double-buffered AUDIO_INFO registers immediately */
0243     ASSERT(enc->afmt);
0244     enc->afmt->funcs->audio_info_immediate_update(enc->afmt);
0245 
0246     /* Select line number on which to send Audio InfoFrame packets */
0247     REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE,
0248                 VBI_LINE_0 + 2);
0249 
0250     /* set HDMI GC AVMUTE */
0251     REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
0252 }
0253 
0254 
0255 
0256 static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
0257 {
0258     bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
0259 
0260     two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
0261             && !timing->dsc_cfg.ycbcr422_simple);
0262     return two_pix;
0263 }
0264 
0265 void enc314_stream_encoder_dp_blank(
0266     struct dc_link *link,
0267     struct stream_encoder *enc)
0268 {
0269     /* New to DCN314 - disable the FIFO before VID stream disable. */
0270     enc314_disable_fifo(enc);
0271 
0272     enc1_stream_encoder_dp_blank(link, enc);
0273 }
0274 
0275 static void enc314_stream_encoder_dp_unblank(
0276         struct dc_link *link,
0277         struct stream_encoder *enc,
0278         const struct encoder_unblank_param *param)
0279 {
0280     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0281 
0282     if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
0283         uint32_t n_vid = 0x8000;
0284         uint32_t m_vid;
0285         uint32_t n_multiply = 0;
0286         uint64_t m_vid_l = n_vid;
0287 
0288         /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
0289         if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1) {
0290             /*this logic should be the same in get_pixel_clock_parameters() */
0291             n_multiply = 1;
0292         }
0293         /* M / N = Fstream / Flink
0294          * m_vid / n_vid = pixel rate / link rate
0295          */
0296 
0297         m_vid_l *= param->timing.pix_clk_100hz / 10;
0298         m_vid_l = div_u64(m_vid_l,
0299             param->link_settings.link_rate
0300                 * LINK_RATE_REF_FREQ_IN_KHZ);
0301 
0302         m_vid = (uint32_t) m_vid_l;
0303 
0304         /* enable auto measurement */
0305 
0306         REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0);
0307 
0308         /* auto measurement need 1 full 0x8000 symbol cycle to kick in,
0309          * therefore program initial value for Mvid and Nvid
0310          */
0311 
0312         REG_UPDATE(DP_VID_N, DP_VID_N, n_vid);
0313 
0314         REG_UPDATE(DP_VID_M, DP_VID_M, m_vid);
0315 
0316         REG_UPDATE_2(DP_VID_TIMING,
0317                 DP_VID_M_N_GEN_EN, 1,
0318                 DP_VID_N_MUL, n_multiply);
0319     }
0320 
0321     /* make sure stream is disabled before resetting steer fifo */
0322     REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
0323     REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
0324 
0325     /* DIG_START is removed from the register spec */
0326 
0327     /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
0328      * that it overflows during mode transition, and sometimes doesn't recover.
0329      */
0330     REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
0331     udelay(10);
0332 
0333     REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
0334 
0335     /* wait 100us for DIG/DP logic to prime
0336      * (i.e. a few video lines)
0337      */
0338     udelay(100);
0339 
0340     /* the hardware would start sending video at the start of the next DP
0341      * frame (i.e. rising edge of the vblank).
0342      * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
0343      * register has no effect on enable transition! HW always guarantees
0344      * VID_STREAM enable at start of next frame, and this is not
0345      * programmable
0346      */
0347 
0348     REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
0349 
0350     /*
0351      * DIG Resync FIFO now needs to be explicitly enabled.
0352      * This should come after DP_VID_STREAM_ENABLE per HW docs.
0353      */
0354     enc314_enable_fifo(enc);
0355 
0356     dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
0357 }
0358 
0359 /* Set DSC-related configuration.
0360  *   dsc_mode: 0 disables DSC, other values enable DSC in specified format
0361  *   sc_bytes_per_pixel: DP_DSC_BYTES_PER_PIXEL removed in DCN32
0362  *   dsc_slice_width: DP_DSC_SLICE_WIDTH removed in DCN32
0363  */
0364 static void enc314_dp_set_dsc_config(struct stream_encoder *enc,
0365                     enum optc_dsc_mode dsc_mode,
0366                     uint32_t dsc_bytes_per_pixel,
0367                     uint32_t dsc_slice_width)
0368 {
0369     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0370 
0371     REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
0372 }
0373 
0374 /* this function read dsc related register fields to be logged later in dcn10_log_hw_state
0375  * into a dcn_dsc_state struct.
0376  */
0377 static void enc314_read_state(struct stream_encoder *enc, struct enc_state *s)
0378 {
0379     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0380 
0381     //if dsc is enabled, continue to read
0382     REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode);
0383     if (s->dsc_mode) {
0384         REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num);
0385 
0386         REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference);
0387         REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num);
0388 
0389         REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable);
0390         REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable);
0391     }
0392 }
0393 
0394 static void enc314_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container)
0395 {
0396     struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
0397 
0398     // The naming of this field is confusing, what it means is the output mode of otg, which
0399     // is the input mode of the dig
0400     REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, pix_per_container == 2 ? 0x1 : 0x0);
0401 }
0402 
0403 
0404 static const struct stream_encoder_funcs dcn314_str_enc_funcs = {
0405     .dp_set_odm_combine =
0406         enc314_dp_set_odm_combine,
0407     .dp_set_stream_attribute =
0408         enc2_stream_encoder_dp_set_stream_attribute,
0409     .hdmi_set_stream_attribute =
0410         enc314_stream_encoder_hdmi_set_stream_attribute,
0411     .dvi_set_stream_attribute =
0412         enc314_stream_encoder_dvi_set_stream_attribute,
0413     .set_throttled_vcp_size =
0414         enc1_stream_encoder_set_throttled_vcp_size,
0415     .update_hdmi_info_packets =
0416         enc3_stream_encoder_update_hdmi_info_packets,
0417     .stop_hdmi_info_packets =
0418         enc3_stream_encoder_stop_hdmi_info_packets,
0419     .update_dp_info_packets =
0420         enc3_stream_encoder_update_dp_info_packets,
0421     .stop_dp_info_packets =
0422         enc1_stream_encoder_stop_dp_info_packets,
0423     .dp_blank =
0424         enc314_stream_encoder_dp_blank,
0425     .dp_unblank =
0426         enc314_stream_encoder_dp_unblank,
0427     .audio_mute_control = enc3_audio_mute_control,
0428 
0429     .dp_audio_setup = enc3_se_dp_audio_setup,
0430     .dp_audio_enable = enc3_se_dp_audio_enable,
0431     .dp_audio_disable = enc1_se_dp_audio_disable,
0432 
0433     .hdmi_audio_setup = enc3_se_hdmi_audio_setup,
0434     .hdmi_audio_disable = enc1_se_hdmi_audio_disable,
0435     .setup_stereo_sync  = enc1_setup_stereo_sync,
0436     .set_avmute = enc1_stream_encoder_set_avmute,
0437     .dig_connect_to_otg = enc1_dig_connect_to_otg,
0438     .dig_source_otg = enc1_dig_source_otg,
0439 
0440     .dp_get_pixel_format  = enc1_stream_encoder_dp_get_pixel_format,
0441 
0442     .enc_read_state = enc314_read_state,
0443     .dp_set_dsc_config = enc314_dp_set_dsc_config,
0444     .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet,
0445     .set_dynamic_metadata = enc2_set_dynamic_metadata,
0446     .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute,
0447 
0448     .enable_fifo = enc314_enable_fifo,
0449     .disable_fifo = enc314_disable_fifo,
0450     .set_input_mode = enc314_set_dig_input_mode,
0451 };
0452 
0453 void dcn314_dio_stream_encoder_construct(
0454     struct dcn10_stream_encoder *enc1,
0455     struct dc_context *ctx,
0456     struct dc_bios *bp,
0457     enum engine_id eng_id,
0458     struct vpg *vpg,
0459     struct afmt *afmt,
0460     const struct dcn10_stream_enc_registers *regs,
0461     const struct dcn10_stream_encoder_shift *se_shift,
0462     const struct dcn10_stream_encoder_mask *se_mask)
0463 {
0464     enc1->base.funcs = &dcn314_str_enc_funcs;
0465     enc1->base.ctx = ctx;
0466     enc1->base.id = eng_id;
0467     enc1->base.bp = bp;
0468     enc1->base.vpg = vpg;
0469     enc1->base.afmt = afmt;
0470     enc1->regs = regs;
0471     enc1->se_shift = se_shift;
0472     enc1->se_mask = se_mask;
0473     enc1->base.stream_enc_inst = vpg->inst;
0474 }
0475