diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/dss.c')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.c | 71 | 
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);  	}  }  |