All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] leds: blink resolution improvements
@ 2015-04-22 17:02 Stas Sergeev
  2015-04-22 17:04 ` [PATCH 1/2] leds: use hrtimer for blinking Stas Sergeev
  2015-04-22 17:06 ` [PATCH 2/2] ledtrig-timer: add blink resolution control Stas Sergeev
  0 siblings, 2 replies; 4+ messages in thread
From: Stas Sergeev @ 2015-04-22 17:02 UTC (permalink / raw)
  To: linux-leds; +Cc: Linux kernel, Stas Sergeev

Hello.

The following patches improve the precision of led
timer trigger and add the resolution control.
That allows to make PWM brightness control with timer
trigger.

^ permalink raw reply	[flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] leds: use hrtimer for blinking
@ 2015-04-24 12:52 Jacek Anaszewski
  0 siblings, 0 replies; 4+ messages in thread
From: Jacek Anaszewski @ 2015-04-24 12:52 UTC (permalink / raw)
  To: Stas Sergeev; +Cc: linux-leds, linux-kernel, rpurdie, cooloney

Hi Stas,

On 22.04.2015 19:06, Stas Sergeev wrote:> 
> Add the following resolutions to led trigger timer:
> 'n' for nanosecond resolution
> 'u' for microsecond resolution
> 'm' for millisecond resolution
> The default is 'm' for backward compatibility.
> 
> This functionality is needed for things like PWM for software
> brightness control, because the default mS resolution is not enough
> for that tasks.
> 
> CC: Bryan Wu <cooloney@gmail.com>
> CC: Richard Purdie <rpurdie@rpsys.net>
> CC: linux-leds@vger.kernel.org
> CC: linux-kernel@vger.kernel.org
> 
> Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net>
> ---
>   drivers/leds/led-class.c             |   18 +++++++++++--
>   drivers/leds/trigger/ledtrig-timer.c |   49
> ++++++++++++++++++++++++++++++++++
> include/linux/leds.h                 |    7 +++++ 3 files changed, 72
> insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
> index f95ce912..2cfbb9d 100644
> --- a/drivers/leds/led-class.c
> +++ b/drivers/leds/led-class.c
> @@ -108,6 +108,7 @@ static enum hrtimer_restart
> led_timer_function(struct hrtimer *timer) struct led_classdev,
> blink_timer); unsigned long brightness;
>   	unsigned long delay;
> +	ktime_t k_delay;
> 
>   	if (!led_cdev->blink_delay_on
> || !led_cdev->blink_delay_off) { led_set_brightness_async(led_cdev,
> LED_OFF); @@ -149,9 +150,22 @@ static enum hrtimer_restart
> led_timer_function(struct hrtimer *timer) }
>   	}
> 
> +	switch (led_cdev->resolution) {
> +	case LED_BLINK_MS:
> +		k_delay = ms_to_ktime(delay);
> +		break;
> +	case LED_BLINK_US:
> +		k_delay = ns_to_ktime(delay * 1000);
> +		break;
> +	case LED_BLINK_NS:
> +		k_delay = ns_to_ktime(delay);
> +		break;
> +	default:
> +		/* should not happen */
> +		return HRTIMER_NORESTART;
> +	}
>   	hrtimer_forward(&led_cdev->blink_timer,
> -			hrtimer_get_expires(&led_cdev->blink_timer),
> -			ms_to_ktime(delay));
> +			hrtimer_get_expires(&led_cdev->blink_timer),
> k_delay); return HRTIMER_RESTART;
>   }
> 
> diff --git a/drivers/leds/trigger/ledtrig-timer.c
> b/drivers/leds/trigger/ledtrig-timer.c index 8d09327..222c755 100644
> --- a/drivers/leds/trigger/ledtrig-timer.c
> +++ b/drivers/leds/trigger/ledtrig-timer.c
> @@ -68,8 +68,51 @@ static ssize_t led_delay_off_store(struct device
> *dev, return size;
>   }
> 
> +static ssize_t led_res_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	const char res_suffix[] = {
> +		[LED_BLINK_MS] = 'm',
> +		[LED_BLINK_US] = 'u',
> +		[LED_BLINK_NS] = 'n',
> +	};
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);

Semantics of sysfs attributes should be self-explanatory.
I propose to rename the attribute to delay_units. Also unit identifiers
could be renamed to milliseconds, microseconds and nanoseconds
respectively. 
Additionally available_delay_units attribute should be added.
The attribute when read shoud return a space separated list of
acceptable delay_units values.

> +	return sprintf(buf, "%c\n",
> res_suffix[led_cdev->resolution]); +}
> +
> +static ssize_t led_res_store(struct device *dev,
> +		struct device_attribute *attr, const char *buf,
> size_t size) +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	int ret = strlen(buf);
> +	/* char and \n */
> +	if (ret != 2)
> +		return -EINVAL;
> +
> +	switch (buf[0]) {
> +	case 'm':
> +		led_cdev->resolution = LED_BLINK_MS;
> +		break;
> +	case 'u':
> +		led_cdev->resolution = LED_BLINK_US;
> +		break;
> +	case 'n':
> +		led_cdev->resolution = LED_BLINK_NS;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	led_blink_set(led_cdev, &led_cdev->blink_delay_on,
> +		      &led_cdev->blink_delay_off);
> +
> +	return ret;
> +}
> +
>   static DEVICE_ATTR(delay_on, 0644, led_delay_on_show,
> led_delay_on_store); static DEVICE_ATTR(delay_off, 0644,
> led_delay_off_show, led_delay_off_store); +static
> DEVICE_ATTR(resolution, 0644, led_res_show, led_res_store);
> 
>   static void timer_trig_activate(struct led_classdev *led_cdev)
>   {
> @@ -83,6 +126,9 @@ static void timer_trig_activate(struct
> led_classdev *led_cdev) rc = device_create_file(led_cdev->dev,
> &dev_attr_delay_off); if (rc)
>   		goto err_out_delayon;
> +	rc = device_create_file(led_cdev->dev, &dev_attr_resolution);
> +	if (rc)
> +		goto err_out_delayoff;

This attribute should be created only if support for hr timers
is enabled in the kernel config.

>   	led_blink_set(led_cdev, &led_cdev->blink_delay_on,
>   		      &led_cdev->blink_delay_off);
> @@ -90,6 +136,8 @@ static void timer_trig_activate(struct
> led_classdev *led_cdev)
> 
>   	return;
> 
> +err_out_delayoff:
> +	device_remove_file(led_cdev->dev, &dev_attr_delay_off);
>   err_out_delayon:
>   	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
>   }
> @@ -99,6 +147,7 @@ static void timer_trig_deactivate(struct
> led_classdev *led_cdev) if (led_cdev->activated) {
>   		device_remove_file(led_cdev->dev,
> &dev_attr_delay_on); device_remove_file(led_cdev->dev,
> &dev_attr_delay_off);
> +		device_remove_file(led_cdev->dev,
> &dev_attr_resolution); led_cdev->activated = false;
>   	}
> 
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index 68f5a23..5e6fe26 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -30,10 +30,17 @@ enum led_brightness {
>   	LED_FULL	= 255,
>   };
> 
> +enum led_blink_resolution {
> +	LED_BLINK_MS,
> +	LED_BLINK_US,
> +	LED_BLINK_NS,
> +};
> +
>   struct led_classdev {
>   	const char		*name;
>   	enum led_brightness	 brightness;
>   	enum led_brightness	 max_brightness;
> +	enum led_blink_resolution resolution;

I'd rename resolution to delay_unit and put it after blink_timer.

Similarly let's rename enum led_blink_resolution to
enum led_blink_delay_unit


>   	int			 flags;
> 
>   	/* Lower 16 bits reflect status */
>

Documentation/leds/leds-class.txt should also be updated in this patch
set.

Please add there information on what CONFIG_* symbols have to be
defined to add support for hr timers.

It would be also nice to have:
- information that not every platform may support hr timers
- description of newly added sysfs attributes
- 

-- 
Best Regards,
Jacek Anaszewski

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-04-24 12:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-22 17:02 [PATCH 0/2] leds: blink resolution improvements Stas Sergeev
2015-04-22 17:04 ` [PATCH 1/2] leds: use hrtimer for blinking Stas Sergeev
2015-04-22 17:06 ` [PATCH 2/2] ledtrig-timer: add blink resolution control Stas Sergeev
  -- strict thread matches above, loose matches on Subject: below --
2015-04-24 12:52 [PATCH 1/2] leds: use hrtimer for blinking Jacek Anaszewski

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.