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/delay.h> 27 #include <linux/slab.h> 28 29 #include "dm_services.h" 30 #include "core_types.h" 31 #include "dce_aux.h" 32 #include "dce/dce_11_0_sh_mask.h" 33 #include "dm_event_log.h" 34 #include "dm_helpers.h" 35 #include "dmub/inc/dmub_cmd.h" 36 37 #define CTX \ 38 aux110->base.ctx 39 #define REG(reg_name)\ 40 (aux110->regs->reg_name) 41 42 #define DC_LOGGER \ 43 engine->ctx->logger 44 45 #include "reg_helper.h" 46 47 #undef FN 48 #define FN(reg_name, field_name) \ 49 aux110->shift->field_name, aux110->mask->field_name 50 51 #define FROM_AUX_ENGINE(ptr) \ 52 container_of((ptr), struct aux_engine_dce110, base) 53 54 #define FROM_ENGINE(ptr) \ 55 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) 56 57 #define FROM_AUX_ENGINE_ENGINE(ptr) \ 58 container_of((ptr), struct dce_aux, base) 59 enum { 60 AUX_INVALID_REPLY_RETRY_COUNTER = 1, 61 AUX_TIMED_OUT_RETRY_COUNTER = 2, 62 AUX_DEFER_RETRY_COUNTER = 6 63 }; 64 65 #define TIME_OUT_INCREMENT 1016 66 #define TIME_OUT_MULTIPLIER_8 8 67 #define TIME_OUT_MULTIPLIER_16 16 68 #define TIME_OUT_MULTIPLIER_32 32 69 #define TIME_OUT_MULTIPLIER_64 64 70 #define MAX_TIMEOUT_LENGTH 127 71 #define DEFAULT_AUX_ENGINE_MULT 0 72 #define DEFAULT_AUX_ENGINE_LENGTH 69 73 74 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ 75 76 static void release_engine( 77 struct dce_aux *engine) 78 { 79 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 80 81 dal_ddc_close(engine->ddc); 82 83 engine->ddc = NULL; 84 85 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); 86 } 87 88 #define SW_CAN_ACCESS_AUX 1 89 #define DMCU_CAN_ACCESS_AUX 2 90 91 static bool is_engine_available( 92 struct dce_aux *engine) 93 { 94 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 95 96 uint32_t value = REG_READ(AUX_ARB_CONTROL); 97 uint32_t field = get_reg_field_value( 98 value, 99 AUX_ARB_CONTROL, 100 AUX_REG_RW_CNTL_STATUS); 101 102 return (field != DMCU_CAN_ACCESS_AUX); 103 } 104 static bool acquire_engine( 105 struct dce_aux *engine) 106 { 107 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 108 109 uint32_t value = REG_READ(AUX_ARB_CONTROL); 110 uint32_t field = get_reg_field_value( 111 value, 112 AUX_ARB_CONTROL, 113 AUX_REG_RW_CNTL_STATUS); 114 if (field == DMCU_CAN_ACCESS_AUX) 115 return false; 116 /* enable AUX before request SW to access AUX */ 117 value = REG_READ(AUX_CONTROL); 118 field = get_reg_field_value(value, 119 AUX_CONTROL, 120 AUX_EN); 121 122 if (field == 0) { 123 set_reg_field_value( 124 value, 125 1, 126 AUX_CONTROL, 127 AUX_EN); 128 129 if (REG(AUX_RESET_MASK)) { 130 /*DP_AUX block as part of the enable sequence*/ 131 set_reg_field_value( 132 value, 133 1, 134 AUX_CONTROL, 135 AUX_RESET); 136 } 137 138 REG_WRITE(AUX_CONTROL, value); 139 140 if (REG(AUX_RESET_MASK)) { 141 /*poll HW to make sure reset it done*/ 142 143 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, 144 1, 11); 145 146 set_reg_field_value( 147 value, 148 0, 149 AUX_CONTROL, 150 AUX_RESET); 151 152 REG_WRITE(AUX_CONTROL, value); 153 154 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, 155 1, 11); 156 } 157 } /*if (field)*/ 158 159 /* request SW to access AUX */ 160 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); 161 162 value = REG_READ(AUX_ARB_CONTROL); 163 field = get_reg_field_value( 164 value, 165 AUX_ARB_CONTROL, 166 AUX_REG_RW_CNTL_STATUS); 167 168 return (field == SW_CAN_ACCESS_AUX); 169 } 170 171 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \ 172 ((command) | ((0xF0000 & (address)) >> 16)) 173 174 #define COMPOSE_AUX_SW_DATA_8_15(address) \ 175 ((0xFF00 & (address)) >> 8) 176 177 #define COMPOSE_AUX_SW_DATA_0_7(address) \ 178 (0xFF & (address)) 179 180 static void submit_channel_request( 181 struct dce_aux *engine, 182 struct aux_request_transaction_data *request) 183 { 184 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 185 uint32_t value; 186 uint32_t length; 187 188 bool is_write = 189 ((request->type == AUX_TRANSACTION_TYPE_DP) && 190 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || 191 ((request->type == AUX_TRANSACTION_TYPE_I2C) && 192 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || 193 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); 194 if (REG(AUXN_IMPCAL)) { 195 /* clear_aux_error */ 196 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 197 AUXN_CALOUT_ERROR_AK, 1, 198 AUXN_CALOUT_ERROR_AK, 0); 199 200 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 201 AUXP_CALOUT_ERROR_AK, 1, 202 AUXP_CALOUT_ERROR_AK, 0); 203 204 /* force_default_calibrate */ 205 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 206 AUXN_IMPCAL_ENABLE, 1, 207 AUXN_IMPCAL_OVERRIDE_ENABLE, 0); 208 209 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ 210 211 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 212 AUXP_IMPCAL_OVERRIDE_ENABLE, 1, 213 AUXP_IMPCAL_OVERRIDE_ENABLE, 0); 214 } 215 216 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 217 218 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 219 10, aux110->polling_timeout_period/10); 220 221 /* set the delay and the number of bytes to write */ 222 223 /* The length include 224 * the 4 bit header and the 20 bit address 225 * (that is 3 byte). 226 * If the requested length is non zero this means 227 * an addition byte specifying the length is required. 228 */ 229 230 length = request->length ? 4 : 3; 231 if (is_write) 232 length += request->length; 233 234 REG_UPDATE_2(AUX_SW_CONTROL, 235 AUX_SW_START_DELAY, request->delay, 236 AUX_SW_WR_BYTES, length); 237 238 /* program action and address and payload data (if 'is_write') */ 239 value = REG_UPDATE_4(AUX_SW_DATA, 240 AUX_SW_INDEX, 0, 241 AUX_SW_DATA_RW, 0, 242 AUX_SW_AUTOINCREMENT_DISABLE, 1, 243 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 244 245 value = REG_SET_2(AUX_SW_DATA, value, 246 AUX_SW_AUTOINCREMENT_DISABLE, 0, 247 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 248 249 value = REG_SET(AUX_SW_DATA, value, 250 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 251 252 if (request->length) { 253 value = REG_SET(AUX_SW_DATA, value, 254 AUX_SW_DATA, request->length - 1); 255 } 256 257 if (is_write) { 258 /* Load the HW buffer with the Data to be sent. 259 * This is relevant for write operation. 260 * For read, the data recived data will be 261 * processed in process_channel_reply(). 262 */ 263 uint32_t i = 0; 264 265 while (i < request->length) { 266 value = REG_SET(AUX_SW_DATA, value, 267 AUX_SW_DATA, request->data[i]); 268 269 ++i; 270 } 271 } 272 273 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 274 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE, 275 request->action, request->address, request->length, request->data); 276 } 277 278 static int read_channel_reply(struct dce_aux *engine, uint32_t size, 279 uint8_t *buffer, uint8_t *reply_result, 280 uint32_t *sw_status) 281 { 282 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 283 uint32_t bytes_replied; 284 uint32_t reply_result_32; 285 286 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 287 &bytes_replied); 288 289 /* In case HPD is LOW, exit AUX transaction */ 290 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 291 return -1; 292 293 /* Need at least the status byte */ 294 if (!bytes_replied) 295 return -1; 296 297 REG_UPDATE_SEQ_3(AUX_SW_DATA, 298 AUX_SW_INDEX, 0, 299 AUX_SW_AUTOINCREMENT_DISABLE, 1, 300 AUX_SW_DATA_RW, 1); 301 302 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 303 reply_result_32 = reply_result_32 >> 4; 304 if (reply_result != NULL) 305 *reply_result = (uint8_t)reply_result_32; 306 307 if (reply_result_32 == 0) { /* ACK */ 308 uint32_t i = 0; 309 310 /* First byte was already used to get the command status */ 311 --bytes_replied; 312 313 /* Do not overflow buffer */ 314 if (bytes_replied > size) 315 return -1; 316 317 while (i < bytes_replied) { 318 uint32_t aux_sw_data_val; 319 320 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 321 buffer[i] = aux_sw_data_val; 322 ++i; 323 } 324 325 return i; 326 } 327 328 return 0; 329 } 330 331 static enum aux_return_code_type get_channel_status( 332 struct dce_aux *engine, 333 uint8_t *returned_bytes) 334 { 335 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 336 337 uint32_t value; 338 339 if (returned_bytes == NULL) { 340 /*caller pass NULL pointer*/ 341 ASSERT_CRITICAL(false); 342 return AUX_RET_ERROR_UNKNOWN; 343 } 344 *returned_bytes = 0; 345 346 /* poll to make sure that SW_DONE is asserted */ 347 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 348 10, aux110->polling_timeout_period/10); 349 350 value = REG_READ(AUX_SW_STATUS); 351 /* in case HPD is LOW, exit AUX transaction */ 352 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 353 return AUX_RET_ERROR_HPD_DISCON; 354 355 /* Note that the following bits are set in 'status.bits' 356 * during CTS 4.2.1.2 (FW 3.3.1): 357 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 358 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 359 * 360 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 361 * HW debugging bit and should be ignored. 362 */ 363 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 364 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 365 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 366 return AUX_RET_ERROR_TIMEOUT; 367 368 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 369 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 370 (value & 371 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 372 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 373 return AUX_RET_ERROR_INVALID_REPLY; 374 375 *returned_bytes = get_reg_field_value(value, 376 AUX_SW_STATUS, 377 AUX_SW_REPLY_BYTE_COUNT); 378 379 if (*returned_bytes == 0) 380 return 381 AUX_RET_ERROR_INVALID_REPLY; 382 else { 383 *returned_bytes -= 1; 384 return AUX_RET_SUCCESS; 385 } 386 } else { 387 /*time_elapsed >= aux_engine->timeout_period 388 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 389 */ 390 ASSERT_CRITICAL(false); 391 return AUX_RET_ERROR_TIMEOUT; 392 } 393 } 394 395 static bool acquire( 396 struct dce_aux *engine, 397 struct ddc *ddc) 398 { 399 enum gpio_result result; 400 401 if ((engine == NULL) || !is_engine_available(engine)) 402 return false; 403 404 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 405 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 406 407 if (result != GPIO_RESULT_OK) 408 return false; 409 410 if (!acquire_engine(engine)) { 411 dal_ddc_close(ddc); 412 return false; 413 } 414 415 engine->ddc = ddc; 416 417 return true; 418 } 419 420 void dce110_engine_destroy(struct dce_aux **engine) 421 { 422 423 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 424 425 kfree(engine110); 426 *engine = NULL; 427 428 } 429 430 static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc, 431 uint32_t timeout_in_us) 432 { 433 uint32_t multiplier = 0; 434 uint32_t length = 0; 435 uint32_t prev_length = 0; 436 uint32_t prev_mult = 0; 437 uint32_t prev_timeout_val = 0; 438 struct ddc *ddc_pin = ddc->ddc_pin; 439 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 440 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 441 442 /* 1-Update polling timeout period */ 443 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER; 444 445 /* 2-Update aux timeout period length and multiplier */ 446 if (timeout_in_us == 0) { 447 multiplier = DEFAULT_AUX_ENGINE_MULT; 448 length = DEFAULT_AUX_ENGINE_LENGTH; 449 } else if (timeout_in_us <= TIME_OUT_INCREMENT) { 450 multiplier = 0; 451 length = timeout_in_us/TIME_OUT_MULTIPLIER_8; 452 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0) 453 length++; 454 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) { 455 multiplier = 1; 456 length = timeout_in_us/TIME_OUT_MULTIPLIER_16; 457 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0) 458 length++; 459 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) { 460 multiplier = 2; 461 length = timeout_in_us/TIME_OUT_MULTIPLIER_32; 462 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0) 463 length++; 464 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) { 465 multiplier = 3; 466 length = timeout_in_us/TIME_OUT_MULTIPLIER_64; 467 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0) 468 length++; 469 } 470 471 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH; 472 473 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult); 474 475 switch (prev_mult) { 476 case 0: 477 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8; 478 break; 479 case 1: 480 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16; 481 break; 482 case 2: 483 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32; 484 break; 485 case 3: 486 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64; 487 break; 488 default: 489 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8; 490 break; 491 } 492 493 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier); 494 495 return prev_timeout_val; 496 } 497 498 static struct dce_aux_funcs aux_functions = { 499 .configure_timeout = NULL, 500 .destroy = NULL, 501 }; 502 503 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 504 struct dc_context *ctx, 505 uint32_t inst, 506 uint32_t timeout_period, 507 const struct dce110_aux_registers *regs, 508 const struct dce110_aux_registers_mask *mask, 509 const struct dce110_aux_registers_shift *shift, 510 bool is_ext_aux_timeout_configurable) 511 { 512 aux_engine110->base.ddc = NULL; 513 aux_engine110->base.ctx = ctx; 514 aux_engine110->base.delay = 0; 515 aux_engine110->base.max_defer_write_retry = 0; 516 aux_engine110->base.inst = inst; 517 aux_engine110->polling_timeout_period = timeout_period; 518 aux_engine110->regs = regs; 519 520 aux_engine110->mask = mask; 521 aux_engine110->shift = shift; 522 aux_engine110->base.funcs = &aux_functions; 523 if (is_ext_aux_timeout_configurable) 524 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout; 525 526 return &aux_engine110->base; 527 } 528 529 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) 530 { 531 if (payload->i2c_over_aux) { 532 if (payload->write) { 533 if (payload->mot) 534 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; 535 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 536 } 537 if (payload->mot) 538 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; 539 return I2CAUX_TRANSACTION_ACTION_I2C_READ; 540 } 541 if (payload->write) 542 return I2CAUX_TRANSACTION_ACTION_DP_WRITE; 543 return I2CAUX_TRANSACTION_ACTION_DP_READ; 544 } 545 546 int dce_aux_transfer_raw(struct ddc_service *ddc, 547 struct aux_payload *payload, 548 enum aux_return_code_type *operation_result) 549 { 550 struct ddc *ddc_pin = ddc->ddc_pin; 551 struct dce_aux *aux_engine; 552 struct aux_request_transaction_data aux_req; 553 struct aux_reply_transaction_data aux_rep; 554 uint8_t returned_bytes = 0; 555 int res = -1; 556 uint32_t status; 557 558 memset(&aux_req, 0, sizeof(aux_req)); 559 memset(&aux_rep, 0, sizeof(aux_rep)); 560 561 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 562 if (!acquire(aux_engine, ddc_pin)) { 563 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 564 return -1; 565 } 566 567 if (payload->i2c_over_aux) 568 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 569 else 570 aux_req.type = AUX_TRANSACTION_TYPE_DP; 571 572 aux_req.action = i2caux_action_from_payload(payload); 573 574 aux_req.address = payload->address; 575 aux_req.delay = 0; 576 aux_req.length = payload->length; 577 aux_req.data = payload->data; 578 579 submit_channel_request(aux_engine, &aux_req); 580 *operation_result = get_channel_status(aux_engine, &returned_bytes); 581 582 if (*operation_result == AUX_RET_SUCCESS) { 583 int __maybe_unused bytes_replied = 0; 584 585 bytes_replied = read_channel_reply(aux_engine, payload->length, 586 payload->data, payload->reply, 587 &status); 588 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en, 589 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply, 590 bytes_replied, payload->data); 591 res = returned_bytes; 592 } else { 593 res = -1; 594 } 595 596 release_engine(aux_engine); 597 return res; 598 } 599 600 int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, 601 struct aux_payload *payload, 602 enum aux_return_code_type *operation_result) 603 { 604 struct ddc *ddc_pin = ddc->ddc_pin; 605 606 if (ddc_pin != NULL) { 607 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 608 /* XXX: Workaround to configure ddc channels for aux transactions */ 609 if (!acquire(aux_engine, ddc_pin)) { 610 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 611 return -1; 612 } 613 release_engine(aux_engine); 614 } 615 616 return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result); 617 } 618 619 #define AUX_MAX_RETRIES 7 620 #define AUX_MIN_DEFER_RETRIES 7 621 #define AUX_MAX_DEFER_TIMEOUT_MS 50 622 #define AUX_MAX_I2C_DEFER_RETRIES 7 623 #define AUX_MAX_INVALID_REPLY_RETRIES 2 624 #define AUX_MAX_TIMEOUT_RETRIES 3 625 626 bool dce_aux_transfer_with_retries(struct ddc_service *ddc, 627 struct aux_payload *payload) 628 { 629 int i, ret = 0; 630 uint8_t reply; 631 bool payload_reply = true; 632 enum aux_return_code_type operation_result; 633 bool retry_on_defer = false; 634 struct ddc *ddc_pin = ddc->ddc_pin; 635 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 636 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 637 uint32_t defer_time_in_ms = 0; 638 639 int aux_ack_retries = 0, 640 aux_defer_retries = 0, 641 aux_i2c_defer_retries = 0, 642 aux_timeout_retries = 0, 643 aux_invalid_reply_retries = 0; 644 645 if (!payload->reply) { 646 payload_reply = false; 647 payload->reply = &reply; 648 } 649 650 for (i = 0; i < AUX_MAX_RETRIES; i++) { 651 ret = dce_aux_transfer_raw(ddc, payload, &operation_result); 652 653 switch (operation_result) { 654 case AUX_RET_SUCCESS: 655 aux_timeout_retries = 0; 656 aux_invalid_reply_retries = 0; 657 658 switch (*payload->reply) { 659 case AUX_TRANSACTION_REPLY_AUX_ACK: 660 if (!payload->write && payload->length != ret) { 661 if (++aux_ack_retries >= AUX_MAX_RETRIES) 662 goto fail; 663 else 664 udelay(300); 665 } else 666 return true; 667 break; 668 669 case AUX_TRANSACTION_REPLY_AUX_DEFER: 670 /* polling_timeout_period is in us */ 671 defer_time_in_ms += aux110->polling_timeout_period / 1000; 672 ++aux_defer_retries; 673 fallthrough; 674 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 675 retry_on_defer = true; 676 fallthrough; 677 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 678 if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES 679 && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { 680 goto fail; 681 } else { 682 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || 683 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { 684 if (payload->defer_delay > 1) { 685 msleep(payload->defer_delay); 686 defer_time_in_ms += payload->defer_delay; 687 } else if (payload->defer_delay <= 1) { 688 udelay(payload->defer_delay * 1000); 689 defer_time_in_ms += payload->defer_delay; 690 } 691 } 692 } 693 break; 694 695 case AUX_TRANSACTION_REPLY_I2C_DEFER: 696 aux_defer_retries = 0; 697 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) 698 goto fail; 699 break; 700 701 case AUX_TRANSACTION_REPLY_AUX_NACK: 702 case AUX_TRANSACTION_REPLY_HPD_DISCON: 703 default: 704 goto fail; 705 } 706 break; 707 708 case AUX_RET_ERROR_INVALID_REPLY: 709 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) 710 goto fail; 711 else 712 udelay(400); 713 break; 714 715 case AUX_RET_ERROR_TIMEOUT: 716 // Check whether a DEFER had occurred before the timeout. 717 // If so, treat timeout as a DEFER. 718 if (retry_on_defer) { 719 if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) 720 goto fail; 721 else if (payload->defer_delay > 0) 722 msleep(payload->defer_delay); 723 } else { 724 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) 725 goto fail; 726 else { 727 /* 728 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts 729 * According to the DP spec there should be 3 retries total 730 * with a 400us wait inbetween each. Hardware already waits 731 * for 550us therefore no wait is required here. 732 */ 733 } 734 } 735 break; 736 737 case AUX_RET_ERROR_HPD_DISCON: 738 case AUX_RET_ERROR_ENGINE_ACQUIRE: 739 case AUX_RET_ERROR_UNKNOWN: 740 default: 741 goto fail; 742 } 743 } 744 745 fail: 746 if (!payload_reply) 747 payload->reply = NULL; 748 749 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 750 WPP_BIT_FLAG_DC_ERROR, 751 "AUX transaction failed. Result: %d", 752 operation_result); 753 754 return false; 755 } 756