mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
drm/rockchip: Move register of dw-hdmi-qp audio device to encoder->late_register
dw-hdmi-qp-i2s-audio 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). Change-Id: Iabfc5e1714cceff26bfbcf559ab66003cc258d84 Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
This commit is contained in:
@@ -3782,6 +3782,11 @@ static void dw_hdmi_qp_hdcp14_get_mem(struct dw_hdmi_qp *hdmi, u8 *data, u32 len
|
||||
hdmi->plat_data->set_hdcp14_mem(hdmi_data, false);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -3813,6 +3818,42 @@ static int dw_hdmi_qp_register_hdcp(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_hdmi_qp_register_audio(struct dw_hdmi_qp *hdmi)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct dw_hdmi_qp_i2s_audio_data audio = {
|
||||
.hdmi = hdmi,
|
||||
.eld = hdmi->connector.eld,
|
||||
.write = hdmi_writel,
|
||||
.read = hdmi_readl,
|
||||
.mod = hdmi_modb,
|
||||
};
|
||||
|
||||
struct platform_device_info pdevinfo = {
|
||||
.parent = hdmi->dev,
|
||||
.id = PLATFORM_DEVID_AUTO,
|
||||
.name = "dw-hdmi-qp-i2s-audio",
|
||||
.data = &audio,
|
||||
.size_data = sizeof(audio),
|
||||
.dma_mask = DMA_BIT_MASK(32),
|
||||
};
|
||||
|
||||
hdmi->enable_audio = dw_hdmi_i2s_audio_enable;
|
||||
hdmi->disable_audio = dw_hdmi_i2s_audio_disable;
|
||||
hdmi->audio = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(hdmi->audio)) {
|
||||
dev_err(hdmi->dev, "cannot register %s device\n", pdevinfo.name);
|
||||
ret = PTR_ERR(hdmi->audio);
|
||||
} else {
|
||||
ret = devm_add_action_or_reset(hdmi->dev, dw_hdmi_qp_unregister_platform_device,
|
||||
hdmi->audio);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_qp_register_audio);
|
||||
|
||||
static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
@@ -3820,7 +3861,6 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi_qp *hdmi;
|
||||
struct dw_hdmi_qp_i2s_audio_data audio;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct dw_hdmi_qp_cec_data cec;
|
||||
struct resource *iores = NULL;
|
||||
@@ -3869,16 +3909,13 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
if (IS_ERR(hdmi->regs)) {
|
||||
ret = PTR_ERR(hdmi->regs);
|
||||
goto err_ddc;
|
||||
}
|
||||
if (IS_ERR(hdmi->regs))
|
||||
return ERR_CAST(hdmi->regs);
|
||||
|
||||
hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
|
||||
if (IS_ERR(hdmi->regm)) {
|
||||
dev_err(dev, "Failed to configure regmap\n");
|
||||
ret = PTR_ERR(hdmi->regm);
|
||||
goto err_ddc;
|
||||
return ERR_CAST(hdmi->regm);
|
||||
}
|
||||
} else {
|
||||
hdmi->regm = plat_data->regm;
|
||||
@@ -3886,7 +3923,7 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
|
||||
ret = dw_hdmi_detect_phy(hdmi);
|
||||
if (ret < 0)
|
||||
goto err_ddc;
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (hdmi->plat_data->get_force_timing(hdmi->plat_data->phy_data))
|
||||
hdmi->force_kernel_output = true;
|
||||
@@ -3947,34 +3984,17 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
|
||||
hdmi->connector.ycbcr_420_allowed = hdmi->plat_data->ycbcr_420_allowed;
|
||||
|
||||
audio.hdmi = hdmi;
|
||||
audio.eld = hdmi->connector.eld;
|
||||
audio.write = hdmi_writel;
|
||||
audio.read = hdmi_readl;
|
||||
audio.mod = hdmi_modb;
|
||||
hdmi->enable_audio = dw_hdmi_i2s_audio_enable;
|
||||
hdmi->disable_audio = dw_hdmi_i2s_audio_disable;
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = dev;
|
||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||
pdevinfo.name = "dw-hdmi-qp-i2s-audio";
|
||||
pdevinfo.data = &audio;
|
||||
pdevinfo.size_data = sizeof(audio);
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
hdmi->audio = platform_device_register_full(&pdevinfo);
|
||||
|
||||
hdmi->extcon = devm_extcon_dev_allocate(hdmi->dev, dw_hdmi_cable);
|
||||
if (IS_ERR(hdmi->extcon)) {
|
||||
dev_err(hdmi->dev, "allocate extcon failed\n");
|
||||
ret = PTR_ERR(hdmi->extcon);
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
}
|
||||
|
||||
ret = devm_extcon_dev_register(hdmi->dev, hdmi->extcon);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev, "failed to register extcon: %d\n", ret);
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
}
|
||||
|
||||
ret = extcon_set_property_capability(hdmi->extcon, EXTCON_DISP_HDMI,
|
||||
@@ -3982,13 +4002,13 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev,
|
||||
"failed to set USB property capability: %d\n", ret);
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
}
|
||||
|
||||
hdmi->avp_irq = irq;
|
||||
@@ -3997,12 +4017,12 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
dw_hdmi_qp_avp_irq, IRQF_ONESHOT,
|
||||
dev_name(dev), hdmi);
|
||||
if (ret)
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
|
||||
irq = platform_get_irq(pdev, 1);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_aud;
|
||||
goto err_ddc;
|
||||
}
|
||||
|
||||
cec.irq = irq;
|
||||
@@ -4066,11 +4086,6 @@ static struct dw_hdmi_qp *dw_hdmi_qp_probe(struct platform_device *pdev,
|
||||
err_cec:
|
||||
if (!IS_ERR(hdmi->cec))
|
||||
platform_device_unregister(hdmi->cec);
|
||||
|
||||
err_aud:
|
||||
if (hdmi->audio && !IS_ERR(hdmi->audio))
|
||||
platform_device_unregister(hdmi->audio);
|
||||
|
||||
err_ddc:
|
||||
if (hdmi->i2c)
|
||||
i2c_del_adapter(&hdmi->i2c->adap);
|
||||
@@ -4106,9 +4121,6 @@ static void dw_hdmi_qp_remove(struct dw_hdmi_qp *hdmi)
|
||||
hdmi->connector.funcs->destroy(&hdmi->connector);
|
||||
}
|
||||
|
||||
if (hdmi->audio && !IS_ERR(hdmi->audio))
|
||||
platform_device_unregister(hdmi->audio);
|
||||
|
||||
if (hdmi->bridge.encoder && !hdmi->plat_data->first_screen)
|
||||
hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder);
|
||||
if (!IS_ERR(hdmi->cec))
|
||||
|
||||
@@ -3454,6 +3454,21 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun
|
||||
.mode_set = dw_hdmi_rockchip_encoder_mode_set,
|
||||
};
|
||||
|
||||
static int dw_hdmi_encoder_late_register(struct drm_encoder *encoder)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
|
||||
|
||||
if (hdmi->is_hdmi_qp)
|
||||
dw_hdmi_qp_register_audio(hdmi->hdmi_qp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
.late_register = dw_hdmi_encoder_late_register,
|
||||
};
|
||||
|
||||
static void
|
||||
dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
|
||||
{
|
||||
@@ -4112,7 +4127,9 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
|
||||
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!plat_data->max_tmdsclk)
|
||||
|
||||
@@ -360,5 +360,6 @@ int dw_hdmi_qp_get_output_type_cap(struct dw_hdmi_qp *hdmi);
|
||||
void dw_hdmi_set_hpd_wake(struct dw_hdmi *hdmi);
|
||||
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);
|
||||
|
||||
#endif /* __IMX_HDMI_H__ */
|
||||
|
||||
Reference in New Issue
Block a user