Commit 22814751 authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

drm/ast: astdp: Perform link training during atomic_enable



The place for link training is in the encoder's atomic_enable
helper. Remove all related tests from other helper ASTDP functions;
especially ast_astdp_is_connected(), which tests HPD status.

DP link training is controlled by the firmware. A status flag reports
success or failure. The process can be fragile on Aspeed hardware. Moving
the test from connector detection to the atomic_enable allows for several
retries and a longer timeout.

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarJocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240717143319.104012-5-tzimmermann@suse.de
parent cbacb1b7
Loading
Loading
Loading
Loading
+22 −23
Original line number Diff line number Diff line
@@ -11,8 +11,6 @@ bool ast_astdp_is_connected(struct ast_device *ast)
{
	if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD))
		return false;
	if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS))
		return false;
	return true;
}

@@ -22,14 +20,10 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
	u8 i = 0, j = 0;

	/*
	 * CRDC[b0]: DP link success
	 * CRE5[b0]: Host reading EDID process is done
	 */
	if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS) &&
		ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5,
								ASTDP_HOST_EDID_READ_DONE_MASK))) {
	if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
		goto err_astdp_edid_not_ready;
	}

	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
							0x00);
@@ -58,11 +52,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
			 */
			mdelay(j+1);

			if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC,
							ASTDP_LINK_SUCCESS))) {
				goto err_astdp_jump_out_loop_of_edid;
			}

			j++;
			if (j > 200)
				goto err_astdp_jump_out_loop_of_edid;
@@ -106,8 +95,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
	return (~(j+256) + 1);

err_astdp_edid_not_ready:
	if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS)))
		return (~0xDC + 1);
	if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
		return (~0xE5 + 1);

@@ -158,7 +145,22 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on)
	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
}

void ast_dp_link_training(struct ast_device *ast)
{
	struct drm_device *dev = &ast->base;
	unsigned int i = 10;

	while (i--) {
		u8 vgacrdc = ast_get_index_reg(ast, AST_IO_VGACRI, 0xdc);

		if (vgacrdc & AST_IO_VGACRDC_LINK_SUCCESS)
			break;
		if (i)
			msleep(100);
	}
	if (!i)
		drm_err(dev, "Link training failed\n");
}

void ast_dp_set_on_off(struct drm_device *dev, bool on)
{
@@ -169,8 +171,6 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
	// Video On/Off
	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);

	// If DP plug in and link successful then check video on / off status
	if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS)) {
	video_on_off <<= 4;
	while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF,
						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
@@ -180,7 +180,6 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
			break;
	}
}
}

void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
{
+1 −0
Original line number Diff line number Diff line
@@ -473,6 +473,7 @@ bool ast_astdp_is_connected(struct ast_device *ast);
int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata);
int ast_dp_launch(struct ast_device *ast);
void ast_dp_power_on_off(struct drm_device *dev, bool no);
void ast_dp_link_training(struct ast_device *ast);
void ast_dp_set_on_off(struct drm_device *dev, bool no);
void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);

+2 −0
Original line number Diff line number Diff line
@@ -1621,6 +1621,8 @@ static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
	struct ast_device *ast = to_ast_device(dev);

	ast_dp_power_on_off(dev, AST_DP_POWER_ON);
	ast_dp_link_training(ast);

	ast_wait_for_vretrace(ast);
	ast_dp_set_on_off(dev, 1);
}
+1 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#define AST_IO_VGACRCB_HWC_ENABLED	BIT(1)

#define AST_IO_VGACRD1_MCU_FW_EXECUTING	BIT(5)
#define AST_IO_VGACRDC_LINK_SUCCESS	BIT(0)
#define AST_IO_VGACRDF_HPD		BIT(0)

#define AST_IO_VGAIR1_R			(0x5A)
@@ -70,10 +71,8 @@
#define AST_DP_VIDEO_ENABLE		BIT(0)

/*
 * CRDC[b0]: DP link success
 * CRE5[b0]: Host reading EDID process is done
 */
#define ASTDP_LINK_SUCCESS		BIT(0)
#define ASTDP_HOST_EDID_READ_DONE	BIT(0)
#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)