diff mbox series

[v3,1/4] drm/omap: Populate DSS children in omapdss driver

Message ID 20181110111654.4387-2-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show
Series omapdrm: Fix runtime PM issues at module load and unload time | expand

Commit Message

Laurent Pinchart Nov. 10, 2018, 11:16 a.m. UTC
The DSS DT node contains children that describe the DSS components
(DISPC and internal encoders). Each of those components is handled by a
platform driver, and thus needs to be backed by a platform device.

The corresponding platform devices are created in mach-omap2 code by a
call to of_platform_populate(). While this approach has worked so far,
it doesn't model the hardware architecture very well, as it creates
child devices before the parent is ready to handle them. This would be
akin to creating I2C slaves before the I2C master is available.

The task can be easily performed in the omapdss driver code instead,
simplifying mach-omap2 code. We however can't remove the mach-omap2 code
completely as the omap2fb driver still depends on it, but we can move it
to the omap2fb-specific section, where it can stay until the omap2fb
driver gets removed.

This has the added benefit of not allowing DSS components to probe
before the DSS itself, which led to runtime PM issues when the DSS probe
is deferred.

Fixes: 27d624527d99 ("drm/omap: dss: Acquire next dssdev at probe time")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/display.c     | 111 ++++++++++++++----------------
 drivers/gpu/drm/omapdrm/dss/dss.c |  11 ++-
 2 files changed, 63 insertions(+), 59 deletions(-)

Comments

Sebastian Reichel Nov. 11, 2018, 12:45 a.m. UTC | #1
Hi,

On Sat, Nov 10, 2018 at 01:16:51PM +0200, Laurent Pinchart wrote:
> The DSS DT node contains children that describe the DSS components
> (DISPC and internal encoders). Each of those components is handled by a
> platform driver, and thus needs to be backed by a platform device.
> 
> The corresponding platform devices are created in mach-omap2 code by a
> call to of_platform_populate(). While this approach has worked so far,
> it doesn't model the hardware architecture very well, as it creates
> child devices before the parent is ready to handle them. This would be
> akin to creating I2C slaves before the I2C master is available.
> 
> The task can be easily performed in the omapdss driver code instead,
> simplifying mach-omap2 code. We however can't remove the mach-omap2 code
> completely as the omap2fb driver still depends on it, but we can move it
> to the omap2fb-specific section, where it can stay until the omap2fb
> driver gets removed.
> 
> This has the added benefit of not allowing DSS components to probe
> before the DSS itself, which led to runtime PM issues when the DSS probe
> is deferred.
> 
> Fixes: 27d624527d99 ("drm/omap: dss: Acquire next dssdev at probe time")
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Acked-by: Tony Lindgren <tony@atomide.com>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>

-- Sebastian

>  arch/arm/mach-omap2/display.c     | 111 ++++++++++++++----------------
>  drivers/gpu/drm/omapdrm/dss/dss.c |  11 ++-
>  2 files changed, 63 insertions(+), 59 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
> index 9500b6e27380..f86b72d1d59e 100644
> --- a/arch/arm/mach-omap2/display.c
> +++ b/arch/arm/mach-omap2/display.c
> @@ -209,11 +209,61 @@ static int __init omapdss_init_fbdev(void)
>  
>  	return 0;
>  }
> -#else
> -static inline int omapdss_init_fbdev(void)
> +
> +static const char * const omapdss_compat_names[] __initconst = {
> +	"ti,omap2-dss",
> +	"ti,omap3-dss",
> +	"ti,omap4-dss",
> +	"ti,omap5-dss",
> +	"ti,dra7-dss",
> +};
> +
> +static struct device_node * __init omapdss_find_dss_of_node(void)
>  {
> -	return 0;
> +	struct device_node *node;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
> +		node = of_find_compatible_node(NULL, NULL,
> +			omapdss_compat_names[i]);
> +		if (node)
> +			return node;
> +	}
> +
> +	return NULL;
>  }
> +
> +static int __init omapdss_init_of(void)
> +{
> +	int r;
> +	struct device_node *node;
> +	struct platform_device *pdev;
> +
> +	/* only create dss helper devices if dss is enabled in the .dts */
> +
> +	node = omapdss_find_dss_of_node();
> +	if (!node)
> +		return 0;
> +
> +	if (!of_device_is_available(node))
> +		return 0;
> +
> +	pdev = of_find_device_by_node(node);
> +
> +	if (!pdev) {
> +		pr_err("Unable to find DSS platform device\n");
> +		return -ENODEV;
> +	}
> +
> +	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
> +	if (r) {
> +		pr_err("Unable to populate DSS submodule devices\n");
> +		return r;
> +	}
> +
> +	return omapdss_init_fbdev();
> +}
> +omap_device_initcall(omapdss_init_of);
>  #endif /* CONFIG_FB_OMAP2 */
>  
>  static void dispc_disable_outputs(void)
> @@ -361,58 +411,3 @@ int omap_dss_reset(struct omap_hwmod *oh)
>  
>  	return r;
>  }
> -
> -static const char * const omapdss_compat_names[] __initconst = {
> -	"ti,omap2-dss",
> -	"ti,omap3-dss",
> -	"ti,omap4-dss",
> -	"ti,omap5-dss",
> -	"ti,dra7-dss",
> -};
> -
> -static struct device_node * __init omapdss_find_dss_of_node(void)
> -{
> -	struct device_node *node;
> -	int i;
> -
> -	for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
> -		node = of_find_compatible_node(NULL, NULL,
> -			omapdss_compat_names[i]);
> -		if (node)
> -			return node;
> -	}
> -
> -	return NULL;
> -}
> -
> -static int __init omapdss_init_of(void)
> -{
> -	int r;
> -	struct device_node *node;
> -	struct platform_device *pdev;
> -
> -	/* only create dss helper devices if dss is enabled in the .dts */
> -
> -	node = omapdss_find_dss_of_node();
> -	if (!node)
> -		return 0;
> -
> -	if (!of_device_is_available(node))
> -		return 0;
> -
> -	pdev = of_find_device_by_node(node);
> -
> -	if (!pdev) {
> -		pr_err("Unable to find DSS platform device\n");
> -		return -ENODEV;
> -	}
> -
> -	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
> -	if (r) {
> -		pr_err("Unable to populate DSS submodule devices\n");
> -		return r;
> -	}
> -
> -	return omapdss_init_fbdev();
> -}
> -omap_device_initcall(omapdss_init_of);
> diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
> index 1aaf260aa9b8..7553c7fc1c45 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dss.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dss.c
> @@ -1484,16 +1484,23 @@ static int dss_probe(struct platform_device *pdev)
>  						   dss);
>  
>  	/* Add all the child devices as components. */
> +	r = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +	if (r)
> +		goto err_uninit_debugfs;
> +
>  	omapdss_gather_components(&pdev->dev);
>  
>  	device_for_each_child(&pdev->dev, &match, dss_add_child_component);
>  
>  	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
>  	if (r)
> -		goto err_uninit_debugfs;
> +		goto err_of_depopulate;
>  
>  	return 0;
>  
> +err_of_depopulate:
> +	of_platform_depopulate(&pdev->dev);
> +
>  err_uninit_debugfs:
>  	dss_debugfs_remove_file(dss->debugfs.clk);
>  	dss_debugfs_remove_file(dss->debugfs.dss);
> @@ -1522,6 +1529,8 @@ static int dss_remove(struct platform_device *pdev)
>  {
>  	struct dss_device *dss = platform_get_drvdata(pdev);
>  
> +	of_platform_depopulate(&pdev->dev);
> +
>  	component_master_del(&pdev->dev, &dss_component_ops);
>  
>  	dss_debugfs_remove_file(dss->debugfs.clk);
> -- 
> Regards,
> 
> Laurent Pinchart
>
diff mbox series

Patch

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 9500b6e27380..f86b72d1d59e 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -209,11 +209,61 @@  static int __init omapdss_init_fbdev(void)
 
 	return 0;
 }
-#else
-static inline int omapdss_init_fbdev(void)
+
+static const char * const omapdss_compat_names[] __initconst = {
+	"ti,omap2-dss",
+	"ti,omap3-dss",
+	"ti,omap4-dss",
+	"ti,omap5-dss",
+	"ti,dra7-dss",
+};
+
+static struct device_node * __init omapdss_find_dss_of_node(void)
 {
-	return 0;
+	struct device_node *node;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
+		node = of_find_compatible_node(NULL, NULL,
+			omapdss_compat_names[i]);
+		if (node)
+			return node;
+	}
+
+	return NULL;
 }
+
+static int __init omapdss_init_of(void)
+{
+	int r;
+	struct device_node *node;
+	struct platform_device *pdev;
+
+	/* only create dss helper devices if dss is enabled in the .dts */
+
+	node = omapdss_find_dss_of_node();
+	if (!node)
+		return 0;
+
+	if (!of_device_is_available(node))
+		return 0;
+
+	pdev = of_find_device_by_node(node);
+
+	if (!pdev) {
+		pr_err("Unable to find DSS platform device\n");
+		return -ENODEV;
+	}
+
+	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	if (r) {
+		pr_err("Unable to populate DSS submodule devices\n");
+		return r;
+	}
+
+	return omapdss_init_fbdev();
+}
+omap_device_initcall(omapdss_init_of);
 #endif /* CONFIG_FB_OMAP2 */
 
 static void dispc_disable_outputs(void)
@@ -361,58 +411,3 @@  int omap_dss_reset(struct omap_hwmod *oh)
 
 	return r;
 }
-
-static const char * const omapdss_compat_names[] __initconst = {
-	"ti,omap2-dss",
-	"ti,omap3-dss",
-	"ti,omap4-dss",
-	"ti,omap5-dss",
-	"ti,dra7-dss",
-};
-
-static struct device_node * __init omapdss_find_dss_of_node(void)
-{
-	struct device_node *node;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
-		node = of_find_compatible_node(NULL, NULL,
-			omapdss_compat_names[i]);
-		if (node)
-			return node;
-	}
-
-	return NULL;
-}
-
-static int __init omapdss_init_of(void)
-{
-	int r;
-	struct device_node *node;
-	struct platform_device *pdev;
-
-	/* only create dss helper devices if dss is enabled in the .dts */
-
-	node = omapdss_find_dss_of_node();
-	if (!node)
-		return 0;
-
-	if (!of_device_is_available(node))
-		return 0;
-
-	pdev = of_find_device_by_node(node);
-
-	if (!pdev) {
-		pr_err("Unable to find DSS platform device\n");
-		return -ENODEV;
-	}
-
-	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
-	if (r) {
-		pr_err("Unable to populate DSS submodule devices\n");
-		return r;
-	}
-
-	return omapdss_init_fbdev();
-}
-omap_device_initcall(omapdss_init_of);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 1aaf260aa9b8..7553c7fc1c45 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1484,16 +1484,23 @@  static int dss_probe(struct platform_device *pdev)
 						   dss);
 
 	/* Add all the child devices as components. */
+	r = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (r)
+		goto err_uninit_debugfs;
+
 	omapdss_gather_components(&pdev->dev);
 
 	device_for_each_child(&pdev->dev, &match, dss_add_child_component);
 
 	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
 	if (r)
-		goto err_uninit_debugfs;
+		goto err_of_depopulate;
 
 	return 0;
 
+err_of_depopulate:
+	of_platform_depopulate(&pdev->dev);
+
 err_uninit_debugfs:
 	dss_debugfs_remove_file(dss->debugfs.clk);
 	dss_debugfs_remove_file(dss->debugfs.dss);
@@ -1522,6 +1529,8 @@  static int dss_remove(struct platform_device *pdev)
 {
 	struct dss_device *dss = platform_get_drvdata(pdev);
 
+	of_platform_depopulate(&pdev->dev);
+
 	component_master_del(&pdev->dev, &dss_component_ops);
 
 	dss_debugfs_remove_file(dss->debugfs.clk);