linux/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include <linux/slab.h>
  27
  28#include "dm_services.h"
  29#include "dm_helpers.h"
  30#include "gpio_service_interface.h"
  31#include "include/ddc_service_types.h"
  32#include "include/grph_object_id.h"
  33#include "include/dpcd_defs.h"
  34#include "include/logger_interface.h"
  35#include "include/vector.h"
  36#include "core_types.h"
  37#include "dc_link_ddc.h"
  38#include "dce/dce_aux.h"
  39#include "dmub/inc/dmub_cmd.h"
  40
  41#define DC_LOGGER_INIT(logger)
  42
  43static const uint8_t DP_VGA_DONGLE_BRANCH_DEV_NAME[] = "DpVga";
  44/* DP to Dual link DVI converter */
  45static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
  46static const uint8_t DP_DVI_CONVERTER_ID_5[] = "3393N2";
  47
  48#define AUX_POWER_UP_WA_DELAY 500
  49#define I2C_OVER_AUX_DEFER_WA_DELAY 70
  50#define DPVGA_DONGLE_AUX_DEFER_WA_DELAY 40
  51#define I2C_OVER_AUX_DEFER_WA_DELAY_1MS 1
  52
  53/* CV smart dongle slave address for retrieving supported HDTV modes*/
  54#define CV_SMART_DONGLE_ADDRESS 0x20
  55/* DVI-HDMI dongle slave address for retrieving dongle signature*/
  56#define DVI_HDMI_DONGLE_ADDRESS 0x68
  57struct dvi_hdmi_dongle_signature_data {
  58        int8_t vendor[3];/* "AMD" */
  59        uint8_t version[2];
  60        uint8_t size;
  61        int8_t id[11];/* "6140063500G"*/
  62};
  63/* DP-HDMI dongle slave address for retrieving dongle signature*/
  64#define DP_HDMI_DONGLE_ADDRESS 0x40
  65static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
  66#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
  67
  68struct dp_hdmi_dongle_signature_data {
  69        int8_t id[15];/* "DP-HDMI ADAPTOR"*/
  70        uint8_t eot;/* end of transmition '\x4' */
  71};
  72
  73/* SCDC Address defines (HDMI 2.0)*/
  74#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
  75#define HDMI_SCDC_ADDRESS  0x54
  76#define HDMI_SCDC_SINK_VERSION 0x01
  77#define HDMI_SCDC_SOURCE_VERSION 0x02
  78#define HDMI_SCDC_UPDATE_0 0x10
  79#define HDMI_SCDC_TMDS_CONFIG 0x20
  80#define HDMI_SCDC_SCRAMBLER_STATUS 0x21
  81#define HDMI_SCDC_CONFIG_0 0x30
  82#define HDMI_SCDC_STATUS_FLAGS 0x40
  83#define HDMI_SCDC_ERR_DETECT 0x50
  84#define HDMI_SCDC_TEST_CONFIG 0xC0
  85
  86union hdmi_scdc_update_read_data {
  87        uint8_t byte[2];
  88        struct {
  89                uint8_t STATUS_UPDATE:1;
  90                uint8_t CED_UPDATE:1;
  91                uint8_t RR_TEST:1;
  92                uint8_t RESERVED:5;
  93                uint8_t RESERVED2:8;
  94        } fields;
  95};
  96
  97union hdmi_scdc_status_flags_data {
  98        uint8_t byte[2];
  99        struct {
 100                uint8_t CLOCK_DETECTED:1;
 101                uint8_t CH0_LOCKED:1;
 102                uint8_t CH1_LOCKED:1;
 103                uint8_t CH2_LOCKED:1;
 104                uint8_t RESERVED:4;
 105                uint8_t RESERVED2:8;
 106                uint8_t RESERVED3:8;
 107
 108        } fields;
 109};
 110
 111union hdmi_scdc_ced_data {
 112        uint8_t byte[7];
 113        struct {
 114                uint8_t CH0_8LOW:8;
 115                uint8_t CH0_7HIGH:7;
 116                uint8_t CH0_VALID:1;
 117                uint8_t CH1_8LOW:8;
 118                uint8_t CH1_7HIGH:7;
 119                uint8_t CH1_VALID:1;
 120                uint8_t CH2_8LOW:8;
 121                uint8_t CH2_7HIGH:7;
 122                uint8_t CH2_VALID:1;
 123                uint8_t CHECKSUM:8;
 124                uint8_t RESERVED:8;
 125                uint8_t RESERVED2:8;
 126                uint8_t RESERVED3:8;
 127                uint8_t RESERVED4:4;
 128        } fields;
 129};
 130
 131struct i2c_payloads {
 132        struct vector payloads;
 133};
 134
 135struct aux_payloads {
 136        struct vector payloads;
 137};
 138
 139static bool dal_ddc_i2c_payloads_create(
 140                struct dc_context *ctx,
 141                struct i2c_payloads *payloads,
 142                uint32_t count)
 143{
 144        if (dal_vector_construct(
 145                &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
 146                return true;
 147
 148        return false;
 149}
 150
 151static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
 152{
 153        return (struct i2c_payload *)p->payloads.container;
 154}
 155
 156static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
 157{
 158        return p->payloads.count;
 159}
 160
 161#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 162
 163void dal_ddc_i2c_payloads_add(
 164        struct i2c_payloads *payloads,
 165        uint32_t address,
 166        uint32_t len,
 167        uint8_t *data,
 168        bool write)
 169{
 170        uint32_t payload_size = EDID_SEGMENT_SIZE;
 171        uint32_t pos;
 172
 173        for (pos = 0; pos < len; pos += payload_size) {
 174                struct i2c_payload payload = {
 175                        .write = write,
 176                        .address = address,
 177                        .length = DDC_MIN(payload_size, len - pos),
 178                        .data = data + pos };
 179                dal_vector_append(&payloads->payloads, &payload);
 180        }
 181
 182}
 183
 184static void ddc_service_construct(
 185        struct ddc_service *ddc_service,
 186        struct ddc_service_init_data *init_data)
 187{
 188        enum connector_id connector_id =
 189                dal_graphics_object_id_get_connector_id(init_data->id);
 190
 191        struct gpio_service *gpio_service = init_data->ctx->gpio_service;
 192        struct graphics_object_i2c_info i2c_info;
 193        struct gpio_ddc_hw_info hw_info;
 194        struct dc_bios *dcb = init_data->ctx->dc_bios;
 195
 196        ddc_service->link = init_data->link;
 197        ddc_service->ctx = init_data->ctx;
 198
 199        if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
 200                ddc_service->ddc_pin = NULL;
 201        } else {
 202                DC_LOGGER_INIT(ddc_service->ctx->logger);
 203                DC_LOG_DC("BIOS object table - i2c_line: %d", i2c_info.i2c_line);
 204                DC_LOG_DC("BIOS object table - i2c_engine_id: %d", i2c_info.i2c_engine_id);
 205
 206                hw_info.ddc_channel = i2c_info.i2c_line;
 207                if (ddc_service->link != NULL)
 208                        hw_info.hw_supported = i2c_info.i2c_hw_assist;
 209                else
 210                        hw_info.hw_supported = false;
 211
 212                ddc_service->ddc_pin = dal_gpio_create_ddc(
 213                        gpio_service,
 214                        i2c_info.gpio_info.clk_a_register_index,
 215                        1 << i2c_info.gpio_info.clk_a_shift,
 216                        &hw_info);
 217        }
 218
 219        ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
 220        ddc_service->flags.FORCE_READ_REPEATED_START = false;
 221        ddc_service->flags.EDID_STRESS_READ = false;
 222
 223        ddc_service->flags.IS_INTERNAL_DISPLAY =
 224                connector_id == CONNECTOR_ID_EDP ||
 225                connector_id == CONNECTOR_ID_LVDS;
 226
 227        ddc_service->wa.raw = 0;
 228}
 229
 230struct ddc_service *dal_ddc_service_create(
 231        struct ddc_service_init_data *init_data)
 232{
 233        struct ddc_service *ddc_service;
 234
 235        ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL);
 236
 237        if (!ddc_service)
 238                return NULL;
 239
 240        ddc_service_construct(ddc_service, init_data);
 241        return ddc_service;
 242}
 243
 244static void ddc_service_destruct(struct ddc_service *ddc)
 245{
 246        if (ddc->ddc_pin)
 247                dal_gpio_destroy_ddc(&ddc->ddc_pin);
 248}
 249
 250void dal_ddc_service_destroy(struct ddc_service **ddc)
 251{
 252        if (!ddc || !*ddc) {
 253                BREAK_TO_DEBUGGER();
 254                return;
 255        }
 256        ddc_service_destruct(*ddc);
 257        kfree(*ddc);
 258        *ddc = NULL;
 259}
 260
 261enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
 262{
 263        return DDC_SERVICE_TYPE_CONNECTOR;
 264}
 265
 266void dal_ddc_service_set_transaction_type(
 267        struct ddc_service *ddc,
 268        enum ddc_transaction_type type)
 269{
 270        ddc->transaction_type = type;
 271}
 272
 273bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
 274{
 275        switch (ddc->transaction_type) {
 276        case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
 277        case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
 278        case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
 279                return true;
 280        default:
 281                break;
 282        }
 283        return false;
 284}
 285
 286void ddc_service_set_dongle_type(struct ddc_service *ddc,
 287                enum display_dongle_type dongle_type)
 288{
 289        ddc->dongle_type = dongle_type;
 290}
 291
 292static uint32_t defer_delay_converter_wa(
 293        struct ddc_service *ddc,
 294        uint32_t defer_delay)
 295{
 296        struct dc_link *link = ddc->link;
 297
 298        if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER &&
 299                link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
 300                !memcmp(link->dpcd_caps.branch_dev_name,
 301                    DP_VGA_DONGLE_BRANCH_DEV_NAME,
 302                        sizeof(link->dpcd_caps.branch_dev_name)))
 303
 304                return defer_delay > DPVGA_DONGLE_AUX_DEFER_WA_DELAY ?
 305                        defer_delay : DPVGA_DONGLE_AUX_DEFER_WA_DELAY;
 306
 307        if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
 308            !memcmp(link->dpcd_caps.branch_dev_name,
 309                    DP_DVI_CONVERTER_ID_4,
 310                    sizeof(link->dpcd_caps.branch_dev_name)))
 311                return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
 312                        defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
 313        if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_006037 &&
 314            !memcmp(link->dpcd_caps.branch_dev_name,
 315                    DP_DVI_CONVERTER_ID_5,
 316                    sizeof(link->dpcd_caps.branch_dev_name)))
 317                return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY_1MS ?
 318                        I2C_OVER_AUX_DEFER_WA_DELAY_1MS : defer_delay;
 319
 320        return defer_delay;
 321}
 322
 323#define DP_TRANSLATOR_DELAY 5
 324
 325uint32_t get_defer_delay(struct ddc_service *ddc)
 326{
 327        uint32_t defer_delay = 0;
 328
 329        switch (ddc->transaction_type) {
 330        case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
 331                if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
 332                        (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
 333                        (DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
 334                                ddc->dongle_type)) {
 335
 336                        defer_delay = DP_TRANSLATOR_DELAY;
 337
 338                        defer_delay =
 339                                defer_delay_converter_wa(ddc, defer_delay);
 340
 341                } else /*sink has a delay different from an Active Converter*/
 342                        defer_delay = 0;
 343                break;
 344        case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
 345                defer_delay = DP_TRANSLATOR_DELAY;
 346                break;
 347        default:
 348                break;
 349        }
 350        return defer_delay;
 351}
 352
 353static bool i2c_read(
 354        struct ddc_service *ddc,
 355        uint32_t address,
 356        uint8_t *buffer,
 357        uint32_t len)
 358{
 359        uint8_t offs_data = 0;
 360        struct i2c_payload payloads[2] = {
 361                {
 362                .write = true,
 363                .address = address,
 364                .length = 1,
 365                .data = &offs_data },
 366                {
 367                .write = false,
 368                .address = address,
 369                .length = len,
 370                .data = buffer } };
 371
 372        struct i2c_command command = {
 373                .payloads = payloads,
 374                .number_of_payloads = 2,
 375                .engine = DDC_I2C_COMMAND_ENGINE,
 376                .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
 377
 378        return dm_helpers_submit_i2c(
 379                        ddc->ctx,
 380                        ddc->link,
 381                        &command);
 382}
 383
 384void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
 385        struct ddc_service *ddc,
 386        struct display_sink_capability *sink_cap)
 387{
 388        uint8_t i;
 389        bool is_valid_hdmi_signature;
 390        enum display_dongle_type *dongle = &sink_cap->dongle_type;
 391        uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
 392        bool is_type2_dongle = false;
 393        int retry_count = 2;
 394        struct dp_hdmi_dongle_signature_data *dongle_signature;
 395
 396        /* Assume we have no valid DP passive dongle connected */
 397        *dongle = DISPLAY_DONGLE_NONE;
 398        sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
 399
 400        /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
 401        if (!i2c_read(
 402                ddc,
 403                DP_HDMI_DONGLE_ADDRESS,
 404                type2_dongle_buf,
 405                sizeof(type2_dongle_buf))) {
 406                /* Passive HDMI dongles can sometimes fail here without retrying*/
 407                while (retry_count > 0) {
 408                        if (i2c_read(ddc,
 409                                DP_HDMI_DONGLE_ADDRESS,
 410                                type2_dongle_buf,
 411                                sizeof(type2_dongle_buf)))
 412                                break;
 413                        retry_count--;
 414                }
 415                if (retry_count == 0) {
 416                        *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
 417                        sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
 418
 419                        CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
 420                                        "DP-DVI passive dongle %dMhz: ",
 421                                        DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
 422                        return;
 423                }
 424        }
 425
 426        /* Check if Type 2 dongle.*/
 427        if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
 428                is_type2_dongle = true;
 429
 430        dongle_signature =
 431                (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
 432
 433        is_valid_hdmi_signature = true;
 434
 435        /* Check EOT */
 436        if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
 437                is_valid_hdmi_signature = false;
 438        }
 439
 440        /* Check signature */
 441        for (i = 0; i < sizeof(dongle_signature->id); ++i) {
 442                /* If its not the right signature,
 443                 * skip mismatch in subversion byte.*/
 444                if (dongle_signature->id[i] !=
 445                        dp_hdmi_dongle_signature_str[i] && i != 3) {
 446
 447                        if (is_type2_dongle) {
 448                                is_valid_hdmi_signature = false;
 449                                break;
 450                        }
 451
 452                }
 453        }
 454
 455        if (is_type2_dongle) {
 456                uint32_t max_tmds_clk =
 457                        type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
 458
 459                max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
 460
 461                if (0 == max_tmds_clk ||
 462                                max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
 463                                max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
 464                        *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
 465
 466                        CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 467                                        sizeof(type2_dongle_buf),
 468                                        "DP-DVI passive dongle %dMhz: ",
 469                                        DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
 470                } else {
 471                        if (is_valid_hdmi_signature == true) {
 472                                *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
 473
 474                                CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 475                                                sizeof(type2_dongle_buf),
 476                                                "Type 2 DP-HDMI passive dongle %dMhz: ",
 477                                                max_tmds_clk);
 478                        } else {
 479                                *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
 480
 481                                CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 482                                                sizeof(type2_dongle_buf),
 483                                                "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ",
 484                                                max_tmds_clk);
 485
 486                        }
 487
 488                        /* Multiply by 1000 to convert to kHz. */
 489                        sink_cap->max_hdmi_pixel_clock =
 490                                max_tmds_clk * 1000;
 491                }
 492
 493        } else {
 494                if (is_valid_hdmi_signature == true) {
 495                        *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
 496
 497                        CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 498                                        sizeof(type2_dongle_buf),
 499                                        "Type 1 DP-HDMI passive dongle %dMhz: ",
 500                                        sink_cap->max_hdmi_pixel_clock / 1000);
 501                } else {
 502                        *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
 503
 504                        CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 505                                        sizeof(type2_dongle_buf),
 506                                        "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ",
 507                                        sink_cap->max_hdmi_pixel_clock / 1000);
 508                }
 509        }
 510
 511        return;
 512}
 513
 514enum {
 515        DP_SINK_CAP_SIZE =
 516                DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1
 517};
 518
 519bool dal_ddc_service_query_ddc_data(
 520        struct ddc_service *ddc,
 521        uint32_t address,
 522        uint8_t *write_buf,
 523        uint32_t write_size,
 524        uint8_t *read_buf,
 525        uint32_t read_size)
 526{
 527        bool success = true;
 528        uint32_t payload_size =
 529                dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
 530                        DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
 531
 532        uint32_t write_payloads =
 533                (write_size + payload_size - 1) / payload_size;
 534
 535        uint32_t read_payloads =
 536                (read_size + payload_size - 1) / payload_size;
 537
 538        uint32_t payloads_num = write_payloads + read_payloads;
 539
 540
 541        if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
 542                return false;
 543
 544        if (!payloads_num)
 545                return false;
 546
 547        /*TODO: len of payload data for i2c and aux is uint8!!!!,
 548         *  but we want to read 256 over i2c!!!!*/
 549        if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
 550                struct aux_payload payload;
 551
 552                payload.i2c_over_aux = true;
 553                payload.address = address;
 554                payload.reply = NULL;
 555                payload.defer_delay = get_defer_delay(ddc);
 556
 557                if (write_size != 0) {
 558                        payload.write = true;
 559                        /* should not set mot (middle of transaction) to 0
 560                         * if there are pending read payloads
 561                         */
 562                        payload.mot = !(read_size == 0);
 563                        payload.length = write_size;
 564                        payload.data = write_buf;
 565
 566                        success = dal_ddc_submit_aux_command(ddc, &payload);
 567                }
 568
 569                if (read_size != 0 && success) {
 570                        payload.write = false;
 571                        /* should set mot (middle of transaction) to 0
 572                         * since it is the last payload to send
 573                         */
 574                        payload.mot = false;
 575                        payload.length = read_size;
 576                        payload.data = read_buf;
 577
 578                        success = dal_ddc_submit_aux_command(ddc, &payload);
 579                }
 580        } else {
 581                struct i2c_command command = {0};
 582                struct i2c_payloads payloads;
 583
 584                if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
 585                        return false;
 586
 587                command.payloads = dal_ddc_i2c_payloads_get(&payloads);
 588                command.number_of_payloads = 0;
 589                command.engine = DDC_I2C_COMMAND_ENGINE;
 590                command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
 591
 592                dal_ddc_i2c_payloads_add(
 593                        &payloads, address, write_size, write_buf, true);
 594
 595                dal_ddc_i2c_payloads_add(
 596                        &payloads, address, read_size, read_buf, false);
 597
 598                command.number_of_payloads =
 599                        dal_ddc_i2c_payloads_get_count(&payloads);
 600
 601                success = dm_helpers_submit_i2c(
 602                                ddc->ctx,
 603                                ddc->link,
 604                                &command);
 605
 606                dal_vector_destruct(&payloads.payloads);
 607        }
 608
 609        return success;
 610}
 611
 612bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
 613                struct aux_payload *payload)
 614{
 615        uint32_t retrieved = 0;
 616        bool ret = false;
 617
 618        if (!ddc)
 619                return false;
 620
 621        if (!payload)
 622                return false;
 623
 624        do {
 625                struct aux_payload current_payload;
 626                bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >=
 627                        payload->length;
 628
 629                current_payload.address = payload->address;
 630                current_payload.data = &payload->data[retrieved];
 631                current_payload.defer_delay = payload->defer_delay;
 632                current_payload.i2c_over_aux = payload->i2c_over_aux;
 633                current_payload.length = is_end_of_payload ?
 634                        payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
 635                /* set mot (middle of transaction) to false
 636                 * if it is the last payload
 637                 */
 638                current_payload.mot = is_end_of_payload ? payload->mot:true;
 639                current_payload.reply = payload->reply;
 640                current_payload.write = payload->write;
 641
 642                ret = dc_link_aux_transfer_with_retries(ddc, &current_payload);
 643
 644                retrieved += current_payload.length;
 645        } while (retrieved < payload->length && ret == true);
 646
 647        return ret;
 648}
 649
 650/* dc_link_aux_transfer_raw() - Attempt to transfer
 651 * the given aux payload.  This function does not perform
 652 * retries or handle error states.  The reply is returned
 653 * in the payload->reply and the result through
 654 * *operation_result.  Returns the number of bytes transferred,
 655 * or -1 on a failure.
 656 */
 657int dc_link_aux_transfer_raw(struct ddc_service *ddc,
 658                struct aux_payload *payload,
 659                enum aux_return_code_type *operation_result)
 660{
 661        if (dc_enable_dmub_notifications(ddc->ctx->dc))
 662                return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
 663        else
 664                return dce_aux_transfer_raw(ddc, payload, operation_result);
 665}
 666
 667/* dc_link_aux_transfer_with_retries() - Attempt to submit an
 668 * aux payload, retrying on timeouts, defers, and busy states
 669 * as outlined in the DP spec.  Returns true if the request
 670 * was successful.
 671 *
 672 * Unless you want to implement your own retry semantics, this
 673 * is probably the one you want.
 674 */
 675bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
 676                struct aux_payload *payload)
 677{
 678        return dce_aux_transfer_with_retries(ddc, payload);
 679}
 680
 681
 682bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc,
 683                uint32_t timeout)
 684{
 685        bool result = false;
 686        struct ddc *ddc_pin = ddc->ddc_pin;
 687
 688        /* Do not try to access nonexistent DDC pin. */
 689        if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY)
 690                return true;
 691
 692        if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout) {
 693                ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
 694                result = true;
 695        }
 696        return result;
 697}
 698
 699/*test only function*/
 700void dal_ddc_service_set_ddc_pin(
 701        struct ddc_service *ddc_service,
 702        struct ddc *ddc)
 703{
 704        ddc_service->ddc_pin = ddc;
 705}
 706
 707struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
 708{
 709        return ddc_service->ddc_pin;
 710}
 711
 712void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
 713                uint32_t pix_clk,
 714                bool lte_340_scramble)
 715{
 716        bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
 717        uint8_t slave_address = HDMI_SCDC_ADDRESS;
 718        uint8_t offset = HDMI_SCDC_SINK_VERSION;
 719        uint8_t sink_version = 0;
 720        uint8_t write_buffer[2] = {0};
 721        /*Lower than 340 Scramble bit from SCDC caps*/
 722
 723        if (ddc_service->link->local_sink &&
 724                ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite)
 725                return;
 726
 727        dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
 728                        sizeof(offset), &sink_version, sizeof(sink_version));
 729        if (sink_version == 1) {
 730                /*Source Version = 1*/
 731                write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
 732                write_buffer[1] = 1;
 733                dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 734                                write_buffer, sizeof(write_buffer), NULL, 0);
 735                /*Read Request from SCDC caps*/
 736        }
 737        write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
 738
 739        if (over_340_mhz) {
 740                write_buffer[1] = 3;
 741        } else if (lte_340_scramble) {
 742                write_buffer[1] = 1;
 743        } else {
 744                write_buffer[1] = 0;
 745        }
 746        dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
 747                        sizeof(write_buffer), NULL, 0);
 748}
 749
 750void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
 751{
 752        uint8_t slave_address = HDMI_SCDC_ADDRESS;
 753        uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
 754        uint8_t tmds_config = 0;
 755
 756        if (ddc_service->link->local_sink &&
 757                ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite)
 758                return;
 759
 760        dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
 761                        sizeof(offset), &tmds_config, sizeof(tmds_config));
 762        if (tmds_config & 0x1) {
 763                union hdmi_scdc_status_flags_data status_data = { {0} };
 764                uint8_t scramble_status = 0;
 765
 766                offset = HDMI_SCDC_SCRAMBLER_STATUS;
 767                dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 768                                &offset, sizeof(offset), &scramble_status,
 769                                sizeof(scramble_status));
 770                offset = HDMI_SCDC_STATUS_FLAGS;
 771                dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 772                                &offset, sizeof(offset), status_data.byte,
 773                                sizeof(status_data.byte));
 774        }
 775}
 776
 777