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 "core_types.h" 28 #include "dce_aux.h" 29 #include "dce/dce_11_0_sh_mask.h" 30 #include "dm_event_log.h" 31 #include "dm_helpers.h" 32 #include "dmub/inc/dmub_cmd.h" 33 34 #define CTX \ 35 aux110->base.ctx 36 #define REG(reg_name)\ 37 (aux110->regs->reg_name) 38 39 #define DC_LOGGER \ 40 engine->ctx->logger 41 42 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) 43 #define IS_DC_I2CAUX_LOGGING_ENABLED() (false) 44 #define LOG_FLAG_Error_I2cAux LOG_ERROR 45 #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX 46 47 #include "reg_helper.h" 48 49 #undef FN 50 #define FN(reg_name, field_name) \ 51 aux110->shift->field_name, aux110->mask->field_name 52 53 #define FROM_AUX_ENGINE(ptr) \ 54 container_of((ptr), struct aux_engine_dce110, base) 55 56 #define FROM_ENGINE(ptr) \ 57 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) 58 59 #define FROM_AUX_ENGINE_ENGINE(ptr) \ 60 container_of((ptr), struct dce_aux, base) 61 enum { 62 AUX_INVALID_REPLY_RETRY_COUNTER = 1, 63 AUX_TIMED_OUT_RETRY_COUNTER = 2, 64 AUX_DEFER_RETRY_COUNTER = 6 65 }; 66 67 #define TIME_OUT_INCREMENT 1016 68 #define TIME_OUT_MULTIPLIER_8 8 69 #define TIME_OUT_MULTIPLIER_16 16 70 #define TIME_OUT_MULTIPLIER_32 32 71 #define TIME_OUT_MULTIPLIER_64 64 72 #define MAX_TIMEOUT_LENGTH 127 73 #define DEFAULT_AUX_ENGINE_MULT 0 74 #define DEFAULT_AUX_ENGINE_LENGTH 69 75 76 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) 77 78 static void release_engine( 79 struct dce_aux *engine) 80 { 81 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 82 83 dal_ddc_close(engine->ddc); 84 85 engine->ddc = NULL; 86 87 REG_UPDATE_2(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1, 88 AUX_SW_USE_AUX_REG_REQ, 0); 89 } 90 91 #define SW_CAN_ACCESS_AUX 1 92 #define DMCU_CAN_ACCESS_AUX 2 93 94 static bool is_engine_available( 95 struct dce_aux *engine) 96 { 97 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 98 99 uint32_t value = REG_READ(AUX_ARB_CONTROL); 100 uint32_t field = get_reg_field_value( 101 value, 102 AUX_ARB_CONTROL, 103 AUX_REG_RW_CNTL_STATUS); 104 105 return (field != DMCU_CAN_ACCESS_AUX); 106 } 107 static bool acquire_engine( 108 struct dce_aux *engine) 109 { 110 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 111 112 uint32_t value = REG_READ(AUX_ARB_CONTROL); 113 uint32_t field = get_reg_field_value( 114 value, 115 AUX_ARB_CONTROL, 116 AUX_REG_RW_CNTL_STATUS); 117 if (field == DMCU_CAN_ACCESS_AUX) 118 return false; 119 /* enable AUX before request SW to access AUX */ 120 value = REG_READ(AUX_CONTROL); 121 field = get_reg_field_value(value, 122 AUX_CONTROL, 123 AUX_EN); 124 125 if (field == 0) { 126 set_reg_field_value( 127 value, 128 1, 129 AUX_CONTROL, 130 AUX_EN); 131 132 if (REG(AUX_RESET_MASK)) { 133 /*DP_AUX block as part of the enable sequence*/ 134 set_reg_field_value( 135 value, 136 1, 137 AUX_CONTROL, 138 AUX_RESET); 139 } 140 141 REG_WRITE(AUX_CONTROL, value); 142 143 if (REG(AUX_RESET_MASK)) { 144 /*poll HW to make sure reset it done*/ 145 146 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, 147 1, 11); 148 149 set_reg_field_value( 150 value, 151 0, 152 AUX_CONTROL, 153 AUX_RESET); 154 155 REG_WRITE(AUX_CONTROL, value); 156 157 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, 158 1, 11); 159 } 160 } /*if (field)*/ 161 162 /* request SW to access AUX */ 163 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); 164 165 value = REG_READ(AUX_ARB_CONTROL); 166 field = get_reg_field_value( 167 value, 168 AUX_ARB_CONTROL, 169 AUX_REG_RW_CNTL_STATUS); 170 171 return (field == SW_CAN_ACCESS_AUX); 172 } 173 174 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \ 175 ((command) | ((0xF0000 & (address)) >> 16)) 176 177 #define COMPOSE_AUX_SW_DATA_8_15(address) \ 178 ((0xFF00 & (address)) >> 8) 179 180 #define COMPOSE_AUX_SW_DATA_0_7(address) \ 181 (0xFF & (address)) 182 183 static void submit_channel_request( 184 struct dce_aux *engine, 185 struct aux_request_transaction_data *request) 186 { 187 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 188 uint32_t value; 189 uint32_t length; 190 191 bool is_write = 192 ((request->type == AUX_TRANSACTION_TYPE_DP) && 193 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || 194 ((request->type == AUX_TRANSACTION_TYPE_I2C) && 195 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || 196 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); 197 if (REG(AUXN_IMPCAL)) { 198 /* clear_aux_error */ 199 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 200 AUXN_CALOUT_ERROR_AK, 1, 201 AUXN_CALOUT_ERROR_AK, 0); 202 203 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 204 AUXP_CALOUT_ERROR_AK, 1, 205 AUXP_CALOUT_ERROR_AK, 0); 206 207 /* force_default_calibrate */ 208 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 209 AUXN_IMPCAL_ENABLE, 1, 210 AUXN_IMPCAL_OVERRIDE_ENABLE, 0); 211 212 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ 213 214 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 215 AUXP_IMPCAL_OVERRIDE_ENABLE, 1, 216 AUXP_IMPCAL_OVERRIDE_ENABLE, 0); 217 } 218 219 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 220 221 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 222 10, aux110->polling_timeout_period/10); 223 224 /* set the delay and the number of bytes to write */ 225 226 /* The length include 227 * the 4 bit header and the 20 bit address 228 * (that is 3 byte). 229 * If the requested length is non zero this means 230 * an addition byte specifying the length is required. 231 */ 232 233 length = request->length ? 4 : 3; 234 if (is_write) 235 length += request->length; 236 237 REG_UPDATE_2(AUX_SW_CONTROL, 238 AUX_SW_START_DELAY, request->delay, 239 AUX_SW_WR_BYTES, length); 240 241 /* program action and address and payload data (if 'is_write') */ 242 value = REG_UPDATE_4(AUX_SW_DATA, 243 AUX_SW_INDEX, 0, 244 AUX_SW_DATA_RW, 0, 245 AUX_SW_AUTOINCREMENT_DISABLE, 1, 246 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 247 248 value = REG_SET_2(AUX_SW_DATA, value, 249 AUX_SW_AUTOINCREMENT_DISABLE, 0, 250 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 251 252 value = REG_SET(AUX_SW_DATA, value, 253 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 254 255 if (request->length) { 256 value = REG_SET(AUX_SW_DATA, value, 257 AUX_SW_DATA, request->length - 1); 258 } 259 260 if (is_write) { 261 /* Load the HW buffer with the Data to be sent. 262 * This is relevant for write operation. 263 * For read, the data recived data will be 264 * processed in process_channel_reply(). 265 */ 266 uint32_t i = 0; 267 268 while (i < request->length) { 269 value = REG_SET(AUX_SW_DATA, value, 270 AUX_SW_DATA, request->data[i]); 271 272 ++i; 273 } 274 } 275 276 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 277 278 if (engine->ddc) { 279 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE, 280 request->action, request->address, request->length, request->data); 281 } else { 282 EVENT_LOG_AUX_REQ(engine->inst, EVENT_LOG_AUX_ORIGIN_NATIVE, 283 request->action, request->address, request->length, request->data); 284 } 285 } 286 287 static int read_channel_reply(struct dce_aux *engine, uint32_t size, 288 uint8_t *buffer, uint8_t *reply_result, 289 uint32_t *sw_status) 290 { 291 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 292 uint32_t bytes_replied; 293 uint32_t reply_result_32; 294 295 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 296 &bytes_replied); 297 298 /* In case HPD is LOW, exit AUX transaction */ 299 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 300 return -1; 301 302 /* Need at least the status byte */ 303 if (!bytes_replied) 304 return -1; 305 306 REG_UPDATE_SEQ_3(AUX_SW_DATA, 307 AUX_SW_INDEX, 0, 308 AUX_SW_AUTOINCREMENT_DISABLE, 1, 309 AUX_SW_DATA_RW, 1); 310 311 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 312 reply_result_32 = reply_result_32 >> 4; 313 if (reply_result != NULL) 314 *reply_result = (uint8_t)reply_result_32; 315 316 if (reply_result_32 == 0) { /* ACK */ 317 uint32_t i = 0; 318 319 /* First byte was already used to get the command status */ 320 --bytes_replied; 321 322 /* Do not overflow buffer */ 323 if (bytes_replied > size) 324 return -1; 325 326 while (i < bytes_replied) { 327 uint32_t aux_sw_data_val; 328 329 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 330 buffer[i] = (uint8_t)aux_sw_data_val; 331 ++i; 332 } 333 334 return i; 335 } 336 337 return 0; 338 } 339 340 static enum aux_return_code_type get_channel_status( 341 struct dce_aux *engine, 342 uint8_t *returned_bytes) 343 { 344 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 345 346 uint32_t value; 347 348 if (returned_bytes == NULL) { 349 /*caller pass NULL pointer*/ 350 ASSERT_CRITICAL(false); 351 return AUX_RET_ERROR_UNKNOWN; 352 } 353 *returned_bytes = 0; 354 355 /* poll to make sure that SW_DONE is asserted */ 356 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 357 10, aux110->polling_timeout_period/10); 358 359 value = REG_READ(AUX_SW_STATUS); 360 /* in case HPD is LOW, exit AUX transaction */ 361 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 362 return AUX_RET_ERROR_HPD_DISCON; 363 364 /* Note that the following bits are set in 'status.bits' 365 * during CTS 4.2.1.2 (FW 3.3.1): 366 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 367 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 368 * 369 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 370 * HW debugging bit and should be ignored. 371 */ 372 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 373 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 374 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 375 return AUX_RET_ERROR_TIMEOUT; 376 377 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 378 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 379 (value & 380 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 381 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 382 return AUX_RET_ERROR_INVALID_REPLY; 383 384 *returned_bytes = (uint8_t)get_reg_field_value(value, 385 AUX_SW_STATUS, 386 AUX_SW_REPLY_BYTE_COUNT); 387 388 if (*returned_bytes == 0) 389 return 390 AUX_RET_ERROR_INVALID_REPLY; 391 else { 392 *returned_bytes -= 1; 393 return AUX_RET_SUCCESS; 394 } 395 } else { 396 /*time_elapsed >= aux_engine->timeout_period 397 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 398 */ 399 ASSERT_CRITICAL(false); 400 return AUX_RET_ERROR_TIMEOUT; 401 } 402 } 403 404 static bool acquire( 405 struct dce_aux *engine, 406 struct ddc *ddc) 407 { 408 enum gpio_result result; 409 410 if ((engine == NULL) || !is_engine_available(engine)) 411 return false; 412 413 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 414 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 415 416 if (result != GPIO_RESULT_OK) 417 return false; 418 419 if (!acquire_engine(engine)) { 420 engine->ddc = ddc; 421 release_engine(engine); 422 return false; 423 } 424 425 engine->ddc = ddc; 426 427 return true; 428 } 429 430 static bool acquire_aux_engine_without_ddc_pin( 431 struct dce_aux *engine, 432 struct ddc *ddc) 433 { 434 (void)ddc; 435 if ((engine == NULL) || !is_engine_available(engine)) 436 return false; 437 438 if (!acquire_engine(engine)) { 439 release_engine(engine); 440 return false; 441 } 442 return true; 443 } 444 445 void dce110_engine_destroy(struct dce_aux **engine) 446 { 447 448 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 449 450 kfree(engine110); 451 *engine = NULL; 452 453 } 454 455 static uint32_t dce_aux_configure_timeout_without_ddc_pin(struct ddc_service *ddc, 456 uint32_t timeout_in_us) 457 { 458 uint32_t multiplier = 0; 459 uint32_t length = 0; 460 uint32_t prev_length = 0; 461 uint32_t prev_mult = 0; 462 uint32_t prev_timeout_val = 0; 463 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]; 464 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 465 466 /* 1-Update polling timeout period */ 467 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER; 468 469 /* 2-Update aux timeout period length and multiplier */ 470 if (timeout_in_us == 0) { 471 multiplier = DEFAULT_AUX_ENGINE_MULT; 472 length = DEFAULT_AUX_ENGINE_LENGTH; 473 } else if (timeout_in_us <= TIME_OUT_INCREMENT) { 474 multiplier = 0; 475 length = timeout_in_us / TIME_OUT_MULTIPLIER_8; 476 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0) 477 length++; 478 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) { 479 multiplier = 1; 480 length = timeout_in_us / TIME_OUT_MULTIPLIER_16; 481 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0) 482 length++; 483 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) { 484 multiplier = 2; 485 length = timeout_in_us / TIME_OUT_MULTIPLIER_32; 486 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0) 487 length++; 488 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) { 489 multiplier = 3; 490 length = timeout_in_us / TIME_OUT_MULTIPLIER_64; 491 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0) 492 length++; 493 } 494 495 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH; 496 497 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult); 498 499 switch (prev_mult) { 500 case 0: 501 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8; 502 break; 503 case 1: 504 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16; 505 break; 506 case 2: 507 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32; 508 break; 509 case 3: 510 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64; 511 break; 512 default: 513 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8; 514 break; 515 } 516 517 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier); 518 519 return prev_timeout_val; 520 } 521 522 static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc, 523 uint32_t timeout_in_us) 524 { 525 uint32_t multiplier = 0; 526 uint32_t length = 0; 527 uint32_t prev_length = 0; 528 uint32_t prev_mult = 0; 529 uint32_t prev_timeout_val = 0; 530 struct ddc *ddc_pin = ddc->ddc_pin; 531 532 if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) 533 return dce_aux_configure_timeout_without_ddc_pin(ddc, timeout_in_us); 534 535 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 536 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 537 538 /* 1-Update polling timeout period */ 539 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER; 540 541 /* 2-Update aux timeout period length and multiplier */ 542 if (timeout_in_us == 0) { 543 multiplier = DEFAULT_AUX_ENGINE_MULT; 544 length = DEFAULT_AUX_ENGINE_LENGTH; 545 } else if (timeout_in_us <= TIME_OUT_INCREMENT) { 546 multiplier = 0; 547 length = timeout_in_us/TIME_OUT_MULTIPLIER_8; 548 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0) 549 length++; 550 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) { 551 multiplier = 1; 552 length = timeout_in_us/TIME_OUT_MULTIPLIER_16; 553 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0) 554 length++; 555 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) { 556 multiplier = 2; 557 length = timeout_in_us/TIME_OUT_MULTIPLIER_32; 558 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0) 559 length++; 560 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) { 561 multiplier = 3; 562 length = timeout_in_us/TIME_OUT_MULTIPLIER_64; 563 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0) 564 length++; 565 } 566 567 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH; 568 569 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult); 570 571 switch (prev_mult) { 572 case 0: 573 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8; 574 break; 575 case 1: 576 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16; 577 break; 578 case 2: 579 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32; 580 break; 581 case 3: 582 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64; 583 break; 584 default: 585 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8; 586 break; 587 } 588 589 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier); 590 591 return prev_timeout_val; 592 } 593 594 static struct dce_aux_funcs aux_functions = { 595 .configure_timeout = NULL, 596 .destroy = NULL, 597 }; 598 599 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 600 struct dc_context *ctx, 601 uint32_t inst, 602 uint32_t timeout_period, 603 const struct dce110_aux_registers *regs, 604 const struct dce110_aux_registers_mask *mask, 605 const struct dce110_aux_registers_shift *shift, 606 bool is_ext_aux_timeout_configurable) 607 { 608 aux_engine110->base.ddc = NULL; 609 aux_engine110->base.ctx = ctx; 610 aux_engine110->base.delay = 0; 611 aux_engine110->base.max_defer_write_retry = 0; 612 aux_engine110->base.inst = inst; 613 aux_engine110->polling_timeout_period = timeout_period; 614 aux_engine110->regs = regs; 615 616 aux_engine110->mask = mask; 617 aux_engine110->shift = shift; 618 aux_engine110->base.funcs = &aux_functions; 619 if (is_ext_aux_timeout_configurable) 620 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout; 621 622 return &aux_engine110->base; 623 } 624 625 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) 626 { 627 if (payload->i2c_over_aux) { 628 if (payload->write_status_update) { 629 if (payload->mot) 630 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT; 631 else 632 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; 633 } 634 if (payload->write) { 635 if (payload->mot) 636 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; 637 else 638 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 639 } 640 if (payload->mot) 641 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; 642 643 return I2CAUX_TRANSACTION_ACTION_I2C_READ; 644 } 645 if (payload->write) 646 return I2CAUX_TRANSACTION_ACTION_DP_WRITE; 647 648 return I2CAUX_TRANSACTION_ACTION_DP_READ; 649 } 650 651 int dce_aux_transfer_raw(struct ddc_service *ddc, 652 struct aux_payload *payload, 653 enum aux_return_code_type *operation_result) 654 { 655 if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) { 656 /* Check whether aux to be processed via dmub or dcn directly */ 657 if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc) { 658 return dce_aux_transfer_dmub_raw(ddc, payload, operation_result); 659 } else { 660 return dce_aux_transfer_raw_without_ddc_pin(ddc, payload, operation_result); 661 } 662 } else { 663 if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc || 664 !ddc->ddc_pin) { 665 return dce_aux_transfer_dmub_raw(ddc, payload, operation_result); 666 } else { 667 return dce_aux_transfer_raw_with_ddc_pin(ddc, payload, operation_result); 668 } 669 } 670 } 671 672 int dce_aux_transfer_raw_with_ddc_pin(struct ddc_service *ddc, 673 struct aux_payload *payload, 674 enum aux_return_code_type *operation_result) 675 { 676 struct ddc *ddc_pin = ddc->ddc_pin; 677 struct dce_aux *aux_engine; 678 struct aux_request_transaction_data aux_req; 679 uint8_t returned_bytes = 0; 680 int res = -1; 681 uint32_t status; 682 683 memset(&aux_req, 0, sizeof(aux_req)); 684 685 if (ddc_pin == NULL) { 686 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 687 return -1; 688 } 689 690 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 691 if (!acquire(aux_engine, ddc_pin)) { 692 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 693 return -1; 694 } 695 696 if (payload->i2c_over_aux) 697 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 698 else 699 aux_req.type = AUX_TRANSACTION_TYPE_DP; 700 701 aux_req.action = i2caux_action_from_payload(payload); 702 703 aux_req.address = payload->address; 704 aux_req.delay = 0; 705 aux_req.length = payload->length; 706 aux_req.data = payload->data; 707 708 submit_channel_request(aux_engine, &aux_req); 709 *operation_result = get_channel_status(aux_engine, &returned_bytes); 710 711 if (*operation_result == AUX_RET_SUCCESS) { 712 int __maybe_unused bytes_replied = 0; 713 714 bytes_replied = read_channel_reply(aux_engine, payload->length, 715 payload->data, payload->reply, 716 &status); 717 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en, 718 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply, 719 bytes_replied, payload->data); 720 res = returned_bytes; 721 } else { 722 res = -1; 723 } 724 725 release_engine(aux_engine); 726 return res; 727 } 728 729 int dce_aux_transfer_raw_without_ddc_pin(struct ddc_service *ddc, 730 struct aux_payload *payload, 731 enum aux_return_code_type *operation_result) 732 { 733 struct ddc *ddc_pin = ddc->ddc_pin; 734 struct dce_aux *aux_engine; 735 struct aux_request_transaction_data aux_req; 736 uint8_t returned_bytes = 0; 737 int res = -1; 738 uint32_t status; 739 740 memset(&aux_req, 0, sizeof(aux_req)); 741 742 aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]; 743 744 if (!acquire_aux_engine_without_ddc_pin(aux_engine, ddc_pin)) { 745 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 746 return -1; 747 } 748 749 if (payload->i2c_over_aux) 750 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 751 else 752 aux_req.type = AUX_TRANSACTION_TYPE_DP; 753 754 aux_req.action = i2caux_action_from_payload(payload); 755 756 aux_req.address = payload->address; 757 aux_req.delay = 0; 758 aux_req.length = payload->length; 759 aux_req.data = payload->data; 760 761 submit_channel_request(aux_engine, &aux_req); 762 *operation_result = get_channel_status(aux_engine, &returned_bytes); 763 764 if (*operation_result == AUX_RET_SUCCESS) { 765 int __maybe_unused bytes_replied = 0; 766 767 bytes_replied = read_channel_reply(aux_engine, payload->length, 768 payload->data, payload->reply, 769 &status); 770 EVENT_LOG_AUX_REP(aux_engine->inst, 771 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply, 772 bytes_replied, payload->data); 773 res = returned_bytes; 774 } else { 775 res = -1; 776 } 777 778 release_engine(aux_engine); 779 return res; 780 } 781 782 int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, 783 struct aux_payload *payload, 784 enum aux_return_code_type *operation_result) 785 { 786 struct ddc *ddc_pin = ddc->ddc_pin; 787 788 if (ddc_pin != NULL) { 789 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 790 /* XXX: Workaround to configure ddc channels for aux transactions */ 791 if (!acquire(aux_engine, ddc_pin)) { 792 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 793 return -1; 794 } 795 release_engine(aux_engine); 796 } 797 798 if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) { 799 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]; 800 801 if (!acquire_aux_engine_without_ddc_pin(aux_engine, ddc_pin)) { 802 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 803 return -1; 804 } 805 release_engine(aux_engine); 806 } 807 808 return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result); 809 } 810 811 #define AUX_MAX_RETRIES 7 812 #define AUX_MIN_DEFER_RETRIES 7 813 #define AUX_MAX_DEFER_TIMEOUT_MS 50 814 #define AUX_MAX_I2C_DEFER_RETRIES 7 815 #define AUX_MAX_INVALID_REPLY_RETRIES 2 816 #define AUX_MAX_TIMEOUT_RETRIES 3 817 #define AUX_DEFER_DELAY_FOR_DPIA 4 /*ms*/ 818 819 static void dce_aux_log_payload(const char *payload_name, 820 unsigned char *payload, uint32_t length, uint32_t max_length_to_log) 821 { 822 if (!IS_DC_I2CAUX_LOGGING_ENABLED()) 823 return; 824 825 if (payload && length) { 826 char hex_str[128] = {0}; 827 char *hex_str_ptr = &hex_str[0]; 828 uint32_t hex_str_remaining = sizeof(hex_str); 829 unsigned char *payload_ptr = payload; 830 unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length); 831 unsigned int count; 832 char *padding = ""; 833 834 while (payload_ptr < payload_max_to_log_ptr) { 835 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr); 836 padding = " "; 837 hex_str_remaining -= count; 838 hex_str_ptr += count; 839 payload_ptr++; 840 } 841 842 count = snprintf_count(hex_str_ptr, hex_str_remaining, " "); 843 hex_str_remaining -= count; 844 hex_str_ptr += count; 845 846 payload_ptr = payload; 847 while (payload_ptr < payload_max_to_log_ptr) { 848 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c", 849 *payload_ptr >= ' ' ? *payload_ptr : '.'); 850 hex_str_remaining -= count; 851 hex_str_ptr += count; 852 payload_ptr++; 853 } 854 855 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 856 LOG_FLAG_I2cAux_DceAux, 857 "dce_aux_log_payload: %s: length=%u: data: %s%s", 858 payload_name, 859 length, 860 hex_str, 861 (length > max_length_to_log ? " (...)" : " ")); 862 } else { 863 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 864 LOG_FLAG_I2cAux_DceAux, 865 "dce_aux_log_payload: %s: length=%u: data: <empty payload>", 866 payload_name, 867 length); 868 } 869 } 870 871 bool dce_aux_transfer_with_retries(struct ddc_service *ddc, 872 struct aux_payload *payload) 873 { 874 int i, ret = 0; 875 uint8_t reply; 876 bool payload_reply = true; 877 enum aux_return_code_type operation_result; 878 bool retry_on_defer = false; 879 struct ddc *ddc_pin = ddc->ddc_pin; 880 struct dce_aux *aux_engine = NULL; 881 struct aux_engine_dce110 *aux110 = NULL; 882 uint32_t defer_time_in_ms = 0; 883 884 int aux_ack_retries = 0, 885 aux_defer_retries = 0, 886 aux_i2c_defer_retries = 0, 887 aux_timeout_retries = 0, 888 aux_invalid_reply_retries = 0, 889 aux_ack_m_retries = 0; 890 891 if (ddc_pin) { 892 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 893 aux110 = FROM_AUX_ENGINE(aux_engine); 894 } 895 896 if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) { 897 aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]; 898 aux110 = FROM_AUX_ENGINE(aux_engine); 899 } 900 901 if (!payload->reply) { 902 payload_reply = false; 903 payload->reply = &reply; 904 } 905 906 for (i = 0; i < AUX_MAX_RETRIES; i++) { 907 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 908 LOG_FLAG_I2cAux_DceAux, 909 "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: " 910 "address=0x%04x length=%u write=%d mot=%d is_i2c=%d is_dpia=%d ddc_hw_inst=%d", 911 ddc && ddc->link ? ddc->link->link_index : UINT_MAX, 912 i + 1, 913 (int)AUX_MAX_RETRIES, 914 payload->address, 915 payload->length, 916 (unsigned int) payload->write, 917 (unsigned int) payload->mot, 918 payload->i2c_over_aux, 919 (ddc->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? true : false, 920 ddc->link->ddc_hw_inst); 921 if (payload->write) 922 dce_aux_log_payload(" write", payload->data, payload->length, 16); 923 924 ret = dce_aux_transfer_raw(ddc, payload, &operation_result); 925 926 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 927 LOG_FLAG_I2cAux_DceAux, 928 "dce_aux_transfer_with_retries: link_index=%u: END: retry %d of %d: " 929 "address=0x%04x length=%u write=%d mot=%d: ret=%d operation_result=%d " 930 "payload->reply=%u is_i2c=%d is_dpia=%d ddc_hw_inst=%d", 931 ddc && ddc->link ? ddc->link->link_index : UINT_MAX, 932 i + 1, 933 (int)AUX_MAX_RETRIES, 934 payload->address, 935 payload->length, 936 (unsigned int) payload->write, 937 (unsigned int) payload->mot, 938 ret, 939 (int)operation_result, 940 (unsigned int) *payload->reply, 941 payload->i2c_over_aux, 942 (ddc->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? true : false, 943 ddc->link->ddc_hw_inst); 944 if (!payload->write) 945 dce_aux_log_payload(" read", payload->data, ret > 0 ? ret : 0, 16); 946 947 switch (operation_result) { 948 case AUX_RET_SUCCESS: 949 aux_timeout_retries = 0; 950 aux_invalid_reply_retries = 0; 951 952 switch (*payload->reply) { 953 case AUX_TRANSACTION_REPLY_AUX_ACK: 954 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 955 LOG_FLAG_I2cAux_DceAux, 956 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK"); 957 if (!payload->write && payload->length != ret) { 958 if (++aux_ack_retries >= AUX_MAX_RETRIES) { 959 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 960 LOG_FLAG_Error_I2cAux, 961 "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d", 962 aux_defer_retries, 963 AUX_MAX_RETRIES); 964 goto fail; 965 } else 966 udelay(300); 967 } else if (payload->write && ret > 0) { 968 /* sink requested more time to complete the write via AUX_ACKM */ 969 if (++aux_ack_m_retries >= AUX_MAX_RETRIES) { 970 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 971 LOG_FLAG_Error_I2cAux, 972 "dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d", 973 aux_ack_m_retries, 974 AUX_MAX_RETRIES); 975 goto fail; 976 } 977 978 /* retry reading the write status until complete 979 * NOTE: payload is modified here 980 */ 981 payload->write = false; 982 payload->write_status_update = true; 983 payload->length = 0; 984 udelay(300); 985 } else 986 return true; 987 break; 988 989 case AUX_TRANSACTION_REPLY_AUX_DEFER: 990 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 991 LOG_FLAG_I2cAux_DceAux, 992 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER"); 993 994 /* polling_timeout_period is in us */ 995 if (aux110) 996 defer_time_in_ms += aux110->polling_timeout_period / 1000; 997 else 998 defer_time_in_ms += AUX_DEFER_DELAY_FOR_DPIA; 999 ++aux_defer_retries; 1000 fallthrough; 1001 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 1002 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER) 1003 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1004 LOG_FLAG_I2cAux_DceAux, 1005 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER"); 1006 1007 retry_on_defer = true; 1008 1009 if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES 1010 && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { 1011 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1012 LOG_FLAG_Error_I2cAux, 1013 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d && defer_time_in_ms=%d >= AUX_MAX_DEFER_TIMEOUT_MS=%d", 1014 aux_defer_retries, 1015 AUX_MIN_DEFER_RETRIES, 1016 defer_time_in_ms, 1017 AUX_MAX_DEFER_TIMEOUT_MS); 1018 goto fail; 1019 } else { 1020 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || 1021 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { 1022 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1023 LOG_FLAG_I2cAux_DceAux, 1024 "dce_aux_transfer_with_retries: payload->defer_delay=%u", 1025 payload->defer_delay); 1026 fsleep(payload->defer_delay * 1000); 1027 defer_time_in_ms += payload->defer_delay; 1028 } 1029 } 1030 break; 1031 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 1032 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1033 LOG_FLAG_I2cAux_DceAux, 1034 "dce_aux_transfer_with_retries: FAILURE: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); 1035 goto fail; 1036 case AUX_TRANSACTION_REPLY_I2C_DEFER: 1037 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1038 LOG_FLAG_I2cAux_DceAux, 1039 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER"); 1040 1041 aux_defer_retries = 0; 1042 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) { 1043 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1044 LOG_FLAG_Error_I2cAux, 1045 "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d", 1046 aux_i2c_defer_retries, 1047 AUX_MAX_I2C_DEFER_RETRIES); 1048 goto fail; 1049 } 1050 break; 1051 1052 case AUX_TRANSACTION_REPLY_AUX_NACK: 1053 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1054 LOG_FLAG_I2cAux_DceAux, 1055 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK"); 1056 goto fail; 1057 1058 case AUX_TRANSACTION_REPLY_HPD_DISCON: 1059 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1060 LOG_FLAG_I2cAux_DceAux, 1061 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON"); 1062 goto fail; 1063 1064 default: 1065 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1066 LOG_FLAG_Error_I2cAux, 1067 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case. Reply: %d", *payload->reply); 1068 goto fail; 1069 } 1070 break; 1071 1072 case AUX_RET_ERROR_INVALID_REPLY: 1073 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1074 LOG_FLAG_I2cAux_DceAux, 1075 "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY"); 1076 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) { 1077 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1078 LOG_FLAG_Error_I2cAux, 1079 "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d", 1080 aux_invalid_reply_retries, 1081 AUX_MAX_INVALID_REPLY_RETRIES); 1082 goto fail; 1083 } else 1084 udelay(400); 1085 break; 1086 1087 case AUX_RET_ERROR_TIMEOUT: 1088 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1089 LOG_FLAG_I2cAux_DceAux, 1090 "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT"); 1091 // Check whether a DEFER had occurred before the timeout. 1092 // If so, treat timeout as a DEFER. 1093 if (retry_on_defer) { 1094 if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) { 1095 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1096 LOG_FLAG_Error_I2cAux, 1097 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d", 1098 aux_defer_retries, 1099 AUX_MIN_DEFER_RETRIES); 1100 goto fail; 1101 } else if (payload->defer_delay > 0) { 1102 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 1103 LOG_FLAG_I2cAux_DceAux, 1104 "dce_aux_transfer_with_retries: payload->defer_delay=%u", 1105 payload->defer_delay); 1106 msleep(payload->defer_delay); 1107 } 1108 } else { 1109 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) { 1110 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1111 LOG_FLAG_Error_I2cAux, 1112 "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d", 1113 aux_timeout_retries, 1114 AUX_MAX_TIMEOUT_RETRIES); 1115 goto fail; 1116 } else { 1117 /* 1118 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts 1119 * According to the DP spec there should be 3 retries total 1120 * with a 400us wait inbetween each. Hardware already waits 1121 * for 550us therefore no wait is required here. 1122 */ 1123 } 1124 } 1125 break; 1126 1127 case AUX_RET_ERROR_HPD_DISCON: 1128 case AUX_RET_ERROR_ENGINE_ACQUIRE: 1129 case AUX_RET_ERROR_UNKNOWN: 1130 default: 1131 goto fail; 1132 } 1133 } 1134 1135 fail: 1136 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 1137 LOG_FLAG_Error_I2cAux, 1138 "%s: Failure: operation_result=%d", 1139 __func__, 1140 (int)operation_result); 1141 if (!payload_reply) 1142 payload->reply = NULL; 1143 1144 return false; 1145 } 1146