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: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240717143319.104012-5-tzimmermann@suse.de
This commit is contained in:
parent
cbacb1b744
commit
2281475168
4 changed files with 26 additions and 25 deletions
|
@ -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)
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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 @@ err_astdp_jump_out_loop_of_edid:
|
||||||
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)
|
||||||
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)
|
||||||
// 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);
|
||||||
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,
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue