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