Skip to content

Commit

Permalink
drm/amd/display: Ignore First MST Sideband Message Return Error
Browse files Browse the repository at this point in the history
[ Upstream commit acea108 ]

[why]
First MST sideband message returns AUX_RET_ERROR_HPD_DISCON
on certain intel platform. Aux transaction considered failure
if HPD unexpected pulled low. The actual aux transaction success
in such case, hence do not return error.

[how]
Not returning error when AUX_RET_ERROR_HPD_DISCON detected
on the first sideband message.

v2: squash in additional DMI entries
v3: squash in static fix

Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Acked-by: Solomon Chiu <solomon.chiu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Fangzhi Zuo authored and gregkh committed Jul 29, 2022
1 parent 8bae037 commit c7720f2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
39 changes: 39 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include <linux/pci.h>
#include <linux/firmware.h>
#include <linux/component.h>
#include <linux/dmi.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
Expand Down Expand Up @@ -1344,6 +1345,41 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev)
return false;
}

static const struct dmi_system_id hpd_disconnect_quirk_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
},
},
{}
};

static void retrieve_dmi_info(struct amdgpu_display_manager *dm)
{
const struct dmi_system_id *dmi_id;

dm->aux_hpd_discon_quirk = false;

dmi_id = dmi_first_match(hpd_disconnect_quirk_table);
if (dmi_id) {
dm->aux_hpd_discon_quirk = true;
DRM_INFO("aux_hpd_discon_quirk attached\n");
}
}

static int amdgpu_dm_init(struct amdgpu_device *adev)
{
struct dc_init_data init_data;
Expand Down Expand Up @@ -1435,6 +1471,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.flags.power_down_display_on_boot = true;

INIT_LIST_HEAD(&adev->dm.da_list);

retrieve_dmi_info(&adev->dm);

/* Display Core create. */
adev->dm.dc = dc_create(&init_data);

Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,14 @@ struct amdgpu_display_manager {
* last successfully applied backlight values.
*/
u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];

/**
* @aux_hpd_discon_quirk:
*
* quirk for hpd discon while aux is on-going.
* occurred on certain intel platform
*/
bool aux_hpd_discon_quirk;
};

enum dsc_clock_force_state {
Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
ssize_t result = 0;
struct aux_payload payload;
enum aux_return_code_type operation_result;
struct amdgpu_device *adev;
struct ddc_service *ddc;

if (WARN_ON(msg->size > 16))
return -E2BIG;
Expand All @@ -71,6 +73,21 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
&operation_result);

/*
* w/a on certain intel platform where hpd is unexpected to pull low during
* 1st sideband message transaction by return AUX_RET_ERROR_HPD_DISCON
* aux transaction is succuess in such case, therefore bypass the error
*/
ddc = TO_DM_AUX(aux)->ddc_service;
adev = ddc->ctx->driver_context;
if (adev->dm.aux_hpd_discon_quirk) {
if (msg->address == DP_SIDEBAND_MSG_DOWN_REQ_BASE &&
operation_result == AUX_RET_ERROR_HPD_DISCON) {
result = 0;
operation_result = AUX_RET_SUCCESS;
}
}

if (payload.write && result >= 0)
result = msg->size;

Expand Down

0 comments on commit c7720f2

Please sign in to comment.