From: Baihan Li <libai...@huawei.com> Our chip support KVM over IP feature, so hibmc diiver need to support displaying without any connectors plugged in. If no connectors connected, set the vdac connector status to 'connected' to handle BMC KVM. Use is_connected to check all physical outputs. For get_modes: using BMC modes for connector if no display is attached to phys VGA cable, otherwise use EDID modes by drm_connector_helper_get_modes.
Fixes: 4c962bc929f1 ("drm/hisilicon/hibmc: Add vga connector detect functions") Signed-off-by: Baihan Li <libai...@huawei.com> Signed-off-by: Yongbang Shi <shiyongb...@huawei.com> --- ChangeLog: v2 -> v3: - fix hibmc_connector_get_modes() and hibmc_vdac_detect() to realize BMC KVM, suggested by Dmitry Baryshkov. --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c | 5 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 4 ++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 55 +++++++++++++------ 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c index 99b30a6c7e06..262ebe6138f0 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c @@ -58,9 +58,12 @@ static int hibmc_dp_detect(struct drm_connector *connector, { struct hibmc_drm_private *priv = to_hibmc_drm_private(connector->dev); - if (!hibmc_dp_detect_link(&priv->dp)) + if (!hibmc_dp_detect_link(&priv->dp)) { + priv->is_connected |= BIT(0); return connector_status_connected; + } + priv->is_connected &= ~BIT(0); return connector_status_disconnected; } diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index ca8502e2760c..d68588ecec9b 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -31,6 +31,7 @@ struct hibmc_vdac { struct drm_connector connector; struct i2c_adapter adapter; struct i2c_algo_bit_data bit_data; + int phys_status; }; struct hibmc_drm_private { @@ -43,6 +44,9 @@ struct hibmc_drm_private { struct drm_crtc crtc; struct hibmc_vdac vdac; struct hibmc_dp dp; + + /* VGA and DP phys connect status, BIT(0) is DP, BIT(1) is VGA */ + int is_connected; }; static inline struct hibmc_vdac *to_hibmc_vdac(struct drm_connector *connector) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 841e81f47b68..3cdf640d1785 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -25,27 +25,18 @@ static int hibmc_connector_get_modes(struct drm_connector *connector) { struct hibmc_vdac *vdac = to_hibmc_vdac(connector); - const struct drm_edid *drm_edid; int count; - drm_edid = drm_edid_read_ddc(connector, &vdac->adapter); - - drm_edid_connector_update(connector, drm_edid); - - if (drm_edid) { - count = drm_edid_connector_add_modes(connector); - if (count) - goto out; + if (vdac->phys_status == connector_status_connected) { + count = drm_connector_helper_get_modes(connector); + } else { + drm_edid_connector_update(connector, NULL); + count = drm_add_modes_noedid(connector, + connector->dev->mode_config.max_width, + connector->dev->mode_config.max_height); + drm_set_preferred_mode(connector, 1024, 768); // 1024x768 } - count = drm_add_modes_noedid(connector, - connector->dev->mode_config.max_width, - connector->dev->mode_config.max_height); - drm_set_preferred_mode(connector, 1024, 768); - -out: - drm_edid_free(drm_edid); - return count; } @@ -57,10 +48,38 @@ static void hibmc_connector_destroy(struct drm_connector *connector) drm_connector_cleanup(connector); } +static int hibmc_vdac_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct hibmc_drm_private *priv = to_hibmc_drm_private(connector->dev); + struct hibmc_vdac *vdac = to_hibmc_vdac(connector); + enum drm_connector_status status; + + status = drm_connector_helper_detect_from_ddc(connector, ctx, force); + + vdac->phys_status = status; + + if (status == connector_status_connected) { + priv->is_connected |= BIT(1); + return connector_status_connected; + } + + priv->is_connected &= ~BIT(1); + + /* if all connectors are disconnected, + * return connected to support BMC KVM display. + */ + if (!priv->is_connected) + return connector_status_connected; + + return connector_status_disconnected; +} + static const struct drm_connector_helper_funcs hibmc_connector_helper_funcs = { .get_modes = hibmc_connector_get_modes, - .detect_ctx = drm_connector_helper_detect_from_ddc, + .detect_ctx = hibmc_vdac_detect, }; static const struct drm_connector_funcs hibmc_connector_funcs = { -- 2.33.0