root/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dal_ddc_i2c_payloads_create
  2. dal_ddc_i2c_payloads_get
  3. dal_ddc_i2c_payloads_get_count
  4. dal_ddc_i2c_payloads_destroy
  5. dal_ddc_i2c_payloads_add
  6. construct
  7. dal_ddc_service_create
  8. destruct
  9. dal_ddc_service_destroy
  10. dal_ddc_service_get_type
  11. dal_ddc_service_set_transaction_type
  12. dal_ddc_service_is_in_aux_transaction_mode
  13. ddc_service_set_dongle_type
  14. defer_delay_converter_wa
  15. get_defer_delay
  16. i2c_read
  17. dal_ddc_service_i2c_query_dp_dual_mode_adaptor
  18. dal_ddc_service_query_ddc_data
  19. dc_link_aux_transfer_raw
  20. dc_link_aux_transfer_with_retries
  21. dal_ddc_service_set_ddc_pin
  22. dal_ddc_service_get_ddc_pin
  23. dal_ddc_service_write_scdc_data
  24. dal_ddc_service_read_scdc_data

   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 
  40 #define AUX_POWER_UP_WA_DELAY 500
  41 #define I2C_OVER_AUX_DEFER_WA_DELAY 70
  42 
  43 /* CV smart dongle slave address for retrieving supported HDTV modes*/
  44 #define CV_SMART_DONGLE_ADDRESS 0x20
  45 /* DVI-HDMI dongle slave address for retrieving dongle signature*/
  46 #define DVI_HDMI_DONGLE_ADDRESS 0x68
  47 struct dvi_hdmi_dongle_signature_data {
  48         int8_t vendor[3];/* "AMD" */
  49         uint8_t version[2];
  50         uint8_t size;
  51         int8_t id[11];/* "6140063500G"*/
  52 };
  53 /* DP-HDMI dongle slave address for retrieving dongle signature*/
  54 #define DP_HDMI_DONGLE_ADDRESS 0x40
  55 static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
  56 #define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
  57 
  58 struct dp_hdmi_dongle_signature_data {
  59         int8_t id[15];/* "DP-HDMI ADAPTOR"*/
  60         uint8_t eot;/* end of transmition '\x4' */
  61 };
  62 
  63 /* SCDC Address defines (HDMI 2.0)*/
  64 #define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
  65 #define HDMI_SCDC_ADDRESS  0x54
  66 #define HDMI_SCDC_SINK_VERSION 0x01
  67 #define HDMI_SCDC_SOURCE_VERSION 0x02
  68 #define HDMI_SCDC_UPDATE_0 0x10
  69 #define HDMI_SCDC_TMDS_CONFIG 0x20
  70 #define HDMI_SCDC_SCRAMBLER_STATUS 0x21
  71 #define HDMI_SCDC_CONFIG_0 0x30
  72 #define HDMI_SCDC_STATUS_FLAGS 0x40
  73 #define HDMI_SCDC_ERR_DETECT 0x50
  74 #define HDMI_SCDC_TEST_CONFIG 0xC0
  75 
  76 union hdmi_scdc_update_read_data {
  77         uint8_t byte[2];
  78         struct {
  79                 uint8_t STATUS_UPDATE:1;
  80                 uint8_t CED_UPDATE:1;
  81                 uint8_t RR_TEST:1;
  82                 uint8_t RESERVED:5;
  83                 uint8_t RESERVED2:8;
  84         } fields;
  85 };
  86 
  87 union hdmi_scdc_status_flags_data {
  88         uint8_t byte[2];
  89         struct {
  90                 uint8_t CLOCK_DETECTED:1;
  91                 uint8_t CH0_LOCKED:1;
  92                 uint8_t CH1_LOCKED:1;
  93                 uint8_t CH2_LOCKED:1;
  94                 uint8_t RESERVED:4;
  95                 uint8_t RESERVED2:8;
  96                 uint8_t RESERVED3:8;
  97 
  98         } fields;
  99 };
 100 
 101 union hdmi_scdc_ced_data {
 102         uint8_t byte[7];
 103         struct {
 104                 uint8_t CH0_8LOW:8;
 105                 uint8_t CH0_7HIGH:7;
 106                 uint8_t CH0_VALID:1;
 107                 uint8_t CH1_8LOW:8;
 108                 uint8_t CH1_7HIGH:7;
 109                 uint8_t CH1_VALID:1;
 110                 uint8_t CH2_8LOW:8;
 111                 uint8_t CH2_7HIGH:7;
 112                 uint8_t CH2_VALID:1;
 113                 uint8_t CHECKSUM:8;
 114                 uint8_t RESERVED:8;
 115                 uint8_t RESERVED2:8;
 116                 uint8_t RESERVED3:8;
 117                 uint8_t RESERVED4:4;
 118         } fields;
 119 };
 120 
 121 struct i2c_payloads {
 122         struct vector payloads;
 123 };
 124 
 125 struct aux_payloads {
 126         struct vector payloads;
 127 };
 128 
 129 static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
 130 {
 131         struct i2c_payloads *payloads;
 132 
 133         payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL);
 134 
 135         if (!payloads)
 136                 return NULL;
 137 
 138         if (dal_vector_construct(
 139                 &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
 140                 return payloads;
 141 
 142         kfree(payloads);
 143         return NULL;
 144 
 145 }
 146 
 147 static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
 148 {
 149         return (struct i2c_payload *)p->payloads.container;
 150 }
 151 
 152 static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
 153 {
 154         return p->payloads.count;
 155 }
 156 
 157 static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
 158 {
 159         if (!p || !*p)
 160                 return;
 161         dal_vector_destruct(&(*p)->payloads);
 162         kfree(*p);
 163         *p = NULL;
 164 
 165 }
 166 
 167 #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 168 
 169 void dal_ddc_i2c_payloads_add(
 170         struct i2c_payloads *payloads,
 171         uint32_t address,
 172         uint32_t len,
 173         uint8_t *data,
 174         bool write)
 175 {
 176         uint32_t payload_size = EDID_SEGMENT_SIZE;
 177         uint32_t pos;
 178 
 179         for (pos = 0; pos < len; pos += payload_size) {
 180                 struct i2c_payload payload = {
 181                         .write = write,
 182                         .address = address,
 183                         .length = DDC_MIN(payload_size, len - pos),
 184                         .data = data + pos };
 185                 dal_vector_append(&payloads->payloads, &payload);
 186         }
 187 
 188 }
 189 
 190 static void construct(
 191         struct ddc_service *ddc_service,
 192         struct ddc_service_init_data *init_data)
 193 {
 194         enum connector_id connector_id =
 195                 dal_graphics_object_id_get_connector_id(init_data->id);
 196 
 197         struct gpio_service *gpio_service = init_data->ctx->gpio_service;
 198         struct graphics_object_i2c_info i2c_info;
 199         struct gpio_ddc_hw_info hw_info;
 200         struct dc_bios *dcb = init_data->ctx->dc_bios;
 201 
 202         ddc_service->link = init_data->link;
 203         ddc_service->ctx = init_data->ctx;
 204 
 205         if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
 206                 ddc_service->ddc_pin = NULL;
 207         } else {
 208                 hw_info.ddc_channel = i2c_info.i2c_line;
 209                 hw_info.hw_supported = i2c_info.i2c_hw_assist;
 210 
 211                 ddc_service->ddc_pin = dal_gpio_create_ddc(
 212                         gpio_service,
 213                         i2c_info.gpio_info.clk_a_register_index,
 214                         1 << i2c_info.gpio_info.clk_a_shift,
 215                         &hw_info);
 216         }
 217 
 218         ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
 219         ddc_service->flags.FORCE_READ_REPEATED_START = false;
 220         ddc_service->flags.EDID_STRESS_READ = false;
 221 
 222         ddc_service->flags.IS_INTERNAL_DISPLAY =
 223                 connector_id == CONNECTOR_ID_EDP ||
 224                 connector_id == CONNECTOR_ID_LVDS;
 225 
 226         ddc_service->wa.raw = 0;
 227 }
 228 
 229 struct ddc_service *dal_ddc_service_create(
 230         struct ddc_service_init_data *init_data)
 231 {
 232         struct ddc_service *ddc_service;
 233 
 234         ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL);
 235 
 236         if (!ddc_service)
 237                 return NULL;
 238 
 239         construct(ddc_service, init_data);
 240         return ddc_service;
 241 }
 242 
 243 static void destruct(struct ddc_service *ddc)
 244 {
 245         if (ddc->ddc_pin)
 246                 dal_gpio_destroy_ddc(&ddc->ddc_pin);
 247 }
 248 
 249 void dal_ddc_service_destroy(struct ddc_service **ddc)
 250 {
 251         if (!ddc || !*ddc) {
 252                 BREAK_TO_DEBUGGER();
 253                 return;
 254         }
 255         destruct(*ddc);
 256         kfree(*ddc);
 257         *ddc = NULL;
 258 }
 259 
 260 enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
 261 {
 262         return DDC_SERVICE_TYPE_CONNECTOR;
 263 }
 264 
 265 void dal_ddc_service_set_transaction_type(
 266         struct ddc_service *ddc,
 267         enum ddc_transaction_type type)
 268 {
 269         ddc->transaction_type = type;
 270 }
 271 
 272 bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
 273 {
 274         switch (ddc->transaction_type) {
 275         case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
 276         case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
 277         case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
 278                 return true;
 279         default:
 280                 break;
 281         }
 282         return false;
 283 }
 284 
 285 void ddc_service_set_dongle_type(struct ddc_service *ddc,
 286                 enum display_dongle_type dongle_type)
 287 {
 288         ddc->dongle_type = dongle_type;
 289 }
 290 
 291 static uint32_t defer_delay_converter_wa(
 292         struct ddc_service *ddc,
 293         uint32_t defer_delay)
 294 {
 295         struct dc_link *link = ddc->link;
 296 
 297         if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
 298                 !memcmp(link->dpcd_caps.branch_dev_name,
 299                         DP_DVI_CONVERTER_ID_4,
 300                         sizeof(link->dpcd_caps.branch_dev_name)))
 301                 return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
 302                         defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
 303 
 304         return defer_delay;
 305 }
 306 
 307 #define DP_TRANSLATOR_DELAY 5
 308 
 309 uint32_t get_defer_delay(struct ddc_service *ddc)
 310 {
 311         uint32_t defer_delay = 0;
 312 
 313         switch (ddc->transaction_type) {
 314         case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
 315                 if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
 316                         (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
 317                         (DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
 318                                 ddc->dongle_type)) {
 319 
 320                         defer_delay = DP_TRANSLATOR_DELAY;
 321 
 322                         defer_delay =
 323                                 defer_delay_converter_wa(ddc, defer_delay);
 324 
 325                 } else /*sink has a delay different from an Active Converter*/
 326                         defer_delay = 0;
 327                 break;
 328         case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
 329                 defer_delay = DP_TRANSLATOR_DELAY;
 330                 break;
 331         default:
 332                 break;
 333         }
 334         return defer_delay;
 335 }
 336 
 337 static bool i2c_read(
 338         struct ddc_service *ddc,
 339         uint32_t address,
 340         uint8_t *buffer,
 341         uint32_t len)
 342 {
 343         uint8_t offs_data = 0;
 344         struct i2c_payload payloads[2] = {
 345                 {
 346                 .write = true,
 347                 .address = address,
 348                 .length = 1,
 349                 .data = &offs_data },
 350                 {
 351                 .write = false,
 352                 .address = address,
 353                 .length = len,
 354                 .data = buffer } };
 355 
 356         struct i2c_command command = {
 357                 .payloads = payloads,
 358                 .number_of_payloads = 2,
 359                 .engine = DDC_I2C_COMMAND_ENGINE,
 360                 .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
 361 
 362         return dm_helpers_submit_i2c(
 363                         ddc->ctx,
 364                         ddc->link,
 365                         &command);
 366 }
 367 
 368 void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
 369         struct ddc_service *ddc,
 370         struct display_sink_capability *sink_cap)
 371 {
 372         uint8_t i;
 373         bool is_valid_hdmi_signature;
 374         enum display_dongle_type *dongle = &sink_cap->dongle_type;
 375         uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
 376         bool is_type2_dongle = false;
 377         int retry_count = 2;
 378         struct dp_hdmi_dongle_signature_data *dongle_signature;
 379 
 380         /* Assume we have no valid DP passive dongle connected */
 381         *dongle = DISPLAY_DONGLE_NONE;
 382         sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
 383 
 384         /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
 385         if (!i2c_read(
 386                 ddc,
 387                 DP_HDMI_DONGLE_ADDRESS,
 388                 type2_dongle_buf,
 389                 sizeof(type2_dongle_buf))) {
 390                 /* Passive HDMI dongles can sometimes fail here without retrying*/
 391                 while (retry_count > 0) {
 392                         if (i2c_read(ddc,
 393                                 DP_HDMI_DONGLE_ADDRESS,
 394                                 type2_dongle_buf,
 395                                 sizeof(type2_dongle_buf)))
 396                                 break;
 397                         retry_count--;
 398                 }
 399                 if (retry_count == 0) {
 400                         *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
 401                         sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
 402 
 403                         CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
 404                                         "DP-DVI passive dongle %dMhz: ",
 405                                         DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
 406                         return;
 407                 }
 408         }
 409 
 410         /* Check if Type 2 dongle.*/
 411         if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
 412                 is_type2_dongle = true;
 413 
 414         dongle_signature =
 415                 (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
 416 
 417         is_valid_hdmi_signature = true;
 418 
 419         /* Check EOT */
 420         if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
 421                 is_valid_hdmi_signature = false;
 422         }
 423 
 424         /* Check signature */
 425         for (i = 0; i < sizeof(dongle_signature->id); ++i) {
 426                 /* If its not the right signature,
 427                  * skip mismatch in subversion byte.*/
 428                 if (dongle_signature->id[i] !=
 429                         dp_hdmi_dongle_signature_str[i] && i != 3) {
 430 
 431                         if (is_type2_dongle) {
 432                                 is_valid_hdmi_signature = false;
 433                                 break;
 434                         }
 435 
 436                 }
 437         }
 438 
 439         if (is_type2_dongle) {
 440                 uint32_t max_tmds_clk =
 441                         type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
 442 
 443                 max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
 444 
 445                 if (0 == max_tmds_clk ||
 446                                 max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
 447                                 max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
 448                         *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
 449 
 450                         CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 451                                         sizeof(type2_dongle_buf),
 452                                         "DP-DVI passive dongle %dMhz: ",
 453                                         DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
 454                 } else {
 455                         if (is_valid_hdmi_signature == true) {
 456                                 *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
 457 
 458                                 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 459                                                 sizeof(type2_dongle_buf),
 460                                                 "Type 2 DP-HDMI passive dongle %dMhz: ",
 461                                                 max_tmds_clk);
 462                         } else {
 463                                 *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
 464 
 465                                 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 466                                                 sizeof(type2_dongle_buf),
 467                                                 "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ",
 468                                                 max_tmds_clk);
 469 
 470                         }
 471 
 472                         /* Multiply by 1000 to convert to kHz. */
 473                         sink_cap->max_hdmi_pixel_clock =
 474                                 max_tmds_clk * 1000;
 475                 }
 476 
 477         } else {
 478                 if (is_valid_hdmi_signature == true) {
 479                         *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
 480 
 481                         CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 482                                         sizeof(type2_dongle_buf),
 483                                         "Type 1 DP-HDMI passive dongle %dMhz: ",
 484                                         sink_cap->max_hdmi_pixel_clock / 1000);
 485                 } else {
 486                         *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
 487 
 488                         CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
 489                                         sizeof(type2_dongle_buf),
 490                                         "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ",
 491                                         sink_cap->max_hdmi_pixel_clock / 1000);
 492                 }
 493         }
 494 
 495         return;
 496 }
 497 
 498 enum {
 499         DP_SINK_CAP_SIZE =
 500                 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1
 501 };
 502 
 503 bool dal_ddc_service_query_ddc_data(
 504         struct ddc_service *ddc,
 505         uint32_t address,
 506         uint8_t *write_buf,
 507         uint32_t write_size,
 508         uint8_t *read_buf,
 509         uint32_t read_size)
 510 {
 511         bool ret;
 512         uint32_t payload_size =
 513                 dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
 514                         DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
 515 
 516         uint32_t write_payloads =
 517                 (write_size + payload_size - 1) / payload_size;
 518 
 519         uint32_t read_payloads =
 520                 (read_size + payload_size - 1) / payload_size;
 521 
 522         uint32_t payloads_num = write_payloads + read_payloads;
 523 
 524         if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
 525                 return false;
 526 
 527         /*TODO: len of payload data for i2c and aux is uint8!!!!,
 528          *  but we want to read 256 over i2c!!!!*/
 529         if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
 530                 struct aux_payload write_payload = {
 531                         .i2c_over_aux = true,
 532                         .write = true,
 533                         .mot = true,
 534                         .address = address,
 535                         .length = write_size,
 536                         .data = write_buf,
 537                         .reply = NULL,
 538                         .defer_delay = get_defer_delay(ddc),
 539                 };
 540 
 541                 struct aux_payload read_payload = {
 542                         .i2c_over_aux = true,
 543                         .write = false,
 544                         .mot = false,
 545                         .address = address,
 546                         .length = read_size,
 547                         .data = read_buf,
 548                         .reply = NULL,
 549                         .defer_delay = get_defer_delay(ddc),
 550                 };
 551 
 552                 ret = dc_link_aux_transfer_with_retries(ddc, &write_payload);
 553 
 554                 if (!ret)
 555                         return false;
 556 
 557                 ret = dc_link_aux_transfer_with_retries(ddc, &read_payload);
 558         } else {
 559                 struct i2c_payloads *payloads =
 560                         dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
 561 
 562                 struct i2c_command command = {
 563                         .payloads = dal_ddc_i2c_payloads_get(payloads),
 564                         .number_of_payloads = 0,
 565                         .engine = DDC_I2C_COMMAND_ENGINE,
 566                         .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
 567 
 568                 dal_ddc_i2c_payloads_add(
 569                         payloads, address, write_size, write_buf, true);
 570 
 571                 dal_ddc_i2c_payloads_add(
 572                         payloads, address, read_size, read_buf, false);
 573 
 574                 command.number_of_payloads =
 575                         dal_ddc_i2c_payloads_get_count(payloads);
 576 
 577                 ret = dm_helpers_submit_i2c(
 578                                 ddc->ctx,
 579                                 ddc->link,
 580                                 &command);
 581 
 582                 dal_ddc_i2c_payloads_destroy(&payloads);
 583         }
 584 
 585         return ret;
 586 }
 587 
 588 /* dc_link_aux_transfer_raw() - Attempt to transfer
 589  * the given aux payload.  This function does not perform
 590  * retries or handle error states.  The reply is returned
 591  * in the payload->reply and the result through
 592  * *operation_result.  Returns the number of bytes transferred,
 593  * or -1 on a failure.
 594  */
 595 int dc_link_aux_transfer_raw(struct ddc_service *ddc,
 596                 struct aux_payload *payload,
 597                 enum aux_channel_operation_result *operation_result)
 598 {
 599         return dce_aux_transfer_raw(ddc, payload, operation_result);
 600 }
 601 
 602 /* dc_link_aux_transfer_with_retries() - Attempt to submit an
 603  * aux payload, retrying on timeouts, defers, and busy states
 604  * as outlined in the DP spec.  Returns true if the request
 605  * was successful.
 606  *
 607  * Unless you want to implement your own retry semantics, this
 608  * is probably the one you want.
 609  */
 610 bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
 611                 struct aux_payload *payload)
 612 {
 613         return dce_aux_transfer_with_retries(ddc, payload);
 614 }
 615 
 616 /*test only function*/
 617 void dal_ddc_service_set_ddc_pin(
 618         struct ddc_service *ddc_service,
 619         struct ddc *ddc)
 620 {
 621         ddc_service->ddc_pin = ddc;
 622 }
 623 
 624 struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
 625 {
 626         return ddc_service->ddc_pin;
 627 }
 628 
 629 void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
 630                 uint32_t pix_clk,
 631                 bool lte_340_scramble)
 632 {
 633         bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
 634         uint8_t slave_address = HDMI_SCDC_ADDRESS;
 635         uint8_t offset = HDMI_SCDC_SINK_VERSION;
 636         uint8_t sink_version = 0;
 637         uint8_t write_buffer[2] = {0};
 638         /*Lower than 340 Scramble bit from SCDC caps*/
 639 
 640         dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
 641                         sizeof(offset), &sink_version, sizeof(sink_version));
 642         if (sink_version == 1) {
 643                 /*Source Version = 1*/
 644                 write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
 645                 write_buffer[1] = 1;
 646                 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 647                                 write_buffer, sizeof(write_buffer), NULL, 0);
 648                 /*Read Request from SCDC caps*/
 649         }
 650         write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
 651 
 652         if (over_340_mhz) {
 653                 write_buffer[1] = 3;
 654         } else if (lte_340_scramble) {
 655                 write_buffer[1] = 1;
 656         } else {
 657                 write_buffer[1] = 0;
 658         }
 659         dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
 660                         sizeof(write_buffer), NULL, 0);
 661 }
 662 
 663 void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
 664 {
 665         uint8_t slave_address = HDMI_SCDC_ADDRESS;
 666         uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
 667         uint8_t tmds_config = 0;
 668 
 669         dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
 670                         sizeof(offset), &tmds_config, sizeof(tmds_config));
 671         if (tmds_config & 0x1) {
 672                 union hdmi_scdc_status_flags_data status_data = { {0} };
 673                 uint8_t scramble_status = 0;
 674 
 675                 offset = HDMI_SCDC_SCRAMBLER_STATUS;
 676                 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 677                                 &offset, sizeof(offset), &scramble_status,
 678                                 sizeof(scramble_status));
 679                 offset = HDMI_SCDC_STATUS_FLAGS;
 680                 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
 681                                 &offset, sizeof(offset), status_data.byte,
 682                                 sizeof(status_data.byte));
 683         }
 684 }
 685 

/* [<][>][^][v][top][bottom][index][help] */