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