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 {