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 <andy.yan@rock-chips.com>
This commit is contained in:
Andy Yan
2024-05-21 20:11:02 +08:00
committed by Tao Huang
parent 17394b0ff4
commit a981063f36
3 changed files with 31 additions and 14 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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__ */