Register the ingenic-drm driver as a component master. This will later allow to plug optional components to the driver, for instance to add support for the IPU, or the SLCD module. Signed-off-by: Paul Cercueil <paul@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/ingenic/ingenic-drm.c | 61 +++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c index f139af5b7a40..b53db3ee001f 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm.c @@ -6,6 +6,7 @@ #include "ingenic-drm.h" +#include <linux/component.h> #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/module.h> @@ -613,10 +614,17 @@ static void ingenic_drm_free_dma_hwdesc(void *d) priv->dma_hwdesc[1], priv->dma_hwdesc_phys[1]); } -static int ingenic_drm_probe(struct platform_device *pdev) +static void ingenic_drm_unbind_all(void *d) { + struct ingenic_drm *priv = d; + + component_unbind_all(priv->dev, &priv->drm); +} + +static int ingenic_drm_bind(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); const struct jz_soc_info *soc_info; - struct device *dev = &pdev->dev; struct ingenic_drm *priv; struct clk *parent_clk; struct drm_bridge *bridge; @@ -653,6 +661,17 @@ static int ingenic_drm_probe(struct platform_device *pdev) drm->mode_config.max_height = 4095; drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; + ret = component_bind_all(dev, drm); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to bind components: %i", ret); + return ret; + } + + ret = devm_add_action_or_reset(dev, ingenic_drm_unbind_all, priv); + if (ret) + return ret; + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_err(dev, "Failed to get memory resource"); @@ -843,9 +862,14 @@ static int ingenic_drm_probe(struct platform_device *pdev) return ret; } -static int ingenic_drm_remove(struct platform_device *pdev) +static int compare_of(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +static void ingenic_drm_unbind(struct device *dev) { - struct ingenic_drm *priv = platform_get_drvdata(pdev); + struct ingenic_drm *priv = dev_get_drvdata(dev); if (priv->lcd_clk) clk_disable_unprepare(priv->lcd_clk); @@ -853,6 +877,35 @@ static int ingenic_drm_remove(struct platform_device *pdev) drm_dev_unregister(&priv->drm); drm_atomic_helper_shutdown(&priv->drm); +} + +static const struct component_master_ops ingenic_master_ops = { + .bind = ingenic_drm_bind, + .unbind = ingenic_drm_unbind, +}; + +static int ingenic_drm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct component_match *match = NULL; + struct device_node *np; + unsigned int i; + + /* Probe components at port address 8 and upwards */ + for (i = 8; ; i++) { + np = of_graph_get_remote_node(dev->of_node, i, 0); + if (!np) + break; + + drm_of_component_match_add(dev, &match, compare_of, np); + } + + return component_master_add_with_match(dev, &ingenic_master_ops, match); +} + +static int ingenic_drm_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &ingenic_master_ops); return 0; } -- 2.26.2