Message ID | 20240717143319.104012-2-tzimmermann@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/ast: Fix DP hotplugging and clean up | expand |
On 17/07/2024 16:24, Thomas Zimmermann wrote: > Power up the ASTDP connector for connection status detection if the > connector is not active. Keep it powered if a display is attached. > > This fixes a bug where the connector does not come back after > disconnecting the display. The encoder's atomic_disable turns off > power on the physical connector. Further HPD reads will fail, > thus preventing the driver from detecting re-connected displays. > > For connectors that are actively used, only test the HPD flag without > touching power. Thanks, it looks good to me. Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> > > Fixes: f81bb0ac7872 ("drm/ast: report connection status on Display Port.") > Cc: Jocelyn Falempe <jfalempe@redhat.com> > Cc: Thomas Zimmermann <tzimmermann@suse.de> > Cc: Dave Airlie <airlied@redhat.com> > Cc: dri-devel@lists.freedesktop.org > Cc: <stable@vger.kernel.org> # v6.6+ > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > --- > drivers/gpu/drm/ast/ast_dp.c | 7 +++++++ > drivers/gpu/drm/ast/ast_drv.h | 1 + > drivers/gpu/drm/ast/ast_mode.c | 29 +++++++++++++++++++++++++++-- > 3 files changed, 35 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c > index 1e9259416980..e6c7f0d64e99 100644 > --- a/drivers/gpu/drm/ast/ast_dp.c > +++ b/drivers/gpu/drm/ast/ast_dp.c > @@ -158,7 +158,14 @@ void ast_dp_launch(struct drm_device *dev) > ASTDP_HOST_EDID_READ_DONE); > } > > +bool ast_dp_power_is_on(struct ast_device *ast) > +{ > + u8 vgacre3; > + > + vgacre3 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xe3); > > + return !(vgacre3 & AST_DP_PHY_SLEEP); > +} > > void ast_dp_power_on_off(struct drm_device *dev, bool on) > { > diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h > index ba3d86973995..47bab5596c16 100644 > --- a/drivers/gpu/drm/ast/ast_drv.h > +++ b/drivers/gpu/drm/ast/ast_drv.h > @@ -472,6 +472,7 @@ void ast_init_3rdtx(struct drm_device *dev); > bool ast_astdp_is_connected(struct ast_device *ast); > int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); > void ast_dp_launch(struct drm_device *dev); > +bool ast_dp_power_is_on(struct ast_device *ast); > void ast_dp_power_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); > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c > index dc8f639e82fd..049ee1477c33 100644 > --- a/drivers/gpu/drm/ast/ast_mode.c > +++ b/drivers/gpu/drm/ast/ast_mode.c > @@ -28,6 +28,7 @@ > * Authors: Dave Airlie <airlied@redhat.com> > */ > > +#include <linux/delay.h> > #include <linux/export.h> > #include <linux/pci.h> > > @@ -1687,11 +1688,35 @@ static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector > struct drm_modeset_acquire_ctx *ctx, > bool force) > { > + struct drm_device *dev = connector->dev; > struct ast_device *ast = to_ast_device(connector->dev); > + enum drm_connector_status status = connector_status_disconnected; > + struct drm_connector_state *connector_state = connector->state; > + bool is_active = false; > + > + mutex_lock(&ast->modeset_lock); > + > + if (connector_state && connector_state->crtc) { > + struct drm_crtc_state *crtc_state = connector_state->crtc->state; > + > + if (crtc_state && crtc_state->active) > + is_active = true; > + } > + > + if (!is_active && !ast_dp_power_is_on(ast)) { > + ast_dp_power_on_off(dev, true); > + msleep(50); > + } > > if (ast_astdp_is_connected(ast)) > - return connector_status_connected; > - return connector_status_disconnected; > + status = connector_status_connected; > + > + if (!is_active && status == connector_status_disconnected) > + ast_dp_power_on_off(dev, false); > + > + mutex_unlock(&ast->modeset_lock); > + > + return status; > } > > static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
I merged this patch into drm-misc-fixes. Am 17.07.24 um 16:24 schrieb Thomas Zimmermann: > Power up the ASTDP connector for connection status detection if the > connector is not active. Keep it powered if a display is attached. > > This fixes a bug where the connector does not come back after > disconnecting the display. The encoder's atomic_disable turns off > power on the physical connector. Further HPD reads will fail, > thus preventing the driver from detecting re-connected displays. > > For connectors that are actively used, only test the HPD flag without > touching power. > > Fixes: f81bb0ac7872 ("drm/ast: report connection status on Display Port.") > Cc: Jocelyn Falempe <jfalempe@redhat.com> > Cc: Thomas Zimmermann <tzimmermann@suse.de> > Cc: Dave Airlie <airlied@redhat.com> > Cc: dri-devel@lists.freedesktop.org > Cc: <stable@vger.kernel.org> # v6.6+ > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > --- > drivers/gpu/drm/ast/ast_dp.c | 7 +++++++ > drivers/gpu/drm/ast/ast_drv.h | 1 + > drivers/gpu/drm/ast/ast_mode.c | 29 +++++++++++++++++++++++++++-- > 3 files changed, 35 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c > index 1e9259416980..e6c7f0d64e99 100644 > --- a/drivers/gpu/drm/ast/ast_dp.c > +++ b/drivers/gpu/drm/ast/ast_dp.c > @@ -158,7 +158,14 @@ void ast_dp_launch(struct drm_device *dev) > ASTDP_HOST_EDID_READ_DONE); > } > > +bool ast_dp_power_is_on(struct ast_device *ast) > +{ > + u8 vgacre3; > + > + vgacre3 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xe3); > > + return !(vgacre3 & AST_DP_PHY_SLEEP); > +} > > void ast_dp_power_on_off(struct drm_device *dev, bool on) > { > diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h > index ba3d86973995..47bab5596c16 100644 > --- a/drivers/gpu/drm/ast/ast_drv.h > +++ b/drivers/gpu/drm/ast/ast_drv.h > @@ -472,6 +472,7 @@ void ast_init_3rdtx(struct drm_device *dev); > bool ast_astdp_is_connected(struct ast_device *ast); > int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); > void ast_dp_launch(struct drm_device *dev); > +bool ast_dp_power_is_on(struct ast_device *ast); > void ast_dp_power_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); > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c > index dc8f639e82fd..049ee1477c33 100644 > --- a/drivers/gpu/drm/ast/ast_mode.c > +++ b/drivers/gpu/drm/ast/ast_mode.c > @@ -28,6 +28,7 @@ > * Authors: Dave Airlie <airlied@redhat.com> > */ > > +#include <linux/delay.h> > #include <linux/export.h> > #include <linux/pci.h> > > @@ -1687,11 +1688,35 @@ static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector > struct drm_modeset_acquire_ctx *ctx, > bool force) > { > + struct drm_device *dev = connector->dev; > struct ast_device *ast = to_ast_device(connector->dev); > + enum drm_connector_status status = connector_status_disconnected; > + struct drm_connector_state *connector_state = connector->state; > + bool is_active = false; > + > + mutex_lock(&ast->modeset_lock); > + > + if (connector_state && connector_state->crtc) { > + struct drm_crtc_state *crtc_state = connector_state->crtc->state; > + > + if (crtc_state && crtc_state->active) > + is_active = true; > + } > + > + if (!is_active && !ast_dp_power_is_on(ast)) { > + ast_dp_power_on_off(dev, true); > + msleep(50); > + } > > if (ast_astdp_is_connected(ast)) > - return connector_status_connected; > - return connector_status_disconnected; > + status = connector_status_connected; > + > + if (!is_active && status == connector_status_disconnected) > + ast_dp_power_on_off(dev, false); > + > + mutex_unlock(&ast->modeset_lock); > + > + return status; > } > > static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 1e9259416980..e6c7f0d64e99 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -158,7 +158,14 @@ void ast_dp_launch(struct drm_device *dev) ASTDP_HOST_EDID_READ_DONE); } +bool ast_dp_power_is_on(struct ast_device *ast) +{ + u8 vgacre3; + + vgacre3 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xe3); + return !(vgacre3 & AST_DP_PHY_SLEEP); +} void ast_dp_power_on_off(struct drm_device *dev, bool on) { diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index ba3d86973995..47bab5596c16 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -472,6 +472,7 @@ void ast_init_3rdtx(struct drm_device *dev); bool ast_astdp_is_connected(struct ast_device *ast); int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void ast_dp_launch(struct drm_device *dev); +bool ast_dp_power_is_on(struct ast_device *ast); void ast_dp_power_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); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index dc8f639e82fd..049ee1477c33 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -28,6 +28,7 @@ * Authors: Dave Airlie <airlied@redhat.com> */ +#include <linux/delay.h> #include <linux/export.h> #include <linux/pci.h> @@ -1687,11 +1688,35 @@ static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector struct drm_modeset_acquire_ctx *ctx, bool force) { + struct drm_device *dev = connector->dev; struct ast_device *ast = to_ast_device(connector->dev); + enum drm_connector_status status = connector_status_disconnected; + struct drm_connector_state *connector_state = connector->state; + bool is_active = false; + + mutex_lock(&ast->modeset_lock); + + if (connector_state && connector_state->crtc) { + struct drm_crtc_state *crtc_state = connector_state->crtc->state; + + if (crtc_state && crtc_state->active) + is_active = true; + } + + if (!is_active && !ast_dp_power_is_on(ast)) { + ast_dp_power_on_off(dev, true); + msleep(50); + } if (ast_astdp_is_connected(ast)) - return connector_status_connected; - return connector_status_disconnected; + status = connector_status_connected; + + if (!is_active && status == connector_status_disconnected) + ast_dp_power_on_off(dev, false); + + mutex_unlock(&ast->modeset_lock); + + return status; } static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
Power up the ASTDP connector for connection status detection if the connector is not active. Keep it powered if a display is attached. This fixes a bug where the connector does not come back after disconnecting the display. The encoder's atomic_disable turns off power on the physical connector. Further HPD reads will fail, thus preventing the driver from detecting re-connected displays. For connectors that are actively used, only test the HPD flag without touching power. Fixes: f81bb0ac7872 ("drm/ast: report connection status on Display Port.") Cc: Jocelyn Falempe <jfalempe@redhat.com> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Dave Airlie <airlied@redhat.com> Cc: dri-devel@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v6.6+ Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/ast/ast_dp.c | 7 +++++++ drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-)