+static int hibmc_dp_hpd_event(struct drm_client_dev *client)
+{
+ struct hibmc_dp *dp = container_of(client, struct hibmc_dp, client);
+ struct hibmc_drm_private *priv = to_hibmc_drm_private(dp->drm_dev);
+ struct drm_display_mode *mode = &priv->crtc.state->adjusted_mode;
+ int ret;
+
+ if (dp->hpd_status) {
+ hibmc_dp_hpd_cfg(&priv->dp);
+ ret = hibmc_dp_prepare(dp, mode);
+ if (ret)
+ return ret;
+
+ hibmc_dp_display_en(dp, true);
+ } else {
+ hibmc_dp_display_en(dp, false);
+ hibmc_dp_reset_link(&priv->dp);
+ }
If I understand this correctly, you are using a separate drm_client to
enable and disable the link & display. Why is it necessary? Existing
drm_clients and userspace compositors use drm framework, they should be
able to turn the display on and off as required.
Thanks for your asking, there are cfg/reset process when the connector 's pluging in/out.
We want to cfg DP registers again when the connector changes. Not only dp link training, but also cfg
the different video modes into DP registers.
+
+ return 0;
+}
+
+static const struct drm_client_funcs hibmc_dp_client_funcs = {
+ .hotplug = hibmc_dp_hpd_event,
+ .unregister = drm_client_release,
+};
+
int hibmc_dp_init(struct hibmc_drm_private *priv)
{
struct drm_device *dev = &priv->dev;
@@ -138,5 +193,11 @@ int hibmc_dp_init(struct hibmc_drm_private *priv)
drm_connector_attach_encoder(connector, encoder);
+ ret = drm_client_init(dev, &dp->client, "hibmc-DP-HPD", &hibmc_dp_client_funcs);
+ if (ret)
+ return ret;
+
+ drm_client_register(&dp->client);
+
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index bc89e4b9f4e3..daed1330b961 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -71,4 +71,6 @@ int hibmc_dp_init(struct hibmc_drm_private *priv);
void hibmc_debugfs_init(struct drm_connector *connector, struct dentry *root);
+irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg);
+
#endif
--
2.33.0