xref: /linux/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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