xref: /dragonfly/sys/dev/drm/amd/display/dc/dce/dce_aux.c (revision 7d3e9a5b)
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 "dce_aux.h"
28 #include "dce/dce_11_0_sh_mask.h"
29 
30 #define CTX \
31 	aux110->base.ctx
32 #define REG(reg_name)\
33 	(aux110->regs->reg_name)
34 
35 #define DC_LOGGER \
36 	engine->ctx->logger
37 
38 #include "reg_helper.h"
39 
40 #define FROM_AUX_ENGINE(ptr) \
41 	container_of((ptr), struct aux_engine_dce110, base)
42 
43 #define FROM_ENGINE(ptr) \
44 	FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
45 
46 #define FROM_AUX_ENGINE_ENGINE(ptr) \
47 	container_of((ptr), struct aux_engine, base)
48 enum {
49 	AUX_INVALID_REPLY_RETRY_COUNTER = 1,
50 	AUX_TIMED_OUT_RETRY_COUNTER = 2,
51 	AUX_DEFER_RETRY_COUNTER = 6
52 };
53 static void release_engine(
54 	struct aux_engine *engine)
55 {
56 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
57 
58 	dal_ddc_close(engine->ddc);
59 
60 	engine->ddc = NULL;
61 
62 	REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
63 }
64 
65 #define SW_CAN_ACCESS_AUX 1
66 #define DMCU_CAN_ACCESS_AUX 2
67 
68 static bool is_engine_available(
69 	struct aux_engine *engine)
70 {
71 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
72 
73 	uint32_t value = REG_READ(AUX_ARB_CONTROL);
74 	uint32_t field = get_reg_field_value(
75 			value,
76 			AUX_ARB_CONTROL,
77 			AUX_REG_RW_CNTL_STATUS);
78 
79 	return (field != DMCU_CAN_ACCESS_AUX);
80 }
81 static bool acquire_engine(
82 	struct aux_engine *engine)
83 {
84 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
85 
86 	uint32_t value = REG_READ(AUX_ARB_CONTROL);
87 	uint32_t field = get_reg_field_value(
88 			value,
89 			AUX_ARB_CONTROL,
90 			AUX_REG_RW_CNTL_STATUS);
91 	if (field == DMCU_CAN_ACCESS_AUX)
92 		return false;
93 	/* enable AUX before request SW to access AUX */
94 	value = REG_READ(AUX_CONTROL);
95 	field = get_reg_field_value(value,
96 				AUX_CONTROL,
97 				AUX_EN);
98 
99 	if (field == 0) {
100 		set_reg_field_value(
101 				value,
102 				1,
103 				AUX_CONTROL,
104 				AUX_EN);
105 
106 		if (REG(AUX_RESET_MASK)) {
107 			/*DP_AUX block as part of the enable sequence*/
108 			set_reg_field_value(
109 				value,
110 				1,
111 				AUX_CONTROL,
112 				AUX_RESET);
113 		}
114 
115 		REG_WRITE(AUX_CONTROL, value);
116 
117 		if (REG(AUX_RESET_MASK)) {
118 			/*poll HW to make sure reset it done*/
119 
120 			REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
121 					1, 11);
122 
123 			set_reg_field_value(
124 				value,
125 				0,
126 				AUX_CONTROL,
127 				AUX_RESET);
128 
129 			REG_WRITE(AUX_CONTROL, value);
130 
131 			REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
132 					1, 11);
133 		}
134 	} /*if (field)*/
135 
136 	/* request SW to access AUX */
137 	REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
138 
139 	value = REG_READ(AUX_ARB_CONTROL);
140 	field = get_reg_field_value(
141 			value,
142 			AUX_ARB_CONTROL,
143 			AUX_REG_RW_CNTL_STATUS);
144 
145 	return (field == SW_CAN_ACCESS_AUX);
146 }
147 
148 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \
149 	((command) | ((0xF0000 & (address)) >> 16))
150 
151 #define COMPOSE_AUX_SW_DATA_8_15(address) \
152 	((0xFF00 & (address)) >> 8)
153 
154 #define COMPOSE_AUX_SW_DATA_0_7(address) \
155 	(0xFF & (address))
156 
157 static void submit_channel_request(
158 	struct aux_engine *engine,
159 	struct aux_request_transaction_data *request)
160 {
161 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
162 	uint32_t value;
163 	uint32_t length;
164 
165 	bool is_write =
166 		((request->type == AUX_TRANSACTION_TYPE_DP) &&
167 		 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
168 		((request->type == AUX_TRANSACTION_TYPE_I2C) &&
169 		((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
170 		 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
171 	if (REG(AUXN_IMPCAL)) {
172 		/* clear_aux_error */
173 		REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK,
174 				1,
175 				0);
176 
177 		REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK,
178 				1,
179 				0);
180 
181 		/* force_default_calibrate */
182 		REG_UPDATE_1BY1_2(AUXN_IMPCAL,
183 				AUXN_IMPCAL_ENABLE, 1,
184 				AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
185 
186 		/* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
187 
188 		REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
189 				1,
190 				0);
191 	}
192 
193 	REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
194 
195 	REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
196 				10, aux110->timeout_period/10);
197 
198 	/* set the delay and the number of bytes to write */
199 
200 	/* The length include
201 	 * the 4 bit header and the 20 bit address
202 	 * (that is 3 byte).
203 	 * If the requested length is non zero this means
204 	 * an addition byte specifying the length is required.
205 	 */
206 
207 	length = request->length ? 4 : 3;
208 	if (is_write)
209 		length += request->length;
210 
211 	REG_UPDATE_2(AUX_SW_CONTROL,
212 			AUX_SW_START_DELAY, request->delay,
213 			AUX_SW_WR_BYTES, length);
214 
215 	/* program action and address and payload data (if 'is_write') */
216 	value = REG_UPDATE_4(AUX_SW_DATA,
217 			AUX_SW_INDEX, 0,
218 			AUX_SW_DATA_RW, 0,
219 			AUX_SW_AUTOINCREMENT_DISABLE, 1,
220 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
221 
222 	value = REG_SET_2(AUX_SW_DATA, value,
223 			AUX_SW_AUTOINCREMENT_DISABLE, 0,
224 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
225 
226 	value = REG_SET(AUX_SW_DATA, value,
227 			AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
228 
229 	if (request->length) {
230 		value = REG_SET(AUX_SW_DATA, value,
231 				AUX_SW_DATA, request->length - 1);
232 	}
233 
234 	if (is_write) {
235 		/* Load the HW buffer with the Data to be sent.
236 		 * This is relevant for write operation.
237 		 * For read, the data recived data will be
238 		 * processed in process_channel_reply().
239 		 */
240 		uint32_t i = 0;
241 
242 		while (i < request->length) {
243 			value = REG_SET(AUX_SW_DATA, value,
244 					AUX_SW_DATA, request->data[i]);
245 
246 			++i;
247 		}
248 	}
249 
250 	REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
251 }
252 
253 static int read_channel_reply(struct aux_engine *engine, uint32_t size,
254 			      uint8_t *buffer, uint8_t *reply_result,
255 			      uint32_t *sw_status)
256 {
257 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
258 	uint32_t bytes_replied;
259 	uint32_t reply_result_32;
260 
261 	*sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
262 			     &bytes_replied);
263 
264 	/* In case HPD is LOW, exit AUX transaction */
265 	if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
266 		return -1;
267 
268 	/* Need at least the status byte */
269 	if (!bytes_replied)
270 		return -1;
271 
272 	REG_UPDATE_1BY1_3(AUX_SW_DATA,
273 			  AUX_SW_INDEX, 0,
274 			  AUX_SW_AUTOINCREMENT_DISABLE, 1,
275 			  AUX_SW_DATA_RW, 1);
276 
277 	REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
278 	reply_result_32 = reply_result_32 >> 4;
279 	*reply_result = (uint8_t)reply_result_32;
280 
281 	if (reply_result_32 == 0) { /* ACK */
282 		uint32_t i = 0;
283 
284 		/* First byte was already used to get the command status */
285 		--bytes_replied;
286 
287 		/* Do not overflow buffer */
288 		if (bytes_replied > size)
289 			return -1;
290 
291 		while (i < bytes_replied) {
292 			uint32_t aux_sw_data_val;
293 
294 			REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
295 			buffer[i] = aux_sw_data_val;
296 			++i;
297 		}
298 
299 		return i;
300 	}
301 
302 	return 0;
303 }
304 
305 static void process_channel_reply(
306 	struct aux_engine *engine,
307 	struct aux_reply_transaction_data *reply)
308 {
309 	int bytes_replied;
310 	uint8_t reply_result;
311 	uint32_t sw_status;
312 
313 	bytes_replied = read_channel_reply(engine, reply->length, reply->data,
314 					   &reply_result, &sw_status);
315 
316 	/* in case HPD is LOW, exit AUX transaction */
317 	if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
318 		reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
319 		return;
320 	}
321 
322 	if (bytes_replied < 0) {
323 		/* Need to handle an error case...
324 		 * Hopefully, upper layer function won't call this function if
325 		 * the number of bytes in the reply was 0, because there was
326 		 * surely an error that was asserted that should have been
327 		 * handled for hot plug case, this could happens
328 		 */
329 		if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
330 			reply->status = AUX_TRANSACTION_REPLY_INVALID;
331 			ASSERT_CRITICAL(false);
332 			return;
333 		}
334 	} else {
335 
336 		switch (reply_result) {
337 		case 0: /* ACK */
338 			reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
339 		break;
340 		case 1: /* NACK */
341 			reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
342 		break;
343 		case 2: /* DEFER */
344 			reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
345 		break;
346 		case 4: /* AUX ACK / I2C NACK */
347 			reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
348 		break;
349 		case 8: /* AUX ACK / I2C DEFER */
350 			reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
351 		break;
352 		default:
353 			reply->status = AUX_TRANSACTION_REPLY_INVALID;
354 		}
355 	}
356 }
357 
358 static enum aux_channel_operation_result get_channel_status(
359 	struct aux_engine *engine,
360 	uint8_t *returned_bytes)
361 {
362 	struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
363 
364 	uint32_t value;
365 
366 	if (returned_bytes == NULL) {
367 		/*caller pass NULL pointer*/
368 		ASSERT_CRITICAL(false);
369 		return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
370 	}
371 	*returned_bytes = 0;
372 
373 	/* poll to make sure that SW_DONE is asserted */
374 	value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
375 				10, aux110->timeout_period/10);
376 
377 	/* in case HPD is LOW, exit AUX transaction */
378 	if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
379 		return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
380 
381 	/* Note that the following bits are set in 'status.bits'
382 	 * during CTS 4.2.1.2 (FW 3.3.1):
383 	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
384 	 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
385 	 *
386 	 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
387 	 * HW debugging bit and should be ignored.
388 	 */
389 	if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
390 		if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
391 			(value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
392 			return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
393 
394 		else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
395 			(value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
396 			(value &
397 				AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
398 			(value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
399 			return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
400 
401 		*returned_bytes = get_reg_field_value(value,
402 				AUX_SW_STATUS,
403 				AUX_SW_REPLY_BYTE_COUNT);
404 
405 		if (*returned_bytes == 0)
406 			return
407 			AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
408 		else {
409 			*returned_bytes -= 1;
410 			return AUX_CHANNEL_OPERATION_SUCCEEDED;
411 		}
412 	} else {
413 		/*time_elapsed >= aux_engine->timeout_period
414 		 *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
415 		 */
416 		ASSERT_CRITICAL(false);
417 		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
418 	}
419 }
420 static void process_read_reply(
421 	struct aux_engine *engine,
422 	struct read_command_context *ctx)
423 {
424 	engine->funcs->process_channel_reply(engine, &ctx->reply);
425 
426 	switch (ctx->reply.status) {
427 	case AUX_TRANSACTION_REPLY_AUX_ACK:
428 		ctx->defer_retry_aux = 0;
429 		if (ctx->returned_byte > ctx->current_read_length) {
430 			ctx->status =
431 				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
432 			ctx->operation_succeeded = false;
433 		} else if (ctx->returned_byte < ctx->current_read_length) {
434 			ctx->current_read_length -= ctx->returned_byte;
435 
436 			ctx->offset += ctx->returned_byte;
437 
438 			++ctx->invalid_reply_retry_aux_on_ack;
439 
440 			if (ctx->invalid_reply_retry_aux_on_ack >
441 				AUX_INVALID_REPLY_RETRY_COUNTER) {
442 				ctx->status =
443 				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
444 				ctx->operation_succeeded = false;
445 			}
446 		} else {
447 			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
448 			ctx->transaction_complete = true;
449 			ctx->operation_succeeded = true;
450 		}
451 	break;
452 	case AUX_TRANSACTION_REPLY_AUX_NACK:
453 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
454 		ctx->operation_succeeded = false;
455 	break;
456 	case AUX_TRANSACTION_REPLY_AUX_DEFER:
457 		++ctx->defer_retry_aux;
458 
459 		if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
460 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
461 			ctx->operation_succeeded = false;
462 		}
463 	break;
464 	case AUX_TRANSACTION_REPLY_I2C_DEFER:
465 		ctx->defer_retry_aux = 0;
466 
467 		++ctx->defer_retry_i2c;
468 
469 		if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
470 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
471 			ctx->operation_succeeded = false;
472 		}
473 	break;
474 	case AUX_TRANSACTION_REPLY_HPD_DISCON:
475 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
476 		ctx->operation_succeeded = false;
477 	break;
478 	default:
479 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
480 		ctx->operation_succeeded = false;
481 	}
482 }
483 static void process_read_request(
484 	struct aux_engine *engine,
485 	struct read_command_context *ctx)
486 {
487 	enum aux_channel_operation_result operation_result;
488 
489 	engine->funcs->submit_channel_request(engine, &ctx->request);
490 
491 	operation_result = engine->funcs->get_channel_status(
492 		engine, &ctx->returned_byte);
493 
494 	switch (operation_result) {
495 	case AUX_CHANNEL_OPERATION_SUCCEEDED:
496 		if (ctx->returned_byte > ctx->current_read_length) {
497 			ctx->status =
498 				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
499 			ctx->operation_succeeded = false;
500 		} else {
501 			ctx->timed_out_retry_aux = 0;
502 			ctx->invalid_reply_retry_aux = 0;
503 
504 			ctx->reply.length = ctx->returned_byte;
505 			ctx->reply.data = ctx->buffer;
506 
507 			process_read_reply(engine, ctx);
508 		}
509 	break;
510 	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
511 		++ctx->invalid_reply_retry_aux;
512 
513 		if (ctx->invalid_reply_retry_aux >
514 			AUX_INVALID_REPLY_RETRY_COUNTER) {
515 			ctx->status =
516 				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
517 			ctx->operation_succeeded = false;
518 		} else
519 			udelay(400);
520 	break;
521 	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
522 		++ctx->timed_out_retry_aux;
523 
524 		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
525 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
526 			ctx->operation_succeeded = false;
527 		} else {
528 			/* DP 1.2a, table 2-58:
529 			 * "S3: AUX Request CMD PENDING:
530 			 * retry 3 times, with 400usec wait on each"
531 			 * The HW timeout is set to 550usec,
532 			 * so we should not wait here
533 			 */
534 		}
535 	break;
536 	case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
537 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
538 		ctx->operation_succeeded = false;
539 	break;
540 	default:
541 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
542 		ctx->operation_succeeded = false;
543 	}
544 }
545 static bool read_command(
546 	struct aux_engine *engine,
547 	struct i2caux_transaction_request *request,
548 	bool middle_of_transaction)
549 {
550 	struct read_command_context ctx;
551 
552 	ctx.buffer = request->payload.data;
553 	ctx.current_read_length = request->payload.length;
554 	ctx.offset = 0;
555 	ctx.timed_out_retry_aux = 0;
556 	ctx.invalid_reply_retry_aux = 0;
557 	ctx.defer_retry_aux = 0;
558 	ctx.defer_retry_i2c = 0;
559 	ctx.invalid_reply_retry_aux_on_ack = 0;
560 	ctx.transaction_complete = false;
561 	ctx.operation_succeeded = true;
562 
563 	if (request->payload.address_space ==
564 		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
565 		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
566 		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
567 		ctx.request.address = request->payload.address;
568 	} else if (request->payload.address_space ==
569 		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
570 		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
571 		ctx.request.action = middle_of_transaction ?
572 			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
573 			I2CAUX_TRANSACTION_ACTION_I2C_READ;
574 		ctx.request.address = request->payload.address >> 1;
575 	} else {
576 		/* in DAL2, there was no return in such case */
577 		BREAK_TO_DEBUGGER();
578 		return false;
579 	}
580 
581 	ctx.request.delay = 0;
582 
583 	do {
584 		memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
585 
586 		ctx.request.data = ctx.buffer + ctx.offset;
587 		ctx.request.length = ctx.current_read_length;
588 
589 		process_read_request(engine, &ctx);
590 
591 		request->status = ctx.status;
592 
593 		if (ctx.operation_succeeded && !ctx.transaction_complete)
594 			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
595 				msleep(engine->delay);
596 	} while (ctx.operation_succeeded && !ctx.transaction_complete);
597 
598 	if (request->payload.address_space ==
599 		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
600 		DC_LOG_I2C_AUX("READ: addr:0x%x  value:0x%x Result:%d",
601 				request->payload.address,
602 				request->payload.data[0],
603 				ctx.operation_succeeded);
604 	}
605 
606 	return ctx.operation_succeeded;
607 }
608 
609 static void process_write_reply(
610 	struct aux_engine *engine,
611 	struct write_command_context *ctx)
612 {
613 	engine->funcs->process_channel_reply(engine, &ctx->reply);
614 
615 	switch (ctx->reply.status) {
616 	case AUX_TRANSACTION_REPLY_AUX_ACK:
617 		ctx->operation_succeeded = true;
618 
619 		if (ctx->returned_byte) {
620 			ctx->request.action = ctx->mot ?
621 			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
622 			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
623 
624 			ctx->current_write_length = 0;
625 
626 			++ctx->ack_m_retry;
627 
628 			if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
629 				ctx->status =
630 				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
631 				ctx->operation_succeeded = false;
632 			} else
633 				udelay(300);
634 		} else {
635 			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
636 			ctx->defer_retry_aux = 0;
637 			ctx->ack_m_retry = 0;
638 			ctx->transaction_complete = true;
639 		}
640 	break;
641 	case AUX_TRANSACTION_REPLY_AUX_NACK:
642 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
643 		ctx->operation_succeeded = false;
644 	break;
645 	case AUX_TRANSACTION_REPLY_AUX_DEFER:
646 		++ctx->defer_retry_aux;
647 
648 		if (ctx->defer_retry_aux > ctx->max_defer_retry) {
649 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
650 			ctx->operation_succeeded = false;
651 		}
652 	break;
653 	case AUX_TRANSACTION_REPLY_I2C_DEFER:
654 		ctx->defer_retry_aux = 0;
655 		ctx->current_write_length = 0;
656 
657 		ctx->request.action = ctx->mot ?
658 			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
659 			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
660 
661 		++ctx->defer_retry_i2c;
662 
663 		if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
664 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
665 			ctx->operation_succeeded = false;
666 		}
667 	break;
668 	case AUX_TRANSACTION_REPLY_HPD_DISCON:
669 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
670 		ctx->operation_succeeded = false;
671 	break;
672 	default:
673 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
674 		ctx->operation_succeeded = false;
675 	}
676 }
677 static void process_write_request(
678 	struct aux_engine *engine,
679 	struct write_command_context *ctx)
680 {
681 	enum aux_channel_operation_result operation_result;
682 
683 	engine->funcs->submit_channel_request(engine, &ctx->request);
684 
685 	operation_result = engine->funcs->get_channel_status(
686 		engine, &ctx->returned_byte);
687 
688 	switch (operation_result) {
689 	case AUX_CHANNEL_OPERATION_SUCCEEDED:
690 		ctx->timed_out_retry_aux = 0;
691 		ctx->invalid_reply_retry_aux = 0;
692 
693 		ctx->reply.length = ctx->returned_byte;
694 		ctx->reply.data = ctx->reply_data;
695 
696 		process_write_reply(engine, ctx);
697 	break;
698 	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
699 		++ctx->invalid_reply_retry_aux;
700 
701 		if (ctx->invalid_reply_retry_aux >
702 			AUX_INVALID_REPLY_RETRY_COUNTER) {
703 			ctx->status =
704 				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
705 			ctx->operation_succeeded = false;
706 		} else
707 			udelay(400);
708 	break;
709 	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
710 		++ctx->timed_out_retry_aux;
711 
712 		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
713 			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
714 			ctx->operation_succeeded = false;
715 		} else {
716 			/* DP 1.2a, table 2-58:
717 			 * "S3: AUX Request CMD PENDING:
718 			 * retry 3 times, with 400usec wait on each"
719 			 * The HW timeout is set to 550usec,
720 			 * so we should not wait here
721 			 */
722 		}
723 	break;
724 	case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
725 		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
726 		ctx->operation_succeeded = false;
727 	break;
728 	default:
729 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
730 		ctx->operation_succeeded = false;
731 	}
732 }
733 static bool write_command(
734 	struct aux_engine *engine,
735 	struct i2caux_transaction_request *request,
736 	bool middle_of_transaction)
737 {
738 	struct write_command_context ctx;
739 
740 	ctx.mot = middle_of_transaction;
741 	ctx.buffer = request->payload.data;
742 	ctx.current_write_length = request->payload.length;
743 	ctx.timed_out_retry_aux = 0;
744 	ctx.invalid_reply_retry_aux = 0;
745 	ctx.defer_retry_aux = 0;
746 	ctx.defer_retry_i2c = 0;
747 	ctx.ack_m_retry = 0;
748 	ctx.transaction_complete = false;
749 	ctx.operation_succeeded = true;
750 
751 	if (request->payload.address_space ==
752 		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
753 		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
754 		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
755 		ctx.request.address = request->payload.address;
756 	} else if (request->payload.address_space ==
757 		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
758 		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
759 		ctx.request.action = middle_of_transaction ?
760 			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
761 			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
762 		ctx.request.address = request->payload.address >> 1;
763 	} else {
764 		/* in DAL2, there was no return in such case */
765 		BREAK_TO_DEBUGGER();
766 		return false;
767 	}
768 
769 	ctx.request.delay = 0;
770 
771 	ctx.max_defer_retry =
772 		(engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
773 			engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
774 
775 	do {
776 		ctx.request.data = ctx.buffer;
777 		ctx.request.length = ctx.current_write_length;
778 
779 		process_write_request(engine, &ctx);
780 
781 		request->status = ctx.status;
782 
783 		if (ctx.operation_succeeded && !ctx.transaction_complete)
784 			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
785 				msleep(engine->delay);
786 	} while (ctx.operation_succeeded && !ctx.transaction_complete);
787 
788 	if (request->payload.address_space ==
789 		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
790 		DC_LOG_I2C_AUX("WRITE: addr:0x%x  value:0x%x Result:%d",
791 				request->payload.address,
792 				request->payload.data[0],
793 				ctx.operation_succeeded);
794 	}
795 
796 	return ctx.operation_succeeded;
797 }
798 static bool end_of_transaction_command(
799 	struct aux_engine *engine,
800 	struct i2caux_transaction_request *request)
801 {
802 	struct i2caux_transaction_request dummy_request;
803 	uint8_t dummy_data;
804 
805 	/* [tcheng] We only need to send the stop (read with MOT = 0)
806 	 * for I2C-over-Aux, not native AUX
807 	 */
808 
809 	if (request->payload.address_space !=
810 		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
811 		return false;
812 
813 	dummy_request.operation = request->operation;
814 	dummy_request.payload.address_space = request->payload.address_space;
815 	dummy_request.payload.address = request->payload.address;
816 
817 	/*
818 	 * Add a dummy byte due to some receiver quirk
819 	 * where one byte is sent along with MOT = 0.
820 	 * Ideally this should be 0.
821 	 */
822 
823 	dummy_request.payload.length = 0;
824 	dummy_request.payload.data = &dummy_data;
825 
826 	if (request->operation == I2CAUX_TRANSACTION_READ)
827 		return read_command(engine, &dummy_request, false);
828 	else
829 		return write_command(engine, &dummy_request, false);
830 
831 	/* according Syed, it does not need now DoDummyMOT */
832 }
833 static bool submit_request(
834 	struct aux_engine *engine,
835 	struct i2caux_transaction_request *request,
836 	bool middle_of_transaction)
837 {
838 
839 	bool result;
840 	bool mot_used = true;
841 
842 	switch (request->operation) {
843 	case I2CAUX_TRANSACTION_READ:
844 		result = read_command(engine, request, mot_used);
845 	break;
846 	case I2CAUX_TRANSACTION_WRITE:
847 		result = write_command(engine, request, mot_used);
848 	break;
849 	default:
850 		result = false;
851 	}
852 
853 	/* [tcheng]
854 	 * need to send stop for the last transaction to free up the AUX
855 	 * if the above command fails, this would be the last transaction
856 	 */
857 
858 	if (!middle_of_transaction || !result)
859 		end_of_transaction_command(engine, request);
860 
861 	/* mask AUX interrupt */
862 
863 	return result;
864 }
865 
866 static
867 enum i2caux_engine_type get_engine_type(
868 		const struct aux_engine *engine)
869 {
870 	return I2CAUX_ENGINE_TYPE_AUX;
871 }
872 
873 static bool acquire(
874 	struct aux_engine *engine,
875 	struct ddc *ddc)
876 {
877 
878 	enum gpio_result result;
879 
880 	if (engine->funcs->is_engine_available) {
881 		/*check whether SW could use the engine*/
882 		if (!engine->funcs->is_engine_available(engine))
883 			return false;
884 	}
885 
886 	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
887 		GPIO_DDC_CONFIG_TYPE_MODE_AUX);
888 
889 	if (result != GPIO_RESULT_OK)
890 		return false;
891 
892 	if (!engine->funcs->acquire_engine(engine)) {
893 		dal_ddc_close(ddc);
894 		return false;
895 	}
896 
897 	engine->ddc = ddc;
898 
899 	return true;
900 }
901 
902 static const struct aux_engine_funcs aux_engine_funcs = {
903 	.acquire_engine = acquire_engine,
904 	.submit_channel_request = submit_channel_request,
905 	.process_channel_reply = process_channel_reply,
906 	.read_channel_reply = read_channel_reply,
907 	.get_channel_status = get_channel_status,
908 	.is_engine_available = is_engine_available,
909 	.release_engine = release_engine,
910 	.destroy_engine = dce110_engine_destroy,
911 	.submit_request = submit_request,
912 	.get_engine_type = get_engine_type,
913 	.acquire = acquire,
914 };
915 
916 void dce110_engine_destroy(struct aux_engine **engine)
917 {
918 
919 	struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
920 
921 	kfree(engine110);
922 	*engine = NULL;
923 
924 }
925 struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
926 		struct dc_context *ctx,
927 		uint32_t inst,
928 		uint32_t timeout_period,
929 		const struct dce110_aux_registers *regs)
930 {
931 	aux_engine110->base.ddc = NULL;
932 	aux_engine110->base.ctx = ctx;
933 	aux_engine110->base.delay = 0;
934 	aux_engine110->base.max_defer_write_retry = 0;
935 	aux_engine110->base.funcs = &aux_engine_funcs;
936 	aux_engine110->base.inst = inst;
937 	aux_engine110->timeout_period = timeout_period;
938 	aux_engine110->regs = regs;
939 
940 	return &aux_engine110->base;
941 }
942 
943