Commit f81bb0ac authored by Jocelyn Falempe's avatar Jocelyn Falempe

drm/ast: report connection status on Display Port.

Aspeed always report the display port as "connected", because it
doesn't set a .detect_ctx callback.
Fix this by providing the proper detect callback for astdp and dp501.

This also fixes the following regression:
Since commit fae7d186 ("drm/probe-helper: Default to 640x480 if no
EDID on DP") The default resolution is now 640x480 when no monitor is
connected. But Aspeed graphics is mostly used in servers, where no monitor
is attached. This also affects the remote BMC resolution to 640x480, which
is inconvenient, and breaks the anaconda installer.

v2: Add .detect callback to the dp/dp501 connector (Jani Nikula)
v3: Use .detect_ctx callback, and refactors (Thomas Zimmermann)
    Add a BMC virtual connector
v4: Better indent detect_ctx() functions (Thomas Zimmermann)
v5: Enable polling of the dp and dp501 connector status
    (Thomas Zimmermann)
v6: Change check order in ast_astdp_is_connected (Jammy Huang)

Fixes: fae7d186 ("drm/probe-helper: Default to 640x480 if no EDID on DP")
Signed-off-by: default avatarJocelyn Falempe <jfalempe@redhat.com>
Reviewed-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230713134316.332502-2-jfalempe@redhat.com
parent e329cb53
...@@ -7,6 +7,17 @@ ...@@ -7,6 +7,17 @@
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include "ast_drv.h" #include "ast_drv.h"
bool ast_astdp_is_connected(struct ast_device *ast)
{
if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING))
return false;
if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))
return false;
if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS))
return false;
return true;
}
int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
{ {
struct ast_device *ast = to_ast_device(dev); struct ast_device *ast = to_ast_device(dev);
......
...@@ -272,11 +272,9 @@ static bool ast_launch_m68k(struct drm_device *dev) ...@@ -272,11 +272,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
return true; return true;
} }
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) bool ast_dp501_is_connected(struct ast_device *ast)
{ {
struct ast_device *ast = to_ast_device(dev); u32 boot_address, offset, data;
u32 i, boot_address, offset, data;
u32 *pEDIDidx;
if (ast->config_mode == ast_use_p2a) { if (ast->config_mode == ast_use_p2a) {
boot_address = get_fw_base(ast); boot_address = get_fw_base(ast);
...@@ -292,14 +290,6 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) ...@@ -292,14 +290,6 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
data = ast_mindwm(ast, boot_address + offset); data = ast_mindwm(ast, boot_address + offset);
if (!(data & AST_DP501_PNP_CONNECTED)) if (!(data & AST_DP501_PNP_CONNECTED))
return false; return false;
/* Read EDID */
offset = AST_DP501_EDID_DATA;
for (i = 0; i < 128; i += 4) {
data = ast_mindwm(ast, boot_address + offset + i);
pEDIDidx = (u32 *)(ediddata + i);
*pEDIDidx = data;
}
} else { } else {
if (!ast->dp501_fw_buf) if (!ast->dp501_fw_buf)
return false; return false;
...@@ -319,7 +309,30 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) ...@@ -319,7 +309,30 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
data = readl(ast->dp501_fw_buf + offset); data = readl(ast->dp501_fw_buf + offset);
if (!(data & AST_DP501_PNP_CONNECTED)) if (!(data & AST_DP501_PNP_CONNECTED))
return false; return false;
}
return true;
}
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
{
struct ast_device *ast = to_ast_device(dev);
u32 i, boot_address, offset, data;
u32 *pEDIDidx;
if (!ast_dp501_is_connected(ast))
return false;
if (ast->config_mode == ast_use_p2a) {
boot_address = get_fw_base(ast);
/* Read EDID */
offset = AST_DP501_EDID_DATA;
for (i = 0; i < 128; i += 4) {
data = ast_mindwm(ast, boot_address + offset + i);
pEDIDidx = (u32 *)(ediddata + i);
*pEDIDidx = data;
}
} else {
/* Read EDID */ /* Read EDID */
offset = AST_DP501_EDID_DATA; offset = AST_DP501_EDID_DATA;
for (i = 0; i < 128; i += 4) { for (i = 0; i < 128; i += 4) {
......
...@@ -514,6 +514,7 @@ void ast_patch_ahb_2500(struct ast_device *ast); ...@@ -514,6 +514,7 @@ void ast_patch_ahb_2500(struct ast_device *ast);
/* ast dp501 */ /* ast dp501 */
void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
bool ast_dp501_is_connected(struct ast_device *ast);
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
u8 ast_get_dp501_max_clk(struct drm_device *dev); u8 ast_get_dp501_max_clk(struct drm_device *dev);
void ast_init_3rdtx(struct drm_device *dev); void ast_init_3rdtx(struct drm_device *dev);
...@@ -522,6 +523,7 @@ void ast_init_3rdtx(struct drm_device *dev); ...@@ -522,6 +523,7 @@ void ast_init_3rdtx(struct drm_device *dev);
struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
/* aspeed DP */ /* aspeed DP */
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);
void ast_dp_launch(struct drm_device *dev); void ast_dp_launch(struct drm_device *dev);
void ast_dp_power_on_off(struct drm_device *dev, bool no); void ast_dp_power_on_off(struct drm_device *dev, bool no);
......
...@@ -1582,8 +1582,20 @@ static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector) ...@@ -1582,8 +1582,20 @@ static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
return 0; return 0;
} }
static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct ast_device *ast = to_ast_device(connector->dev);
if (ast_dp501_is_connected(ast))
return connector_status_connected;
return connector_status_disconnected;
}
static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = { static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
.get_modes = ast_dp501_connector_helper_get_modes, .get_modes = ast_dp501_connector_helper_get_modes,
.detect_ctx = ast_dp501_connector_helper_detect_ctx,
}; };
static const struct drm_connector_funcs ast_dp501_connector_funcs = { static const struct drm_connector_funcs ast_dp501_connector_funcs = {
...@@ -1608,7 +1620,7 @@ static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector ...@@ -1608,7 +1620,7 @@ static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
connector->polled = DRM_CONNECTOR_POLL_CONNECT; connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
return 0; return 0;
} }
...@@ -1680,8 +1692,20 @@ static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector) ...@@ -1680,8 +1692,20 @@ static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
return 0; return 0;
} }
static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct ast_device *ast = to_ast_device(connector->dev);
if (ast_astdp_is_connected(ast))
return connector_status_connected;
return connector_status_disconnected;
}
static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = { static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
.get_modes = ast_astdp_connector_helper_get_modes, .get_modes = ast_astdp_connector_helper_get_modes,
.detect_ctx = ast_astdp_connector_helper_detect_ctx,
}; };
static const struct drm_connector_funcs ast_astdp_connector_funcs = { static const struct drm_connector_funcs ast_astdp_connector_funcs = {
...@@ -1706,7 +1730,7 @@ static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector ...@@ -1706,7 +1730,7 @@ static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
connector->polled = DRM_CONNECTOR_POLL_CONNECT; connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
return 0; return 0;
} }
...@@ -1902,5 +1926,7 @@ int ast_mode_config_init(struct ast_device *ast) ...@@ -1902,5 +1926,7 @@ int ast_mode_config_init(struct ast_device *ast)
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return 0; return 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