[PATCH 10/12] gpu/drm: Ingenic: Register driver as component master
Paul Cercueil
paul at crapouillou.net
Sat May 16 21:50:55 UTC 2020
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 at crapouillou.net>
---
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
More information about the dri-devel
mailing list