Blob Blame History Raw
From: Hersen Wu <hersenxs.wu@amd.com>
Date: Mon, 23 Apr 2018 19:21:45 -0400
Subject: drm/amd/display: AUX will exit when HPD LOW detected
Git-commit: 73770ca53f63489b32175ab8b5ddd4632b747275
Patch-mainline: v4.19-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

This change shorten wait time when HPD LOW. With HPD LOW, without this
change, AUX routine delay is 450us. With this change, it is 42us.

Signed-off-by: Hersen Wu <hersenxs.wu@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c               |   16 +++++++
 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h               |    5 +-
 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c |   22 +++++++---
 drivers/gpu/drm/amd/display/dc/i2caux/engine.h                   |    3 -
 drivers/gpu/drm/amd/display/include/ddc_service_types.h          |    3 -
 5 files changed, 41 insertions(+), 8 deletions(-)

--- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
@@ -157,6 +157,10 @@ static void process_read_reply(
 			ctx->operation_succeeded = false;
 		}
 	break;
+	case AUX_TRANSACTION_REPLY_HPD_DISCON:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
+		ctx->operation_succeeded = false;
+	break;
 	default:
 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
 		ctx->operation_succeeded = false;
@@ -215,6 +219,10 @@ static void process_read_request(
 			 * so we should not wait here */
 		}
 	break;
+	case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
+		ctx->operation_succeeded = false;
+	break;
 	default:
 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
 		ctx->operation_succeeded = false;
@@ -370,6 +378,10 @@ static void process_write_reply(
 			ctx->operation_succeeded = false;
 		}
 	break;
+	case AUX_TRANSACTION_REPLY_HPD_DISCON:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
+		ctx->operation_succeeded = false;
+	break;
 	default:
 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
 		ctx->operation_succeeded = false;
@@ -422,6 +434,10 @@ static void process_write_request(
 			 * so we should not wait here */
 		}
 	break;
+	case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
+		ctx->operation_succeeded = false;
+	break;
 	default:
 		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
 		ctx->operation_succeeded = false;
--- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h
@@ -51,6 +51,8 @@ enum aux_transaction_reply {
 	AUX_TRANSACTION_REPLY_I2C_NACK = 0x10,
 	AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20,
 
+	AUX_TRANSACTION_REPLY_HPD_DISCON = 0x40,
+
 	AUX_TRANSACTION_REPLY_INVALID = 0xFF
 };
 
@@ -64,7 +66,8 @@ enum aux_channel_operation_result {
 	AUX_CHANNEL_OPERATION_SUCCEEDED,
 	AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN,
 	AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY,
-	AUX_CHANNEL_OPERATION_FAILED_TIMEOUT
+	AUX_CHANNEL_OPERATION_FAILED_TIMEOUT,
+	AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON
 };
 
 struct aux_engine;
--- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
@@ -291,6 +291,12 @@ static void process_channel_reply(
 	value = REG_GET(AUX_SW_STATUS,
 			AUX_SW_REPLY_BYTE_COUNT, &bytes_replied);
 
+	/* in case HPD is LOW, exit AUX transaction */
+	if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
+		reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
+		return;
+	}
+
 	if (bytes_replied) {
 		uint32_t reply_result;
 
@@ -347,8 +353,10 @@ static void process_channel_reply(
 		 * because there was surely an error that was asserted
 		 * that should have been handled
 		 * for hot plug case, this could happens*/
-		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
+			reply->status = AUX_TRANSACTION_REPLY_INVALID;
 			ASSERT_CRITICAL(false);
+		}
 	}
 }
 
@@ -371,6 +379,10 @@ static enum aux_channel_operation_result
 	value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
 				10, aux110->timeout_period/10);
 
+	/* in case HPD is LOW, exit AUX transaction */
+	if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+		return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
+
 	/* Note that the following bits are set in 'status.bits'
 	 * during CTS 4.2.1.2 (FW 3.3.1):
 	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
@@ -402,10 +414,10 @@ static enum aux_channel_operation_result
 			return AUX_CHANNEL_OPERATION_SUCCEEDED;
 		}
 	} else {
-		/*time_elapsed >= aux_engine->timeout_period */
-		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
-			ASSERT_CRITICAL(false);
-
+		/*time_elapsed >= aux_engine->timeout_period
+		 *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
+		 */
+		ASSERT_CRITICAL(false);
 		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
 	}
 }
--- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h
@@ -53,7 +53,8 @@ enum i2caux_transaction_status {
 	I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE,
 	I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION,
 	I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION,
-	I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW
+	I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW,
+	I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON
 };
 
 struct i2caux_transaction_request {
--- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h
@@ -40,7 +40,8 @@ enum ddc_result {
 	DDC_RESULT_FAILED_INCOMPLETE,
 	DDC_RESULT_FAILED_OPERATION,
 	DDC_RESULT_FAILED_INVALID_OPERATION,
-	DDC_RESULT_FAILED_BUFFER_OVERFLOW
+	DDC_RESULT_FAILED_BUFFER_OVERFLOW,
+	DDC_RESULT_FAILED_HPD_DISCON
 };
 
 enum ddc_service_type {