All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Courbot <acourbot@nvidia.com>
To: Andrew Chew <achew@nvidia.com>
Cc: "thierry.reding@avionic-design.de"
	<thierry.reding@avionic-design.de>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 1/1 v3] pwm_bl: Add support for backlight enable regulator
Date: Wed, 6 Mar 2013 11:18:41 +0900	[thread overview]
Message-ID: <5136A781.2050303@nvidia.com> (raw)
In-Reply-To: <1362527485-8611-1-git-send-email-achew@nvidia.com>

On 03/06/2013 08:51 AM, Andrew Chew wrote:
> The backlight enable regulator is specified in the device tree node for
> backlight.
>
> Signed-off-by: Andrew Chew <achew@nvidia.com>
> ---
> Applied all recommendations from Thierry Reding and Alex Courbot, including
> making pwm_bl take an optional regulator instead of a GPIO, which solves
> the platform data issue (platform data will default the regulator to NULL,
> which is the right thing).
>
>   .../bindings/video/backlight/pwm-backlight.txt     |    1 +
>   drivers/video/backlight/pwm_bl.c                   |   53 +++++++++++++++++---
>   include/linux/pwm_backlight.h                      |    1 +
>   3 files changed, 48 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
> index 1e4fc72..e0bccd30 100644
> --- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
> @@ -14,6 +14,7 @@ Required properties:
>   Optional properties:
>     - pwm-names: a list of names for the PWM devices specified in the
>                  "pwms" property (see PWM binding[0])
> +  - en-supply: phandle to the regulator device tree node

You may want to specify what this regulator does - namely, that is 
enables the BL. May I also suggest to rename it to "enable-supply" since 
the other properties do not use abbreviations.

>   [0]: Documentation/devicetree/bindings/pwm/pwm.txt
>
> diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> index 069983c..c4da5e2 100644
> --- a/drivers/video/backlight/pwm_bl.c
> +++ b/drivers/video/backlight/pwm_bl.c
> @@ -20,10 +20,13 @@
>   #include <linux/pwm.h>
>   #include <linux/pwm_backlight.h>
>   #include <linux/slab.h>
> +#include <linux/regulator/consumer.h>
>
>   struct pwm_bl_data {
>   	struct pwm_device	*pwm;
>   	struct device		*dev;
> +	struct regulator	*en_supply;
> +	bool			en_supply_enabled;

Couldn't you use regulator_is_enabled() and get rid of 
en_supply_enabled? It would also ensure the driver performs correctly no 
matter what the initial state of the regulator is.

>   	unsigned int		period;
>   	unsigned int		lth_brightness;
>   	unsigned int		*levels;
> @@ -35,6 +38,34 @@ struct pwm_bl_data {
>   	void			(*exit)(struct device *);
>   };
>
> +static void pwm_backlight_enable(struct backlight_device *bl)
> +{
> +	struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
> +
> +	pwm_enable(pb->pwm);
> +
> +	if (pb->en_supply && !pb->en_supply_enabled) {
> +		if (regulator_enable(pb->en_supply) != 0)
> +			dev_warn(&bl->dev, "Failed to enable regulator");
> +		else
> +			pb->en_supply_enabled = true;
> +	}
> +}
> +
> +static void pwm_backlight_disable(struct backlight_device *bl)
> +{
> +	struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
> +
> +	if (pb->en_supply && pb->en_supply_enabled) {
> +		if (regulator_disable(pb->en_supply) != 0)
> +			dev_warn(&bl->dev, "Failed to disable regulator");
> +		else
> +			pb->en_supply_enabled = false;
> +	}
> +
> +	pwm_disable(pb->pwm);
> +}
> +
>   static int pwm_backlight_update_status(struct backlight_device *bl)
>   {
>   	struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
> @@ -52,7 +83,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
>
>   	if (brightness == 0) {
>   		pwm_config(pb->pwm, 0, pb->period);
> -		pwm_disable(pb->pwm);
> +		pwm_backlight_disable(bl);
>   	} else {
>   		int duty_cycle;
>
> @@ -66,7 +97,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
>   		duty_cycle = pb->lth_brightness +
>   		     (duty_cycle * (pb->period - pb->lth_brightness) / max);
>   		pwm_config(pb->pwm, duty_cycle, pb->period);
> -		pwm_enable(pb->pwm);
> +		pwm_backlight_enable(bl);
>   	}
>
>   	if (pb->notify_after)
> @@ -146,10 +177,17 @@ static int pwm_backlight_parse_dt(struct device *dev,
>   	}
>
>   	/*
> -	 * TODO: Most users of this driver use a number of GPIOs to control
> -	 *       backlight power. Support for specifying these needs to be
> -	 *       added.
> +	 * If "en-supply" is present, use that regulator to enable the
> +	 * backlight.  If a GPIO is used to enable the backlight, make
> +	 * a fixed regulator with that particular GPIO and use that
> +	 * regulator for "en-supply".
>   	 */
> +	data->en_supply = devm_regulator_get(dev, "en");
> +	if (IS_ERR_OR_NULL(data->en_supply)) {

devm_regulator_get() is performed at the wrong place, but I will come 
back to this later. As a sidenote though: you should use IS_ERR here. 
regulator_get() will never return NULL - also using IS_ERR_OR_NULL is 
strongly discouraged and it will probably disappear soon anyway:

https://patchwork.kernel.org/patch/1953211/

> +		ret = PTR_ERR(data->en_supply);

... and this is the reason why you should use IS_ERR: because in the 
(impossible anyway) error case where regulator_get() returns NULL, you 
will return 0 (success).

> +		data->en_supply = NULL;
> +		return ret;
> +	}
>
>   	return 0;
>   }
> @@ -207,6 +245,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
>   	} else
>   		max = data->max_brightness;
>
> +	pb->en_supply = data->en_supply;
>   	pb->notify = data->notify;
>   	pb->notify_after = data->notify_after;
>   	pb->check_fb = data->check_fb;
> @@ -268,7 +307,7 @@ static int pwm_backlight_remove(struct platform_device *pdev)
>
>   	backlight_device_unregister(bl);
>   	pwm_config(pb->pwm, 0, pb->period);
> -	pwm_disable(pb->pwm);
> +	pwm_backlight_disable(bl);
>   	if (pb->exit)
>   		pb->exit(&pdev->dev);
>   	return 0;
> @@ -283,7 +322,7 @@ static int pwm_backlight_suspend(struct device *dev)
>   	if (pb->notify)
>   		pb->notify(pb->dev, 0);
>   	pwm_config(pb->pwm, 0, pb->period);
> -	pwm_disable(pb->pwm);
> +	pwm_backlight_disable(bl);
>   	if (pb->notify_after)
>   		pb->notify_after(pb->dev, 0);
>   	return 0;
> diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
> index 56f4a86..330512b 100644
> --- a/include/linux/pwm_backlight.h
> +++ b/include/linux/pwm_backlight.h
> @@ -8,6 +8,7 @@
>
>   struct platform_pwm_backlight_data {
>   	int pwm_id;
> +	struct regulator *en_supply;

You should not have this here. Platform data is supposed to provide the 
necessary information for the driver to resolve the resource - not the 
resource itself.

Instead machines that rely on platform data will associate the right 
regulator to the backlight device in their board code, through an 
instance of the regulator_consumer_supply structure (see 
include/linux/regulator/machine.h), and submit it to the regulator 
framework. Thus it is enough for you to just perform a call to 
devm_regulator_get() in the probe function, and the regulator framework 
will resolve the right regulator through the device tree or the provided 
platform data. I.e. you don't have to worry about whether you are using 
the DT or platform data here.

There is one catch though: in case you don't want to use a regulator, 
and thus have none defined, regulator_get() will return -EPROBE_DEFER, 
so you cannot distinguish between "no regulator needed" and "supplier 
not ready yet" and your driver will always *require* a regulator. So at 
the end of the day you might still need a "use_enable_regulator" in the 
platform data to explicitly ask for probe() to look for it. This 
variable would also be set by parse_dt() if the "enable-supply" property 
exists.

But this somehow kills the purpose of using a regulator here, since part 
of the motivation was to avoid this boolean variable. Maybe Thierry has 
a better idea.

I like the general idea of this patch however - with this and a couple 
of always-on regulators we should be able to enable the panels of some 
Tegra boards until the CDF gets merged. It won't be optimal from a power 
point of view, but at least we will finally see something. :)

Alex.


  reply	other threads:[~2013-03-06  2:18 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-05 23:51 [PATCH 1/1 v3] pwm_bl: Add support for backlight enable regulator Andrew Chew
2013-03-06  2:18 ` Alex Courbot [this message]
2013-03-06  2:41   ` Andrew Chew
2013-03-06  4:53     ` Alex Courbot
2013-03-06  7:00       ` Thierry Reding
2013-03-06  8:37         ` Alex Courbot
2013-03-06 10:11           ` Thierry Reding
2013-03-06  4:20   ` Stephen Warren
2013-03-06  4:56     ` Alex Courbot
2013-03-06  7:10       ` Thierry Reding

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=5136A781.2050303@nvidia.com \
    --to=acourbot@nvidia.com \
    --cc=achew@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=thierry.reding@avionic-design.de \
    /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.