From a981063f3600385caea748edaf97ab87ffe1e6a7 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 21 May 2024 20:11:02 +0800 Subject: [PATCH] drm/rockchip: Move register of dw-hdmi-qp hdcp device to encoder->late_register w-hdmi-qp-hdcp device is very easy to register and probe it's driver, move it out of bind callback to avoid create child device when hdmi driver or other components run probe(this may cause infinite loop probe as these components are very easy run into defer probe). Note: Documentation/driver-api/driver-model/driver.rst Change-Id: I99ec2bcbe7ef39a91a4bd01cd73b8f251db8b42d Signed-off-by: Andy Yan --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 34 ++++++++++++-------- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 10 ++++++ include/drm/bridge/dw_hdmi.h | 1 + 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 50689a190c2c..55c465053f0a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -3775,9 +3775,10 @@ static void dw_hdmi_qp_unregister_platform_device(void *pdev) platform_device_unregister(pdev); } -static int dw_hdmi_qp_register_hdcp(struct device *dev, - struct dw_hdmi_qp *hdmi) +int dw_hdmi_qp_register_hdcp(struct dw_hdmi_qp *hdmi) { + int ret = 0; + struct dw_qp_hdcp hdmi_hdcp = { .hdmi = hdmi, .write = hdmi_writel, @@ -3785,8 +3786,9 @@ static int dw_hdmi_qp_register_hdcp(struct device *dev, .regs = hdmi->regs, .get_mem = dw_hdmi_qp_hdcp14_get_mem, }; + struct platform_device_info hdcp_device_info = { - .parent = dev, + .parent = hdmi->dev, .id = PLATFORM_DEVID_AUTO, .res = NULL, .num_res = 0, @@ -3795,16 +3797,23 @@ static int dw_hdmi_qp_register_hdcp(struct device *dev, .size_data = sizeof(hdmi_hdcp), .dma_mask = DMA_BIT_MASK(32), }; - hdmi->hdcp_dev = platform_device_register_full(&hdcp_device_info); - if (IS_ERR(hdmi->hdcp_dev)) { - dev_err(dev, "failed to register hdcp!\n"); - return -ENOMEM; + + if (hdmi->hdcp14_mem) { + hdmi->hdcp_dev = platform_device_register_full(&hdcp_device_info); + if (IS_ERR(hdmi->hdcp_dev)) { + dev_err(hdmi->dev, "Failed to register hdcp device!\n"); + ret = PTR_ERR(hdmi->hdcp_dev); + } else { + hdmi->hdcp = hdmi->hdcp_dev->dev.platform_data; + ret = devm_add_action_or_reset(hdmi->dev, + dw_hdmi_qp_unregister_platform_device, + hdmi->hdcp_dev); + } } - hdmi->hdcp = hdmi->hdcp_dev->dev.platform_data; - - return 0; + return ret; } +EXPORT_SYMBOL_GPL(dw_hdmi_qp_register_hdcp); int dw_hdmi_qp_register_audio(struct dw_hdmi_qp *hdmi) { @@ -4097,12 +4106,9 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev, if (IS_ERR(hdmi->hdcp14_mem)) { ret = PTR_ERR(hdmi->hdcp14_mem); + hdmi->hdcp14_mem = NULL; goto err_ddc; } - - ret = dw_hdmi_qp_register_hdcp(dev, hdmi); - if (ret) - goto err_ddc; } return hdmi; diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index d3cc51f316e8..0100065d0362 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -3454,6 +3454,15 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun .mode_set = dw_hdmi_rockchip_encoder_mode_set, }; +/* + * Register child devices like audio/cec/hdcp at late_register stage + * to avoid register these devie at probe/bind(which may cause + * infinite loop of .probe() if a component is always defer) + * + * As these devices are not that critical, so we don't check + * the register results here, just give warning in it's register + * function if it failed, let the drm bringup. + */ static int dw_hdmi_encoder_late_register(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); @@ -3461,6 +3470,7 @@ static int dw_hdmi_encoder_late_register(struct drm_encoder *encoder) if (hdmi->is_hdmi_qp) { dw_hdmi_qp_register_audio(hdmi->hdmi_qp); dw_hdmi_qp_register_cec(hdmi->hdmi_qp); + dw_hdmi_qp_register_hdcp(hdmi->hdmi_qp); } return 0; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 0bd76c26c4f6..64ccc38300a9 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -362,5 +362,6 @@ void dw_hdmi_cec_wake_ops_register(struct dw_hdmi *hdmi, const struct dw_hdmi_cec_wake_ops *cec_ops); int dw_hdmi_qp_register_audio(struct dw_hdmi_qp *hdmi); int dw_hdmi_qp_register_cec(struct dw_hdmi_qp *hdmi); +int dw_hdmi_qp_register_hdcp(struct dw_hdmi_qp *hdmi); #endif /* __IMX_HDMI_H__ */