aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/omapdrm/dss/dss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/dss.c')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 225ec808b01a..4d5739fa4a5d 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = {
.has_lcd_clk_src = true,
};
-static int dss_init_ports(struct dss_device *dss)
+static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports)
{
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
unsigned int i;
- int r;
- for (i = 0; i < dss->feat->num_ports; i++) {
+ for (i = 0; i < num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
if (!port)
continue;
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
- r = dpi_init_port(dss, pdev, port, dss->feat->model);
- if (r)
- return r;
+ dpi_uninit_port(port);
break;
-
case OMAP_DISPLAY_TYPE_SDI:
- r = sdi_init_port(dss, pdev, port);
- if (r)
- return r;
+ sdi_uninit_port(port);
break;
-
default:
break;
}
}
-
- return 0;
}
-static void dss_uninit_ports(struct dss_device *dss)
+static int dss_init_ports(struct dss_device *dss)
{
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
- int i;
+ unsigned int i;
+ int r;
for (i = 0; i < dss->feat->num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss)
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
- dpi_uninit_port(port);
+ r = dpi_init_port(dss, pdev, port, dss->feat->model);
+ if (r)
+ goto error;
break;
+
case OMAP_DISPLAY_TYPE_SDI:
- sdi_uninit_port(port);
+ r = sdi_init_port(dss, pdev, port);
+ if (r)
+ goto error;
break;
+
default:
break;
}
}
+
+ return 0;
+
+error:
+ __dss_uninit_ports(dss, i);
+ return r;
+}
+
+static void dss_uninit_ports(struct dss_device *dss)
+{
+ __dss_uninit_ports(dss, dss->feat->num_ports);
}
static int dss_video_pll_probe(struct dss_device *dss)
@@ -1339,9 +1348,15 @@ static int dss_component_compare(struct device *dev, void *data)
return dev == child;
}
+struct dss_component_match_data {
+ struct device *dev;
+ struct component_match **match;
+};
+
static int dss_add_child_component(struct device *dev, void *data)
{
- struct component_match **match = data;
+ struct dss_component_match_data *cmatch = data;
+ struct component_match **match = cmatch->match;
/*
* HACK
@@ -1352,7 +1367,17 @@ static int dss_add_child_component(struct device *dev, void *data)
if (strstr(dev_name(dev), "rfbi"))
return 0;
- component_match_add(dev->parent, match, dss_component_compare, dev);
+ /*
+ * Handle possible interconnect target modules defined within the DSS.
+ * The DSS components can be children of an interconnect target module
+ * after the device tree has been updated for the module data.
+ * See also omapdss_boot_init() for compatible fixup.
+ */
+ if (strstr(dev_name(dev), "target-module"))
+ return device_for_each_child(dev, cmatch,
+ dss_add_child_component);
+
+ component_match_add(cmatch->dev, match, dss_component_compare, dev);
return 0;
}
@@ -1395,6 +1420,7 @@ static int dss_probe_hardware(struct dss_device *dss)
static int dss_probe(struct platform_device *pdev)
{
const struct soc_device_attribute *soc;
+ struct dss_component_match_data cmatch;
struct component_match *match = NULL;
struct resource *dss_mem;
struct dss_device *dss;
@@ -1472,7 +1498,9 @@ static int dss_probe(struct platform_device *pdev)
omapdss_gather_components(&pdev->dev);
- device_for_each_child(&pdev->dev, &match, dss_add_child_component);
+ cmatch.dev = &pdev->dev;
+ cmatch.match = &match;
+ device_for_each_child(&pdev->dev, &cmatch, dss_add_child_component);
r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
if (r)
@@ -1543,7 +1571,8 @@ static void dss_shutdown(struct platform_device *pdev)
DSSDBG("shutdown\n");
for_each_dss_output(dssdev) {
- if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
+ dssdev->ops && dssdev->ops->disable)
dssdev->ops->disable(dssdev);
}
}