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

Commit a8998202 authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

Merge omapdss componentization work

parents 9f5ddefd ad4eaef7
Loading
Loading
Loading
Loading
+27 −53
Original line number Diff line number Diff line
@@ -50,8 +50,6 @@ static char *def_disp_name;
module_param_named(def_disp, def_disp_name, charp, 0);
MODULE_PARM_DESC(def_disp, "default display name");

static bool dss_initialized;

const char *omapdss_get_default_display_name(void)
{
	return core.default_display_name;
@@ -65,12 +63,6 @@ enum omapdss_version omapdss_get_version(void)
}
EXPORT_SYMBOL(omapdss_get_version);

bool omapdss_is_initialized(void)
{
	return dss_initialized;
}
EXPORT_SYMBOL(omapdss_is_initialized);

struct platform_device *dss_get_core_pdev(void)
{
	return core.pdev;
@@ -253,6 +245,8 @@ static struct platform_driver omap_dss_driver = {

/* INIT */
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
	dss_init_platform_driver,
	dispc_init_platform_driver,
#ifdef CONFIG_OMAP2_DSS_DSI
	dsi_init_platform_driver,
#endif
@@ -276,32 +270,32 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#endif
};

static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP2_DSS_DSI
	dsi_uninit_platform_driver,
static void (*dss_output_drv_unreg_funcs[])(void) = {
#ifdef CONFIG_OMAP5_DSS_HDMI
	hdmi5_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_DPI
	dpi_uninit_platform_driver,
#ifdef CONFIG_OMAP4_DSS_HDMI
	hdmi4_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_SDI
	sdi_uninit_platform_driver,
#ifdef CONFIG_OMAP2_DSS_VENC
	venc_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_RFBI
	rfbi_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_VENC
	venc_uninit_platform_driver,
#ifdef CONFIG_OMAP2_DSS_SDI
	sdi_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
	hdmi4_uninit_platform_driver,
#ifdef CONFIG_OMAP2_DSS_DPI
	dpi_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP5_DSS_HDMI
	hdmi5_uninit_platform_driver,
#ifdef CONFIG_OMAP2_DSS_DSI
	dsi_uninit_platform_driver,
#endif
	dispc_uninit_platform_driver,
	dss_uninit_platform_driver,
};

static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];

static int __init omap_dss_init(void)
{
	int r;
@@ -311,35 +305,20 @@ static int __init omap_dss_init(void)
	if (r)
		return r;

	r = dss_init_platform_driver();
	if (r) {
		DSSERR("Failed to initialize DSS platform driver\n");
		goto err_dss;
	}

	r = dispc_init_platform_driver();
	if (r) {
		DSSERR("Failed to initialize dispc platform driver\n");
		goto err_dispc;
	}

	/*
	 * It's ok if the output-driver register fails. It happens, for example,
	 * when there is no output-device (e.g. SDI for OMAP4).
	 */
	for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
		r = dss_output_drv_reg_funcs[i]();
		if (r == 0)
			dss_output_drv_loaded[i] = true;
		if (r)
			goto err_reg;
	}

	dss_initialized = true;

	return 0;

err_dispc:
	dss_uninit_platform_driver();
err_dss:
err_reg:
	for (i = ARRAY_SIZE(dss_output_drv_reg_funcs) - i;
			i < ARRAY_SIZE(dss_output_drv_reg_funcs);
			++i)
		dss_output_drv_unreg_funcs[i]();

	platform_driver_unregister(&omap_dss_driver);

	return r;
@@ -349,13 +328,8 @@ static void __exit omap_dss_exit(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
		if (dss_output_drv_loaded[i])
	for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i)
		dss_output_drv_unreg_funcs[i]();
	}

	dispc_uninit_platform_driver();
	dss_uninit_platform_driver();

	platform_driver_unregister(&omap_dss_driver);
}
+30 −12
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>

@@ -3692,7 +3693,7 @@ static void _omap_dispc_initial_config(void)
		dispc_init_mflag();
}

static const struct dispc_features omap24xx_dispc_feats __initconst = {
static const struct dispc_features omap24xx_dispc_feats = {
	.sw_start		=	5,
	.fp_start		=	15,
	.bp_start		=	27,
@@ -3711,7 +3712,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
	.set_max_preload	=	false,
};

static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
	.sw_start		=	5,
	.fp_start		=	15,
	.bp_start		=	27,
@@ -3731,7 +3732,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
	.set_max_preload	=	false,
};

static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
	.sw_start		=	7,
	.fp_start		=	19,
	.bp_start		=	31,
@@ -3751,7 +3752,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
	.set_max_preload	=	false,
};

static const struct dispc_features omap44xx_dispc_feats __initconst = {
static const struct dispc_features omap44xx_dispc_feats = {
	.sw_start		=	7,
	.fp_start		=	19,
	.bp_start		=	31,
@@ -3771,7 +3772,7 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
	.set_max_preload	=	true,
};

static const struct dispc_features omap54xx_dispc_feats __initconst = {
static const struct dispc_features omap54xx_dispc_feats = {
	.sw_start		=	7,
	.fp_start		=	19,
	.bp_start		=	31,
@@ -3792,7 +3793,7 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = {
	.set_max_preload	=	true,
};

static int __init dispc_init_features(struct platform_device *pdev)
static int dispc_init_features(struct platform_device *pdev)
{
	const struct dispc_features *src;
	struct dispc_features *dst;
@@ -3882,8 +3883,9 @@ void dispc_free_irq(void *dev_id)
EXPORT_SYMBOL(dispc_free_irq);

/* DISPC HW IP initialisation */
static int __init 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 __init omap_dispchw_probe(struct platform_device *pdev)
	return r;
}

static int __exit 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         = __exit_p(omap_dispchw_remove),
	.probe		= dispc_probe,
	.remove         = dispc_remove,
	.driver         = {
		.name   = "omapdss_dispc",
		.pm	= &dispc_pm_ops,
@@ -4024,10 +4042,10 @@ 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 __exit dispc_uninit_platform_driver(void)
void dispc_uninit_platform_driver(void)
{
	platform_driver_unregister(&omap_dispchw_driver);
}
+27 −9
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>

@@ -731,7 +732,7 @@ static void dpi_init_output(struct platform_device *pdev)
	omapdss_register_output(out);
}

static void __exit dpi_uninit_output(struct platform_device *pdev)
static void dpi_uninit_output(struct platform_device *pdev)
{
	struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
	struct omap_dss_device *out = &dpi->output;
@@ -775,7 +776,7 @@ static void dpi_init_output_port(struct platform_device *pdev,
	omapdss_register_output(out);
}

static void __exit dpi_uninit_output_port(struct device_node *port)
static void dpi_uninit_output_port(struct device_node *port)
{
	struct dpi_data *dpi = port->data;
	struct omap_dss_device *out = &dpi->output;
@@ -783,8 +784,9 @@ static void __exit 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 __exit 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         = __exit_p(omap_dpi_remove),
	.probe		= dpi_probe,
	.remove		= dpi_remove,
	.driver         = {
		.name   = "omapdss_dpi",
		.suppress_bind_attrs = true,
@@ -823,12 +841,12 @@ int __init dpi_init_platform_driver(void)
	return platform_driver_register(&omap_dpi_driver);
}

void __exit dpi_uninit_platform_driver(void)
void dpi_uninit_platform_driver(void)
{
	platform_driver_unregister(&omap_dpi_driver);
}

int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
int dpi_init_port(struct platform_device *pdev, struct device_node *port)
{
	struct dpi_data *dpi;
	struct device_node *ep;
@@ -870,7 +888,7 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
	return r;
}

void __exit dpi_uninit_port(struct device_node *port)
void dpi_uninit_port(struct device_node *port)
{
	struct dpi_data *dpi = port->data;

+22 −5
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 __exit 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 __exit 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         = __exit_p(omap_dsihw_remove),
	.probe		= dsi_probe,
	.remove		= dsi_remove,
	.driver         = {
		.name   = "omapdss_dsi",
		.pm	= &dsi_pm_ops,
@@ -5584,7 +5601,7 @@ int __init dsi_init_platform_driver(void)
	return platform_driver_register(&omap_dsihw_driver);
}

void __exit dsi_uninit_platform_driver(void)
void dsi_uninit_platform_driver(void)
{
	platform_driver_unregister(&omap_dsihw_driver);
}
+151 −72
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>

@@ -111,6 +112,14 @@ static const char * const dss_generic_clk_source_names[] = {
	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
};

static bool dss_initialized;

bool omapdss_is_initialized(void)
{
	return dss_initialized;
}
EXPORT_SYMBOL(omapdss_is_initialized);

static inline void dss_write_reg(const struct dss_reg idx, u32 val)
{
	__raw_writel(val, dss.base + idx.idx);
@@ -811,7 +820,7 @@ static const enum omap_display_type dra7xx_ports[] = {
	OMAP_DISPLAY_TYPE_DPI,
};

static const struct dss_features omap24xx_dss_feats __initconst = {
static const struct dss_features omap24xx_dss_feats = {
	/*
	 * fck div max is really 16, but the divider range has gaps. The range
	 * from 1 to 6 has no gaps, so let's use that as a max.
@@ -824,7 +833,7 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
};

static const struct dss_features omap34xx_dss_feats __initconst = {
static const struct dss_features omap34xx_dss_feats = {
	.fck_div_max		=	16,
	.dss_fck_multiplier	=	2,
	.parent_clk_name	=	"dpll4_ck",
@@ -833,7 +842,7 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap34xx_ports),
};

static const struct dss_features omap3630_dss_feats __initconst = {
static const struct dss_features omap3630_dss_feats = {
	.fck_div_max		=	32,
	.dss_fck_multiplier	=	1,
	.parent_clk_name	=	"dpll4_ck",
@@ -842,7 +851,7 @@ static const struct dss_features omap3630_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
};

static const struct dss_features omap44xx_dss_feats __initconst = {
static const struct dss_features omap44xx_dss_feats = {
	.fck_div_max		=	32,
	.dss_fck_multiplier	=	1,
	.parent_clk_name	=	"dpll_per_x2_ck",
@@ -851,7 +860,7 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
};

static const struct dss_features omap54xx_dss_feats __initconst = {
static const struct dss_features omap54xx_dss_feats = {
	.fck_div_max		=	64,
	.dss_fck_multiplier	=	1,
	.parent_clk_name	=	"dpll_per_x2_ck",
@@ -860,7 +869,7 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
};

static const struct dss_features am43xx_dss_feats __initconst = {
static const struct dss_features am43xx_dss_feats = {
	.fck_div_max		=	0,
	.dss_fck_multiplier	=	0,
	.parent_clk_name	=	NULL,
@@ -869,7 +878,7 @@ static const struct dss_features am43xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
};

static const struct dss_features dra7xx_dss_feats __initconst = {
static const struct dss_features dra7xx_dss_feats = {
	.fck_div_max		=	64,
	.dss_fck_multiplier	=	1,
	.parent_clk_name	=	"dpll_per_x2_ck",
@@ -878,7 +887,7 @@ static const struct dss_features dra7xx_dss_feats __initconst = {
	.num_ports		=	ARRAY_SIZE(dra7xx_ports),
};

static int __init dss_init_features(struct platform_device *pdev)
static int dss_init_features(struct platform_device *pdev)
{
	const struct dss_features *src;
	struct dss_features *dst;
@@ -932,7 +941,7 @@ static int __init dss_init_features(struct platform_device *pdev)
	return 0;
}

static int __init dss_init_ports(struct platform_device *pdev)
static int dss_init_ports(struct platform_device *pdev)
{
	struct device_node *parent = pdev->dev.of_node;
	struct device_node *port;
@@ -976,7 +985,7 @@ static int __init dss_init_ports(struct platform_device *pdev)
	return 0;
}

static void __exit dss_uninit_ports(struct platform_device *pdev)
static void dss_uninit_ports(struct platform_device *pdev)
{
	struct device_node *parent = pdev->dev.of_node;
	struct device_node *port;
@@ -1018,14 +1027,74 @@ static void __exit dss_uninit_ports(struct platform_device *pdev)
	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
}

static int dss_video_pll_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct regulator *pll_regulator;
	int r;

	if (!np)
		return 0;

	if (of_property_read_bool(np, "syscon-pll-ctrl")) {
		dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
			"syscon-pll-ctrl");
		if (IS_ERR(dss.syscon_pll_ctrl)) {
			dev_err(&pdev->dev,
				"failed to get syscon-pll-ctrl regmap\n");
			return PTR_ERR(dss.syscon_pll_ctrl);
		}

		if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
				&dss.syscon_pll_ctrl_offset)) {
			dev_err(&pdev->dev,
				"failed to get syscon-pll-ctrl offset\n");
			return -EINVAL;
		}
	}

	pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
	if (IS_ERR(pll_regulator)) {
		r = PTR_ERR(pll_regulator);

		switch (r) {
		case -ENOENT:
			pll_regulator = NULL;
			break;

		case -EPROBE_DEFER:
			return -EPROBE_DEFER;

		default:
			DSSERR("can't get DPLL VDDA regulator\n");
			return r;
		}
	}

	if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
		dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
		if (IS_ERR(dss.video1_pll))
			return PTR_ERR(dss.video1_pll);
	}

	if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
		dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
		if (IS_ERR(dss.video2_pll)) {
			dss_video_pll_uninit(dss.video1_pll);
			return PTR_ERR(dss.video2_pll);
		}
	}

	return 0;
}

/* DSS HW IP initialisation */
static int __init 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;
	struct device_node *np = pdev->dev.of_node;
	u32 rev;
	int r;
	struct regulator *pll_regulator;

	dss.pdev = pdev;

@@ -1054,6 +1123,14 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
	if (r)
		goto err_setup_clocks;

	r = dss_video_pll_probe(pdev);
	if (r)
		goto err_pll_init;

	r = dss_init_ports(pdev);
	if (r)
		goto err_init_ports;

	pm_runtime_enable(&pdev->dev);

	r = dss_runtime_get();
@@ -1078,86 +1155,48 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;

	dss_init_ports(pdev);

	if (np && of_property_read_bool(np, "syscon-pll-ctrl")) {
		dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
			"syscon-pll-ctrl");
		if (IS_ERR(dss.syscon_pll_ctrl)) {
			dev_err(&pdev->dev,
				"failed to get syscon-pll-ctrl regmap\n");
			return PTR_ERR(dss.syscon_pll_ctrl);
		}

		if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
				&dss.syscon_pll_ctrl_offset)) {
			dev_err(&pdev->dev,
				"failed to get syscon-pll-ctrl offset\n");
			return -EINVAL;
		}
	}

	pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
	if (IS_ERR(pll_regulator)) {
		r = PTR_ERR(pll_regulator);

		switch (r) {
		case -ENOENT:
			pll_regulator = NULL;
			break;

		case -EPROBE_DEFER:
			return -EPROBE_DEFER;

		default:
			DSSERR("can't get DPLL VDDA regulator\n");
			return r;
		}
	}

	if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
		dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
		if (IS_ERR(dss.video1_pll)) {
			r = PTR_ERR(dss.video1_pll);
			goto err_pll_init;
		}
	}

	if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
		dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
		if (IS_ERR(dss.video2_pll)) {
			r = PTR_ERR(dss.video2_pll);
			goto err_pll_init;
		}
	}

	rev = dss_read_reg(DSS_REVISION);
	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));

	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);

	dss_initialized = true;

	return 0;

err_pll_init:
err_component:
err_runtime_get:
	pm_runtime_disable(&pdev->dev);
	dss_uninit_ports(pdev);
err_init_ports:
	if (dss.video1_pll)
		dss_video_pll_uninit(dss.video1_pll);

	if (dss.video2_pll)
		dss_video_pll_uninit(dss.video2_pll);
err_runtime_get:
	pm_runtime_disable(&pdev->dev);
err_pll_init:
err_setup_clocks:
	dss_put_clocks();
	return r;
}

static int __exit 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);

@@ -1169,7 +1208,46 @@ static int __exit 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;
}

@@ -1215,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         = __exit_p(omap_dsshw_remove),
	.probe		= dss_probe,
	.remove		= dss_remove,
	.driver         = {
		.name   = "omapdss_dss",
		.pm	= &dss_pm_ops,
@@ -1226,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)
Loading