linux/drivers/gpu/drm/amd/display/dc/core/dc_link.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 "dm_services.h"
  27#include "atom.h"
  28#include "dm_helpers.h"
  29#include "dc.h"
  30#include "grph_object_id.h"
  31#include "gpio_service_interface.h"
  32#include "core_status.h"
  33#include "dc_link_dp.h"
  34#include "dc_link_ddc.h"
  35#include "link_hwss.h"
  36#include "opp.h"
  37
  38#include "link_encoder.h"
  39#include "hw_sequencer.h"
  40#include "resource.h"
  41#include "abm.h"
  42#include "fixed31_32.h"
  43#include "dpcd_defs.h"
  44#include "dmcu.h"
  45
  46#include "dce/dce_11_0_d.h"
  47#include "dce/dce_11_0_enum.h"
  48#include "dce/dce_11_0_sh_mask.h"
  49
  50#define DC_LOGGER_INIT(logger)
  51
  52
  53#define LINK_INFO(...) \
  54        DC_LOG_HW_HOTPLUG(  \
  55                __VA_ARGS__)
  56
  57/*******************************************************************************
  58 * Private structures
  59 ******************************************************************************/
  60
  61enum {
  62        LINK_RATE_REF_FREQ_IN_MHZ = 27,
  63        PEAK_FACTOR_X1000 = 1006,
  64        /*
  65        * Some receivers fail to train on first try and are good
  66        * on subsequent tries. 2 retries should be plenty. If we
  67        * don't have a successful training then we don't expect to
  68        * ever get one.
  69        */
  70        LINK_TRAINING_MAX_VERIFY_RETRY = 2
  71};
  72
  73/*******************************************************************************
  74 * Private functions
  75 ******************************************************************************/
  76static void destruct(struct dc_link *link)
  77{
  78        int i;
  79
  80        if (link->ddc)
  81                dal_ddc_service_destroy(&link->ddc);
  82
  83        if(link->link_enc)
  84                link->link_enc->funcs->destroy(&link->link_enc);
  85
  86        if (link->local_sink)
  87                dc_sink_release(link->local_sink);
  88
  89        for (i = 0; i < link->sink_count; ++i)
  90                dc_sink_release(link->remote_sinks[i]);
  91}
  92
  93struct gpio *get_hpd_gpio(struct dc_bios *dcb,
  94                struct graphics_object_id link_id,
  95                struct gpio_service *gpio_service)
  96{
  97        enum bp_result bp_result;
  98        struct graphics_object_hpd_info hpd_info;
  99        struct gpio_pin_info pin_info;
 100
 101        if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
 102                return NULL;
 103
 104        bp_result = dcb->funcs->get_gpio_pin_info(dcb,
 105                hpd_info.hpd_int_gpio_uid, &pin_info);
 106
 107        if (bp_result != BP_RESULT_OK) {
 108                ASSERT(bp_result == BP_RESULT_NORECORD);
 109                return NULL;
 110        }
 111
 112        return dal_gpio_service_create_irq(
 113                gpio_service,
 114                pin_info.offset,
 115                pin_info.mask);
 116}
 117
 118/*
 119 *  Function: program_hpd_filter
 120 *
 121 *  @brief
 122 *     Programs HPD filter on associated HPD line
 123 *
 124 *  @param [in] delay_on_connect_in_ms: Connect filter timeout
 125 *  @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
 126 *
 127 *  @return
 128 *     true on success, false otherwise
 129 */
 130static bool program_hpd_filter(
 131        const struct dc_link *link)
 132{
 133        bool result = false;
 134
 135        struct gpio *hpd;
 136
 137        int delay_on_connect_in_ms = 0;
 138        int delay_on_disconnect_in_ms = 0;
 139
 140        if (link->is_hpd_filter_disabled)
 141                return false;
 142        /* Verify feature is supported */
 143        switch (link->connector_signal) {
 144        case SIGNAL_TYPE_DVI_SINGLE_LINK:
 145        case SIGNAL_TYPE_DVI_DUAL_LINK:
 146        case SIGNAL_TYPE_HDMI_TYPE_A:
 147                /* Program hpd filter */
 148                delay_on_connect_in_ms = 500;
 149                delay_on_disconnect_in_ms = 100;
 150                break;
 151        case SIGNAL_TYPE_DISPLAY_PORT:
 152        case SIGNAL_TYPE_DISPLAY_PORT_MST:
 153                /* Program hpd filter to allow DP signal to settle */
 154                /* 500: not able to detect MST <-> SST switch as HPD is low for
 155                 *      only 100ms on DELL U2413
 156                 * 0:   some passive dongle still show aux mode instead of i2c
 157                 * 20-50:not enough to hide bouncing HPD with passive dongle.
 158                 *      also see intermittent i2c read issues.
 159                 */
 160                delay_on_connect_in_ms = 80;
 161                delay_on_disconnect_in_ms = 0;
 162                break;
 163        case SIGNAL_TYPE_LVDS:
 164        case SIGNAL_TYPE_EDP:
 165        default:
 166                /* Don't program hpd filter */
 167                return false;
 168        }
 169
 170        /* Obtain HPD handle */
 171        hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 172
 173        if (!hpd)
 174                return result;
 175
 176        /* Setup HPD filtering */
 177        if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
 178                struct gpio_hpd_config config;
 179
 180                config.delay_on_connect = delay_on_connect_in_ms;
 181                config.delay_on_disconnect = delay_on_disconnect_in_ms;
 182
 183                dal_irq_setup_hpd_filter(hpd, &config);
 184
 185                dal_gpio_close(hpd);
 186
 187                result = true;
 188        } else {
 189                ASSERT_CRITICAL(false);
 190        }
 191
 192        /* Release HPD handle */
 193        dal_gpio_destroy_irq(&hpd);
 194
 195        return result;
 196}
 197
 198bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
 199{
 200        uint32_t is_hpd_high = 0;
 201        struct gpio *hpd_pin;
 202
 203        /* todo: may need to lock gpio access */
 204        hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 205        if (hpd_pin == NULL)
 206                goto hpd_gpio_failure;
 207
 208        dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
 209        dal_gpio_get_value(hpd_pin, &is_hpd_high);
 210        dal_gpio_close(hpd_pin);
 211        dal_gpio_destroy_irq(&hpd_pin);
 212
 213        if (is_hpd_high) {
 214                *type = dc_connection_single;
 215                /* TODO: need to do the actual detection */
 216        } else {
 217                *type = dc_connection_none;
 218        }
 219
 220        return true;
 221
 222hpd_gpio_failure:
 223        return false;
 224}
 225
 226static enum ddc_transaction_type get_ddc_transaction_type(
 227                enum signal_type sink_signal)
 228{
 229        enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
 230
 231        switch (sink_signal) {
 232        case SIGNAL_TYPE_DVI_SINGLE_LINK:
 233        case SIGNAL_TYPE_DVI_DUAL_LINK:
 234        case SIGNAL_TYPE_HDMI_TYPE_A:
 235        case SIGNAL_TYPE_LVDS:
 236        case SIGNAL_TYPE_RGB:
 237                transaction_type = DDC_TRANSACTION_TYPE_I2C;
 238                break;
 239
 240        case SIGNAL_TYPE_DISPLAY_PORT:
 241        case SIGNAL_TYPE_EDP:
 242                transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
 243                break;
 244
 245        case SIGNAL_TYPE_DISPLAY_PORT_MST:
 246                /* MST does not use I2COverAux, but there is the
 247                 * SPECIAL use case for "immediate dwnstrm device
 248                 * access" (EPR#370830). */
 249                transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
 250                break;
 251
 252        default:
 253                break;
 254        }
 255
 256        return transaction_type;
 257}
 258
 259static enum signal_type get_basic_signal_type(
 260        struct graphics_object_id encoder,
 261        struct graphics_object_id downstream)
 262{
 263        if (downstream.type == OBJECT_TYPE_CONNECTOR) {
 264                switch (downstream.id) {
 265                case CONNECTOR_ID_SINGLE_LINK_DVII:
 266                        switch (encoder.id) {
 267                        case ENCODER_ID_INTERNAL_DAC1:
 268                        case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
 269                        case ENCODER_ID_INTERNAL_DAC2:
 270                        case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
 271                                return SIGNAL_TYPE_RGB;
 272                        default:
 273                                return SIGNAL_TYPE_DVI_SINGLE_LINK;
 274                        }
 275                break;
 276                case CONNECTOR_ID_DUAL_LINK_DVII:
 277                {
 278                        switch (encoder.id) {
 279                        case ENCODER_ID_INTERNAL_DAC1:
 280                        case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
 281                        case ENCODER_ID_INTERNAL_DAC2:
 282                        case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
 283                                return SIGNAL_TYPE_RGB;
 284                        default:
 285                                return SIGNAL_TYPE_DVI_DUAL_LINK;
 286                        }
 287                }
 288                break;
 289                case CONNECTOR_ID_SINGLE_LINK_DVID:
 290                        return SIGNAL_TYPE_DVI_SINGLE_LINK;
 291                case CONNECTOR_ID_DUAL_LINK_DVID:
 292                        return SIGNAL_TYPE_DVI_DUAL_LINK;
 293                case CONNECTOR_ID_VGA:
 294                        return SIGNAL_TYPE_RGB;
 295                case CONNECTOR_ID_HDMI_TYPE_A:
 296                        return SIGNAL_TYPE_HDMI_TYPE_A;
 297                case CONNECTOR_ID_LVDS:
 298                        return SIGNAL_TYPE_LVDS;
 299                case CONNECTOR_ID_DISPLAY_PORT:
 300                        return SIGNAL_TYPE_DISPLAY_PORT;
 301                case CONNECTOR_ID_EDP:
 302                        return SIGNAL_TYPE_EDP;
 303                default:
 304                        return SIGNAL_TYPE_NONE;
 305                }
 306        } else if (downstream.type == OBJECT_TYPE_ENCODER) {
 307                switch (downstream.id) {
 308                case ENCODER_ID_EXTERNAL_NUTMEG:
 309                case ENCODER_ID_EXTERNAL_TRAVIS:
 310                        return SIGNAL_TYPE_DISPLAY_PORT;
 311                default:
 312                        return SIGNAL_TYPE_NONE;
 313                }
 314        }
 315
 316        return SIGNAL_TYPE_NONE;
 317}
 318
 319/*
 320 * @brief
 321 * Check whether there is a dongle on DP connector
 322 */
 323bool dc_link_is_dp_sink_present(struct dc_link *link)
 324{
 325        enum gpio_result gpio_result;
 326        uint32_t clock_pin = 0;
 327
 328        struct ddc *ddc;
 329
 330        enum connector_id connector_id =
 331                dal_graphics_object_id_get_connector_id(link->link_id);
 332
 333        bool present =
 334                ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
 335                (connector_id == CONNECTOR_ID_EDP));
 336
 337        ddc = dal_ddc_service_get_ddc_pin(link->ddc);
 338
 339        if (!ddc) {
 340                BREAK_TO_DEBUGGER();
 341                return present;
 342        }
 343
 344        /* Open GPIO and set it to I2C mode */
 345        /* Note: this GpioMode_Input will be converted
 346         * to GpioConfigType_I2cAuxDualMode in GPIO component,
 347         * which indicates we need additional delay */
 348
 349        if (GPIO_RESULT_OK != dal_ddc_open(
 350                ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
 351                dal_gpio_destroy_ddc(&ddc);
 352
 353                return present;
 354        }
 355
 356        /* Read GPIO: DP sink is present if both clock and data pins are zero */
 357        /* [anaumov] in DAL2, there was no check for GPIO failure */
 358
 359        gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin);
 360        ASSERT(gpio_result == GPIO_RESULT_OK);
 361
 362        present = (gpio_result == GPIO_RESULT_OK) && !clock_pin;
 363
 364        dal_ddc_close(ddc);
 365
 366        return present;
 367}
 368
 369/*
 370 * @brief
 371 * Detect output sink type
 372 */
 373static enum signal_type link_detect_sink(
 374        struct dc_link *link,
 375        enum dc_detect_reason reason)
 376{
 377        enum signal_type result = get_basic_signal_type(
 378                link->link_enc->id, link->link_id);
 379
 380        /* Internal digital encoder will detect only dongles
 381         * that require digital signal */
 382
 383        /* Detection mechanism is different
 384         * for different native connectors.
 385         * LVDS connector supports only LVDS signal;
 386         * PCIE is a bus slot, the actual connector needs to be detected first;
 387         * eDP connector supports only eDP signal;
 388         * HDMI should check straps for audio */
 389
 390        /* PCIE detects the actual connector on add-on board */
 391
 392        if (link->link_id.id == CONNECTOR_ID_PCIE) {
 393                /* ZAZTODO implement PCIE add-on card detection */
 394        }
 395
 396        switch (link->link_id.id) {
 397        case CONNECTOR_ID_HDMI_TYPE_A: {
 398                /* check audio support:
 399                 * if native HDMI is not supported, switch to DVI */
 400                struct audio_support *aud_support = &link->dc->res_pool->audio_support;
 401
 402                if (!aud_support->hdmi_audio_native)
 403                        if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
 404                                result = SIGNAL_TYPE_DVI_SINGLE_LINK;
 405        }
 406        break;
 407        case CONNECTOR_ID_DISPLAY_PORT: {
 408                /* DP HPD short pulse. Passive DP dongle will not
 409                 * have short pulse
 410                 */
 411                if (reason != DETECT_REASON_HPDRX) {
 412                        /* Check whether DP signal detected: if not -
 413                         * we assume signal is DVI; it could be corrected
 414                         * to HDMI after dongle detection
 415                         */
 416                        if (!dm_helpers_is_dp_sink_present(link))
 417                                result = SIGNAL_TYPE_DVI_SINGLE_LINK;
 418                }
 419        }
 420        break;
 421        default:
 422        break;
 423        }
 424
 425        return result;
 426}
 427
 428static enum signal_type decide_signal_from_strap_and_dongle_type(
 429                enum display_dongle_type dongle_type,
 430                struct audio_support *audio_support)
 431{
 432        enum signal_type signal = SIGNAL_TYPE_NONE;
 433
 434        switch (dongle_type) {
 435        case DISPLAY_DONGLE_DP_HDMI_DONGLE:
 436                if (audio_support->hdmi_audio_on_dongle)
 437                        signal =  SIGNAL_TYPE_HDMI_TYPE_A;
 438                else
 439                        signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 440                break;
 441        case DISPLAY_DONGLE_DP_DVI_DONGLE:
 442                signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 443                break;
 444        case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
 445                if (audio_support->hdmi_audio_native)
 446                        signal =  SIGNAL_TYPE_HDMI_TYPE_A;
 447                else
 448                        signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 449                break;
 450        default:
 451                signal = SIGNAL_TYPE_NONE;
 452                break;
 453        }
 454
 455        return signal;
 456}
 457
 458static enum signal_type dp_passive_dongle_detection(
 459                struct ddc_service *ddc,
 460                struct display_sink_capability *sink_cap,
 461                struct audio_support *audio_support)
 462{
 463        dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
 464                                                ddc, sink_cap);
 465        return decide_signal_from_strap_and_dongle_type(
 466                        sink_cap->dongle_type,
 467                        audio_support);
 468}
 469
 470static void link_disconnect_sink(struct dc_link *link)
 471{
 472        if (link->local_sink) {
 473                dc_sink_release(link->local_sink);
 474                link->local_sink = NULL;
 475        }
 476
 477        link->dpcd_sink_count = 0;
 478}
 479
 480static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
 481{
 482        dc_sink_release(link->local_sink);
 483        link->local_sink = prev_sink;
 484}
 485
 486
 487static bool detect_dp(
 488        struct dc_link *link,
 489        struct display_sink_capability *sink_caps,
 490        bool *converter_disable_audio,
 491        struct audio_support *audio_support,
 492        enum dc_detect_reason reason)
 493{
 494        bool boot = false;
 495        sink_caps->signal = link_detect_sink(link, reason);
 496        sink_caps->transaction_type =
 497                get_ddc_transaction_type(sink_caps->signal);
 498
 499        if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
 500                sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
 501                if (!detect_dp_sink_caps(link))
 502                        return false;
 503
 504                if (is_mst_supported(link)) {
 505                        sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
 506                        link->type = dc_connection_mst_branch;
 507
 508                        dal_ddc_service_set_transaction_type(
 509                                                        link->ddc,
 510                                                        sink_caps->transaction_type);
 511
 512                        /*
 513                         * This call will initiate MST topology discovery. Which
 514                         * will detect MST ports and add new DRM connector DRM
 515                         * framework. Then read EDID via remote i2c over aux. In
 516                         * the end, will notify DRM detect result and save EDID
 517                         * into DRM framework.
 518                         *
 519                         * .detect is called by .fill_modes.
 520                         * .fill_modes is called by user mode ioctl
 521                         * DRM_IOCTL_MODE_GETCONNECTOR.
 522                         *
 523                         * .get_modes is called by .fill_modes.
 524                         *
 525                         * call .get_modes, AMDGPU DM implementation will create
 526                         * new dc_sink and add to dc_link. For long HPD plug
 527                         * in/out, MST has its own handle.
 528                         *
 529                         * Therefore, just after dc_create, link->sink is not
 530                         * created for MST until user mode app calls
 531                         * DRM_IOCTL_MODE_GETCONNECTOR.
 532                         *
 533                         * Need check ->sink usages in case ->sink = NULL
 534                         * TODO: s3 resume check
 535                         */
 536                        if (reason == DETECT_REASON_BOOT)
 537                                boot = true;
 538
 539                        dm_helpers_dp_update_branch_info(
 540                                link->ctx,
 541                                link);
 542
 543                        if (!dm_helpers_dp_mst_start_top_mgr(
 544                                link->ctx,
 545                                link, boot)) {
 546                                /* MST not supported */
 547                                link->type = dc_connection_single;
 548                                sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
 549                        }
 550                }
 551
 552                if (link->type != dc_connection_mst_branch &&
 553                        is_dp_active_dongle(link)) {
 554                        /* DP active dongles */
 555                        link->type = dc_connection_active_dongle;
 556                        if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
 557                                /*
 558                                 * active dongle unplug processing for short irq
 559                                 */
 560                                link_disconnect_sink(link);
 561                                return true;
 562                        }
 563
 564                        if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER)
 565                                *converter_disable_audio = true;
 566                }
 567        } else {
 568                /* DP passive dongles */
 569                sink_caps->signal = dp_passive_dongle_detection(link->ddc,
 570                                sink_caps,
 571                                audio_support);
 572        }
 573
 574        return true;
 575}
 576
 577static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
 578{
 579        if (old_edid->length != new_edid->length)
 580                return false;
 581
 582        if (new_edid->length == 0)
 583                return false;
 584
 585        return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0);
 586}
 587
 588bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
 589{
 590        struct dc_sink_init_data sink_init_data = { 0 };
 591        struct display_sink_capability sink_caps = { 0 };
 592        uint8_t i;
 593        bool converter_disable_audio = false;
 594        struct audio_support *aud_support = &link->dc->res_pool->audio_support;
 595        bool same_edid = false;
 596        enum dc_edid_status edid_status;
 597        struct dc_context *dc_ctx = link->ctx;
 598        struct dc_sink *sink = NULL;
 599        struct dc_sink *prev_sink = NULL;
 600        struct dpcd_caps prev_dpcd_caps;
 601        bool same_dpcd = true;
 602        enum dc_connection_type new_connection_type = dc_connection_none;
 603        DC_LOGGER_INIT(link->ctx->logger);
 604        if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
 605                return false;
 606
 607        if (false == dc_link_detect_sink(link, &new_connection_type)) {
 608                BREAK_TO_DEBUGGER();
 609                return false;
 610        }
 611
 612        if (link->connector_signal == SIGNAL_TYPE_EDP &&
 613                        link->local_sink)
 614                return true;
 615
 616        prev_sink = link->local_sink;
 617        if (prev_sink != NULL) {
 618                dc_sink_retain(prev_sink);
 619                memcpy(&prev_dpcd_caps, &link->dpcd_caps, sizeof(struct dpcd_caps));
 620        }
 621        link_disconnect_sink(link);
 622
 623        if (new_connection_type != dc_connection_none) {
 624                link->type = new_connection_type;
 625
 626                /* From Disconnected-to-Connected. */
 627                switch (link->connector_signal) {
 628                case SIGNAL_TYPE_HDMI_TYPE_A: {
 629                        sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
 630                        if (aud_support->hdmi_audio_native)
 631                                sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
 632                        else
 633                                sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 634                        break;
 635                }
 636
 637                case SIGNAL_TYPE_DVI_SINGLE_LINK: {
 638                        sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
 639                        sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 640                        break;
 641                }
 642
 643                case SIGNAL_TYPE_DVI_DUAL_LINK: {
 644                        sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
 645                        sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
 646                        break;
 647                }
 648
 649                case SIGNAL_TYPE_EDP: {
 650                        detect_edp_sink_caps(link);
 651                        sink_caps.transaction_type =
 652                                DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
 653                        sink_caps.signal = SIGNAL_TYPE_EDP;
 654                        break;
 655                }
 656
 657                case SIGNAL_TYPE_DISPLAY_PORT: {
 658                        if (!detect_dp(
 659                                link,
 660                                &sink_caps,
 661                                &converter_disable_audio,
 662                                aud_support, reason)) {
 663                                if (prev_sink != NULL)
 664                                        dc_sink_release(prev_sink);
 665                                return false;
 666                        }
 667
 668                        // Check if dpcp block is the same
 669                        if (prev_sink != NULL) {
 670                                if (memcmp(&link->dpcd_caps, &prev_dpcd_caps, sizeof(struct dpcd_caps)))
 671                                        same_dpcd = false;
 672                        }
 673                        /* Active dongle downstream unplug */
 674                        if (link->type == dc_connection_active_dongle
 675                                        && link->dpcd_caps.sink_count.
 676                                        bits.SINK_COUNT == 0) {
 677                                if (prev_sink != NULL)
 678                                        dc_sink_release(prev_sink);
 679                                return true;
 680                        }
 681
 682                        if (link->type == dc_connection_mst_branch) {
 683                                LINK_INFO("link=%d, mst branch is now Connected\n",
 684                                        link->link_index);
 685                                /* Need to setup mst link_cap struct here
 686                                 * otherwise dc_link_detect() will leave mst link_cap
 687                                 * empty which leads to allocate_mst_payload() has "0"
 688                                 * pbn_per_slot value leading to exception on dc_fixpt_div()
 689                                 */
 690                                link->verified_link_cap = link->reported_link_cap;
 691                                if (prev_sink != NULL)
 692                                        dc_sink_release(prev_sink);
 693                                return false;
 694                        }
 695
 696                        break;
 697                }
 698
 699                default:
 700                        DC_ERROR("Invalid connector type! signal:%d\n",
 701                                link->connector_signal);
 702                        if (prev_sink != NULL)
 703                                dc_sink_release(prev_sink);
 704                        return false;
 705                } /* switch() */
 706
 707                if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
 708                        link->dpcd_sink_count = link->dpcd_caps.sink_count.
 709                                        bits.SINK_COUNT;
 710                else
 711                        link->dpcd_sink_count = 1;
 712
 713                dal_ddc_service_set_transaction_type(
 714                                                link->ddc,
 715                                                sink_caps.transaction_type);
 716
 717                link->aux_mode = dal_ddc_service_is_in_aux_transaction_mode(
 718                                link->ddc);
 719
 720                sink_init_data.link = link;
 721                sink_init_data.sink_signal = sink_caps.signal;
 722
 723                sink = dc_sink_create(&sink_init_data);
 724                if (!sink) {
 725                        DC_ERROR("Failed to create sink!\n");
 726                        if (prev_sink != NULL)
 727                                dc_sink_release(prev_sink);
 728                        return false;
 729                }
 730
 731                sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
 732                sink->converter_disable_audio = converter_disable_audio;
 733
 734                link->local_sink = sink;
 735
 736                edid_status = dm_helpers_read_local_edid(
 737                                link->ctx,
 738                                link,
 739                                sink);
 740
 741                switch (edid_status) {
 742                case EDID_BAD_CHECKSUM:
 743                        DC_LOG_ERROR("EDID checksum invalid.\n");
 744                        break;
 745                case EDID_NO_RESPONSE:
 746                        DC_LOG_ERROR("No EDID read.\n");
 747
 748                        /*
 749                         * Abort detection for non-DP connectors if we have
 750                         * no EDID
 751                         *
 752                         * DP needs to report as connected if HDP is high
 753                         * even if we have no EDID in order to go to
 754                         * fail-safe mode
 755                         */
 756                        if (dc_is_hdmi_signal(link->connector_signal) ||
 757                            dc_is_dvi_signal(link->connector_signal)) {
 758                                if (prev_sink != NULL)
 759                                        dc_sink_release(prev_sink);
 760
 761                                return false;
 762                        }
 763                default:
 764                        break;
 765                }
 766
 767                // Check if edid is the same
 768                if ((prev_sink != NULL) && ((edid_status == EDID_THE_SAME) || (edid_status == EDID_OK)))
 769                        same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid);
 770
 771                if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
 772                        sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX &&
 773                        reason != DETECT_REASON_HPDRX) {
 774                        /*
 775                         * TODO debug why Dell 2413 doesn't like
 776                         *  two link trainings
 777                         */
 778
 779                        /* deal with non-mst cases */
 780                        for (i = 0; i < LINK_TRAINING_MAX_VERIFY_RETRY; i++) {
 781                                int fail_count = 0;
 782
 783                                dp_verify_link_cap(link,
 784                                                  &link->reported_link_cap,
 785                                                  &fail_count);
 786
 787                                if (fail_count == 0)
 788                                        break;
 789                        }
 790
 791                } else {
 792                        // If edid is the same, then discard new sink and revert back to original sink
 793                        if (same_edid) {
 794                                link_disconnect_remap(prev_sink, link);
 795                                sink = prev_sink;
 796                                prev_sink = NULL;
 797
 798                        }
 799                }
 800
 801                /* HDMI-DVI Dongle */
 802                if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
 803                                !sink->edid_caps.edid_hdmi)
 804                        sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
 805
 806                /* Connectivity log: detection */
 807                for (i = 0; i < sink->dc_edid.length / EDID_BLOCK_SIZE; i++) {
 808                        CONN_DATA_DETECT(link,
 809                                        &sink->dc_edid.raw_edid[i * EDID_BLOCK_SIZE],
 810                                        EDID_BLOCK_SIZE,
 811                                        "%s: [Block %d] ", sink->edid_caps.display_name, i);
 812                }
 813
 814                DC_LOG_DETECTION_EDID_PARSER("%s: "
 815                        "manufacturer_id = %X, "
 816                        "product_id = %X, "
 817                        "serial_number = %X, "
 818                        "manufacture_week = %d, "
 819                        "manufacture_year = %d, "
 820                        "display_name = %s, "
 821                        "speaker_flag = %d, "
 822                        "audio_mode_count = %d\n",
 823                        __func__,
 824                        sink->edid_caps.manufacturer_id,
 825                        sink->edid_caps.product_id,
 826                        sink->edid_caps.serial_number,
 827                        sink->edid_caps.manufacture_week,
 828                        sink->edid_caps.manufacture_year,
 829                        sink->edid_caps.display_name,
 830                        sink->edid_caps.speaker_flags,
 831                        sink->edid_caps.audio_mode_count);
 832
 833                for (i = 0; i < sink->edid_caps.audio_mode_count; i++) {
 834                        DC_LOG_DETECTION_EDID_PARSER("%s: mode number = %d, "
 835                                "format_code = %d, "
 836                                "channel_count = %d, "
 837                                "sample_rate = %d, "
 838                                "sample_size = %d\n",
 839                                __func__,
 840                                i,
 841                                sink->edid_caps.audio_modes[i].format_code,
 842                                sink->edid_caps.audio_modes[i].channel_count,
 843                                sink->edid_caps.audio_modes[i].sample_rate,
 844                                sink->edid_caps.audio_modes[i].sample_size);
 845                }
 846
 847        } else {
 848                /* From Connected-to-Disconnected. */
 849                if (link->type == dc_connection_mst_branch) {
 850                        LINK_INFO("link=%d, mst branch is now Disconnected\n",
 851                                link->link_index);
 852
 853                        dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
 854
 855                        link->mst_stream_alloc_table.stream_count = 0;
 856                        memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations));
 857                }
 858
 859                link->type = dc_connection_none;
 860                sink_caps.signal = SIGNAL_TYPE_NONE;
 861        }
 862
 863        LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n",
 864                link->link_index, sink,
 865                (sink_caps.signal == SIGNAL_TYPE_NONE ?
 866                        "Disconnected":"Connected"), prev_sink,
 867                        same_dpcd, same_edid);
 868
 869        if (prev_sink != NULL)
 870                dc_sink_release(prev_sink);
 871
 872        return true;
 873}
 874
 875static enum hpd_source_id get_hpd_line(
 876                struct dc_link *link)
 877{
 878        struct gpio *hpd;
 879        enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
 880
 881        hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 882
 883        if (hpd) {
 884                switch (dal_irq_get_source(hpd)) {
 885                case DC_IRQ_SOURCE_HPD1:
 886                        hpd_id = HPD_SOURCEID1;
 887                break;
 888                case DC_IRQ_SOURCE_HPD2:
 889                        hpd_id = HPD_SOURCEID2;
 890                break;
 891                case DC_IRQ_SOURCE_HPD3:
 892                        hpd_id = HPD_SOURCEID3;
 893                break;
 894                case DC_IRQ_SOURCE_HPD4:
 895                        hpd_id = HPD_SOURCEID4;
 896                break;
 897                case DC_IRQ_SOURCE_HPD5:
 898                        hpd_id = HPD_SOURCEID5;
 899                break;
 900                case DC_IRQ_SOURCE_HPD6:
 901                        hpd_id = HPD_SOURCEID6;
 902                break;
 903                default:
 904                        BREAK_TO_DEBUGGER();
 905                break;
 906                }
 907
 908                dal_gpio_destroy_irq(&hpd);
 909        }
 910
 911        return hpd_id;
 912}
 913
 914static enum channel_id get_ddc_line(struct dc_link *link)
 915{
 916        struct ddc *ddc;
 917        enum channel_id channel = CHANNEL_ID_UNKNOWN;
 918
 919        ddc = dal_ddc_service_get_ddc_pin(link->ddc);
 920
 921        if (ddc) {
 922                switch (dal_ddc_get_line(ddc)) {
 923                case GPIO_DDC_LINE_DDC1:
 924                        channel = CHANNEL_ID_DDC1;
 925                        break;
 926                case GPIO_DDC_LINE_DDC2:
 927                        channel = CHANNEL_ID_DDC2;
 928                        break;
 929                case GPIO_DDC_LINE_DDC3:
 930                        channel = CHANNEL_ID_DDC3;
 931                        break;
 932                case GPIO_DDC_LINE_DDC4:
 933                        channel = CHANNEL_ID_DDC4;
 934                        break;
 935                case GPIO_DDC_LINE_DDC5:
 936                        channel = CHANNEL_ID_DDC5;
 937                        break;
 938                case GPIO_DDC_LINE_DDC6:
 939                        channel = CHANNEL_ID_DDC6;
 940                        break;
 941                case GPIO_DDC_LINE_DDC_VGA:
 942                        channel = CHANNEL_ID_DDC_VGA;
 943                        break;
 944                case GPIO_DDC_LINE_I2C_PAD:
 945                        channel = CHANNEL_ID_I2C_PAD;
 946                        break;
 947                default:
 948                        BREAK_TO_DEBUGGER();
 949                        break;
 950                }
 951        }
 952
 953        return channel;
 954}
 955
 956static enum transmitter translate_encoder_to_transmitter(
 957        struct graphics_object_id encoder)
 958{
 959        switch (encoder.id) {
 960        case ENCODER_ID_INTERNAL_UNIPHY:
 961                switch (encoder.enum_id) {
 962                case ENUM_ID_1:
 963                        return TRANSMITTER_UNIPHY_A;
 964                case ENUM_ID_2:
 965                        return TRANSMITTER_UNIPHY_B;
 966                default:
 967                        return TRANSMITTER_UNKNOWN;
 968                }
 969        break;
 970        case ENCODER_ID_INTERNAL_UNIPHY1:
 971                switch (encoder.enum_id) {
 972                case ENUM_ID_1:
 973                        return TRANSMITTER_UNIPHY_C;
 974                case ENUM_ID_2:
 975                        return TRANSMITTER_UNIPHY_D;
 976                default:
 977                        return TRANSMITTER_UNKNOWN;
 978                }
 979        break;
 980        case ENCODER_ID_INTERNAL_UNIPHY2:
 981                switch (encoder.enum_id) {
 982                case ENUM_ID_1:
 983                        return TRANSMITTER_UNIPHY_E;
 984                case ENUM_ID_2:
 985                        return TRANSMITTER_UNIPHY_F;
 986                default:
 987                        return TRANSMITTER_UNKNOWN;
 988                }
 989        break;
 990        case ENCODER_ID_INTERNAL_UNIPHY3:
 991                switch (encoder.enum_id) {
 992                case ENUM_ID_1:
 993                        return TRANSMITTER_UNIPHY_G;
 994                default:
 995                        return TRANSMITTER_UNKNOWN;
 996                }
 997        break;
 998        case ENCODER_ID_EXTERNAL_NUTMEG:
 999                switch (encoder.enum_id) {
1000                case ENUM_ID_1:
1001                        return TRANSMITTER_NUTMEG_CRT;
1002                default:
1003                        return TRANSMITTER_UNKNOWN;
1004                }
1005        break;
1006        case ENCODER_ID_EXTERNAL_TRAVIS:
1007                switch (encoder.enum_id) {
1008                case ENUM_ID_1:
1009                        return TRANSMITTER_TRAVIS_CRT;
1010                case ENUM_ID_2:
1011                        return TRANSMITTER_TRAVIS_LCD;
1012                default:
1013                        return TRANSMITTER_UNKNOWN;
1014                }
1015        break;
1016        default:
1017                return TRANSMITTER_UNKNOWN;
1018        }
1019}
1020
1021static bool construct(
1022        struct dc_link *link,
1023        const struct link_init_data *init_params)
1024{
1025        uint8_t i;
1026        struct gpio *hpd_gpio = NULL;
1027        struct ddc_service_init_data ddc_service_init_data = { { 0 } };
1028        struct dc_context *dc_ctx = init_params->ctx;
1029        struct encoder_init_data enc_init_data = { 0 };
1030        struct integrated_info info = {{{ 0 }}};
1031        struct dc_bios *bios = init_params->dc->ctx->dc_bios;
1032        const struct dc_vbios_funcs *bp_funcs = bios->funcs;
1033        DC_LOGGER_INIT(dc_ctx->logger);
1034
1035        link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1036        link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
1037
1038        link->link_status.dpcd_caps = &link->dpcd_caps;
1039
1040        link->dc = init_params->dc;
1041        link->ctx = dc_ctx;
1042        link->link_index = init_params->link_index;
1043
1044        link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index);
1045
1046        if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
1047                dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
1048                         __func__, init_params->connector_index,
1049                         link->link_id.type, OBJECT_TYPE_CONNECTOR);
1050                goto create_fail;
1051        }
1052
1053        if (link->dc->res_pool->funcs->link_init)
1054                link->dc->res_pool->funcs->link_init(link);
1055
1056        hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
1057
1058        if (hpd_gpio != NULL)
1059                link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
1060
1061        switch (link->link_id.id) {
1062        case CONNECTOR_ID_HDMI_TYPE_A:
1063                link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
1064
1065                break;
1066        case CONNECTOR_ID_SINGLE_LINK_DVID:
1067        case CONNECTOR_ID_SINGLE_LINK_DVII:
1068                link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1069                break;
1070        case CONNECTOR_ID_DUAL_LINK_DVID:
1071        case CONNECTOR_ID_DUAL_LINK_DVII:
1072                link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
1073                break;
1074        case CONNECTOR_ID_DISPLAY_PORT:
1075                link->connector_signal =        SIGNAL_TYPE_DISPLAY_PORT;
1076
1077                if (hpd_gpio != NULL)
1078                        link->irq_source_hpd_rx =
1079                                        dal_irq_get_rx_source(hpd_gpio);
1080
1081                break;
1082        case CONNECTOR_ID_EDP:
1083                link->connector_signal = SIGNAL_TYPE_EDP;
1084
1085                if (hpd_gpio != NULL) {
1086                        link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1087                        link->irq_source_hpd_rx =
1088                                        dal_irq_get_rx_source(hpd_gpio);
1089                }
1090                break;
1091        default:
1092                DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id);
1093                goto create_fail;
1094        }
1095
1096        if (hpd_gpio != NULL) {
1097                dal_gpio_destroy_irq(&hpd_gpio);
1098                hpd_gpio = NULL;
1099        }
1100
1101        /* TODO: #DAL3 Implement id to str function.*/
1102        LINK_INFO("Connector[%d] description:"
1103                        "signal %d\n",
1104                        init_params->connector_index,
1105                        link->connector_signal);
1106
1107        ddc_service_init_data.ctx = link->ctx;
1108        ddc_service_init_data.id = link->link_id;
1109        ddc_service_init_data.link = link;
1110        link->ddc = dal_ddc_service_create(&ddc_service_init_data);
1111
1112        if (link->ddc == NULL) {
1113                DC_ERROR("Failed to create ddc_service!\n");
1114                goto ddc_create_fail;
1115        }
1116
1117        link->ddc_hw_inst =
1118                dal_ddc_get_line(
1119                        dal_ddc_service_get_ddc_pin(link->ddc));
1120
1121        enc_init_data.ctx = dc_ctx;
1122        bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder);
1123        enc_init_data.connector = link->link_id;
1124        enc_init_data.channel = get_ddc_line(link);
1125        enc_init_data.hpd_source = get_hpd_line(link);
1126
1127        link->hpd_src = enc_init_data.hpd_source;
1128
1129        enc_init_data.transmitter =
1130                        translate_encoder_to_transmitter(enc_init_data.encoder);
1131        link->link_enc = link->dc->res_pool->funcs->link_enc_create(
1132                                                                &enc_init_data);
1133
1134        if( link->link_enc == NULL) {
1135                DC_ERROR("Failed to create link encoder!\n");
1136                goto link_enc_create_fail;
1137        }
1138
1139        link->link_enc_hw_inst = link->link_enc->transmitter;
1140
1141        for (i = 0; i < 4; i++) {
1142                if (BP_RESULT_OK !=
1143                                bp_funcs->get_device_tag(dc_ctx->dc_bios, link->link_id, i, &link->device_tag)) {
1144                        DC_ERROR("Failed to find device tag!\n");
1145                        goto device_tag_fail;
1146                }
1147
1148                /* Look for device tag that matches connector signal,
1149                 * CRT for rgb, LCD for other supported signal tyes
1150                 */
1151                if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id))
1152                        continue;
1153                if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT
1154                        && link->connector_signal != SIGNAL_TYPE_RGB)
1155                        continue;
1156                if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD
1157                        && link->connector_signal == SIGNAL_TYPE_RGB)
1158                        continue;
1159                break;
1160        }
1161
1162        if (bios->integrated_info)
1163                info = *bios->integrated_info;
1164
1165        /* Look for channel mapping corresponding to connector and device tag */
1166        for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
1167                struct external_display_path *path =
1168                        &info.ext_disp_conn_info.path[i];
1169                if (path->device_connector_id.enum_id == link->link_id.enum_id
1170                        && path->device_connector_id.id == link->link_id.id
1171                        && path->device_connector_id.type == link->link_id.type) {
1172
1173                        if (link->device_tag.acpi_device != 0
1174                                && path->device_acpi_enum == link->device_tag.acpi_device) {
1175                                link->ddi_channel_mapping = path->channel_mapping;
1176                                link->chip_caps = path->caps;
1177                        } else if (path->device_tag ==
1178                                        link->device_tag.dev_id.raw_device_tag) {
1179                                link->ddi_channel_mapping = path->channel_mapping;
1180                                link->chip_caps = path->caps;
1181                        }
1182                        break;
1183                }
1184        }
1185
1186        /*
1187         * TODO check if GPIO programmed correctly
1188         *
1189         * If GPIO isn't programmed correctly HPD might not rise or drain
1190         * fast enough, leading to bounces.
1191         */
1192        program_hpd_filter(link);
1193
1194        return true;
1195device_tag_fail:
1196        link->link_enc->funcs->destroy(&link->link_enc);
1197link_enc_create_fail:
1198        dal_ddc_service_destroy(&link->ddc);
1199ddc_create_fail:
1200create_fail:
1201
1202        if (hpd_gpio != NULL) {
1203                dal_gpio_destroy_irq(&hpd_gpio);
1204        }
1205
1206        return false;
1207}
1208
1209/*******************************************************************************
1210 * Public functions
1211 ******************************************************************************/
1212struct dc_link *link_create(const struct link_init_data *init_params)
1213{
1214        struct dc_link *link =
1215                        kzalloc(sizeof(*link), GFP_KERNEL);
1216
1217        if (NULL == link)
1218                goto alloc_fail;
1219
1220        if (false == construct(link, init_params))
1221                goto construct_fail;
1222
1223        return link;
1224
1225construct_fail:
1226        kfree(link);
1227
1228alloc_fail:
1229        return NULL;
1230}
1231
1232void link_destroy(struct dc_link **link)
1233{
1234        destruct(*link);
1235        kfree(*link);
1236        *link = NULL;
1237}
1238
1239static void dpcd_configure_panel_mode(
1240        struct dc_link *link,
1241        enum dp_panel_mode panel_mode)
1242{
1243        union dpcd_edp_config edp_config_set;
1244        bool panel_mode_edp = false;
1245        DC_LOGGER_INIT(link->ctx->logger);
1246
1247        memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
1248
1249        if (DP_PANEL_MODE_DEFAULT != panel_mode) {
1250
1251                switch (panel_mode) {
1252                case DP_PANEL_MODE_EDP:
1253                case DP_PANEL_MODE_SPECIAL:
1254                        panel_mode_edp = true;
1255                        break;
1256
1257                default:
1258                        break;
1259                }
1260
1261                /*set edp panel mode in receiver*/
1262                core_link_read_dpcd(
1263                        link,
1264                        DP_EDP_CONFIGURATION_SET,
1265                        &edp_config_set.raw,
1266                        sizeof(edp_config_set.raw));
1267
1268                if (edp_config_set.bits.PANEL_MODE_EDP
1269                        != panel_mode_edp) {
1270                        enum ddc_result result = DDC_RESULT_UNKNOWN;
1271
1272                        edp_config_set.bits.PANEL_MODE_EDP =
1273                        panel_mode_edp;
1274                        result = core_link_write_dpcd(
1275                                link,
1276                                DP_EDP_CONFIGURATION_SET,
1277                                &edp_config_set.raw,
1278                                sizeof(edp_config_set.raw));
1279
1280                        ASSERT(result == DDC_RESULT_SUCESSFULL);
1281                }
1282        }
1283        DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
1284                        "eDP panel mode enabled: %d \n",
1285                        link->link_index,
1286                        link->dpcd_caps.panel_mode_edp,
1287                        panel_mode_edp);
1288}
1289
1290static void enable_stream_features(struct pipe_ctx *pipe_ctx)
1291{
1292        struct dc_stream_state *stream = pipe_ctx->stream;
1293        struct dc_link *link = stream->sink->link;
1294        union down_spread_ctrl old_downspread;
1295        union down_spread_ctrl new_downspread;
1296
1297        core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,
1298                        &old_downspread.raw, sizeof(old_downspread));
1299
1300        new_downspread.raw = old_downspread.raw;
1301
1302        new_downspread.bits.IGNORE_MSA_TIMING_PARAM =
1303                        (stream->ignore_msa_timing_param) ? 1 : 0;
1304
1305        if (new_downspread.raw != old_downspread.raw) {
1306                core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
1307                        &new_downspread.raw, sizeof(new_downspread));
1308        }
1309}
1310
1311static enum dc_status enable_link_dp(
1312                struct dc_state *state,
1313                struct pipe_ctx *pipe_ctx)
1314{
1315        struct dc_stream_state *stream = pipe_ctx->stream;
1316        enum dc_status status;
1317        bool skip_video_pattern;
1318        struct dc_link *link = stream->sink->link;
1319        struct dc_link_settings link_settings = {0};
1320        enum dp_panel_mode panel_mode;
1321        enum dc_link_rate max_link_rate = LINK_RATE_HIGH2;
1322
1323        /* get link settings for video mode timing */
1324        decide_link_settings(stream, &link_settings);
1325
1326        /* raise clock state for HBR3 if required. Confirmed with HW DCE/DPCS
1327         * logic for HBR3 still needs Nominal (0.8V) on VDDC rail
1328         */
1329        if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
1330                max_link_rate = LINK_RATE_HIGH3;
1331
1332        if (link_settings.link_rate == max_link_rate) {
1333                struct dc_clocks clocks = state->bw.dcn.clk;
1334
1335                /* dce/dcn compat, do not update dispclk */
1336                clocks.dispclk_khz = 0;
1337                /* 27mhz = 27000000hz= 27000khz */
1338                clocks.phyclk_khz = link_settings.link_rate * 27000;
1339
1340                state->dis_clk->funcs->update_clocks(
1341                                state->dis_clk, &clocks, false);
1342        }
1343
1344        dp_enable_link_phy(
1345                link,
1346                pipe_ctx->stream->signal,
1347                pipe_ctx->clock_source->id,
1348                &link_settings);
1349
1350        if (stream->sink->edid_caps.panel_patch.dppowerup_delay > 0) {
1351                int delay_dp_power_up_in_ms = stream->sink->edid_caps.panel_patch.dppowerup_delay;
1352
1353                msleep(delay_dp_power_up_in_ms);
1354        }
1355
1356        panel_mode = dp_get_panel_mode(link);
1357        dpcd_configure_panel_mode(link, panel_mode);
1358
1359        skip_video_pattern = true;
1360
1361        if (link_settings.link_rate == LINK_RATE_LOW)
1362                        skip_video_pattern = false;
1363
1364        if (perform_link_training_with_retries(
1365                        link,
1366                        &link_settings,
1367                        skip_video_pattern,
1368                        LINK_TRAINING_ATTEMPTS)) {
1369                link->cur_link_settings = link_settings;
1370                status = DC_OK;
1371        }
1372        else
1373                status = DC_FAIL_DP_LINK_TRAINING;
1374
1375        enable_stream_features(pipe_ctx);
1376
1377        return status;
1378}
1379
1380static enum dc_status enable_link_edp(
1381                struct dc_state *state,
1382                struct pipe_ctx *pipe_ctx)
1383{
1384        enum dc_status status;
1385        struct dc_stream_state *stream = pipe_ctx->stream;
1386        struct dc_link *link = stream->sink->link;
1387        /*in case it is not on*/
1388        link->dc->hwss.edp_power_control(link, true);
1389        link->dc->hwss.edp_wait_for_hpd_ready(link, true);
1390
1391        status = enable_link_dp(state, pipe_ctx);
1392
1393
1394        return status;
1395}
1396
1397static enum dc_status enable_link_dp_mst(
1398                struct dc_state *state,
1399                struct pipe_ctx *pipe_ctx)
1400{
1401        struct dc_link *link = pipe_ctx->stream->sink->link;
1402
1403        /* sink signal type after MST branch is MST. Multiple MST sinks
1404         * share one link. Link DP PHY is enable or training only once.
1405         */
1406        if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
1407                return DC_OK;
1408
1409        /* clear payload table */
1410        dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
1411
1412        /* set the sink to MST mode before enabling the link */
1413        dp_enable_mst_on_sink(link, true);
1414
1415        return enable_link_dp(state, pipe_ctx);
1416}
1417
1418static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
1419                enum engine_id eng_id,
1420                struct ext_hdmi_settings *settings)
1421{
1422        bool result = false;
1423        int i = 0;
1424        struct integrated_info *integrated_info =
1425                        pipe_ctx->stream->ctx->dc_bios->integrated_info;
1426
1427        if (integrated_info == NULL)
1428                return false;
1429
1430        /*
1431         * Get retimer settings from sbios for passing SI eye test for DCE11
1432         * The setting values are varied based on board revision and port id
1433         * Therefore the setting values of each ports is passed by sbios.
1434         */
1435
1436        // Check if current bios contains ext Hdmi settings
1437        if (integrated_info->gpu_cap_info & 0x20) {
1438                switch (eng_id) {
1439                case ENGINE_ID_DIGA:
1440                        settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;
1441                        settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;
1442                        settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;
1443                        memmove(settings->reg_settings,
1444                                        integrated_info->dp0_ext_hdmi_reg_settings,
1445                                        sizeof(integrated_info->dp0_ext_hdmi_reg_settings));
1446                        memmove(settings->reg_settings_6g,
1447                                        integrated_info->dp0_ext_hdmi_6g_reg_settings,
1448                                        sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings));
1449                        result = true;
1450                        break;
1451                case ENGINE_ID_DIGB:
1452                        settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;
1453                        settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;
1454                        settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;
1455                        memmove(settings->reg_settings,
1456                                        integrated_info->dp1_ext_hdmi_reg_settings,
1457                                        sizeof(integrated_info->dp1_ext_hdmi_reg_settings));
1458                        memmove(settings->reg_settings_6g,
1459                                        integrated_info->dp1_ext_hdmi_6g_reg_settings,
1460                                        sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings));
1461                        result = true;
1462                        break;
1463                case ENGINE_ID_DIGC:
1464                        settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;
1465                        settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;
1466                        settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;
1467                        memmove(settings->reg_settings,
1468                                        integrated_info->dp2_ext_hdmi_reg_settings,
1469                                        sizeof(integrated_info->dp2_ext_hdmi_reg_settings));
1470                        memmove(settings->reg_settings_6g,
1471                                        integrated_info->dp2_ext_hdmi_6g_reg_settings,
1472                                        sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));
1473                        result = true;
1474                        break;
1475                case ENGINE_ID_DIGD:
1476                        settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;
1477                        settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;
1478                        settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;
1479                        memmove(settings->reg_settings,
1480                                        integrated_info->dp3_ext_hdmi_reg_settings,
1481                                        sizeof(integrated_info->dp3_ext_hdmi_reg_settings));
1482                        memmove(settings->reg_settings_6g,
1483                                        integrated_info->dp3_ext_hdmi_6g_reg_settings,
1484                                        sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));
1485                        result = true;
1486                        break;
1487                default:
1488                        break;
1489                }
1490
1491                if (result == true) {
1492                        // Validate settings from bios integrated info table
1493                        if (settings->slv_addr == 0)
1494                                return false;
1495                        if (settings->reg_num > 9)
1496                                return false;
1497                        if (settings->reg_num_6g > 3)
1498                                return false;
1499
1500                        for (i = 0; i < settings->reg_num; i++) {
1501                                if (settings->reg_settings[i].i2c_reg_index > 0x20)
1502                                        return false;
1503                        }
1504
1505                        for (i = 0; i < settings->reg_num_6g; i++) {
1506                                if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)
1507                                        return false;
1508                        }
1509                }
1510        }
1511
1512        return result;
1513}
1514
1515static bool i2c_write(struct pipe_ctx *pipe_ctx,
1516                uint8_t address, uint8_t *buffer, uint32_t length)
1517{
1518        struct i2c_command cmd = {0};
1519        struct i2c_payload payload = {0};
1520
1521        memset(&payload, 0, sizeof(payload));
1522        memset(&cmd, 0, sizeof(cmd));
1523
1524        cmd.number_of_payloads = 1;
1525        cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
1526        cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;
1527
1528        payload.address = address;
1529        payload.data = buffer;
1530        payload.length = length;
1531        payload.write = true;
1532        cmd.payloads = &payload;
1533
1534        if (dc_submit_i2c(pipe_ctx->stream->ctx->dc,
1535                        pipe_ctx->stream->sink->link->link_index, &cmd))
1536                return true;
1537
1538        return false;
1539}
1540
1541static void write_i2c_retimer_setting(
1542                struct pipe_ctx *pipe_ctx,
1543                bool is_vga_mode,
1544                bool is_over_340mhz,
1545                struct ext_hdmi_settings *settings)
1546{
1547        uint8_t slave_address = (settings->slv_addr >> 1);
1548        uint8_t buffer[2];
1549        const uint8_t apply_rx_tx_change = 0x4;
1550        uint8_t offset = 0xA;
1551        uint8_t value = 0;
1552        int i = 0;
1553        bool i2c_success = false;
1554
1555        memset(&buffer, 0, sizeof(buffer));
1556
1557        /* Start Ext-Hdmi programming*/
1558
1559        for (i = 0; i < settings->reg_num; i++) {
1560                /* Apply 3G settings */
1561                if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
1562
1563                        buffer[0] = settings->reg_settings[i].i2c_reg_index;
1564                        buffer[1] = settings->reg_settings[i].i2c_reg_val;
1565                        i2c_success = i2c_write(pipe_ctx, slave_address,
1566                                                buffer, sizeof(buffer));
1567
1568                        if (!i2c_success)
1569                                /* Write failure */
1570                                ASSERT(i2c_success);
1571
1572                        /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
1573                         * needs to be set to 1 on every 0xA-0xC write.
1574                         */
1575                        if (settings->reg_settings[i].i2c_reg_index == 0xA ||
1576                                settings->reg_settings[i].i2c_reg_index == 0xB ||
1577                                settings->reg_settings[i].i2c_reg_index == 0xC) {
1578
1579                                /* Query current value from offset 0xA */
1580                                if (settings->reg_settings[i].i2c_reg_index == 0xA)
1581                                        value = settings->reg_settings[i].i2c_reg_val;
1582                                else {
1583                                        i2c_success =
1584                                                dal_ddc_service_query_ddc_data(
1585                                                pipe_ctx->stream->sink->link->ddc,
1586                                                slave_address, &offset, 1, &value, 1);
1587                                        if (!i2c_success)
1588                                                /* Write failure */
1589                                                ASSERT(i2c_success);
1590                                }
1591
1592                                buffer[0] = offset;
1593                                /* Set APPLY_RX_TX_CHANGE bit to 1 */
1594                                buffer[1] = value | apply_rx_tx_change;
1595                                i2c_success = i2c_write(pipe_ctx, slave_address,
1596                                                buffer, sizeof(buffer));
1597                                if (!i2c_success)
1598                                        /* Write failure */
1599                                        ASSERT(i2c_success);
1600                        }
1601                }
1602        }
1603
1604        /* Apply 3G settings */
1605        if (is_over_340mhz) {
1606                for (i = 0; i < settings->reg_num_6g; i++) {
1607                        /* Apply 3G settings */
1608                        if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
1609
1610                                buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;
1611                                buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;
1612                                i2c_success = i2c_write(pipe_ctx, slave_address,
1613                                                        buffer, sizeof(buffer));
1614
1615                                if (!i2c_success)
1616                                        /* Write failure */
1617                                        ASSERT(i2c_success);
1618
1619                                /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
1620                                 * needs to be set to 1 on every 0xA-0xC write.
1621                                 */
1622                                if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||
1623                                        settings->reg_settings_6g[i].i2c_reg_index == 0xB ||
1624                                        settings->reg_settings_6g[i].i2c_reg_index == 0xC) {
1625
1626                                        /* Query current value from offset 0xA */
1627                                        if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)
1628                                                value = settings->reg_settings_6g[i].i2c_reg_val;
1629                                        else {
1630                                                i2c_success =
1631                                                                dal_ddc_service_query_ddc_data(
1632                                                                pipe_ctx->stream->sink->link->ddc,
1633                                                                slave_address, &offset, 1, &value, 1);
1634                                                if (!i2c_success)
1635                                                        /* Write failure */
1636                                                        ASSERT(i2c_success);
1637                                        }
1638
1639                                        buffer[0] = offset;
1640                                        /* Set APPLY_RX_TX_CHANGE bit to 1 */
1641                                        buffer[1] = value | apply_rx_tx_change;
1642                                        i2c_success = i2c_write(pipe_ctx, slave_address,
1643                                                        buffer, sizeof(buffer));
1644                                        if (!i2c_success)
1645                                                /* Write failure */
1646                                                ASSERT(i2c_success);
1647                                }
1648                        }
1649                }
1650        }
1651
1652        if (is_vga_mode) {
1653                /* Program additional settings if using 640x480 resolution */
1654
1655                /* Write offset 0xFF to 0x01 */
1656                buffer[0] = 0xff;
1657                buffer[1] = 0x01;
1658                i2c_success = i2c_write(pipe_ctx, slave_address,
1659                                buffer, sizeof(buffer));
1660                if (!i2c_success)
1661                        /* Write failure */
1662                        ASSERT(i2c_success);
1663
1664                /* Write offset 0x00 to 0x23 */
1665                buffer[0] = 0x00;
1666                buffer[1] = 0x23;
1667                i2c_success = i2c_write(pipe_ctx, slave_address,
1668                                buffer, sizeof(buffer));
1669                if (!i2c_success)
1670                        /* Write failure */
1671                        ASSERT(i2c_success);
1672
1673                /* Write offset 0xff to 0x00 */
1674                buffer[0] = 0xff;
1675                buffer[1] = 0x00;
1676                i2c_success = i2c_write(pipe_ctx, slave_address,
1677                                buffer, sizeof(buffer));
1678                if (!i2c_success)
1679                        /* Write failure */
1680                        ASSERT(i2c_success);
1681
1682        }
1683}
1684
1685static void write_i2c_default_retimer_setting(
1686                struct pipe_ctx *pipe_ctx,
1687                bool is_vga_mode,
1688                bool is_over_340mhz)
1689{
1690        uint8_t slave_address = (0xBA >> 1);
1691        uint8_t buffer[2];
1692        bool i2c_success = false;
1693
1694        memset(&buffer, 0, sizeof(buffer));
1695
1696        /* Program Slave Address for tuning single integrity */
1697        /* Write offset 0x0A to 0x13 */
1698        buffer[0] = 0x0A;
1699        buffer[1] = 0x13;
1700        i2c_success = i2c_write(pipe_ctx, slave_address,
1701                        buffer, sizeof(buffer));
1702        if (!i2c_success)
1703                /* Write failure */
1704                ASSERT(i2c_success);
1705
1706        /* Write offset 0x0A to 0x17 */
1707        buffer[0] = 0x0A;
1708        buffer[1] = 0x17;
1709        i2c_success = i2c_write(pipe_ctx, slave_address,
1710                        buffer, sizeof(buffer));
1711        if (!i2c_success)
1712                /* Write failure */
1713                ASSERT(i2c_success);
1714
1715        /* Write offset 0x0B to 0xDA or 0xD8 */
1716        buffer[0] = 0x0B;
1717        buffer[1] = is_over_340mhz ? 0xDA : 0xD8;
1718        i2c_success = i2c_write(pipe_ctx, slave_address,
1719                        buffer, sizeof(buffer));
1720        if (!i2c_success)
1721                /* Write failure */
1722                ASSERT(i2c_success);
1723
1724        /* Write offset 0x0A to 0x17 */
1725        buffer[0] = 0x0A;
1726        buffer[1] = 0x17;
1727        i2c_success = i2c_write(pipe_ctx, slave_address,
1728                        buffer, sizeof(buffer));
1729        if (!i2c_success)
1730                /* Write failure */
1731                ASSERT(i2c_success);
1732
1733        /* Write offset 0x0C to 0x1D or 0x91 */
1734        buffer[0] = 0x0C;
1735        buffer[1] = is_over_340mhz ? 0x1D : 0x91;
1736        i2c_success = i2c_write(pipe_ctx, slave_address,
1737                        buffer, sizeof(buffer));
1738        if (!i2c_success)
1739                /* Write failure */
1740                ASSERT(i2c_success);
1741
1742        /* Write offset 0x0A to 0x17 */
1743        buffer[0] = 0x0A;
1744        buffer[1] = 0x17;
1745        i2c_success = i2c_write(pipe_ctx, slave_address,
1746                        buffer, sizeof(buffer));
1747        if (!i2c_success)
1748                /* Write failure */
1749                ASSERT(i2c_success);
1750
1751
1752        if (is_vga_mode) {
1753                /* Program additional settings if using 640x480 resolution */
1754
1755                /* Write offset 0xFF to 0x01 */
1756                buffer[0] = 0xff;
1757                buffer[1] = 0x01;
1758                i2c_success = i2c_write(pipe_ctx, slave_address,
1759                                buffer, sizeof(buffer));
1760                if (!i2c_success)
1761                        /* Write failure */
1762                        ASSERT(i2c_success);
1763
1764                /* Write offset 0x00 to 0x23 */
1765                buffer[0] = 0x00;
1766                buffer[1] = 0x23;
1767                i2c_success = i2c_write(pipe_ctx, slave_address,
1768                                buffer, sizeof(buffer));
1769                if (!i2c_success)
1770                        /* Write failure */
1771                        ASSERT(i2c_success);
1772
1773                /* Write offset 0xff to 0x00 */
1774                buffer[0] = 0xff;
1775                buffer[1] = 0x00;
1776                i2c_success = i2c_write(pipe_ctx, slave_address,
1777                                buffer, sizeof(buffer));
1778                if (!i2c_success)
1779                        /* Write failure */
1780                        ASSERT(i2c_success);
1781        }
1782}
1783
1784static void write_i2c_redriver_setting(
1785                struct pipe_ctx *pipe_ctx,
1786                bool is_over_340mhz)
1787{
1788        uint8_t slave_address = (0xF0 >> 1);
1789        uint8_t buffer[16];
1790        bool i2c_success = false;
1791
1792        memset(&buffer, 0, sizeof(buffer));
1793
1794        // Program Slave Address for tuning single integrity
1795        buffer[3] = 0x4E;
1796        buffer[4] = 0x4E;
1797        buffer[5] = 0x4E;
1798        buffer[6] = is_over_340mhz ? 0x4E : 0x4A;
1799
1800        i2c_success = i2c_write(pipe_ctx, slave_address,
1801                                        buffer, sizeof(buffer));
1802
1803        if (!i2c_success)
1804                /* Write failure */
1805                ASSERT(i2c_success);
1806}
1807
1808static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
1809{
1810        struct dc_stream_state *stream = pipe_ctx->stream;
1811        struct dc_link *link = stream->sink->link;
1812        enum dc_color_depth display_color_depth;
1813        enum engine_id eng_id;
1814        struct ext_hdmi_settings settings = {0};
1815        bool is_over_340mhz = false;
1816        bool is_vga_mode = (stream->timing.h_addressable == 640)
1817                        && (stream->timing.v_addressable == 480);
1818
1819        if (stream->phy_pix_clk == 0)
1820                stream->phy_pix_clk = stream->timing.pix_clk_khz;
1821        if (stream->phy_pix_clk > 340000)
1822                is_over_340mhz = true;
1823
1824        if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
1825                unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps &
1826                                EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
1827                if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
1828                        /* DP159, Retimer settings */
1829                        eng_id = pipe_ctx->stream_res.stream_enc->id;
1830
1831                        if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {
1832                                write_i2c_retimer_setting(pipe_ctx,
1833                                                is_vga_mode, is_over_340mhz, &settings);
1834                        } else {
1835                                write_i2c_default_retimer_setting(pipe_ctx,
1836                                                is_vga_mode, is_over_340mhz);
1837                        }
1838                } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
1839                        /* PI3EQX1204, Redriver settings */
1840                        write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);
1841                }
1842        }
1843
1844        if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1845                dal_ddc_service_write_scdc_data(
1846                        stream->sink->link->ddc,
1847                        stream->phy_pix_clk,
1848                        stream->timing.flags.LTE_340MCSC_SCRAMBLE);
1849
1850        memset(&stream->sink->link->cur_link_settings, 0,
1851                        sizeof(struct dc_link_settings));
1852
1853        display_color_depth = stream->timing.display_color_depth;
1854        if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
1855                display_color_depth = COLOR_DEPTH_888;
1856
1857        link->link_enc->funcs->enable_tmds_output(
1858                        link->link_enc,
1859                        pipe_ctx->clock_source->id,
1860                        display_color_depth,
1861                        pipe_ctx->stream->signal,
1862                        stream->phy_pix_clk);
1863
1864        if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
1865                dal_ddc_service_read_scdc_data(link->ddc);
1866}
1867
1868/****************************enable_link***********************************/
1869static enum dc_status enable_link(
1870                struct dc_state *state,
1871                struct pipe_ctx *pipe_ctx)
1872{
1873        enum dc_status status = DC_ERROR_UNEXPECTED;
1874        switch (pipe_ctx->stream->signal) {
1875        case SIGNAL_TYPE_DISPLAY_PORT:
1876                status = enable_link_dp(state, pipe_ctx);
1877                break;
1878        case SIGNAL_TYPE_EDP:
1879                status = enable_link_edp(state, pipe_ctx);
1880                break;
1881        case SIGNAL_TYPE_DISPLAY_PORT_MST:
1882                status = enable_link_dp_mst(state, pipe_ctx);
1883                msleep(200);
1884                break;
1885        case SIGNAL_TYPE_DVI_SINGLE_LINK:
1886        case SIGNAL_TYPE_DVI_DUAL_LINK:
1887        case SIGNAL_TYPE_HDMI_TYPE_A:
1888                enable_link_hdmi(pipe_ctx);
1889                status = DC_OK;
1890                break;
1891        case SIGNAL_TYPE_VIRTUAL:
1892                status = DC_OK;
1893                break;
1894        default:
1895                break;
1896        }
1897
1898        return status;
1899}
1900
1901static void disable_link(struct dc_link *link, enum signal_type signal)
1902{
1903        /*
1904         * TODO: implement call for dp_set_hw_test_pattern
1905         * it is needed for compliance testing
1906         */
1907
1908        /* here we need to specify that encoder output settings
1909         * need to be calculated as for the set mode,
1910         * it will lead to querying dynamic link capabilities
1911         * which should be done before enable output */
1912
1913        if (dc_is_dp_signal(signal)) {
1914                /* SST DP, eDP */
1915                if (dc_is_dp_sst_signal(signal))
1916                        dp_disable_link_phy(link, signal);
1917                else
1918                        dp_disable_link_phy_mst(link, signal);
1919        } else
1920                link->link_enc->funcs->disable_output(link->link_enc, signal);
1921}
1922
1923static bool dp_active_dongle_validate_timing(
1924                const struct dc_crtc_timing *timing,
1925                const struct dpcd_caps *dpcd_caps)
1926{
1927        unsigned int required_pix_clk = timing->pix_clk_khz;
1928        const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
1929
1930        switch (dpcd_caps->dongle_type) {
1931        case DISPLAY_DONGLE_DP_VGA_CONVERTER:
1932        case DISPLAY_DONGLE_DP_DVI_CONVERTER:
1933        case DISPLAY_DONGLE_DP_DVI_DONGLE:
1934                if (timing->pixel_encoding == PIXEL_ENCODING_RGB)
1935                        return true;
1936                else
1937                        return false;
1938        default:
1939                break;
1940        }
1941
1942        if (dongle_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
1943                dongle_caps->extendedCapValid == false)
1944                return true;
1945
1946        /* Check Pixel Encoding */
1947        switch (timing->pixel_encoding) {
1948        case PIXEL_ENCODING_RGB:
1949        case PIXEL_ENCODING_YCBCR444:
1950                break;
1951        case PIXEL_ENCODING_YCBCR422:
1952                if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through)
1953                        return false;
1954                break;
1955        case PIXEL_ENCODING_YCBCR420:
1956                if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through)
1957                        return false;
1958                break;
1959        default:
1960                /* Invalid Pixel Encoding*/
1961                return false;
1962        }
1963
1964
1965        /* Check Color Depth and Pixel Clock */
1966        if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1967                required_pix_clk /= 2;
1968        else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
1969                required_pix_clk = required_pix_clk * 2 / 3;
1970
1971        switch (timing->display_color_depth) {
1972        case COLOR_DEPTH_666:
1973        case COLOR_DEPTH_888:
1974                /*888 and 666 should always be supported*/
1975                break;
1976        case COLOR_DEPTH_101010:
1977                if (dongle_caps->dp_hdmi_max_bpc < 10)
1978                        return false;
1979                required_pix_clk = required_pix_clk * 10 / 8;
1980                break;
1981        case COLOR_DEPTH_121212:
1982                if (dongle_caps->dp_hdmi_max_bpc < 12)
1983                        return false;
1984                required_pix_clk = required_pix_clk * 12 / 8;
1985                break;
1986
1987        case COLOR_DEPTH_141414:
1988        case COLOR_DEPTH_161616:
1989        default:
1990                /* These color depths are currently not supported */
1991                return false;
1992        }
1993
1994        if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk)
1995                return false;
1996
1997        return true;
1998}
1999
2000enum dc_status dc_link_validate_mode_timing(
2001                const struct dc_stream_state *stream,
2002                struct dc_link *link,
2003                const struct dc_crtc_timing *timing)
2004{
2005        uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
2006        struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
2007
2008        /* A hack to avoid failing any modes for EDID override feature on
2009         * topology change such as lower quality cable for DP or different dongle
2010         */
2011        if (link->remote_sinks[0])
2012                return DC_OK;
2013
2014        /* Passive Dongle */
2015        if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
2016                return DC_EXCEED_DONGLE_CAP;
2017
2018        /* Active Dongle*/
2019        if (!dp_active_dongle_validate_timing(timing, dpcd_caps))
2020                return DC_EXCEED_DONGLE_CAP;
2021
2022        switch (stream->signal) {
2023        case SIGNAL_TYPE_EDP:
2024        case SIGNAL_TYPE_DISPLAY_PORT:
2025                if (!dp_validate_mode_timing(
2026                                link,
2027                                timing))
2028                        return DC_NO_DP_LINK_BANDWIDTH;
2029                break;
2030
2031        default:
2032                break;
2033        }
2034
2035        return DC_OK;
2036}
2037
2038int dc_link_get_backlight_level(const struct dc_link *link)
2039{
2040        struct abm *abm = link->ctx->dc->res_pool->abm;
2041
2042        if (abm == NULL || abm->funcs->get_current_backlight_8_bit == NULL)
2043                return DC_ERROR_UNEXPECTED;
2044
2045        return (int) abm->funcs->get_current_backlight_8_bit(abm);
2046}
2047
2048bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
2049                uint32_t frame_ramp, const struct dc_stream_state *stream)
2050{
2051        struct dc  *core_dc = link->ctx->dc;
2052        struct abm *abm = core_dc->res_pool->abm;
2053        struct dmcu *dmcu = core_dc->res_pool->dmcu;
2054        unsigned int controller_id = 0;
2055        bool use_smooth_brightness = true;
2056        int i;
2057        DC_LOGGER_INIT(link->ctx->logger);
2058
2059        if ((dmcu == NULL) ||
2060                (abm == NULL) ||
2061                (abm->funcs->set_backlight_level == NULL))
2062                return false;
2063
2064        if (stream) {
2065                if (stream->bl_pwm_level == EDP_BACKLIGHT_RAMP_DISABLE_LEVEL)
2066                        frame_ramp = 0;
2067
2068                ((struct dc_stream_state *)stream)->bl_pwm_level = level;
2069        }
2070
2071        use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
2072
2073        DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", level, level);
2074
2075        if (dc_is_embedded_signal(link->connector_signal)) {
2076                if (stream != NULL) {
2077                        for (i = 0; i < MAX_PIPES; i++) {
2078                                if (core_dc->current_state->res_ctx.
2079                                                pipe_ctx[i].stream
2080                                                == stream)
2081                                        /* DMCU -1 for all controller id values,
2082                                         * therefore +1 here
2083                                         */
2084                                        controller_id =
2085                                                core_dc->current_state->
2086                                                res_ctx.pipe_ctx[i].stream_res.tg->inst +
2087                                                1;
2088                        }
2089                }
2090                abm->funcs->set_backlight_level(
2091                                abm,
2092                                level,
2093                                frame_ramp,
2094                                controller_id,
2095                                use_smooth_brightness);
2096        }
2097
2098        return true;
2099}
2100
2101bool dc_link_set_abm_disable(const struct dc_link *link)
2102{
2103        struct dc  *core_dc = link->ctx->dc;
2104        struct abm *abm = core_dc->res_pool->abm;
2105
2106        if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL))
2107                return false;
2108
2109        abm->funcs->set_abm_immediate_disable(abm);
2110
2111        return true;
2112}
2113
2114bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait)
2115{
2116        struct dc  *core_dc = link->ctx->dc;
2117        struct dmcu *dmcu = core_dc->res_pool->dmcu;
2118
2119        if (dmcu != NULL && link->psr_enabled)
2120                dmcu->funcs->set_psr_enable(dmcu, enable, wait);
2121
2122        return true;
2123}
2124
2125const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
2126{
2127        return &link->link_status;
2128}
2129
2130void core_link_resume(struct dc_link *link)
2131{
2132        if (link->connector_signal != SIGNAL_TYPE_VIRTUAL)
2133                program_hpd_filter(link);
2134}
2135
2136static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
2137{
2138        struct dc_link_settings *link_settings =
2139                        &stream->sink->link->cur_link_settings;
2140        uint32_t link_rate_in_mbps =
2141                        link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
2142        struct fixed31_32 mbps = dc_fixpt_from_int(
2143                        link_rate_in_mbps * link_settings->lane_count);
2144
2145        return dc_fixpt_div_int(mbps, 54);
2146}
2147
2148static int get_color_depth(enum dc_color_depth color_depth)
2149{
2150        switch (color_depth) {
2151        case COLOR_DEPTH_666: return 6;
2152        case COLOR_DEPTH_888: return 8;
2153        case COLOR_DEPTH_101010: return 10;
2154        case COLOR_DEPTH_121212: return 12;
2155        case COLOR_DEPTH_141414: return 14;
2156        case COLOR_DEPTH_161616: return 16;
2157        default: return 0;
2158        }
2159}
2160
2161static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
2162{
2163        uint32_t bpc;
2164        uint64_t kbps;
2165        struct fixed31_32 peak_kbps;
2166        uint32_t numerator;
2167        uint32_t denominator;
2168
2169        bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
2170        kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3;
2171
2172        /*
2173         * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
2174         * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
2175         * common multiplier to render an integer PBN for all link rate/lane
2176         * counts combinations
2177         * calculate
2178         * peak_kbps *= (1006/1000)
2179         * peak_kbps *= (64/54)
2180         * peak_kbps *= 8    convert to bytes
2181         */
2182
2183        numerator = 64 * PEAK_FACTOR_X1000;
2184        denominator = 54 * 8 * 1000 * 1000;
2185        kbps *= numerator;
2186        peak_kbps = dc_fixpt_from_fraction(kbps, denominator);
2187
2188        return peak_kbps;
2189}
2190
2191static void update_mst_stream_alloc_table(
2192        struct dc_link *link,
2193        struct stream_encoder *stream_enc,
2194        const struct dp_mst_stream_allocation_table *proposed_table)
2195{
2196        struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
2197                        { 0 } };
2198        struct link_mst_stream_allocation *dc_alloc;
2199
2200        int i;
2201        int j;
2202
2203        /* if DRM proposed_table has more than one new payload */
2204        ASSERT(proposed_table->stream_count -
2205                        link->mst_stream_alloc_table.stream_count < 2);
2206
2207        /* copy proposed_table to link, add stream encoder */
2208        for (i = 0; i < proposed_table->stream_count; i++) {
2209
2210                for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
2211                        dc_alloc =
2212                        &link->mst_stream_alloc_table.stream_allocations[j];
2213
2214                        if (dc_alloc->vcp_id ==
2215                                proposed_table->stream_allocations[i].vcp_id) {
2216
2217                                work_table[i] = *dc_alloc;
2218                                break; /* exit j loop */
2219                        }
2220                }
2221
2222                /* new vcp_id */
2223                if (j == link->mst_stream_alloc_table.stream_count) {
2224                        work_table[i].vcp_id =
2225                                proposed_table->stream_allocations[i].vcp_id;
2226                        work_table[i].slot_count =
2227                                proposed_table->stream_allocations[i].slot_count;
2228                        work_table[i].stream_enc = stream_enc;
2229                }
2230        }
2231
2232        /* update link->mst_stream_alloc_table with work_table */
2233        link->mst_stream_alloc_table.stream_count =
2234                        proposed_table->stream_count;
2235        for (i = 0; i < MAX_CONTROLLER_NUM; i++)
2236                link->mst_stream_alloc_table.stream_allocations[i] =
2237                                work_table[i];
2238}
2239
2240/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
2241 * because stream_encoder is not exposed to dm
2242 */
2243static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
2244{
2245        struct dc_stream_state *stream = pipe_ctx->stream;
2246        struct dc_link *link = stream->sink->link;
2247        struct link_encoder *link_encoder = link->link_enc;
2248        struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
2249        struct dp_mst_stream_allocation_table proposed_table = {0};
2250        struct fixed31_32 avg_time_slots_per_mtp;
2251        struct fixed31_32 pbn;
2252        struct fixed31_32 pbn_per_slot;
2253        uint8_t i;
2254        DC_LOGGER_INIT(link->ctx->logger);
2255
2256        /* enable_link_dp_mst already check link->enabled_stream_count
2257         * and stream is in link->stream[]. This is called during set mode,
2258         * stream_enc is available.
2259         */
2260
2261        /* get calculate VC payload for stream: stream_alloc */
2262        if (dm_helpers_dp_mst_write_payload_allocation_table(
2263                stream->ctx,
2264                stream,
2265                &proposed_table,
2266                true)) {
2267                update_mst_stream_alloc_table(
2268                                        link, pipe_ctx->stream_res.stream_enc, &proposed_table);
2269        }
2270        else
2271                DC_LOG_WARNING("Failed to update"
2272                                "MST allocation table for"
2273                                "pipe idx:%d\n",
2274                                pipe_ctx->pipe_idx);
2275
2276        DC_LOG_MST("%s  "
2277                        "stream_count: %d: \n ",
2278                        __func__,
2279                        link->mst_stream_alloc_table.stream_count);
2280
2281        for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
2282                DC_LOG_MST("stream_enc[%d]: %p      "
2283                "stream[%d].vcp_id: %d      "
2284                "stream[%d].slot_count: %d\n",
2285                i,
2286                (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
2287                i,
2288                link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
2289                i,
2290                link->mst_stream_alloc_table.stream_allocations[i].slot_count);
2291        }
2292
2293        ASSERT(proposed_table.stream_count > 0);
2294
2295        /* program DP source TX for payload */
2296        link_encoder->funcs->update_mst_stream_allocation_table(
2297                link_encoder,
2298                &link->mst_stream_alloc_table);
2299
2300        /* send down message */
2301        dm_helpers_dp_mst_poll_for_allocation_change_trigger(
2302                        stream->ctx,
2303                        stream);
2304
2305        dm_helpers_dp_mst_send_payload_allocation(
2306                        stream->ctx,
2307                        stream,
2308                        true);
2309
2310        /* slot X.Y for only current stream */
2311        pbn_per_slot = get_pbn_per_slot(stream);
2312        pbn = get_pbn_from_timing(pipe_ctx);
2313        avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
2314
2315        stream_encoder->funcs->set_mst_bandwidth(
2316                stream_encoder,
2317                avg_time_slots_per_mtp);
2318
2319        return DC_OK;
2320
2321}
2322
2323static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
2324{
2325        struct dc_stream_state *stream = pipe_ctx->stream;
2326        struct dc_link *link = stream->sink->link;
2327        struct link_encoder *link_encoder = link->link_enc;
2328        struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
2329        struct dp_mst_stream_allocation_table proposed_table = {0};
2330        struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
2331        uint8_t i;
2332        bool mst_mode = (link->type == dc_connection_mst_branch);
2333        DC_LOGGER_INIT(link->ctx->logger);
2334
2335        /* deallocate_mst_payload is called before disable link. When mode or
2336         * disable/enable monitor, new stream is created which is not in link
2337         * stream[] yet. For this, payload is not allocated yet, so de-alloc
2338         * should not done. For new mode set, map_resources will get engine
2339         * for new stream, so stream_enc->id should be validated until here.
2340         */
2341
2342        /* slot X.Y */
2343        stream_encoder->funcs->set_mst_bandwidth(
2344                stream_encoder,
2345                avg_time_slots_per_mtp);
2346
2347        /* TODO: which component is responsible for remove payload table? */
2348        if (mst_mode) {
2349                if (dm_helpers_dp_mst_write_payload_allocation_table(
2350                                stream->ctx,
2351                                stream,
2352                                &proposed_table,
2353                                false)) {
2354
2355                        update_mst_stream_alloc_table(
2356                                link, pipe_ctx->stream_res.stream_enc, &proposed_table);
2357                }
2358                else {
2359                                DC_LOG_WARNING("Failed to update"
2360                                                "MST allocation table for"
2361                                                "pipe idx:%d\n",
2362                                                pipe_ctx->pipe_idx);
2363                }
2364        }
2365
2366        DC_LOG_MST("%s"
2367                        "stream_count: %d: ",
2368                        __func__,
2369                        link->mst_stream_alloc_table.stream_count);
2370
2371        for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
2372                DC_LOG_MST("stream_enc[%d]: %p      "
2373                "stream[%d].vcp_id: %d      "
2374                "stream[%d].slot_count: %d\n",
2375                i,
2376                (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
2377                i,
2378                link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
2379                i,
2380                link->mst_stream_alloc_table.stream_allocations[i].slot_count);
2381        }
2382
2383        link_encoder->funcs->update_mst_stream_allocation_table(
2384                link_encoder,
2385                &link->mst_stream_alloc_table);
2386
2387        if (mst_mode) {
2388                dm_helpers_dp_mst_poll_for_allocation_change_trigger(
2389                        stream->ctx,
2390                        stream);
2391
2392                dm_helpers_dp_mst_send_payload_allocation(
2393                        stream->ctx,
2394                        stream,
2395                        false);
2396        }
2397
2398        return DC_OK;
2399}
2400
2401void core_link_enable_stream(
2402                struct dc_state *state,
2403                struct pipe_ctx *pipe_ctx)
2404{
2405        struct dc  *core_dc = pipe_ctx->stream->ctx->dc;
2406        enum dc_status status;
2407        DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
2408
2409        /* eDP lit up by bios already, no need to enable again. */
2410        if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
2411                core_dc->apply_edp_fast_boot_optimization) {
2412                core_dc->apply_edp_fast_boot_optimization = false;
2413                pipe_ctx->stream->dpms_off = false;
2414                return;
2415        }
2416
2417        if (pipe_ctx->stream->dpms_off)
2418                return;
2419
2420        status = enable_link(state, pipe_ctx);
2421
2422        if (status != DC_OK) {
2423                        DC_LOG_WARNING("enabling link %u failed: %d\n",
2424                        pipe_ctx->stream->sink->link->link_index,
2425                        status);
2426
2427                        /* Abort stream enable *unless* the failure was due to
2428                         * DP link training - some DP monitors will recover and
2429                         * show the stream anyway. But MST displays can't proceed
2430                         * without link training.
2431                         */
2432                        if (status != DC_FAIL_DP_LINK_TRAINING ||
2433                                        pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
2434                                BREAK_TO_DEBUGGER();
2435                                return;
2436                        }
2437        }
2438
2439        core_dc->hwss.enable_audio_stream(pipe_ctx);
2440
2441        /* turn off otg test pattern if enable */
2442        if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
2443                pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
2444                                CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
2445                                COLOR_DEPTH_UNDEFINED);
2446
2447        core_dc->hwss.enable_stream(pipe_ctx);
2448
2449        if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
2450                allocate_mst_payload(pipe_ctx);
2451
2452        core_dc->hwss.unblank_stream(pipe_ctx,
2453                &pipe_ctx->stream->sink->link->cur_link_settings);
2454}
2455
2456void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
2457{
2458        struct dc  *core_dc = pipe_ctx->stream->ctx->dc;
2459
2460        if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
2461                deallocate_mst_payload(pipe_ctx);
2462
2463        core_dc->hwss.blank_stream(pipe_ctx);
2464
2465        core_dc->hwss.disable_stream(pipe_ctx, option);
2466
2467        disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
2468}
2469
2470void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
2471{
2472        struct dc  *core_dc = pipe_ctx->stream->ctx->dc;
2473
2474        if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
2475                return;
2476
2477        core_dc->hwss.set_avmute(pipe_ctx, enable);
2478}
2479
2480/**
2481 *****************************************************************************
2482 *  Function: dc_link_enable_hpd_filter
2483 *
2484 *  @brief
2485 *     If enable is true, programs HPD filter on associated HPD line using
2486 *     delay_on_disconnect/delay_on_connect values dependent on
2487 *     link->connector_signal
2488 *
2489 *     If enable is false, programs HPD filter on associated HPD line with no
2490 *     delays on connect or disconnect
2491 *
2492 *  @param [in] link: pointer to the dc link
2493 *  @param [in] enable: boolean specifying whether to enable hbd
2494 *****************************************************************************
2495 */
2496void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
2497{
2498        struct gpio *hpd;
2499
2500        if (enable) {
2501                link->is_hpd_filter_disabled = false;
2502                program_hpd_filter(link);
2503        } else {
2504                link->is_hpd_filter_disabled = true;
2505                /* Obtain HPD handle */
2506                hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
2507
2508                if (!hpd)
2509                        return;
2510
2511                /* Setup HPD filtering */
2512                if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
2513                        struct gpio_hpd_config config;
2514
2515                        config.delay_on_connect = 0;
2516                        config.delay_on_disconnect = 0;
2517
2518                        dal_irq_setup_hpd_filter(hpd, &config);
2519
2520                        dal_gpio_close(hpd);
2521                } else {
2522                        ASSERT_CRITICAL(false);
2523                }
2524                /* Release HPD handle */
2525                dal_gpio_destroy_irq(&hpd);
2526        }
2527}
2528
2529