Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 736e60dd authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

OMAPDSS: componentize omapdss



omapdss kernel module contains drivers for multiple devices, one for
each DSS submodule. The probing we have at the moment is a mess, and
doesn't give us proper deferred probing nor ensure that all the devices
are probed before omapfb/omapdrm start using omapdss.

This patch solves the mess by using the component system for DSS
submodules.

The changes to all DSS submodules (dispc, dpi, dsi, hdmi4/5, rfbi, sdi,
venc) are the same: probe & remove functions are changed to bind &
unbind, and new probe & remove functions are added which call
component_add/del.

The dss_core driver (dss.c) acts as a component master. Adding and
matching the components is simple: all dss device's child devices are
added as components.

However, we do have some dependencies between the drivers. The order in
which they should be probed is reflected by the list in core.c
(dss_output_drv_reg_funcs). The drivers are registered in that order,
which causes the components to be added in that order, which makes the
components to be bound in that order. This feels a bit fragile, and we
probably should improve the code to manage binds in random order.
However, for now, this works fine.

Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent 606ae486
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/component.h>

#include <video/omapdss.h>

@@ -3882,8 +3883,9 @@ void dispc_free_irq(void *dev_id)
EXPORT_SYMBOL(dispc_free_irq);

/* DISPC HW IP initialisation */
static int omap_dispchw_probe(struct platform_device *pdev)
static int dispc_bind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	u32 rev;
	int r = 0;
	struct resource *dispc_mem;
@@ -3955,12 +3957,27 @@ static int omap_dispchw_probe(struct platform_device *pdev)
	return r;
}

static int omap_dispchw_remove(struct platform_device *pdev)
static void dispc_unbind(struct device *dev, struct device *master,
			       void *data)
{
	pm_runtime_disable(&pdev->dev);
	pm_runtime_disable(dev);

	dss_uninit_overlay_managers();
}

static const struct component_ops dispc_component_ops = {
	.bind	= dispc_bind,
	.unbind	= dispc_unbind,
};

static int dispc_probe(struct platform_device *pdev)
{
	return component_add(&pdev->dev, &dispc_component_ops);
}

static int dispc_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &dispc_component_ops);
	return 0;
}

@@ -4013,7 +4030,8 @@ static const struct of_device_id dispc_of_match[] = {
};

static struct platform_driver omap_dispchw_driver = {
	.remove         = omap_dispchw_remove,
	.probe		= dispc_probe,
	.remove         = dispc_remove,
	.driver         = {
		.name   = "omapdss_dispc",
		.pm	= &dispc_pm_ops,
@@ -4024,7 +4042,7 @@ static struct platform_driver omap_dispchw_driver = {

int __init dispc_init_platform_driver(void)
{
	return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
	return platform_driver_register(&omap_dispchw_driver);
}

void dispc_uninit_platform_driver(void)
+22 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/string.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/component.h>

#include <video/omapdss.h>

@@ -783,8 +784,9 @@ static void dpi_uninit_output_port(struct device_node *port)
	omapdss_unregister_output(out);
}

static int omap_dpi_probe(struct platform_device *pdev)
static int dpi_bind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct dpi_data *dpi;

	dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
@@ -802,16 +804,32 @@ static int omap_dpi_probe(struct platform_device *pdev)
	return 0;
}

static int omap_dpi_remove(struct platform_device *pdev)
static void dpi_unbind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);

	dpi_uninit_output(pdev);
}

static const struct component_ops dpi_component_ops = {
	.bind	= dpi_bind,
	.unbind	= dpi_unbind,
};

static int dpi_probe(struct platform_device *pdev)
{
	return component_add(&pdev->dev, &dpi_component_ops);
}

static int dpi_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &dpi_component_ops);
	return 0;
}

static struct platform_driver omap_dpi_driver = {
	.probe		= omap_dpi_probe,
	.remove         = omap_dpi_remove,
	.probe		= dpi_probe,
	.remove		= dpi_remove,
	.driver         = {
		.name   = "omapdss_dpi",
		.suppress_bind_attrs = true,
+21 −4
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/component.h>

#include <video/omapdss.h>
#include <video/mipi_display.h>
@@ -5274,8 +5275,9 @@ static int dsi_init_pll_data(struct platform_device *dsidev)
}

/* DSI1 HW IP initialisation */
static int omap_dsihw_probe(struct platform_device *dsidev)
static int dsi_bind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *dsidev = to_platform_device(dev);
	u32 rev;
	int r, i;
	struct dsi_data *dsi;
@@ -5484,8 +5486,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
	return r;
}

static int omap_dsihw_remove(struct platform_device *dsidev)
static void dsi_unbind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *dsidev = to_platform_device(dev);
	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);

	of_platform_depopulate(&dsidev->dev);
@@ -5502,7 +5505,21 @@ static int omap_dsihw_remove(struct platform_device *dsidev)
		regulator_disable(dsi->vdds_dsi_reg);
		dsi->vdds_dsi_enabled = false;
	}
}

static const struct component_ops dsi_component_ops = {
	.bind	= dsi_bind,
	.unbind	= dsi_unbind,
};

static int dsi_probe(struct platform_device *pdev)
{
	return component_add(&pdev->dev, &dsi_component_ops);
}

static int dsi_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &dsi_component_ops);
	return 0;
}

@@ -5569,8 +5586,8 @@ static const struct of_device_id dsi_of_match[] = {
};

static struct platform_driver omap_dsihw_driver = {
	.probe		= omap_dsihw_probe,
	.remove         = omap_dsihw_remove,
	.probe		= dsi_probe,
	.remove		= dsi_remove,
	.driver         = {
		.name   = "omapdss_dsi",
		.pm	= &dsi_pm_ops,
+55 −4
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/suspend.h>
#include <linux/component.h>

#include <video/omapdss.h>

@@ -1088,8 +1089,9 @@ static int dss_video_pll_probe(struct platform_device *pdev)
}

/* DSS HW IP initialisation */
static int omap_dsshw_probe(struct platform_device *pdev)
static int dss_bind(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *dss_mem;
	u32 rev;
	int r;
@@ -1159,6 +1161,10 @@ static int omap_dsshw_probe(struct platform_device *pdev)

	dss_runtime_put();

	r = component_bind_all(&pdev->dev, NULL);
	if (r)
		goto err_component;

	dss_debugfs_create_file("dss", dss_dump_regs);

	pm_set_vt_switch(0);
@@ -1167,6 +1173,7 @@ static int omap_dsshw_probe(struct platform_device *pdev)

	return 0;

err_component:
err_runtime_get:
	pm_runtime_disable(&pdev->dev);
	dss_uninit_ports(pdev);
@@ -1182,10 +1189,14 @@ static int omap_dsshw_probe(struct platform_device *pdev)
	return r;
}

static int omap_dsshw_remove(struct platform_device *pdev)
static void dss_unbind(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);

	dss_initialized = false;

	component_unbind_all(&pdev->dev, NULL);

	if (dss.video1_pll)
		dss_video_pll_uninit(dss.video1_pll);

@@ -1197,7 +1208,46 @@ static int omap_dsshw_remove(struct platform_device *pdev)
	pm_runtime_disable(&pdev->dev);

	dss_put_clocks();
}

static const struct component_master_ops dss_component_ops = {
	.bind = dss_bind,
	.unbind = dss_unbind,
};

static int dss_component_compare(struct device *dev, void *data)
{
	struct device *child = data;
	return dev == child;
}

static int dss_add_child_component(struct device *dev, void *data)
{
	struct component_match **match = data;

	component_match_add(dev->parent, match, dss_component_compare, dev);

	return 0;
}

static int dss_probe(struct platform_device *pdev)
{
	struct component_match *match = NULL;
	int r;

	/* add all the child devices as components */
	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)
		return r;

	return 0;
}

static int dss_remove(struct platform_device *pdev)
{
	component_master_del(&pdev->dev, &dss_component_ops);
	return 0;
}

@@ -1243,7 +1293,8 @@ static const struct of_device_id dss_of_match[] = {
MODULE_DEVICE_TABLE(of, dss_of_match);

static struct platform_driver omap_dsshw_driver = {
	.remove         = omap_dsshw_remove,
	.probe		= dss_probe,
	.remove		= dss_remove,
	.driver         = {
		.name   = "omapdss_dss",
		.pm	= &dss_pm_ops,
@@ -1254,7 +1305,7 @@ static struct platform_driver omap_dsshw_driver = {

int __init dss_init_platform_driver(void)
{
	return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
	return platform_driver_register(&omap_dsshw_driver);
}

void dss_uninit_platform_driver(void)
+22 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/component.h>
#include <video/omapdss.h>
#include <sound/omap-hdmi-audio.h>

@@ -646,8 +647,9 @@ static int hdmi_audio_register(struct device *dev)
}

/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
static int hdmi4_bind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	int r;
	int irq;

@@ -713,8 +715,10 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
	return r;
}

static int omapdss_hdmihw_remove(struct platform_device *pdev)
static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);

	if (hdmi.audio_pdev)
		platform_device_unregister(hdmi.audio_pdev);

@@ -723,7 +727,21 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
	hdmi_pll_uninit(&hdmi.pll);

	pm_runtime_disable(&pdev->dev);
}

static const struct component_ops hdmi4_component_ops = {
	.bind	= hdmi4_bind,
	.unbind	= hdmi4_unbind,
};

static int hdmi4_probe(struct platform_device *pdev)
{
	return component_add(&pdev->dev, &hdmi4_component_ops);
}

static int hdmi4_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &hdmi4_component_ops);
	return 0;
}

@@ -756,8 +774,8 @@ static const struct of_device_id hdmi_of_match[] = {
};

static struct platform_driver omapdss_hdmihw_driver = {
	.probe		= omapdss_hdmihw_probe,
	.remove         = omapdss_hdmihw_remove,
	.probe		= hdmi4_probe,
	.remove		= hdmi4_remove,
	.driver         = {
		.name   = "omapdss_hdmi",
		.pm	= &hdmi_pm_ops,
Loading