aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4909-drm-amd-display-Return-aux-replies-directly-to-DRM.patch
diff options
context:
space:
mode:
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.patch324
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
+