Commit acea108f authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher
Browse files

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: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Acked-by: default avatarSolomon Chiu <solomon.chiu@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 3590b44b
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@
#include <linux/pci.h>
#include <linux/firmware.h>
#include <linux/component.h>
#include <linux/dmi.h>

#include <drm/display/drm_dp_mst_helper.h>
#include <drm/display/drm_hdmi_helper.h>
@@ -1382,6 +1383,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;
@@ -1508,6 +1544,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
	}

	INIT_LIST_HEAD(&adev->dm.da_list);

	retrieve_dmi_info(&adev->dm);

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

+8 −0
Original line number Diff line number Diff line
@@ -540,6 +540,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 {
+17 −0
Original line number Diff line number Diff line
@@ -56,6 +56,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;
@@ -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,
				      &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;