summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/ast
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2024-07-17 16:24:19 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2024-07-30 12:15:37 +0200
commit2281475168d2ab3fbd763c2fd762f99a411fa1b6 (patch)
treeec53dd17b217a5453c8583e810dfe9ac4406cf89 /drivers/gpu/drm/ast
parentdrm/ast: astdp: Only test HDP state in ast_astdp_is_connected() (diff)
downloadlinux-2281475168d2ab3fbd763c2fd762f99a411fa1b6.tar.xz
linux-2281475168d2ab3fbd763c2fd762f99a411fa1b6.zip
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
Diffstat (limited to 'drivers/gpu/drm/ast')
-rw-r--r--drivers/gpu/drm/ast/ast_dp.c45
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h1
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c2
-rw-r--r--drivers/gpu/drm/ast/ast_reg.h3
4 files changed, 26 insertions, 25 deletions
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
index 4bd98c720d4a..0d9615656539 100644
--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -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 @@ err_astdp_jump_out_loop_of_edid:
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,16 +171,13 @@ 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,
+ video_on_off <<= 4;
+ while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF,
ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
- // wait 1 ms
- mdelay(1);
- if (++i > 200)
- break;
- }
+ // wait 1 ms
+ mdelay(1);
+ if (++i > 200)
+ break;
}
}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 80e968f15fc9..b54a89676e9f 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -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);
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index dc8f639e82fd..0a206b17e22b 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -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);
}
diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h
index e61954dabf1a..28bb43f6795b 100644
--- a/drivers/gpu/drm/ast/ast_reg.h
+++ b/drivers/gpu/drm/ast/ast_reg.h
@@ -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)