diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch new file mode 100644 index 00000000..2e84b8e9 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch @@ -0,0 +1,324 @@ +From 723cf443e6a2864784a9be8c3c31d247705eeb0e Mon Sep 17 00:00:00 2001 +From: Harry Wentland <harry.wentland@amd.com> +Date: Wed, 9 May 2018 16:26:17 -0400 +Subject: [PATCH 4909/5725] drm/amd/display: Return aux replies directly to DRM + +Currently we still go through DC code that does error checking, retries, +etc. There's no need for that since DRM already does that for us. This +simplifies the code a bit and makes it easier to debug. + +This also ensures we correctly tell DRM how many bytes have actually +been read, as we should. This allows DRM to correctly read the EDID on +the Chamelium DP port. + +Signed-off-by: Harry Wentland <harry.wentland@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 89 +++++++++------ + drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 120 ++++++++++----------- + drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 22 ++-- + 3 files changed, 117 insertions(+), 114 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index d48a37a..26d5e9d 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -79,52 +79,72 @@ static void log_dpcd(uint8_t type, + static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) + { +- enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? +- I2C_MOT_TRUE : I2C_MOT_FALSE; +- enum ddc_result res; ++ ssize_t result = 0; ++ enum i2caux_transaction_action action; ++ enum aux_transaction_type type; + + if (WARN_ON(msg->size > 16)) + return -E2BIG; + + switch (msg->request & ~DP_AUX_I2C_MOT) { + case DP_AUX_NATIVE_READ: +- res = dal_ddc_service_read_dpcd_data( +- TO_DM_AUX(aux)->ddc_service, +- false, +- I2C_MOT_UNDEF, +- msg->address, +- msg->buffer, +- msg->size); ++ type = AUX_TRANSACTION_TYPE_DP; ++ action = I2CAUX_TRANSACTION_ACTION_DP_READ; ++ ++ result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, ++ msg->address, ++ &msg->reply, ++ msg->buffer, ++ msg->size, ++ type, ++ action); + break; + case DP_AUX_NATIVE_WRITE: +- res = dal_ddc_service_write_dpcd_data( +- TO_DM_AUX(aux)->ddc_service, +- false, +- I2C_MOT_UNDEF, +- msg->address, +- msg->buffer, +- msg->size); ++ type = AUX_TRANSACTION_TYPE_DP; ++ action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; ++ ++ dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, ++ msg->address, ++ &msg->reply, ++ msg->buffer, ++ msg->size, ++ type, ++ action); ++ result = msg->size; + break; + case DP_AUX_I2C_READ: +- res = dal_ddc_service_read_dpcd_data( +- TO_DM_AUX(aux)->ddc_service, +- true, +- mot, +- msg->address, +- msg->buffer, +- msg->size); ++ type = AUX_TRANSACTION_TYPE_I2C; ++ if (msg->request & DP_AUX_I2C_MOT) ++ action = I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; ++ else ++ action = I2CAUX_TRANSACTION_ACTION_I2C_READ; ++ ++ result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, ++ msg->address, ++ &msg->reply, ++ msg->buffer, ++ msg->size, ++ type, ++ action); + break; + case DP_AUX_I2C_WRITE: +- res = dal_ddc_service_write_dpcd_data( +- TO_DM_AUX(aux)->ddc_service, +- true, +- mot, +- msg->address, +- msg->buffer, +- msg->size); ++ type = AUX_TRANSACTION_TYPE_I2C; ++ if (msg->request & DP_AUX_I2C_MOT) ++ action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; ++ else ++ action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; ++ ++ dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, ++ msg->address, ++ &msg->reply, ++ msg->buffer, ++ msg->size, ++ type, ++ action); ++ result = msg->size; + break; + default: +- return 0; ++ return -EINVAL; + } + + #ifdef TRACE_DPCD +@@ -135,7 +155,10 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, + r == DDC_RESULT_SUCESSFULL); + #endif + +- return msg->size; ++ if (result < 0) /* DC doesn't know about kernel error codes */ ++ result = -EIO; ++ ++ return result; + } + + static enum drm_connector_status +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +index d5294798b..d108ccf 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +@@ -33,6 +33,10 @@ + #include "include/vector.h" + #include "core_types.h" + #include "dc_link_ddc.h" ++#include "i2caux/engine.h" ++#include "i2caux/i2c_engine.h" ++#include "i2caux/aux_engine.h" ++#include "i2caux/i2caux.h" + + #define AUX_POWER_UP_WA_DELAY 500 + #define I2C_OVER_AUX_DEFER_WA_DELAY 70 +@@ -629,78 +633,62 @@ bool dal_ddc_service_query_ddc_data( + return ret; + } + +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- bool i2c, +- enum i2c_mot_mode mot, +- uint32_t address, +- uint8_t *data, +- uint32_t len) ++int dc_link_aux_transfer(struct ddc_service *ddc, ++ unsigned int address, ++ uint8_t *reply, ++ void *buffer, ++ unsigned int size, ++ enum aux_transaction_type type, ++ enum i2caux_transaction_action action) + { +- struct aux_payload read_payload = { +- .i2c_over_aux = i2c, +- .write = false, +- .address = address, +- .length = len, +- .data = data, +- }; +- struct aux_command command = { +- .payloads = &read_payload, +- .number_of_payloads = 1, +- .defer_delay = 0, +- .max_defer_write_retry = 0, +- .mot = mot +- }; +- +- if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +- BREAK_TO_DEBUGGER(); +- return DDC_RESULT_FAILED_INVALID_OPERATION; +- } ++ struct i2caux *i2caux = ddc->ctx->i2caux; ++ struct ddc *ddc_pin = ddc->ddc_pin; ++ struct aux_engine *engine; ++ enum aux_channel_operation_result operation_result; ++ struct aux_request_transaction_data aux_req; ++ struct aux_reply_transaction_data aux_rep; ++ uint8_t returned_bytes = 0; ++ int res = -1; ++ uint32_t status; + +- if (dal_i2caux_submit_aux_command( +- ddc->ctx->i2caux, +- ddc->ddc_pin, +- &command)) +- return DDC_RESULT_SUCESSFULL; ++ memset(&aux_req, 0, sizeof(aux_req)); ++ memset(&aux_rep, 0, sizeof(aux_rep)); + +- return DDC_RESULT_FAILED_OPERATION; +-} ++ engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc_pin); + +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- bool i2c, +- enum i2c_mot_mode mot, +- uint32_t address, +- const uint8_t *data, +- uint32_t len) +-{ +- struct aux_payload write_payload = { +- .i2c_over_aux = i2c, +- .write = true, +- .address = address, +- .length = len, +- .data = (uint8_t *)data, +- }; +- struct aux_command command = { +- .payloads = &write_payload, +- .number_of_payloads = 1, +- .defer_delay = 0, +- .max_defer_write_retry = 0, +- .mot = mot +- }; +- +- if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +- BREAK_TO_DEBUGGER(); +- return DDC_RESULT_FAILED_INVALID_OPERATION; +- } ++ aux_req.type = type; ++ aux_req.action = action; ++ ++ aux_req.address = address; ++ aux_req.delay = 0; ++ aux_req.length = size; ++ aux_req.data = buffer; ++ ++ engine->funcs->submit_channel_request(engine, &aux_req); ++ operation_result = engine->funcs->get_channel_status(engine, &returned_bytes); + +- if (dal_i2caux_submit_aux_command( +- ddc->ctx->i2caux, +- ddc->ddc_pin, +- &command)) +- return DDC_RESULT_SUCESSFULL; ++ switch (operation_result) { ++ case AUX_CHANNEL_OPERATION_SUCCEEDED: ++ res = returned_bytes; ++ ++ if (res <= size && res > 0) ++ res = engine->funcs->read_channel_reply(engine, size, ++ buffer, reply, ++ &status); ++ ++ break; ++ case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: ++ res = 0; ++ break; ++ case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN: ++ case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: ++ case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: ++ res = -1; ++ break; ++ } + +- return DDC_RESULT_FAILED_OPERATION; ++ i2caux->funcs->release_engine(i2caux, &engine->base); ++ return res; + } + + /*test only function*/ +diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +index 0bf73b7..538b833 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +@@ -102,21 +102,13 @@ bool dal_ddc_service_query_ddc_data( + uint8_t *read_buf, + uint32_t read_size); + +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- bool i2c, +- enum i2c_mot_mode mot, +- uint32_t address, +- uint8_t *data, +- uint32_t len); +- +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- bool i2c, +- enum i2c_mot_mode mot, +- uint32_t address, +- const uint8_t *data, +- uint32_t len); ++int dc_link_aux_transfer(struct ddc_service *ddc, ++ unsigned int address, ++ uint8_t *reply, ++ void *buffer, ++ unsigned int size, ++ enum aux_transaction_type type, ++ enum i2caux_transaction_action action); + + void dal_ddc_service_write_scdc_data( + struct ddc_service *ddc_service, +-- +2.7.4 + |