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