diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4908-drm-amd-display-Break-out-function-to-simply-read-au.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4908-drm-amd-display-Break-out-function-to-simply-read-au.patch | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4908-drm-amd-display-Break-out-function-to-simply-read-au.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4908-drm-amd-display-Break-out-function-to-simply-read-au.patch new file mode 100644 index 00000000..73a18a5b --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4908-drm-amd-display-Break-out-function-to-simply-read-au.patch @@ -0,0 +1,200 @@ +From 462e24fa4f1c1af6bd5ee845d2f757fcd1b8dec9 Mon Sep 17 00:00:00 2001 +From: Harry Wentland <harry.wentland@amd.com> +Date: Tue, 8 May 2018 16:28:31 -0400 +Subject: [PATCH 4908/5725] drm/amd/display: Break out function to simply read + aux reply + +DRM's DP helpers take care of dealing with the error code for us. In +order not to step on each other's toes we'll need to be able to simply +read auch channel replies without further logic based on return values. + +Signed-off-by: Harry Wentland <harry.wentland@amd.com> +Reviewed-by: Sun peng Li <Sunpeng.Li@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 6 ++ + .../display/dc/i2caux/dce110/aux_engine_dce110.c | 119 ++++++++++++--------- + 2 files changed, 76 insertions(+), 49 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +index b01488f..c33a289 100644 +--- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h ++++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +@@ -44,6 +44,12 @@ struct aux_engine_funcs { + void (*process_channel_reply)( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply); ++ int (*read_channel_reply)( ++ struct aux_engine *engine, ++ uint32_t size, ++ uint8_t *buffer, ++ uint8_t *reply_result, ++ uint32_t *sw_status); + enum aux_channel_operation_result (*get_channel_status)( + struct aux_engine *engine, + uint8_t *returned_bytes); +diff --git 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 +index 2b927f2..1f39406 100644 +--- 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 +@@ -275,61 +275,92 @@ static void submit_channel_request( + REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); + } + +-static void process_channel_reply( +- struct aux_engine *engine, +- struct aux_reply_transaction_data *reply) ++static int read_channel_reply(struct aux_engine *engine, uint32_t size, ++ uint8_t *buffer, uint8_t *reply_result, ++ uint32_t *sw_status) + { + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); ++ uint32_t bytes_replied; ++ uint32_t reply_result_32; + +- /* Need to do a read to get the number of bytes to process +- * Alternatively, this information can be passed - +- * but that causes coupling which isn't good either. */ ++ *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, ++ &bytes_replied); + +- uint32_t bytes_replied; +- uint32_t value; ++ /* In case HPD is LOW, exit AUX transaction */ ++ if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) ++ return -1; + +- value = REG_GET(AUX_SW_STATUS, +- AUX_SW_REPLY_BYTE_COUNT, &bytes_replied); ++ /* Need at least the status byte */ ++ if (!bytes_replied) ++ return -1; + +- /* 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; +- } ++ REG_UPDATE_1BY1_3(AUX_SW_DATA, ++ AUX_SW_INDEX, 0, ++ AUX_SW_AUTOINCREMENT_DISABLE, 1, ++ AUX_SW_DATA_RW, 1); ++ ++ REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); ++ *reply_result = (uint8_t)reply_result_32; + +- if (bytes_replied) { +- uint32_t reply_result; ++ if (reply_result_32 >> 4 == 0) { /* ACK */ ++ uint32_t i = 0; + +- REG_UPDATE_1BY1_3(AUX_SW_DATA, +- AUX_SW_INDEX, 0, +- AUX_SW_AUTOINCREMENT_DISABLE, 1, +- AUX_SW_DATA_RW, 1); ++ /* First byte was already used to get the command status */ ++ --bytes_replied; + +- REG_GET(AUX_SW_DATA, +- AUX_SW_DATA, &reply_result); ++ /* Do not overflow buffer */ ++ if (bytes_replied > size) ++ return -1; + +- reply_result = reply_result >> 4; ++ while (i < bytes_replied) { ++ uint32_t aux_sw_data_val; + +- switch (reply_result) { +- case 0: /* ACK */ { +- uint32_t i = 0; ++ REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); ++ buffer[i] = aux_sw_data_val; ++ ++i; ++ } + +- /* first byte was already used +- * to get the command status */ +- --bytes_replied; ++ return i; ++ } ++ ++ return 0; ++} ++ ++static void process_channel_reply( ++ struct aux_engine *engine, ++ struct aux_reply_transaction_data *reply) ++{ ++ int bytes_replied; ++ uint8_t reply_result; ++ uint32_t sw_status; + +- while (i < bytes_replied) { +- uint32_t aux_sw_data_val; ++ bytes_replied = read_channel_reply(engine, reply->length, reply->data, ++ &reply_result, &sw_status); + +- REG_GET(AUX_SW_DATA, +- AUX_SW_DATA, &aux_sw_data_val); ++ /* in case HPD is LOW, exit AUX transaction */ ++ if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { ++ reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; ++ return; ++ } + +- reply->data[i] = aux_sw_data_val; +- ++i; +- } ++ if (bytes_replied < 0) { ++ /* Need to handle an error case... ++ * Hopefully, upper layer function won't call this function if ++ * the number of bytes in the reply was 0, because there was ++ * surely an error that was asserted that should have been ++ * handled for hot plug case, this could happens ++ */ ++ if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { ++ reply->status = AUX_TRANSACTION_REPLY_INVALID; ++ ASSERT_CRITICAL(false); ++ return; ++ } ++ } else { ++ reply_result = reply_result >> 4; + ++ switch (reply_result) { ++ case 0: /* ACK */ + reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; +- } + break; + case 1: /* NACK */ + reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; +@@ -346,17 +377,6 @@ static void process_channel_reply( + default: + reply->status = AUX_TRANSACTION_REPLY_INVALID; + } +- } else { +- /* Need to handle an error case... +- * hopefully, upper layer function won't call this function +- * if the number of bytes in the reply was 0 +- * 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)) { +- reply->status = AUX_TRANSACTION_REPLY_INVALID; +- ASSERT_CRITICAL(false); +- } + } + } + +@@ -427,6 +447,7 @@ static const struct aux_engine_funcs aux_engine_funcs = { + .acquire_engine = acquire_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, ++ .read_channel_reply = read_channel_reply, + .get_channel_status = get_channel_status, + .is_engine_available = is_engine_available, + }; +-- +2.7.4 + |