All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding@gmail.com>
To: Dmitry Osipenko <digetx@gmail.com>
Cc: "Jonathan Hunter" <jonathanh@nvidia.com>,
	"Alan Stern" <stern@rowland.harvard.edu>,
	"Peter Chen" <Peter.Chen@nxp.com>,
	"Mark Brown" <broonie@kernel.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Mauro Carvalho Chehab" <mchehab@kernel.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Peter Geis" <pgwipeout@gmail.com>,
	"Nicolas Chauvet" <kwizart@gmail.com>,
	linux-samsung-soc@vger.kernel.org, devel@driverdev.osuosl.org,
	linux-usb@vger.kernel.org, linux-pwm@vger.kernel.org,
	linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org,
	linux-media@vger.kernel.org, linux-tegra@vger.kernel.org
Subject: Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
Date: Tue, 10 Nov 2020 21:29:45 +0100	[thread overview]
Message-ID: <20201110202945.GF2375022@ulmo> (raw)
In-Reply-To: <20201104234427.26477-12-digetx@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9116 bytes --]

On Thu, Nov 05, 2020 at 02:44:08AM +0300, Dmitry Osipenko wrote:
> Add OPP and SoC core voltage scaling support to the display controller
> driver. This is required for enabling system-wide DVFS on older Tegra
> SoCs.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com>
> Tested-by: Nicolas Chauvet <kwizart@gmail.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/gpu/drm/tegra/Kconfig |   1 +
>  drivers/gpu/drm/tegra/dc.c    | 138 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/tegra/dc.h    |   5 ++
>  3 files changed, 143 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
> index 1650a448eabd..9eec4c3fbd3b 100644
> --- a/drivers/gpu/drm/tegra/Kconfig
> +++ b/drivers/gpu/drm/tegra/Kconfig
> @@ -12,6 +12,7 @@ config DRM_TEGRA
>  	select INTERCONNECT
>  	select IOMMU_IOVA
>  	select CEC_CORE if CEC_NOTIFIER
> +	select PM_OPP
>  	help
>  	  Choose this option if you have an NVIDIA Tegra SoC.
>  
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index fd7c8828652d..babcb66a335b 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -11,9 +11,13 @@
>  #include <linux/interconnect.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> +#include <linux/pm_opp.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/reset.h>
>  
> +#include <soc/tegra/common.h>
> +#include <soc/tegra/fuse.h>
>  #include <soc/tegra/pmc.h>
>  
>  #include <drm/drm_atomic.h>
> @@ -1699,6 +1703,55 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
>  	return 0;
>  }
>  
> +static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
> +					  struct tegra_dc_state *state)
> +{
> +	struct dev_pm_opp *opp;
> +	unsigned long rate;
> +	int err, min_uV;
> +
> +	/* OPP usage is optional */
> +	if (!dc->opp_table)
> +		return;
> +
> +	/* calculate actual pixel clock rate which depends on internal divider */
> +	rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
> +
> +	/* find suitable OPP for the rate */
> +	opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);
> +
> +	if (opp == ERR_PTR(-ERANGE))
> +		opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);
> +
> +	if (IS_ERR(opp)) {
> +		dev_err(dc->dev, "failed to find OPP for %lu Hz: %ld\n",
> +			rate, PTR_ERR(opp));
> +		return;
> +	}
> +
> +	min_uV = dev_pm_opp_get_voltage(opp);
> +	dev_pm_opp_put(opp);
> +
> +	/*
> +	 * Voltage scaling is optional and trying to set voltage for a dummy
> +	 * regulator will error out.
> +	 */
> +	if (!device_property_present(dc->dev, "core-supply"))
> +		return;

This is a potentially heavy operation, so I think we should avoid that
here. How about you use devm_regulator_get_optional() in ->probe()? That
returns -ENODEV if no regulator was specified, in which case you can set
dc->core_reg = NULL and use that as the condition here.

> +
> +	/*
> +	 * Note that the minimum core voltage depends on the pixel clock
> +	 * rate (which depends on internal clock divider of CRTC) and not on
> +	 * the rate of the display controller clock. This is why we're not
> +	 * using dev_pm_opp_set_rate() API and instead are managing the
> +	 * voltage by ourselves.
> +	 */
> +	err = regulator_set_voltage(dc->core_reg, min_uV, INT_MAX);
> +	if (err)
> +		dev_err(dc->dev, "failed to set CORE voltage to %duV: %d\n",
> +			min_uV, err);
> +}

Also, I'd prefer if the flow here was more linear, such as:

	if (dc->core_reg) {
		err = regulator_set_voltage(...);
		...
	}

> +
>  static void tegra_dc_commit_state(struct tegra_dc *dc,
>  				  struct tegra_dc_state *state)
>  {
> @@ -1738,6 +1791,8 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
>  	if (err < 0)
>  		dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
>  			dc->clk, state->pclk, err);
> +
> +	tegra_dc_update_voltage_state(dc, state);
>  }
>  
>  static void tegra_dc_stop(struct tegra_dc *dc)
> @@ -2521,6 +2576,7 @@ static int tegra_dc_runtime_suspend(struct host1x_client *client)
>  
>  	clk_disable_unprepare(dc->clk);
>  	pm_runtime_put_sync(dev);
> +	regulator_disable(dc->core_reg);
>  
>  	return 0;
>  }
> @@ -2531,10 +2587,16 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	struct device *dev = client->dev;
>  	int err;
>  
> +	err = regulator_enable(dc->core_reg);
> +	if (err < 0) {
> +		dev_err(dev, "failed to enable CORE regulator: %d\n", err);
> +		return err;
> +	}
> +
>  	err = pm_runtime_get_sync(dev);
>  	if (err < 0) {
>  		dev_err(dev, "failed to get runtime PM: %d\n", err);
> -		return err;
> +		goto disable_regulator;
>  	}
>  
>  	if (dc->soc->has_powergate) {
> @@ -2564,6 +2626,9 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	clk_disable_unprepare(dc->clk);
>  put_rpm:
>  	pm_runtime_put_sync(dev);
> +disable_regulator:
> +	regulator_disable(dc->core_reg);
> +
>  	return err;
>  }
>  
> @@ -2879,6 +2944,72 @@ static int tegra_dc_couple(struct tegra_dc *dc)
>  	return 0;
>  }
>  
> +static void tegra_dc_deinit_opp_table(void *data)
> +{
> +	struct tegra_dc *dc = data;
> +
> +	dev_pm_opp_of_remove_table(dc->dev);
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +	dev_pm_opp_put_regulators(dc->opp_table);
> +}
> +
> +static int devm_tegra_dc_opp_table_init(struct tegra_dc *dc)
> +{
> +	struct opp_table *hw_opp_table;
> +	u32 hw_version;
> +	int err;
> +
> +	/* voltage scaling is optional */
> +	dc->core_reg = devm_regulator_get(dc->dev, "core");
> +	if (IS_ERR(dc->core_reg))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->core_reg),
> +				     "failed to get CORE regulator\n");
> +
> +	/* legacy device-trees don't have OPP table */
> +	if (!device_property_present(dc->dev, "operating-points-v2"))
> +		return 0;

"Legacy" is a bit confusing here. For one, no device trees currently
have these tables and secondly, for newer SoCs we may never need them.

> +
> +	dc->opp_table = dev_pm_opp_get_opp_table(dc->dev);
> +	if (IS_ERR(dc->opp_table))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->opp_table),
> +				     "failed to prepare OPP table\n");
> +
> +	if (of_machine_is_compatible("nvidia,tegra20"))
> +		hw_version = BIT(tegra_sku_info.soc_process_id);
> +	else
> +		hw_version = BIT(tegra_sku_info.soc_speedo_id);
> +
> +	hw_opp_table = dev_pm_opp_set_supported_hw(dc->dev, &hw_version, 1);
> +	err = PTR_ERR_OR_ZERO(hw_opp_table);

What's the point of this? A more canonical version would be:

	if (IS_ERR(hw_opp_table)) {
		err = PTR_ERR(hw_opp_table);
		dev_err(dc->dev, ...);
		goto put_table;
	}

That uses the same number of lines but is much easier to read, in my
opinion, because it is the canonical form.

> +	if (err) {
> +		dev_err(dc->dev, "failed to set supported HW: %d\n", err);
> +		goto put_table;
> +	}
> +
> +	err = dev_pm_opp_of_add_table(dc->dev);
> +	if (err) {
> +		dev_err(dc->dev, "failed to add OPP table: %d\n", err);
> +		goto put_hw;
> +	}
> +
> +	err = devm_add_action(dc->dev, tegra_dc_deinit_opp_table, dc);
> +	if (err)
> +		goto remove_table;

Do these functions return positive values? If not, I'd prefer if this
check was more explicit (i.e. err < 0) for consistency with the rest of
this code.

> +
> +	dev_info(dc->dev, "OPP HW ver. 0x%x\n", hw_version);
> +
> +	return 0;
> +
> +remove_table:
> +	dev_pm_opp_of_remove_table(dc->dev);
> +put_hw:
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +put_table:
> +	dev_pm_opp_put_opp_table(dc->opp_table);
> +
> +	return err;
> +}
> +
>  static int tegra_dc_probe(struct platform_device *pdev)
>  {
>  	struct tegra_dc *dc;
> @@ -2937,6 +3068,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
>  		tegra_powergate_power_off(dc->powergate);
>  	}
>  
> +	err = devm_tegra_dc_opp_table_init(dc);
> +	if (err < 0)
> +		return err;
> +
>  	dc->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(dc->regs))
>  		return PTR_ERR(dc->regs);
> @@ -3007,6 +3142,7 @@ struct platform_driver tegra_dc_driver = {
>  	.driver = {
>  		.name = "tegra-dc",
>  		.of_match_table = tegra_dc_of_match,
> +		.sync_state = tegra_soc_device_sync_state,
>  	},
>  	.probe = tegra_dc_probe,
>  	.remove = tegra_dc_remove,
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index ba4ed35139fb..fd774fc5c2e4 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -13,6 +13,8 @@
>  
>  #include "drm.h"
>  
> +struct opp_table;
> +struct regulator;
>  struct tegra_output;
>  
>  #define TEGRA_DC_LEGACY_PLANES_NUM	6
> @@ -107,6 +109,9 @@ struct tegra_dc {
>  	struct drm_info_list *debugfs_files;
>  
>  	const struct tegra_dc_soc_info *soc;
> +
> +	struct opp_table *opp_table;
> +	struct regulator *core_reg;

We typically use a _supply suffix on regulators to avoid confusing this
with "register".

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

WARNING: multiple messages have this Message-ID (diff)
From: Thierry Reding <thierry.reding@gmail.com>
To: Dmitry Osipenko <digetx@gmail.com>
Cc: "Peter Chen" <Peter.Chen@nxp.com>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	dri-devel@lists.freedesktop.org,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	devicetree@vger.kernel.org, "Lee Jones" <lee.jones@linaro.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	devel@driverdev.osuosl.org, linux-samsung-soc@vger.kernel.org,
	"Nicolas Chauvet" <kwizart@gmail.com>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Jonathan Hunter" <jonathanh@nvidia.com>,
	"Alan Stern" <stern@rowland.harvard.edu>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	linux-media@vger.kernel.org, linux-pwm@vger.kernel.org,
	"Rob Herring" <robh+dt@kernel.org>,
	linux-tegra@vger.kernel.org,
	"Mauro Carvalho Chehab" <mchehab@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	linux-usb@vger.kernel.org, linux-mmc@vger.kernel.org,
	linux-kernel@vger.kernel.org, "Mark Brown" <broonie@kernel.org>,
	"Peter Geis" <pgwipeout@gmail.com>
Subject: Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
Date: Tue, 10 Nov 2020 21:29:45 +0100	[thread overview]
Message-ID: <20201110202945.GF2375022@ulmo> (raw)
In-Reply-To: <20201104234427.26477-12-digetx@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 9116 bytes --]

On Thu, Nov 05, 2020 at 02:44:08AM +0300, Dmitry Osipenko wrote:
> Add OPP and SoC core voltage scaling support to the display controller
> driver. This is required for enabling system-wide DVFS on older Tegra
> SoCs.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com>
> Tested-by: Nicolas Chauvet <kwizart@gmail.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/gpu/drm/tegra/Kconfig |   1 +
>  drivers/gpu/drm/tegra/dc.c    | 138 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/tegra/dc.h    |   5 ++
>  3 files changed, 143 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
> index 1650a448eabd..9eec4c3fbd3b 100644
> --- a/drivers/gpu/drm/tegra/Kconfig
> +++ b/drivers/gpu/drm/tegra/Kconfig
> @@ -12,6 +12,7 @@ config DRM_TEGRA
>  	select INTERCONNECT
>  	select IOMMU_IOVA
>  	select CEC_CORE if CEC_NOTIFIER
> +	select PM_OPP
>  	help
>  	  Choose this option if you have an NVIDIA Tegra SoC.
>  
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index fd7c8828652d..babcb66a335b 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -11,9 +11,13 @@
>  #include <linux/interconnect.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> +#include <linux/pm_opp.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/reset.h>
>  
> +#include <soc/tegra/common.h>
> +#include <soc/tegra/fuse.h>
>  #include <soc/tegra/pmc.h>
>  
>  #include <drm/drm_atomic.h>
> @@ -1699,6 +1703,55 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
>  	return 0;
>  }
>  
> +static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
> +					  struct tegra_dc_state *state)
> +{
> +	struct dev_pm_opp *opp;
> +	unsigned long rate;
> +	int err, min_uV;
> +
> +	/* OPP usage is optional */
> +	if (!dc->opp_table)
> +		return;
> +
> +	/* calculate actual pixel clock rate which depends on internal divider */
> +	rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
> +
> +	/* find suitable OPP for the rate */
> +	opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);
> +
> +	if (opp == ERR_PTR(-ERANGE))
> +		opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);
> +
> +	if (IS_ERR(opp)) {
> +		dev_err(dc->dev, "failed to find OPP for %lu Hz: %ld\n",
> +			rate, PTR_ERR(opp));
> +		return;
> +	}
> +
> +	min_uV = dev_pm_opp_get_voltage(opp);
> +	dev_pm_opp_put(opp);
> +
> +	/*
> +	 * Voltage scaling is optional and trying to set voltage for a dummy
> +	 * regulator will error out.
> +	 */
> +	if (!device_property_present(dc->dev, "core-supply"))
> +		return;

This is a potentially heavy operation, so I think we should avoid that
here. How about you use devm_regulator_get_optional() in ->probe()? That
returns -ENODEV if no regulator was specified, in which case you can set
dc->core_reg = NULL and use that as the condition here.

> +
> +	/*
> +	 * Note that the minimum core voltage depends on the pixel clock
> +	 * rate (which depends on internal clock divider of CRTC) and not on
> +	 * the rate of the display controller clock. This is why we're not
> +	 * using dev_pm_opp_set_rate() API and instead are managing the
> +	 * voltage by ourselves.
> +	 */
> +	err = regulator_set_voltage(dc->core_reg, min_uV, INT_MAX);
> +	if (err)
> +		dev_err(dc->dev, "failed to set CORE voltage to %duV: %d\n",
> +			min_uV, err);
> +}

Also, I'd prefer if the flow here was more linear, such as:

	if (dc->core_reg) {
		err = regulator_set_voltage(...);
		...
	}

> +
>  static void tegra_dc_commit_state(struct tegra_dc *dc,
>  				  struct tegra_dc_state *state)
>  {
> @@ -1738,6 +1791,8 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
>  	if (err < 0)
>  		dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
>  			dc->clk, state->pclk, err);
> +
> +	tegra_dc_update_voltage_state(dc, state);
>  }
>  
>  static void tegra_dc_stop(struct tegra_dc *dc)
> @@ -2521,6 +2576,7 @@ static int tegra_dc_runtime_suspend(struct host1x_client *client)
>  
>  	clk_disable_unprepare(dc->clk);
>  	pm_runtime_put_sync(dev);
> +	regulator_disable(dc->core_reg);
>  
>  	return 0;
>  }
> @@ -2531,10 +2587,16 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	struct device *dev = client->dev;
>  	int err;
>  
> +	err = regulator_enable(dc->core_reg);
> +	if (err < 0) {
> +		dev_err(dev, "failed to enable CORE regulator: %d\n", err);
> +		return err;
> +	}
> +
>  	err = pm_runtime_get_sync(dev);
>  	if (err < 0) {
>  		dev_err(dev, "failed to get runtime PM: %d\n", err);
> -		return err;
> +		goto disable_regulator;
>  	}
>  
>  	if (dc->soc->has_powergate) {
> @@ -2564,6 +2626,9 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	clk_disable_unprepare(dc->clk);
>  put_rpm:
>  	pm_runtime_put_sync(dev);
> +disable_regulator:
> +	regulator_disable(dc->core_reg);
> +
>  	return err;
>  }
>  
> @@ -2879,6 +2944,72 @@ static int tegra_dc_couple(struct tegra_dc *dc)
>  	return 0;
>  }
>  
> +static void tegra_dc_deinit_opp_table(void *data)
> +{
> +	struct tegra_dc *dc = data;
> +
> +	dev_pm_opp_of_remove_table(dc->dev);
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +	dev_pm_opp_put_regulators(dc->opp_table);
> +}
> +
> +static int devm_tegra_dc_opp_table_init(struct tegra_dc *dc)
> +{
> +	struct opp_table *hw_opp_table;
> +	u32 hw_version;
> +	int err;
> +
> +	/* voltage scaling is optional */
> +	dc->core_reg = devm_regulator_get(dc->dev, "core");
> +	if (IS_ERR(dc->core_reg))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->core_reg),
> +				     "failed to get CORE regulator\n");
> +
> +	/* legacy device-trees don't have OPP table */
> +	if (!device_property_present(dc->dev, "operating-points-v2"))
> +		return 0;

"Legacy" is a bit confusing here. For one, no device trees currently
have these tables and secondly, for newer SoCs we may never need them.

> +
> +	dc->opp_table = dev_pm_opp_get_opp_table(dc->dev);
> +	if (IS_ERR(dc->opp_table))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->opp_table),
> +				     "failed to prepare OPP table\n");
> +
> +	if (of_machine_is_compatible("nvidia,tegra20"))
> +		hw_version = BIT(tegra_sku_info.soc_process_id);
> +	else
> +		hw_version = BIT(tegra_sku_info.soc_speedo_id);
> +
> +	hw_opp_table = dev_pm_opp_set_supported_hw(dc->dev, &hw_version, 1);
> +	err = PTR_ERR_OR_ZERO(hw_opp_table);

What's the point of this? A more canonical version would be:

	if (IS_ERR(hw_opp_table)) {
		err = PTR_ERR(hw_opp_table);
		dev_err(dc->dev, ...);
		goto put_table;
	}

That uses the same number of lines but is much easier to read, in my
opinion, because it is the canonical form.

> +	if (err) {
> +		dev_err(dc->dev, "failed to set supported HW: %d\n", err);
> +		goto put_table;
> +	}
> +
> +	err = dev_pm_opp_of_add_table(dc->dev);
> +	if (err) {
> +		dev_err(dc->dev, "failed to add OPP table: %d\n", err);
> +		goto put_hw;
> +	}
> +
> +	err = devm_add_action(dc->dev, tegra_dc_deinit_opp_table, dc);
> +	if (err)
> +		goto remove_table;

Do these functions return positive values? If not, I'd prefer if this
check was more explicit (i.e. err < 0) for consistency with the rest of
this code.

> +
> +	dev_info(dc->dev, "OPP HW ver. 0x%x\n", hw_version);
> +
> +	return 0;
> +
> +remove_table:
> +	dev_pm_opp_of_remove_table(dc->dev);
> +put_hw:
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +put_table:
> +	dev_pm_opp_put_opp_table(dc->opp_table);
> +
> +	return err;
> +}
> +
>  static int tegra_dc_probe(struct platform_device *pdev)
>  {
>  	struct tegra_dc *dc;
> @@ -2937,6 +3068,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
>  		tegra_powergate_power_off(dc->powergate);
>  	}
>  
> +	err = devm_tegra_dc_opp_table_init(dc);
> +	if (err < 0)
> +		return err;
> +
>  	dc->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(dc->regs))
>  		return PTR_ERR(dc->regs);
> @@ -3007,6 +3142,7 @@ struct platform_driver tegra_dc_driver = {
>  	.driver = {
>  		.name = "tegra-dc",
>  		.of_match_table = tegra_dc_of_match,
> +		.sync_state = tegra_soc_device_sync_state,
>  	},
>  	.probe = tegra_dc_probe,
>  	.remove = tegra_dc_remove,
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index ba4ed35139fb..fd774fc5c2e4 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -13,6 +13,8 @@
>  
>  #include "drm.h"
>  
> +struct opp_table;
> +struct regulator;
>  struct tegra_output;
>  
>  #define TEGRA_DC_LEGACY_PLANES_NUM	6
> @@ -107,6 +109,9 @@ struct tegra_dc {
>  	struct drm_info_list *debugfs_files;
>  
>  	const struct tegra_dc_soc_info *soc;
> +
> +	struct opp_table *opp_table;
> +	struct regulator *core_reg;

We typically use a _supply suffix on regulators to avoid confusing this
with "register".

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2020-11-10 20:29 UTC|newest]

Thread overview: 216+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
2020-11-04 23:43 ` Dmitry Osipenko
2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
2020-11-04 23:43   ` Dmitry Osipenko
2020-11-09 18:57   ` Rob Herring
2020-11-09 18:57     ` Rob Herring
2020-11-11 11:45   ` Ulf Hansson
2020-11-11 11:45     ` Ulf Hansson
2020-11-04 23:43 ` [PATCH v1 02/30] dt-bindings: mmc: tegra: " Dmitry Osipenko
2020-11-04 23:43   ` Dmitry Osipenko
2020-11-09 18:58   ` Rob Herring
2020-11-09 18:58     ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 03/30] dt-bindings: pwm: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-09 19:00   ` Rob Herring
2020-11-09 19:00     ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 04/30] media: dt: bindings: tegra-vde: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-09 19:01     ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-09 19:01     ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-09 19:01     ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 07/30] soc/tegra: Add sync state API Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-10 20:47   ` Thierry Reding
2020-11-10 20:47     ` Thierry Reding
2020-11-10 21:22     ` Dmitry Osipenko
2020-11-10 21:22       ` Dmitry Osipenko
2020-11-10 21:32       ` Dmitry Osipenko
2020-11-10 21:32         ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 09/30] soc/tegra: regulators: Fix lockup when voltage-spread is out of range Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 10/30] regulator: Allow skipping disabled regulators in regulator_check_consumers() Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-10 20:29   ` Thierry Reding [this message]
2020-11-10 20:29     ` Thierry Reding
2020-11-10 20:32     ` Mark Brown
2020-11-10 20:32       ` Mark Brown
2020-11-10 21:23       ` Dmitry Osipenko
2020-11-10 21:23         ` Dmitry Osipenko
2020-11-11 11:55         ` Mark Brown
2020-11-11 11:55           ` Mark Brown
2020-11-12 16:59           ` Dmitry Osipenko
2020-11-12 16:59             ` Dmitry Osipenko
2020-11-12 17:16             ` Mark Brown
2020-11-12 17:16               ` Mark Brown
2020-11-12 19:16               ` Dmitry Osipenko
2020-11-12 19:16                 ` Dmitry Osipenko
2020-11-12 20:01                 ` Mark Brown
2020-11-12 20:01                   ` Mark Brown
2020-11-12 22:37                   ` Dmitry Osipenko
2020-11-12 22:37                     ` Dmitry Osipenko
2020-11-13 14:29                     ` Mark Brown
2020-11-13 14:29                       ` Mark Brown
2020-11-13 15:55                       ` Dmitry Osipenko
2020-11-13 15:55                         ` Dmitry Osipenko
2020-11-13 16:15                         ` Mark Brown
2020-11-13 16:15                           ` Mark Brown
2020-11-13 17:13                           ` Dmitry Osipenko
2020-11-13 17:13                             ` Dmitry Osipenko
2020-11-13 17:28                             ` Mark Brown
2020-11-13 17:28                               ` Mark Brown
2020-11-15 17:42                               ` Dmitry Osipenko
2020-11-15 17:42                                 ` Dmitry Osipenko
2020-11-16 13:33                                 ` Mark Brown
2020-11-16 13:33                                   ` Mark Brown
2020-11-19 14:22                                   ` Dmitry Osipenko
2020-11-19 14:22                                     ` Dmitry Osipenko
2020-11-19 15:19                                     ` Mark Brown
2020-11-19 15:19                                       ` Mark Brown
2020-11-13 17:30                             ` Thierry Reding
2020-11-13 17:30                               ` Thierry Reding
2020-11-10 21:17     ` Dmitry Osipenko
2020-11-10 21:17       ` Dmitry Osipenko
2020-11-10 21:50     ` Dmitry Osipenko
2020-11-10 21:50       ` Dmitry Osipenko
2020-11-11  9:28     ` Dan Carpenter
2020-11-11  9:28       ` Dan Carpenter
2020-11-04 23:44 ` [PATCH v1 12/30] drm/tegra: gr2d: Correct swapped device-tree compatibles Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 13/30] drm/tegra: gr2d: Support OPP and SoC core voltage scaling Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 14/30] drm/tegra: gr3d: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 15/30] drm/tegra: hdmi: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 16/30] gpu: host1x: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-05  9:58   ` Viresh Kumar
2020-11-05  9:58     ` Viresh Kumar
2020-11-05 14:18     ` Dmitry Osipenko
2020-11-05 14:18       ` Dmitry Osipenko
2020-11-06  6:15       ` Viresh Kumar
2020-11-06  6:15         ` Viresh Kumar
2020-11-06 13:17         ` Dmitry Osipenko
2020-11-06 13:41           ` Frank Lee
2020-11-09  5:00             ` Viresh Kumar
2020-11-09  5:00               ` Viresh Kumar
2020-11-09  5:08               ` Dmitry Osipenko
2020-11-09  5:08                 ` Dmitry Osipenko
2020-11-09  5:10                 ` Viresh Kumar
2020-11-09  5:10                   ` Viresh Kumar
2020-11-09  5:19                   ` Dmitry Osipenko
2020-11-09  5:19                     ` Dmitry Osipenko
2020-11-09  5:35                     ` Viresh Kumar
2020-11-09  5:35                       ` Viresh Kumar
2020-11-09  5:44                       ` Dmitry Osipenko
2020-11-09  5:44                         ` Dmitry Osipenko
2020-11-09  5:53                         ` Viresh Kumar
2020-11-09  5:53                           ` Viresh Kumar
2020-11-09 11:20                           ` Frank Lee
2020-11-09 11:20                             ` Frank Lee
2020-12-22  8:54                             ` Viresh Kumar
2020-12-22  8:54                               ` Viresh Kumar
2020-11-04 23:44 ` [PATCH v1 18/30] pwm: tegra: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-10 20:50   ` Thierry Reding
2020-11-10 20:50     ` Thierry Reding
2020-11-10 21:17     ` Dmitry Osipenko
2020-11-10 21:17       ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 19/30] media: staging: tegra-vde: Support OPP and SoC " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 20/30] usb: chipidea: tegra: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 21/30] usb: host: ehci-tegra: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-05 16:07   ` Alan Stern
2020-11-05 16:07     ` Alan Stern
2020-11-05 17:54     ` Dmitry Osipenko
2020-11-05 17:54       ` Dmitry Osipenko
2020-11-05 18:02     ` Dmitry Osipenko
2020-11-05 18:02       ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 22/30] memory: tegra20-emc: Support Tegra SoC device state syncing Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 23/30] memory: tegra30-emc: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 24/30] ARM: tegra: Add OPP tables for Tegra20 peripheral devices Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 25/30] ARM: tegra: Add OPP tables for Tegra30 " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 26/30] ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 27/30] ARM: tegra: paz00: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 28/30] ARM: tegra: acer-a500: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 29/30] ARM: tegra: cardhu-a04: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 30/30] ARM: tegra: nexus7: " Dmitry Osipenko
2020-11-04 23:44   ` Dmitry Osipenko
2020-11-05  1:45 ` [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Michał Mirosław
2020-11-05  1:45   ` Michał Mirosław
2020-11-05 13:57   ` Dmitry Osipenko
2020-11-05 13:57     ` Dmitry Osipenko
2020-11-05  9:45 ` Ulf Hansson
2020-11-05  9:45   ` Ulf Hansson
2020-11-05 10:06   ` Viresh Kumar
2020-11-05 10:06     ` Viresh Kumar
2020-11-05 10:34     ` Ulf Hansson
2020-11-05 10:34       ` Ulf Hansson
2020-11-05 10:40       ` Viresh Kumar
2020-11-05 10:40         ` Viresh Kumar
2020-11-05 10:56         ` Ulf Hansson
2020-11-05 10:56           ` Ulf Hansson
2020-11-05 11:13           ` Viresh Kumar
2020-11-05 11:13             ` Viresh Kumar
2020-11-05 12:52             ` Ulf Hansson
2020-11-05 12:52               ` Ulf Hansson
2020-11-05 15:22   ` Dmitry Osipenko
2020-11-05 15:22     ` Dmitry Osipenko
2020-11-08 12:19     ` Dmitry Osipenko
2020-11-08 12:19       ` Dmitry Osipenko
2020-11-09  4:43       ` Viresh Kumar
2020-11-09  4:43         ` Viresh Kumar
2020-11-09  4:47         ` Dmitry Osipenko
2020-11-09  4:47           ` Dmitry Osipenko
2020-11-09  5:10           ` Dmitry Osipenko
2020-11-09  5:10             ` Dmitry Osipenko
2020-11-09  5:12             ` Viresh Kumar
2020-11-09  5:12               ` Viresh Kumar
2020-11-11 11:38       ` Ulf Hansson
2020-11-11 11:38         ` Ulf Hansson
2020-11-12 19:57         ` Dmitry Osipenko
2020-11-12 19:57           ` Dmitry Osipenko
2020-11-12 20:43           ` Thierry Reding
2020-11-12 20:43             ` Thierry Reding
2020-11-12 22:14             ` Dmitry Osipenko
2020-11-12 22:14               ` Dmitry Osipenko
2020-11-13 14:45               ` Ulf Hansson
2020-11-13 14:45                 ` Ulf Hansson
2020-11-13 16:00                 ` Dmitry Osipenko
2020-11-13 16:00                   ` Dmitry Osipenko
2020-11-13 16:35               ` Thierry Reding
2020-11-13 16:35                 ` Thierry Reding
2020-11-15 16:29                 ` Dmitry Osipenko
2020-11-15 16:29                   ` Dmitry Osipenko
2020-12-01 13:57 ` Mark Brown
2020-12-01 13:57   ` Mark Brown
2020-12-01 14:17   ` Dmitry Osipenko
2020-12-01 14:17     ` Dmitry Osipenko
2020-12-01 14:34     ` Mark Brown
2020-12-01 14:34       ` Mark Brown
2020-12-01 14:44       ` Dmitry Osipenko
2020-12-01 14:44         ` Dmitry Osipenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201110202945.GF2375022@ulmo \
    --to=thierry.reding@gmail.com \
    --cc=Peter.Chen@nxp.com \
    --cc=adrian.hunter@intel.com \
    --cc=broonie@kernel.org \
    --cc=devel@driverdev.osuosl.org \
    --cc=devicetree@vger.kernel.org \
    --cc=digetx@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jonathanh@nvidia.com \
    --cc=krzk@kernel.org \
    --cc=kwizart@gmail.com \
    --cc=lee.jones@linaro.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=mchehab@kernel.org \
    --cc=pgwipeout@gmail.com \
    --cc=robh+dt@kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=u.kleine-koenig@pengutronix.de \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.