drm/amd/display: Ignore First MST Sideband Message Return Error
[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>
This commit is contained in:
parent
50e8ca0b67
commit
57b9f3384c
@ -72,6 +72,7 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
|
||||||
#include <drm/display/drm_dp_mst_helper.h>
|
#include <drm/display/drm_dp_mst_helper.h>
|
||||||
#include <drm/display/drm_hdmi_helper.h>
|
#include <drm/display/drm_hdmi_helper.h>
|
||||||
@ -1401,6 +1402,41 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev)
|
|||||||
return false;
|
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)
|
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct dc_init_data init_data;
|
struct dc_init_data init_data;
|
||||||
@ -1529,6 +1565,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||||||
init_data.flags.enable_mipi_converter_optimization = true;
|
init_data.flags.enable_mipi_converter_optimization = true;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&adev->dm.da_list);
|
INIT_LIST_HEAD(&adev->dm.da_list);
|
||||||
|
|
||||||
|
retrieve_dmi_info(&adev->dm);
|
||||||
|
|
||||||
/* Display Core create. */
|
/* Display Core create. */
|
||||||
adev->dm.dc = dc_create(&init_data);
|
adev->dm.dc = dc_create(&init_data);
|
||||||
|
|
||||||
|
@ -547,6 +547,14 @@ struct amdgpu_display_manager {
|
|||||||
* last successfully applied backlight values.
|
* last successfully applied backlight values.
|
||||||
*/
|
*/
|
||||||
u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
|
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 {
|
enum dsc_clock_force_state {
|
||||||
|
@ -56,6 +56,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
|||||||
ssize_t result = 0;
|
ssize_t result = 0;
|
||||||
struct aux_payload payload;
|
struct aux_payload payload;
|
||||||
enum aux_return_code_type operation_result;
|
enum aux_return_code_type operation_result;
|
||||||
|
struct amdgpu_device *adev;
|
||||||
|
struct ddc_service *ddc;
|
||||||
|
|
||||||
if (WARN_ON(msg->size > 16))
|
if (WARN_ON(msg->size > 16))
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
@ -74,6 +76,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,
|
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
|
||||||
&operation_result);
|
&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)
|
if (payload.write && result >= 0)
|
||||||
result = msg->size;
|
result = msg->size;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user