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