Commit 22814751 authored by Thomas Zimmermann's avatar Thomas Zimmermann

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
...@@ -11,8 +11,6 @@ bool ast_astdp_is_connected(struct ast_device *ast) ...@@ -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)) if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD))
return false; return false;
if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS))
return false;
return true; return true;
} }
...@@ -22,14 +20,10 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) ...@@ -22,14 +20,10 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
u8 i = 0, j = 0; u8 i = 0, j = 0;
/* /*
* CRDC[b0]: DP link success
* CRE5[b0]: Host reading EDID process is done * CRE5[b0]: Host reading EDID process is done
*/ */
if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS) && if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5,
ASTDP_HOST_EDID_READ_DONE_MASK))) {
goto err_astdp_edid_not_ready; goto err_astdp_edid_not_ready;
}
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
0x00); 0x00);
...@@ -58,11 +52,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) ...@@ -58,11 +52,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
*/ */
mdelay(j+1); 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++; j++;
if (j > 200) if (j > 200)
goto err_astdp_jump_out_loop_of_edid; goto err_astdp_jump_out_loop_of_edid;
...@@ -106,8 +95,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) ...@@ -106,8 +95,6 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
return (~(j+256) + 1); return (~(j+256) + 1);
err_astdp_edid_not_ready: 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))) if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
return (~0xE5 + 1); return (~0xE5 + 1);
...@@ -158,7 +145,22 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on) ...@@ -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); 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) void ast_dp_set_on_off(struct drm_device *dev, bool on)
{ {
...@@ -169,16 +171,13 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) ...@@ -169,16 +171,13 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
// Video On/Off // Video On/Off
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on); 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 video_on_off <<= 4;
if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS)) { while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF,
video_on_off <<= 4;
while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF,
ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) { ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
// wait 1 ms // wait 1 ms
mdelay(1); mdelay(1);
if (++i > 200) if (++i > 200)
break; break;
}
} }
} }
......
...@@ -473,6 +473,7 @@ bool ast_astdp_is_connected(struct ast_device *ast); ...@@ -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_astdp_read_edid(struct drm_device *dev, u8 *ediddata);
int ast_dp_launch(struct ast_device *ast); int ast_dp_launch(struct ast_device *ast);
void ast_dp_power_on_off(struct drm_device *dev, bool no); 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_on_off(struct drm_device *dev, bool no);
void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode); void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
......
...@@ -1621,6 +1621,8 @@ static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder, ...@@ -1621,6 +1621,8 @@ static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
struct ast_device *ast = to_ast_device(dev); struct ast_device *ast = to_ast_device(dev);
ast_dp_power_on_off(dev, AST_DP_POWER_ON); ast_dp_power_on_off(dev, AST_DP_POWER_ON);
ast_dp_link_training(ast);
ast_wait_for_vretrace(ast); ast_wait_for_vretrace(ast);
ast_dp_set_on_off(dev, 1); ast_dp_set_on_off(dev, 1);
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#define AST_IO_VGACRCB_HWC_ENABLED BIT(1) #define AST_IO_VGACRCB_HWC_ENABLED BIT(1)
#define AST_IO_VGACRD1_MCU_FW_EXECUTING BIT(5) #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_VGACRDF_HPD BIT(0)
#define AST_IO_VGAIR1_R (0x5A) #define AST_IO_VGAIR1_R (0x5A)
...@@ -70,10 +71,8 @@ ...@@ -70,10 +71,8 @@
#define AST_DP_VIDEO_ENABLE BIT(0) #define AST_DP_VIDEO_ENABLE BIT(0)
/* /*
* CRDC[b0]: DP link success
* CRE5[b0]: Host reading EDID process is done * 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 BIT(0)
#define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0) #define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment