diff options
Diffstat (limited to 'drivers/gpu/drm/tegra/sor.c')
| -rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 76 | 
1 files changed, 35 insertions, 41 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index e88a17c2937f..cc2aa2308a51 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -397,7 +397,6 @@ struct tegra_sor;  struct tegra_sor_ops {  	const char *name;  	int (*probe)(struct tegra_sor *sor); -	int (*remove)(struct tegra_sor *sor);  	void (*audio_enable)(struct tegra_sor *sor);  	void (*audio_disable)(struct tegra_sor *sor);  }; @@ -2942,6 +2941,24 @@ static const struct drm_encoder_helper_funcs tegra_sor_dp_helpers = {  	.atomic_check = tegra_sor_encoder_atomic_check,  }; +static void tegra_sor_disable_regulator(void *data) +{ +	struct regulator *reg = data; + +	regulator_disable(reg); +} + +static int tegra_sor_enable_regulator(struct tegra_sor *sor, struct regulator *reg) +{ +	int err; + +	err = regulator_enable(reg); +	if (err) +		return err; + +	return devm_add_action_or_reset(sor->dev, tegra_sor_disable_regulator, reg); +} +  static int tegra_sor_hdmi_probe(struct tegra_sor *sor)  {  	int err; @@ -2953,7 +2970,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)  		return PTR_ERR(sor->avdd_io_supply);  	} -	err = regulator_enable(sor->avdd_io_supply); +	err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);  	if (err < 0) {  		dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",  			err); @@ -2967,7 +2984,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)  		return PTR_ERR(sor->vdd_pll_supply);  	} -	err = regulator_enable(sor->vdd_pll_supply); +	err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);  	if (err < 0) {  		dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",  			err); @@ -2981,7 +2998,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)  		return PTR_ERR(sor->hdmi_supply);  	} -	err = regulator_enable(sor->hdmi_supply); +	err = tegra_sor_enable_regulator(sor, sor->hdmi_supply);  	if (err < 0) {  		dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);  		return err; @@ -2992,19 +3009,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)  	return 0;  } -static int tegra_sor_hdmi_remove(struct tegra_sor *sor) -{ -	regulator_disable(sor->hdmi_supply); -	regulator_disable(sor->vdd_pll_supply); -	regulator_disable(sor->avdd_io_supply); - -	return 0; -} -  static const struct tegra_sor_ops tegra_sor_hdmi_ops = {  	.name = "HDMI",  	.probe = tegra_sor_hdmi_probe, -	.remove = tegra_sor_hdmi_remove,  	.audio_enable = tegra_sor_hdmi_audio_enable,  	.audio_disable = tegra_sor_hdmi_audio_disable,  }; @@ -3017,7 +3024,7 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)  	if (IS_ERR(sor->avdd_io_supply))  		return PTR_ERR(sor->avdd_io_supply); -	err = regulator_enable(sor->avdd_io_supply); +	err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);  	if (err < 0)  		return err; @@ -3025,25 +3032,16 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)  	if (IS_ERR(sor->vdd_pll_supply))  		return PTR_ERR(sor->vdd_pll_supply); -	err = regulator_enable(sor->vdd_pll_supply); +	err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);  	if (err < 0)  		return err;  	return 0;  } -static int tegra_sor_dp_remove(struct tegra_sor *sor) -{ -	regulator_disable(sor->vdd_pll_supply); -	regulator_disable(sor->avdd_io_supply); - -	return 0; -} -  static const struct tegra_sor_ops tegra_sor_dp_ops = {  	.name = "DP",  	.probe = tegra_sor_dp_probe, -	.remove = tegra_sor_dp_remove,  };  static int tegra_sor_init(struct host1x_client *client) @@ -3145,6 +3143,7 @@ static int tegra_sor_init(struct host1x_client *client)  		if (err < 0) {  			dev_err(sor->dev, "failed to deassert SOR reset: %d\n",  				err); +			clk_disable_unprepare(sor->clk);  			return err;  		} @@ -3152,12 +3151,17 @@ static int tegra_sor_init(struct host1x_client *client)  	}  	err = clk_prepare_enable(sor->clk_safe); -	if (err < 0) +	if (err < 0) { +		clk_disable_unprepare(sor->clk);  		return err; +	}  	err = clk_prepare_enable(sor->clk_dp); -	if (err < 0) +	if (err < 0) { +		clk_disable_unprepare(sor->clk_safe); +		clk_disable_unprepare(sor->clk);  		return err; +	}  	return 0;  } @@ -3764,17 +3768,16 @@ static int tegra_sor_probe(struct platform_device *pdev)  		return err;  	err = tegra_output_probe(&sor->output); -	if (err < 0) { -		dev_err(&pdev->dev, "failed to probe output: %d\n", err); -		return err; -	} +	if (err < 0) +		return dev_err_probe(&pdev->dev, err, +				     "failed to probe output\n");  	if (sor->ops && sor->ops->probe) {  		err = sor->ops->probe(sor);  		if (err < 0) {  			dev_err(&pdev->dev, "failed to probe %s: %d\n",  				sor->ops->name, err); -			goto output; +			goto remove;  		}  	} @@ -3955,9 +3958,6 @@ unregister:  rpm_disable:  	pm_runtime_disable(&pdev->dev);  remove: -	if (sor->ops && sor->ops->remove) -		sor->ops->remove(sor); -output:  	tegra_output_remove(&sor->output);  	return err;  } @@ -3976,12 +3976,6 @@ static int tegra_sor_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev); -	if (sor->ops && sor->ops->remove) { -		err = sor->ops->remove(sor); -		if (err < 0) -			dev_err(&pdev->dev, "failed to remove SOR: %d\n", err); -	} -  	tegra_output_remove(&sor->output);  	return 0;  |