All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kim, Milo" <milo.kim@ti.com>
To: Jacek Anaszewski <j.anaszewski@samsung.com>
Cc: robh+dt@kernel.org, lee.jones@linaro.org, broonie@kernel.org,
	devicetree@vger.kernel.org, linux-leds@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 8/9] leds: add LM3633 driver
Date: Mon, 30 Nov 2015 17:48:47 +0900	[thread overview]
Message-ID: <565C0D6F.9000709@ti.com> (raw)
In-Reply-To: <56583C37.1050307@samsung.com>

Hi Jacek,

Thanks for your detailed feedback. Please refer to my comments below.

On 11/27/2015 8:19 PM, Jacek Anaszewski wrote:
> Hi Milo,
>
> Thanks for the update. I have few comments below.
>
>> diff --git a/drivers/leds/leds-lm3633.c b/drivers/leds/leds-lm3633.c
>> new file mode 100644
>> index 0000000..9c391ca
>> --- /dev/null
>> +++ b/drivers/leds/leds-lm3633.c
>> @@ -0,0 +1,840 @@
>> +/*
>> + * TI LM3633 LED driver
>> + *
>> + * Copyright 2015 Texas Instruments
>> + *
>> + * Author: Milo Kim <milo.kim@ti.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/bitops.h>
>> +#include <linux/kernel.h>
>> +#include <linux/leds.h>
>> +#include <linux/mfd/ti-lmu.h>
>> +#include <linux/mfd/ti-lmu-register.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/notifier.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +
>> +#define LM3633_MAX_PWM				255
>> +#define LM3633_MIN_CURRENT			5000
>> +#define LM3633_MAX_CURRENT			30000
>> +#define LM3633_MAX_PERIOD			9700
>> +#define LM3633_SHORT_TIMESTEP			16
>> +#define LM3633_LONG_TIMESTEP			131
>> +#define LM3633_TIME_OFFSET			61
>> +#define LM3633_PATTERN_REG_OFFSET		16
>> +#define LM3633_IMAX_OFFSET			6
>> +
>> +enum lm3633_led_bank_id {
>> +	LM3633_LED_BANK_C,
>> +	LM3633_LED_BANK_D,
>> +	LM3633_LED_BANK_E,
>> +	LM3633_LED_BANK_F,
>> +	LM3633_LED_BANK_G,
>> +	LM3633_LED_BANK_H,
>> +	LM3633_MAX_LEDS,
>> +};
>> +
>> +/**
>> + * struct ti_lmu_led_chip
>> + *
>> + * @dev:		Parent device pointer
>> + * @lmu:		LMU structure. Used for register R/W access.
>> + * @lock:		Secure handling for multiple user interface access
>> + * @lmu_led:		Multiple LED strings
>
> Could you clarify what "string" means here?
>
>> + * @num_leds:		Number of LED strings
>
> and here?

Oops! I forgot to replace this term with 'output channel'. Thanks for 
catching this.

>> +static u8 lm3633_convert_time_to_index(unsigned int msec)
>> +{
>> +	u8 idx, offset;
>> +
>> +	/*
>> +	 * Find an approximate index
>
> I think that we shouldn't approximate but clamp the msec
> to the nearest possible device setting.
>
>> +	 *
>> +	 *      0 <= time <= 1000 : 16ms step
>> +	 *   1000 <  time <= 9700 : 131ms step, base index is 61
>> +	 */
>> +
>> +	msec = min_t(int, msec, LM3633_MAX_PERIOD);
>> +
>> +	if (msec <= 1000) {
>> +		idx = msec / LM3633_SHORT_TIMESTEP;
>> +		if (idx > 1)
>> +			idx--;
>> +		offset = 0;
>> +	} else {
>> +		idx = (msec - 1000) / LM3633_LONG_TIMESTEP;
>> +		offset = LM3633_TIME_OFFSET;
>> +	}
>> +
>> +	return idx + offset;
>> +}
>> +
>> +static u8 lm3633_convert_ramp_to_index(unsigned int msec)
>> +{
>> +	const int ramp_table[] = { 2, 250, 500, 1000, 2000, 4000, 8000, 16000 };
>> +	int size = ARRAY_SIZE(ramp_table);
>> +	int i;
>> +
>> +	if (msec <= ramp_table[0])
>> +		return 0;
>> +
>> +	if (msec > ramp_table[size - 1])
>> +		return size - 1;
>> +
>> +	for (i = 1; i < size; i++) {
>> +		if (msec == ramp_table[i])
>> +			return i;
>> +
>> +		/* Find an approximate index by looking up the table */
>
> Similarly here. So you should have an array of the possible msec
> values and iterate through it to look for the nearest one.

Driver uses 'ramp_table[]' for this purpose. Could you describe it in 
more details?

>> +
>> +static int lm3633_led_brightness_set(struct led_classdev *cdev,
>> +				     enum led_brightness brightness)
>> +{
>> +	struct ti_lmu_led *lmu_led = container_of(cdev, struct ti_lmu_led,
>> +						  cdev);
>> +	struct ti_lmu_led_chip *chip = lmu_led->chip;
>> +	struct regmap *regmap = chip->lmu->regmap;
>> +	u8 reg = LM3633_REG_BRT_LVLED_BASE + lmu_led->bank_id;
>> +	int ret;
>> +
>> +	mutex_lock(&chip->lock);
>> +
>> +	ret = regmap_write(regmap, reg, brightness);
>> +	if (ret) {
>> +		mutex_unlock(&chip->lock);
>> +		return ret;
>> +	}
>> +
>> +	if (brightness == 0)
>> +		lm3633_led_disable_bank(lmu_led);
>
> This should be checked at first, as I suppose that disabling
> a bank suffices to turn the LED off.

Well, it's not a big deal when turn off the LED. However, our silicon 
designer recommended brightness update should be done prior to enabling 
LED bank. Let me share some block diagram.

[I2C logic] - [brightness control] - [control bank] - [output channel]

If control bank is enabled first, then previous brightness value in 
register can be used instead of new updated brightness. So brightness 
update should be done first.

>> +static u8 lm3633_led_scale_max_brightness(struct ti_lmu_led *lmu_led, u32 imax)
>> +{
>> +	u8 max_current = lm3633_led_convert_current_to_index(imax);
>> +	const u8 max_brightness_table[] = {
>> +		[LMU_IMAX_5mA]  = 191,
>> +		[LMU_IMAX_6mA]  = 197,
>> +		[LMU_IMAX_7mA]  = 203,
>> +		[LMU_IMAX_8mA]  = 208,
>> +		[LMU_IMAX_9mA]  = 212,
>> +		[LMU_IMAX_10mA] = 216,
>> +		[LMU_IMAX_11mA] = 219,
>> +		[LMU_IMAX_12mA] = 222,
>> +		[LMU_IMAX_13mA] = 225,
>> +		[LMU_IMAX_14mA] = 228,
>> +		[LMU_IMAX_15mA] = 230,
>> +		[LMU_IMAX_16mA] = 233,
>> +		[LMU_IMAX_17mA] = 235,
>> +		[LMU_IMAX_18mA] = 237,
>> +		[LMU_IMAX_19mA] = 239,
>> +		[LMU_IMAX_20mA] = 241,
>> +		[LMU_IMAX_21mA] = 242,
>> +		[LMU_IMAX_22mA] = 244,
>> +		[LMU_IMAX_23mA] = 246,
>> +		[LMU_IMAX_24mA] = 247,
>> +		[LMU_IMAX_25mA] = 249,
>> +		[LMU_IMAX_26mA] = 250,
>> +		[LMU_IMAX_27mA] = 251,
>> +		[LMU_IMAX_28mA] = 253,
>> +		[LMU_IMAX_29mA] = 254,
>> +		[LMU_IMAX_30mA] = 255,
>> +	};
>
> After analyzing the subject one more time I think that we need to
> change the approach regarding max brightness issue.
>
> At first - we shouldn't fix max current to max possible register value.
> Instead we should take led-max-microamp property and write its value
> to the [0x22 + bank offset] registers.
>
> With this approach whole 0-255 range of brightness levels will be
> valid for the driver.
>
> In effect all LMU_IMAX* enums seem to be not needed.

Good to hear that, it's the most simplest work for the device ;)
Let me update the driver. Thanks!

Best regards,
Milo

WARNING: multiple messages have this Message-ID (diff)
From: "Kim, Milo" <milo.kim@ti.com>
To: Jacek Anaszewski <j.anaszewski@samsung.com>
Cc: <robh+dt@kernel.org>, <lee.jones@linaro.org>,
	<broonie@kernel.org>, <devicetree@vger.kernel.org>,
	<linux-leds@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v2 8/9] leds: add LM3633 driver
Date: Mon, 30 Nov 2015 17:48:47 +0900	[thread overview]
Message-ID: <565C0D6F.9000709@ti.com> (raw)
In-Reply-To: <56583C37.1050307@samsung.com>

Hi Jacek,

Thanks for your detailed feedback. Please refer to my comments below.

On 11/27/2015 8:19 PM, Jacek Anaszewski wrote:
> Hi Milo,
>
> Thanks for the update. I have few comments below.
>
>> diff --git a/drivers/leds/leds-lm3633.c b/drivers/leds/leds-lm3633.c
>> new file mode 100644
>> index 0000000..9c391ca
>> --- /dev/null
>> +++ b/drivers/leds/leds-lm3633.c
>> @@ -0,0 +1,840 @@
>> +/*
>> + * TI LM3633 LED driver
>> + *
>> + * Copyright 2015 Texas Instruments
>> + *
>> + * Author: Milo Kim <milo.kim@ti.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/bitops.h>
>> +#include <linux/kernel.h>
>> +#include <linux/leds.h>
>> +#include <linux/mfd/ti-lmu.h>
>> +#include <linux/mfd/ti-lmu-register.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/notifier.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +
>> +#define LM3633_MAX_PWM				255
>> +#define LM3633_MIN_CURRENT			5000
>> +#define LM3633_MAX_CURRENT			30000
>> +#define LM3633_MAX_PERIOD			9700
>> +#define LM3633_SHORT_TIMESTEP			16
>> +#define LM3633_LONG_TIMESTEP			131
>> +#define LM3633_TIME_OFFSET			61
>> +#define LM3633_PATTERN_REG_OFFSET		16
>> +#define LM3633_IMAX_OFFSET			6
>> +
>> +enum lm3633_led_bank_id {
>> +	LM3633_LED_BANK_C,
>> +	LM3633_LED_BANK_D,
>> +	LM3633_LED_BANK_E,
>> +	LM3633_LED_BANK_F,
>> +	LM3633_LED_BANK_G,
>> +	LM3633_LED_BANK_H,
>> +	LM3633_MAX_LEDS,
>> +};
>> +
>> +/**
>> + * struct ti_lmu_led_chip
>> + *
>> + * @dev:		Parent device pointer
>> + * @lmu:		LMU structure. Used for register R/W access.
>> + * @lock:		Secure handling for multiple user interface access
>> + * @lmu_led:		Multiple LED strings
>
> Could you clarify what "string" means here?
>
>> + * @num_leds:		Number of LED strings
>
> and here?

Oops! I forgot to replace this term with 'output channel'. Thanks for 
catching this.

>> +static u8 lm3633_convert_time_to_index(unsigned int msec)
>> +{
>> +	u8 idx, offset;
>> +
>> +	/*
>> +	 * Find an approximate index
>
> I think that we shouldn't approximate but clamp the msec
> to the nearest possible device setting.
>
>> +	 *
>> +	 *      0 <= time <= 1000 : 16ms step
>> +	 *   1000 <  time <= 9700 : 131ms step, base index is 61
>> +	 */
>> +
>> +	msec = min_t(int, msec, LM3633_MAX_PERIOD);
>> +
>> +	if (msec <= 1000) {
>> +		idx = msec / LM3633_SHORT_TIMESTEP;
>> +		if (idx > 1)
>> +			idx--;
>> +		offset = 0;
>> +	} else {
>> +		idx = (msec - 1000) / LM3633_LONG_TIMESTEP;
>> +		offset = LM3633_TIME_OFFSET;
>> +	}
>> +
>> +	return idx + offset;
>> +}
>> +
>> +static u8 lm3633_convert_ramp_to_index(unsigned int msec)
>> +{
>> +	const int ramp_table[] = { 2, 250, 500, 1000, 2000, 4000, 8000, 16000 };
>> +	int size = ARRAY_SIZE(ramp_table);
>> +	int i;
>> +
>> +	if (msec <= ramp_table[0])
>> +		return 0;
>> +
>> +	if (msec > ramp_table[size - 1])
>> +		return size - 1;
>> +
>> +	for (i = 1; i < size; i++) {
>> +		if (msec == ramp_table[i])
>> +			return i;
>> +
>> +		/* Find an approximate index by looking up the table */
>
> Similarly here. So you should have an array of the possible msec
> values and iterate through it to look for the nearest one.

Driver uses 'ramp_table[]' for this purpose. Could you describe it in 
more details?

>> +
>> +static int lm3633_led_brightness_set(struct led_classdev *cdev,
>> +				     enum led_brightness brightness)
>> +{
>> +	struct ti_lmu_led *lmu_led = container_of(cdev, struct ti_lmu_led,
>> +						  cdev);
>> +	struct ti_lmu_led_chip *chip = lmu_led->chip;
>> +	struct regmap *regmap = chip->lmu->regmap;
>> +	u8 reg = LM3633_REG_BRT_LVLED_BASE + lmu_led->bank_id;
>> +	int ret;
>> +
>> +	mutex_lock(&chip->lock);
>> +
>> +	ret = regmap_write(regmap, reg, brightness);
>> +	if (ret) {
>> +		mutex_unlock(&chip->lock);
>> +		return ret;
>> +	}
>> +
>> +	if (brightness == 0)
>> +		lm3633_led_disable_bank(lmu_led);
>
> This should be checked at first, as I suppose that disabling
> a bank suffices to turn the LED off.

Well, it's not a big deal when turn off the LED. However, our silicon 
designer recommended brightness update should be done prior to enabling 
LED bank. Let me share some block diagram.

[I2C logic] - [brightness control] - [control bank] - [output channel]

If control bank is enabled first, then previous brightness value in 
register can be used instead of new updated brightness. So brightness 
update should be done first.

>> +static u8 lm3633_led_scale_max_brightness(struct ti_lmu_led *lmu_led, u32 imax)
>> +{
>> +	u8 max_current = lm3633_led_convert_current_to_index(imax);
>> +	const u8 max_brightness_table[] = {
>> +		[LMU_IMAX_5mA]  = 191,
>> +		[LMU_IMAX_6mA]  = 197,
>> +		[LMU_IMAX_7mA]  = 203,
>> +		[LMU_IMAX_8mA]  = 208,
>> +		[LMU_IMAX_9mA]  = 212,
>> +		[LMU_IMAX_10mA] = 216,
>> +		[LMU_IMAX_11mA] = 219,
>> +		[LMU_IMAX_12mA] = 222,
>> +		[LMU_IMAX_13mA] = 225,
>> +		[LMU_IMAX_14mA] = 228,
>> +		[LMU_IMAX_15mA] = 230,
>> +		[LMU_IMAX_16mA] = 233,
>> +		[LMU_IMAX_17mA] = 235,
>> +		[LMU_IMAX_18mA] = 237,
>> +		[LMU_IMAX_19mA] = 239,
>> +		[LMU_IMAX_20mA] = 241,
>> +		[LMU_IMAX_21mA] = 242,
>> +		[LMU_IMAX_22mA] = 244,
>> +		[LMU_IMAX_23mA] = 246,
>> +		[LMU_IMAX_24mA] = 247,
>> +		[LMU_IMAX_25mA] = 249,
>> +		[LMU_IMAX_26mA] = 250,
>> +		[LMU_IMAX_27mA] = 251,
>> +		[LMU_IMAX_28mA] = 253,
>> +		[LMU_IMAX_29mA] = 254,
>> +		[LMU_IMAX_30mA] = 255,
>> +	};
>
> After analyzing the subject one more time I think that we need to
> change the approach regarding max brightness issue.
>
> At first - we shouldn't fix max current to max possible register value.
> Instead we should take led-max-microamp property and write its value
> to the [0x22 + bank offset] registers.
>
> With this approach whole 0-255 range of brightness levels will be
> valid for the driver.
>
> In effect all LMU_IMAX* enums seem to be not needed.

Good to hear that, it's the most simplest work for the device ;)
Let me update the driver. Thanks!

Best regards,
Milo

  parent reply	other threads:[~2015-11-30  8:48 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-26  6:56 [PATCH v2 0/9] Support TI LMU devices Milo Kim
2015-11-26  6:56 ` Milo Kim
2015-11-26  6:56 ` [PATCH v2 1/9] Documentation: dt-bindings: mfd: add TI LMU device binding information Milo Kim
2015-11-26  6:56   ` Milo Kim
2015-11-27 20:55   ` Rob Herring
2016-01-11  9:46   ` Lee Jones
2015-11-26  6:56 ` [PATCH v2 2/9] Documentation: dt-bindings: leds: backlight: add TI LMU backlight " Milo Kim
2015-11-26  6:56   ` Milo Kim
2016-01-11  9:53   ` Lee Jones
2015-11-26  6:56 ` [PATCH v2 3/9] Documentation: dt-bindings: leds: add LM3633 LED " Milo Kim
2015-11-26  6:56   ` Milo Kim
2015-11-27 11:19   ` Jacek Anaszewski
2015-11-30  8:19     ` Kim, Milo
2015-11-30  8:19       ` Kim, Milo
2015-11-30 12:26       ` Jacek Anaszewski
     [not found]         ` <565C408B.9070703-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-12-07  8:46           ` Kim, Milo
2015-12-07  8:46             ` Kim, Milo
2015-12-07 10:50             ` Jacek Anaszewski
2015-11-26  6:57 ` [PATCH v2 4/9] Documentation: dt-bindings: regulator: add LM363x regulator " Milo Kim
2015-11-26  6:57   ` Milo Kim
2015-11-27 12:37   ` Mark Brown
2015-11-27 20:44     ` Rob Herring
2015-11-27 22:07       ` Mark Brown
2015-11-27 12:55   ` Applied "regulator: lm363x: add LM363x regulator binding information" to the regulator tree Mark Brown
2015-11-27 20:57   ` [PATCH v2 4/9] Documentation: dt-bindings: regulator: add LM363x regulator binding information Rob Herring
2015-11-26  6:57 ` [PATCH v2 5/9] mfd: add TI LMU driver Milo Kim
2015-11-26  6:57   ` Milo Kim
2016-01-11 10:17   ` Lee Jones
2015-11-26  6:57 ` [PATCH v2 6/9] mfd: add TI LMU hardware fault monitoring driver Milo Kim
2015-11-26  6:57   ` Milo Kim
2016-01-11 10:21   ` Lee Jones
2016-01-12  3:36     ` Milo Kim
2016-01-12  3:36       ` Milo Kim
2016-01-12  7:37       ` Lee Jones
2015-11-26  6:57 ` [PATCH v2 7/9] backlight: add TI LMU backlight driver Milo Kim
2015-11-26  6:57   ` Milo Kim
2016-01-11  9:57   ` Lee Jones
2016-01-11 23:32     ` Milo Kim
2016-01-11 23:32       ` Milo Kim
2015-11-26  6:57 ` [PATCH v2 8/9] leds: add LM3633 driver Milo Kim
2015-11-26  6:57   ` Milo Kim
2015-11-27 11:19   ` Jacek Anaszewski
     [not found]     ` <56583C37.1050307-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-11-28  8:28       ` Jacek Anaszewski
2015-11-28  8:28         ` Jacek Anaszewski
2015-11-30  8:48     ` Kim, Milo [this message]
2015-11-30  8:48       ` Kim, Milo
2015-11-30 12:26       ` Jacek Anaszewski
2015-11-26  6:57 ` [PATCH v2 9/9] regulator: add LM363X driver Milo Kim
2015-11-26  6:57   ` Milo Kim
2015-11-27 12:55   ` Applied "regulator: add LM363X driver" to the regulator tree Mark Brown
2016-01-14  7:56   ` [PATCH v2 9/9] regulator: add LM363X driver Milo Kim
2016-01-14  7:56     ` Milo Kim
     [not found]     ` <56975493.7050900-l0cyMroinI0@public.gmane.org>
2016-01-14 10:27       ` Mark Brown
2016-01-14 10:27         ` Mark Brown
2016-01-14 23:41         ` Kim, Milo
2016-01-14 23:41           ` Kim, Milo
2016-01-06  7:20 ` [PATCH v2 0/9] Support TI LMU devices Milo Kim
2016-01-06  7:20   ` Milo Kim

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=565C0D6F.9000709@ti.com \
    --to=milo.kim@ti.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=j.anaszewski@samsung.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=robh+dt@kernel.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.