All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515
@ 2020-11-11  1:14 Linus Walleij
  2020-11-11  1:14 ` [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
  2020-11-11 11:04 ` [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Sakari Ailus
  0 siblings, 2 replies; 11+ messages in thread
From: Linus Walleij @ 2020-11-11  1:14 UTC (permalink / raw)
  To: Jacek Anaszewski, Pavel Machek, Dan Murphy
  Cc: linux-leds, Linus Walleij, Sakari Ailus, newbytee,
	Stephan Gerhold, devicetree

Add a YAML devicetree binding for the Richtek RT8515
dual channel flash/torch LED driver.

Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: newbytee@protonmail.com
Cc: Stephan Gerhold <stephan@gerhold.net>
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Add Sakari to CC
- Resend
ChangeLog v1->v2:
- Explicitly inherit function, color and flash-max-timeout-us
  from common.yaml
- Add "led" node as required.
---
 .../bindings/leds/richtek,rt8515.yaml         | 59 +++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/richtek,rt8515.yaml

diff --git a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
new file mode 100644
index 000000000000..0d8bb635370c
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/richtek,rt8515.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Richtek RT8515 1.5A dual channel LED driver
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  The Richtek RT8515 is a dual channel (two mode) LED driver that
+  supports driving a white LED in flash or torch mode.
+
+properties:
+  compatible:
+    const: richtek,rt8515
+
+  enf-gpios:
+    maxItems: 1
+    description: A connection to the 'ENF' (enable flash) pin.
+
+  ent-gpios:
+    maxItems: 1
+    description: A connection to the 'ENT' (enable torch) pin.
+
+  led:
+    type: object
+    $ref: common.yaml#
+    properties:
+      function: true
+      color: true
+      flash-max-timeout-us: true
+
+required:
+  - compatible
+  - ent-gpios
+  - enf-gpios
+  - led
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/leds/common.h>
+
+    led-controller {
+        compatible = "richtek,rt8515";
+        enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+        ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+
+        led {
+            function = LED_FUNCTION_FLASH;
+            color = <LED_COLOR_ID_WHITE>;
+            flash-max-timeout-us = <250000>;
+        };
+    };
-- 
2.26.2


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

* [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11  1:14 [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
@ 2020-11-11  1:14 ` Linus Walleij
  2020-11-11  7:59   ` Pavel Machek
  2020-11-11 11:38   ` Sakari Ailus
  2020-11-11 11:04 ` [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Sakari Ailus
  1 sibling, 2 replies; 11+ messages in thread
From: Linus Walleij @ 2020-11-11  1:14 UTC (permalink / raw)
  To: Jacek Anaszewski, Pavel Machek, Dan Murphy
  Cc: linux-leds, Linus Walleij, Sakari Ailus, newbytee, Stephan Gerhold

This adds a driver for the Richtek RT8515 dual channel
torch/flash white LED driver.

This LED driver is found in some mobile phones from
Samsung such as the GT-S7710 and GT-I8190.

A V4L interface is added.

I do not have any datsheet for the Richtek RT8515.
In the outoftree code that exists for example for Asus
Zenfone the intensity is set to min/max in percent
(0-100%) so the numerals 1-100 step 1 so the same as
the brightness. I do not know the actuall current
this results in.

Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: newbytee@protonmail.com
Cc: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Changelog v2->v3:
- Expand commit message.
- Add Sakari to Cc.
- Resend.
ChangeLog v1->v2:
- Break out routine to bitbang the brightness on a
  GPIO pin.
- Do not hardcode the LED name so that the framework
  can name it from DT properties.
---
 drivers/leds/Kconfig       |  11 ++
 drivers/leds/Makefile      |   1 +
 drivers/leds/leds-rt8515.c | 303 +++++++++++++++++++++++++++++++++++++
 3 files changed, 315 insertions(+)
 create mode 100644 drivers/leds/leds-rt8515.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 849d3c5f908e..df632608d732 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -913,6 +913,17 @@ config LEDS_IP30
 	  To compile this driver as a module, choose M here: the module
 	  will be called leds-ip30.
 
+config LEDS_RT8515
+	tristate "LED support for Richtek RT8515 flash/torch LED"
+	depends on LEDS_CLASS_FLASH
+	depends on GPIOLIB
+	help
+	  This option enables support for the Richtek RT8515 flash
+	  and torch LEDs found on some mobile phones.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-rt8515.
+
 config LEDS_SGM3140
 	tristate "LED support for the SGM3140"
 	depends on LEDS_CLASS_FLASH
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 73e603e1727e..aa6b2a19e051 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
 obj-$(CONFIG_LEDS_POWERNV)		+= leds-powernv.o
 obj-$(CONFIG_LEDS_PWM)			+= leds-pwm.o
 obj-$(CONFIG_LEDS_REGULATOR)		+= leds-regulator.o
+obj-$(CONFIG_LEDS_RT8515)		+= leds-rt8515.o
 obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
 obj-$(CONFIG_LEDS_SC27XX_BLTC)		+= leds-sc27xx-bltc.o
 obj-$(CONFIG_LEDS_SGM3140)		+= leds-sgm3140.o
diff --git a/drivers/leds/leds-rt8515.c b/drivers/leds/leds-rt8515.c
new file mode 100644
index 000000000000..a87019b7eebe
--- /dev/null
+++ b/drivers/leds/leds-rt8515.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * LED driver for Richtek RT8515 flash/torch white LEDs
+ * found on some Samsung mobile phones.
+ * This is a 1.5A Boost dual channel driver produced around 2011.
+ *
+ * Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/led-class-flash.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-flash-led-class.h>
+
+#define RT8515_FLASH_MAX 16
+#define RT8515_TORCH_MAX 100
+
+#define RT8515_TIMEOUT_DEFAULT		250000U /* 250ms */
+#define RT8515_MAX_TIMEOUT_DEFAULT	300000U /* 300ms */
+
+struct rt8515 {
+	struct led_classdev_flash fled;
+	struct v4l2_flash *v4l2_flash;
+	struct mutex lock;
+	struct regulator *reg;
+	struct gpio_desc *ent;
+	struct gpio_desc *enf;
+	struct timer_list powerdown_timer;
+	u32 max_timeout; /* Flash max timeout */
+};
+
+static struct rt8515 *to_rt8515(struct led_classdev_flash *fled)
+{
+	return container_of(fled, struct rt8515, fled);
+}
+
+static void rt8515_gpio_brightness_commit(struct gpio_desc *gpiod,
+					  int brightness)
+{
+	int i;
+
+	/*
+	 * Toggling a GPIO line with a small delay increases the
+	 * brightness one step at a time.
+	 */
+	for (i = 0; i < brightness; i++) {
+		gpiod_set_value(gpiod, 0);
+		udelay(1);
+		gpiod_set_value(gpiod, 1);
+		udelay(1);
+	}
+}
+
+/* This is setting the torch light level */
+static int rt8515_led_brightness_set(struct led_classdev *led,
+				     enum led_brightness brightness)
+{
+	struct led_classdev_flash *fled = lcdev_to_flcdev(led);
+	struct rt8515 *rt = to_rt8515(fled);
+
+	mutex_lock(&rt->lock);
+
+	if (brightness == LED_OFF) {
+		/* Off */
+		gpiod_set_value(rt->enf, 0);
+		gpiod_set_value(rt->ent, 0);
+	} else if (brightness < RT8515_TORCH_MAX) {
+		/* Step it up to movie mode brightness using the flash pin */
+		rt8515_gpio_brightness_commit(rt->ent, brightness);
+	} else {
+		/* Max torch brightness requested */
+		gpiod_set_value(rt->ent, 1);
+	}
+
+	mutex_unlock(&rt->lock);
+
+	return 0;
+}
+
+static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled,
+				       bool state)
+{
+	struct rt8515 *rt = to_rt8515(fled);
+	struct led_flash_setting *timeout = &fled->timeout;
+	int brightness = 4; /* max 16 */
+
+	mutex_lock(&rt->lock);
+
+	if (state) {
+		/* Enable LED flash mode and set brightness */
+		rt8515_gpio_brightness_commit(rt->enf, brightness);
+		/* Set timeout */
+		mod_timer(&rt->powerdown_timer,
+			  jiffies + usecs_to_jiffies(timeout->val));
+	} else {
+		del_timer_sync(&rt->powerdown_timer);
+		/* Turn the LED off */
+		gpiod_set_value(rt->enf, 0);
+		gpiod_set_value(rt->ent, 0);
+	}
+
+	fled->led_cdev.brightness = LED_OFF;
+	/* After this the torch LED will be disabled */
+
+	mutex_unlock(&rt->lock);
+
+	return 0;
+}
+
+static int rt8515_led_flash_strobe_get(struct led_classdev_flash *fled,
+				       bool *state)
+{
+	struct rt8515 *rt = to_rt8515(fled);
+
+	*state = timer_pending(&rt->powerdown_timer);
+
+	return 0;
+}
+
+static int rt8515_led_flash_timeout_set(struct led_classdev_flash *fled,
+					u32 timeout)
+{
+	/* The timeout is stored in the led-class-flash core */
+	return 0;
+}
+
+static const struct led_flash_ops rt8515_flash_ops = {
+	.strobe_set = rt8515_led_flash_strobe_set,
+	.strobe_get = rt8515_led_flash_strobe_get,
+	.timeout_set = rt8515_led_flash_timeout_set,
+};
+
+static void rt8515_powerdown_timer(struct timer_list *t)
+{
+	struct rt8515 *rt = from_timer(rt, t, powerdown_timer);
+
+	/* Turn the LED off */
+	gpiod_set_value(rt->enf, 0);
+	gpiod_set_value(rt->ent, 0);
+}
+
+static void rt8515_init_flash_timeout(struct rt8515 *rt)
+{
+	struct led_classdev_flash *fled = &rt->fled;
+	struct led_flash_setting *s;
+
+	/* Init flash timeout setting */
+	s = &fled->timeout;
+	s->min = 1;
+	s->max = rt->max_timeout;
+	s->step = 1;
+	/*
+	 * Set default timeout to RT8515_DEFAULT_TIMEOUT except if
+	 * max_timeout from DT is lower.
+	 */
+	s->val = min(rt->max_timeout, RT8515_TIMEOUT_DEFAULT);
+}
+
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+/* Configure the V2L2 flash subdevice */
+static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
+					  struct v4l2_flash_config *v4l2_sd_cfg)
+{
+	struct led_classdev *led = &rt->fled.led_cdev;
+	struct led_flash_setting *s;
+
+	strscpy(v4l2_sd_cfg->dev_name, led->dev->kobj.name,
+		sizeof(v4l2_sd_cfg->dev_name));
+
+	/* Init flash intensity setting */
+	s = &v4l2_sd_cfg->intensity;
+	s->min = 0;
+	s->max = rt->fled.led_cdev.max_brightness;
+	s->step = 1;
+	s->val = s->max;
+}
+
+#else
+static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
+					  struct v4l2_flash_config *v4l2_sd_cfg)
+{
+}
+#endif
+
+static int rt8515_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fwnode_handle *child;
+	struct rt8515 *rt;
+	struct led_classdev *led;
+	struct led_classdev_flash *fled;
+	struct led_init_data init_data = {};
+	struct v4l2_flash_config v4l2_sd_cfg = {};
+	int ret;
+
+	rt = devm_kzalloc(dev, sizeof(*rt), GFP_KERNEL);
+	if (!rt)
+		return -ENOMEM;
+
+	fled = &rt->fled;
+	led = &fled->led_cdev;
+
+	/* ENF - Enable Flash line */
+	rt->enf = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW);
+	if (IS_ERR(rt->enf)) {
+		dev_err(dev, "cannot get ENF (enable flash) GPIO\n");
+		return PTR_ERR(rt->enf);
+	}
+
+	/* ENT - Enable Torch line */
+	rt->ent = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW);
+	if (IS_ERR(rt->ent)) {
+		dev_err(dev, "cannot get ENT (enable torch) GPIO\n");
+		return PTR_ERR(rt->ent);
+	}
+
+	child = fwnode_get_next_available_child_node(dev->fwnode, NULL);
+	if (!child) {
+		dev_err(dev,
+			"No fwnode child node found for connected LED.\n");
+		return -EINVAL;
+	}
+	init_data.fwnode = child;
+
+	ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
+				       &rt->max_timeout);
+	if (ret) {
+		rt->max_timeout = RT8515_MAX_TIMEOUT_DEFAULT;
+		dev_warn(dev,
+			 "flash-max-timeout-us property missing\n");
+	}
+	timer_setup(&rt->powerdown_timer, rt8515_powerdown_timer, 0);
+	rt8515_init_flash_timeout(rt);
+
+	fled->ops = &rt8515_flash_ops;
+
+	led->max_brightness = RT8515_TORCH_MAX;
+	led->brightness_set_blocking = rt8515_led_brightness_set;
+	led->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
+
+	mutex_init(&rt->lock);
+
+	platform_set_drvdata(pdev, rt);
+
+	ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data);
+	if (ret) {
+		dev_err(dev, "can't register LED %s\n", led->name);
+		mutex_destroy(&rt->lock);
+		return ret;
+	}
+
+	rt8515_init_v4l2_flash_config(rt, &v4l2_sd_cfg);
+
+	/* Create a V4L2 Flash device if V4L2 flash is enabled */
+	rt->v4l2_flash = v4l2_flash_init(dev, child, fled, NULL, &v4l2_sd_cfg);
+	if (IS_ERR(rt->v4l2_flash)) {
+		ret = PTR_ERR(rt->v4l2_flash);
+		dev_err(dev, "failed to register V4L2 flash device (%d)\n",
+			ret);
+		/*
+		 * Continue without the V4L2 flash
+		 * (we still have the classdev)
+		 */
+	}
+
+	return 0;
+}
+
+static int rt8515_remove(struct platform_device *pdev)
+{
+	struct rt8515 *rt = platform_get_drvdata(pdev);
+
+	v4l2_flash_release(rt->v4l2_flash);
+	del_timer_sync(&rt->powerdown_timer);
+	mutex_destroy(&rt->lock);
+
+	return 0;
+}
+
+static const struct of_device_id rt8515_match[] = {
+	{ .compatible = "richtek,rt8515", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rt8515_match);
+
+static struct platform_driver rt8515_driver = {
+	.driver = {
+		.name  = "rt8515",
+		.of_match_table = rt8515_match,
+	},
+	.probe  = rt8515_probe,
+	.remove = rt8515_remove,
+};
+module_platform_driver(rt8515_driver);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Richtek RT8515 LED driver");
+MODULE_LICENSE("GPL v2");
-- 
2.26.2


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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11  1:14 ` [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
@ 2020-11-11  7:59   ` Pavel Machek
  2020-11-11 11:38   ` Sakari Ailus
  1 sibling, 0 replies; 11+ messages in thread
From: Pavel Machek @ 2020-11-11  7:59 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Dan Murphy, linux-leds, Sakari Ailus, newbytee,
	Stephan Gerhold

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

Hi!

> This adds a driver for the Richtek RT8515 dual channel
> torch/flash white LED driver.
> 
> This LED driver is found in some mobile phones from
> Samsung such as the GT-S7710 and GT-I8190.

Cc: phone-devel@vger.

>  drivers/leds/Kconfig       |  11 ++
>  drivers/leds/Makefile      |   1 +
>  drivers/leds/leds-rt8515.c | 303 +++++++++++++++++++++++++++++++++++++

Let's put this into drivers/leds/flash. You may need to create it.

> +// SPDX-License-Identifier: GPL-2.0-only

GPL-2+ would be nicer if you can.

> +struct rt8515 {
> +	struct led_classdev_flash fled;
> +	struct v4l2_flash *v4l2_flash;
> +	struct mutex lock;
> +	struct regulator *reg;
> +	struct gpio_desc *ent;
> +	struct gpio_desc *enf;

-> enable_torch or at least en_torch / en_flash?

Otherwise it looks good.

Best regards,
							Pavel

-- 
http://www.livejournal.com/~pavelmachek

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515
  2020-11-11  1:14 [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
  2020-11-11  1:14 ` [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
@ 2020-11-11 11:04 ` Sakari Ailus
  2020-11-11 13:44   ` Linus Walleij
  1 sibling, 1 reply; 11+ messages in thread
From: Sakari Ailus @ 2020-11-11 11:04 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, linux-leds, newbytee,
	Stephan Gerhold, devicetree

Hi Linus,

Thanks for the patch (and cc'ing me).

On Wed, Nov 11, 2020 at 02:14:16AM +0100, Linus Walleij wrote:
> Add a YAML devicetree binding for the Richtek RT8515
> dual channel flash/torch LED driver.
> 
> Cc: Sakari Ailus <sakari.ailus@iki.fi>
> Cc: newbytee@protonmail.com
> Cc: Stephan Gerhold <stephan@gerhold.net>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v2->v3:
> - Add Sakari to CC
> - Resend
> ChangeLog v1->v2:
> - Explicitly inherit function, color and flash-max-timeout-us
>   from common.yaml
> - Add "led" node as required.
> ---
>  .../bindings/leds/richtek,rt8515.yaml         | 59 +++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> 
> diff --git a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> new file mode 100644
> index 000000000000..0d8bb635370c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> @@ -0,0 +1,59 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/leds/richtek,rt8515.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Richtek RT8515 1.5A dual channel LED driver
> +
> +maintainers:
> +  - Linus Walleij <linus.walleij@linaro.org>
> +
> +description: |
> +  The Richtek RT8515 is a dual channel (two mode) LED driver that
> +  supports driving a white LED in flash or torch mode.
> +
> +properties:
> +  compatible:
> +    const: richtek,rt8515
> +
> +  enf-gpios:
> +    maxItems: 1
> +    description: A connection to the 'ENF' (enable flash) pin.
> +
> +  ent-gpios:
> +    maxItems: 1
> +    description: A connection to the 'ENT' (enable torch) pin.
> +
> +  led:
> +    type: object
> +    $ref: common.yaml#
> +    properties:
> +      function: true
> +      color: true
> +      flash-max-timeout-us: true

Don't you also need flash-max-microamp and led-max-microamp? As the maximum
current for the LED may well be less than the driver can provide.

> +
> +required:
> +  - compatible
> +  - ent-gpios
> +  - enf-gpios
> +  - led
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/leds/common.h>
> +
> +    led-controller {
> +        compatible = "richtek,rt8515";
> +        enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
> +        ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
> +
> +        led {
> +            function = LED_FUNCTION_FLASH;
> +            color = <LED_COLOR_ID_WHITE>;
> +            flash-max-timeout-us = <250000>;
> +        };
> +    };
> -- 
> 2.26.2
> 

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11  1:14 ` [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
  2020-11-11  7:59   ` Pavel Machek
@ 2020-11-11 11:38   ` Sakari Ailus
  2020-11-11 16:34     ` Linus Walleij
  1 sibling, 1 reply; 11+ messages in thread
From: Sakari Ailus @ 2020-11-11 11:38 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, linux-leds, newbytee,
	Stephan Gerhold

Hi Linus,

On Wed, Nov 11, 2020 at 02:14:17AM +0100, Linus Walleij wrote:
> This adds a driver for the Richtek RT8515 dual channel
> torch/flash white LED driver.
> 
> This LED driver is found in some mobile phones from
> Samsung such as the GT-S7710 and GT-I8190.
> 
> A V4L interface is added.
> 
> I do not have any datsheet for the Richtek RT8515.
> In the outoftree code that exists for example for Asus
> Zenfone the intensity is set to min/max in percent
> (0-100%) so the numerals 1-100 step 1 so the same as
> the brightness. I do not know the actuall current
> this results in.
> 
> Cc: Sakari Ailus <sakari.ailus@iki.fi>
> Cc: newbytee@protonmail.com
> Cc: Stephan Gerhold <stephan@gerhold.net>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Changelog v2->v3:
> - Expand commit message.
> - Add Sakari to Cc.
> - Resend.
> ChangeLog v1->v2:
> - Break out routine to bitbang the brightness on a
>   GPIO pin.
> - Do not hardcode the LED name so that the framework
>   can name it from DT properties.
> ---
>  drivers/leds/Kconfig       |  11 ++
>  drivers/leds/Makefile      |   1 +
>  drivers/leds/leds-rt8515.c | 303 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 315 insertions(+)
>  create mode 100644 drivers/leds/leds-rt8515.c
> 
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index 849d3c5f908e..df632608d732 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -913,6 +913,17 @@ config LEDS_IP30
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called leds-ip30.
>  
> +config LEDS_RT8515
> +	tristate "LED support for Richtek RT8515 flash/torch LED"
> +	depends on LEDS_CLASS_FLASH
> +	depends on GPIOLIB
> +	help
> +	  This option enables support for the Richtek RT8515 flash
> +	  and torch LEDs found on some mobile phones.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called leds-rt8515.
> +
>  config LEDS_SGM3140
>  	tristate "LED support for the SGM3140"
>  	depends on LEDS_CLASS_FLASH
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index 73e603e1727e..aa6b2a19e051 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -80,6 +80,7 @@ obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
>  obj-$(CONFIG_LEDS_POWERNV)		+= leds-powernv.o
>  obj-$(CONFIG_LEDS_PWM)			+= leds-pwm.o
>  obj-$(CONFIG_LEDS_REGULATOR)		+= leds-regulator.o
> +obj-$(CONFIG_LEDS_RT8515)		+= leds-rt8515.o
>  obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
>  obj-$(CONFIG_LEDS_SC27XX_BLTC)		+= leds-sc27xx-bltc.o
>  obj-$(CONFIG_LEDS_SGM3140)		+= leds-sgm3140.o
> diff --git a/drivers/leds/leds-rt8515.c b/drivers/leds/leds-rt8515.c
> new file mode 100644
> index 000000000000..a87019b7eebe
> --- /dev/null
> +++ b/drivers/leds/leds-rt8515.c
> @@ -0,0 +1,303 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * LED driver for Richtek RT8515 flash/torch white LEDs
> + * found on some Samsung mobile phones.
> + * This is a 1.5A Boost dual channel driver produced around 2011.
> + *
> + * Linus Walleij <linus.walleij@linaro.org>
> + */
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/led-class-flash.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <media/v4l2-flash-led-class.h>
> +
> +#define RT8515_FLASH_MAX 16

This is unused.

> +#define RT8515_TORCH_MAX 100
> +
> +#define RT8515_TIMEOUT_DEFAULT		250000U /* 250ms */
> +#define RT8515_MAX_TIMEOUT_DEFAULT	300000U /* 300ms */
> +
> +struct rt8515 {
> +	struct led_classdev_flash fled;
> +	struct v4l2_flash *v4l2_flash;
> +	struct mutex lock;
> +	struct regulator *reg;
> +	struct gpio_desc *ent;
> +	struct gpio_desc *enf;
> +	struct timer_list powerdown_timer;
> +	u32 max_timeout; /* Flash max timeout */
> +};
> +
> +static struct rt8515 *to_rt8515(struct led_classdev_flash *fled)
> +{
> +	return container_of(fled, struct rt8515, fled);
> +}
> +
> +static void rt8515_gpio_brightness_commit(struct gpio_desc *gpiod,
> +					  int brightness)
> +{
> +	int i;
> +
> +	/*
> +	 * Toggling a GPIO line with a small delay increases the
> +	 * brightness one step at a time.
> +	 */

Wow.

> +	for (i = 0; i < brightness; i++) {
> +		gpiod_set_value(gpiod, 0);
> +		udelay(1);
> +		gpiod_set_value(gpiod, 1);
> +		udelay(1);
> +	}
> +}
> +
> +/* This is setting the torch light level */
> +static int rt8515_led_brightness_set(struct led_classdev *led,
> +				     enum led_brightness brightness)
> +{
> +	struct led_classdev_flash *fled = lcdev_to_flcdev(led);
> +	struct rt8515 *rt = to_rt8515(fled);
> +
> +	mutex_lock(&rt->lock);
> +
> +	if (brightness == LED_OFF) {
> +		/* Off */
> +		gpiod_set_value(rt->enf, 0);
> +		gpiod_set_value(rt->ent, 0);
> +	} else if (brightness < RT8515_TORCH_MAX) {
> +		/* Step it up to movie mode brightness using the flash pin */
> +		rt8515_gpio_brightness_commit(rt->ent, brightness);

What's the unit of brightness here? If you don't know the unit, you could
still assume something and fix it later if needed. Or the current could be
just measured.

It's usually linear but if the number of steps is small then logarithmic
scale is also not unforeseen.

> +	} else {
> +		/* Max torch brightness requested */
> +		gpiod_set_value(rt->ent, 1);

What's the current in this case? The maximum really should come from DT to
avoid frying components.

> +	}
> +
> +	mutex_unlock(&rt->lock);
> +
> +	return 0;
> +}
> +
> +static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled,
> +				       bool state)
> +{
> +	struct rt8515 *rt = to_rt8515(fled);
> +	struct led_flash_setting *timeout = &fled->timeout;
> +	int brightness = 4; /* max 16 */
> +
> +	mutex_lock(&rt->lock);
> +
> +	if (state) {
> +		/* Enable LED flash mode and set brightness */
> +		rt8515_gpio_brightness_commit(rt->enf, brightness);
> +		/* Set timeout */
> +		mod_timer(&rt->powerdown_timer,
> +			  jiffies + usecs_to_jiffies(timeout->val));
> +	} else {
> +		del_timer_sync(&rt->powerdown_timer);
> +		/* Turn the LED off */
> +		gpiod_set_value(rt->enf, 0);
> +		gpiod_set_value(rt->ent, 0);
> +	}
> +
> +	fled->led_cdev.brightness = LED_OFF;
> +	/* After this the torch LED will be disabled */
> +
> +	mutex_unlock(&rt->lock);
> +
> +	return 0;
> +}
> +
> +static int rt8515_led_flash_strobe_get(struct led_classdev_flash *fled,
> +				       bool *state)
> +{
> +	struct rt8515 *rt = to_rt8515(fled);
> +
> +	*state = timer_pending(&rt->powerdown_timer);
> +
> +	return 0;
> +}
> +
> +static int rt8515_led_flash_timeout_set(struct led_classdev_flash *fled,
> +					u32 timeout)
> +{
> +	/* The timeout is stored in the led-class-flash core */
> +	return 0;
> +}
> +
> +static const struct led_flash_ops rt8515_flash_ops = {
> +	.strobe_set = rt8515_led_flash_strobe_set,
> +	.strobe_get = rt8515_led_flash_strobe_get,
> +	.timeout_set = rt8515_led_flash_timeout_set,
> +};
> +
> +static void rt8515_powerdown_timer(struct timer_list *t)
> +{
> +	struct rt8515 *rt = from_timer(rt, t, powerdown_timer);
> +
> +	/* Turn the LED off */
> +	gpiod_set_value(rt->enf, 0);
> +	gpiod_set_value(rt->ent, 0);
> +}
> +
> +static void rt8515_init_flash_timeout(struct rt8515 *rt)
> +{
> +	struct led_classdev_flash *fled = &rt->fled;
> +	struct led_flash_setting *s;
> +
> +	/* Init flash timeout setting */
> +	s = &fled->timeout;
> +	s->min = 1;
> +	s->max = rt->max_timeout;
> +	s->step = 1;
> +	/*
> +	 * Set default timeout to RT8515_DEFAULT_TIMEOUT except if
> +	 * max_timeout from DT is lower.
> +	 */
> +	s->val = min(rt->max_timeout, RT8515_TIMEOUT_DEFAULT);
> +}
> +
> +#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
> +/* Configure the V2L2 flash subdevice */
> +static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
> +					  struct v4l2_flash_config *v4l2_sd_cfg)
> +{
> +	struct led_classdev *led = &rt->fled.led_cdev;
> +	struct led_flash_setting *s;
> +
> +	strscpy(v4l2_sd_cfg->dev_name, led->dev->kobj.name,
> +		sizeof(v4l2_sd_cfg->dev_name));
> +
> +	/* Init flash intensity setting */
> +	s = &v4l2_sd_cfg->intensity;
> +	s->min = 0;
> +	s->max = rt->fled.led_cdev.max_brightness;
> +	s->step = 1;
> +	s->val = s->max;
> +}
> +
> +#else
> +static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
> +					  struct v4l2_flash_config *v4l2_sd_cfg)
> +{
> +}
> +#endif
> +
> +static int rt8515_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct fwnode_handle *child;
> +	struct rt8515 *rt;
> +	struct led_classdev *led;
> +	struct led_classdev_flash *fled;
> +	struct led_init_data init_data = {};
> +	struct v4l2_flash_config v4l2_sd_cfg = {};
> +	int ret;
> +
> +	rt = devm_kzalloc(dev, sizeof(*rt), GFP_KERNEL);
> +	if (!rt)
> +		return -ENOMEM;
> +
> +	fled = &rt->fled;
> +	led = &fled->led_cdev;
> +
> +	/* ENF - Enable Flash line */
> +	rt->enf = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW);
> +	if (IS_ERR(rt->enf)) {
> +		dev_err(dev, "cannot get ENF (enable flash) GPIO\n");
> +		return PTR_ERR(rt->enf);
> +	}
> +
> +	/* ENT - Enable Torch line */
> +	rt->ent = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW);
> +	if (IS_ERR(rt->ent)) {
> +		dev_err(dev, "cannot get ENT (enable torch) GPIO\n");
> +		return PTR_ERR(rt->ent);
> +	}
> +
> +	child = fwnode_get_next_available_child_node(dev->fwnode, NULL);
> +	if (!child) {
> +		dev_err(dev,
> +			"No fwnode child node found for connected LED.\n");
> +		return -EINVAL;
> +	}
> +	init_data.fwnode = child;
> +
> +	ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
> +				       &rt->max_timeout);
> +	if (ret) {
> +		rt->max_timeout = RT8515_MAX_TIMEOUT_DEFAULT;
> +		dev_warn(dev,
> +			 "flash-max-timeout-us property missing\n");
> +	}
> +	timer_setup(&rt->powerdown_timer, rt8515_powerdown_timer, 0);
> +	rt8515_init_flash_timeout(rt);
> +
> +	fled->ops = &rt8515_flash_ops;
> +
> +	led->max_brightness = RT8515_TORCH_MAX;
> +	led->brightness_set_blocking = rt8515_led_brightness_set;
> +	led->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
> +
> +	mutex_init(&rt->lock);
> +
> +	platform_set_drvdata(pdev, rt);
> +
> +	ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data);
> +	if (ret) {
> +		dev_err(dev, "can't register LED %s\n", led->name);
> +		mutex_destroy(&rt->lock);
> +		return ret;
> +	}
> +
> +	rt8515_init_v4l2_flash_config(rt, &v4l2_sd_cfg);
> +
> +	/* Create a V4L2 Flash device if V4L2 flash is enabled */
> +	rt->v4l2_flash = v4l2_flash_init(dev, child, fled, NULL, &v4l2_sd_cfg);
> +	if (IS_ERR(rt->v4l2_flash)) {
> +		ret = PTR_ERR(rt->v4l2_flash);
> +		dev_err(dev, "failed to register V4L2 flash device (%d)\n",
> +			ret);
> +		/*
> +		 * Continue without the V4L2 flash
> +		 * (we still have the classdev)
> +		 */
> +	}
> +
> +	return 0;
> +}
> +
> +static int rt8515_remove(struct platform_device *pdev)
> +{
> +	struct rt8515 *rt = platform_get_drvdata(pdev);
> +
> +	v4l2_flash_release(rt->v4l2_flash);
> +	del_timer_sync(&rt->powerdown_timer);
> +	mutex_destroy(&rt->lock);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id rt8515_match[] = {
> +	{ .compatible = "richtek,rt8515", },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, rt8515_match);
> +
> +static struct platform_driver rt8515_driver = {
> +	.driver = {
> +		.name  = "rt8515",
> +		.of_match_table = rt8515_match,
> +	},
> +	.probe  = rt8515_probe,
> +	.remove = rt8515_remove,
> +};
> +module_platform_driver(rt8515_driver);
> +
> +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> +MODULE_DESCRIPTION("Richtek RT8515 LED driver");
> +MODULE_LICENSE("GPL v2");

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515
  2020-11-11 11:04 ` [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Sakari Ailus
@ 2020-11-11 13:44   ` Linus Walleij
  0 siblings, 0 replies; 11+ messages in thread
From: Linus Walleij @ 2020-11-11 13:44 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Wed, Nov 11, 2020 at 12:05 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:
> On Wed, Nov 11, 2020 at 02:14:16AM +0100, Linus Walleij wrote:

> > Add a YAML devicetree binding for the Richtek RT8515
> > dual channel flash/torch LED driver.

> > +  led:
> > +    type: object
> > +    $ref: common.yaml#
> > +    properties:
> > +      function: true
> > +      color: true
> > +      flash-max-timeout-us: true
>
> Don't you also need flash-max-microamp and led-max-microamp? As the maximum
> current for the LED may well be less than the driver can provide.

I wish I could add that.

The problem is that we don't know anything about the microamps
for this Richtek component.

There is no public datasheet available. I have asked Richtek, they
answered as follows:

"RT8515 had EOL already.
 So, we couldn't provide the datasheet.
 Thank you."

I do not quite understand their answer but they at least answered.

I have a few out-of-tree drivers, from Asus Zenfone, and from the
numerous Samsung mobiles using this. None of the outoftree code
makes any reference to the actual microamperes.

They make a setting from 1..100 "units" and that is handled by some
kind of userspace that I do not have the code for. If someone knows
of a source code for this userspace I would be happy to take a look
so we can at least figure out if it is linear.

Yours,
Linus Walleij

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11 11:38   ` Sakari Ailus
@ 2020-11-11 16:34     ` Linus Walleij
  2020-11-11 16:55       ` Sakari Ailus
  0 siblings, 1 reply; 11+ messages in thread
From: Linus Walleij @ 2020-11-11 16:34 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold

On Wed, Nov 11, 2020 at 12:40 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:
> On Wed, Nov 11, 2020 at 02:14:17AM +0100, Linus Walleij wrote:

> > +     } else if (brightness < RT8515_TORCH_MAX) {
> > +             /* Step it up to movie mode brightness using the flash pin */
> > +             rt8515_gpio_brightness_commit(rt->ent, brightness);
>
> What's the unit of brightness here? If you don't know the unit, you could
> still assume something and fix it later if needed. Or the current could be
> just measured.
>
> It's usually linear but if the number of steps is small then logarithmic
> scale is also not unforeseen.

I will try to come up with something...

> > +     } else {
> > +             /* Max torch brightness requested */
> > +             gpiod_set_value(rt->ent, 1);
>
> What's the current in this case? The maximum really should come from DT to
> avoid frying components.

The way I understand it is that this component contains its own
current regulation electronic. You request a brightness
between 1-100 and it will support this range (no external
current boost). And as a user that is "all you need to know".

Isn't this problem more prevalent when you have some kind of
external current-regulator that you need to program?

This component draws its power directly from VBAT (the main
battery) so regulating how much of that it takes is up to the
component.

I could think of the component brightness being a problem if
the flash is embedded in some kind of plastic that cannot
take the heat though, but I haven't seen any code trying to
hold it down for this reason. I suppose the component
datasheet (that I don't have) specifies all these things...

Yours,
Linus Walleij

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11 16:34     ` Linus Walleij
@ 2020-11-11 16:55       ` Sakari Ailus
  2020-11-11 22:07         ` Linus Walleij
  0 siblings, 1 reply; 11+ messages in thread
From: Sakari Ailus @ 2020-11-11 16:55 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold

Hi Linus,

On Wed, Nov 11, 2020 at 05:34:58PM +0100, Linus Walleij wrote:
> On Wed, Nov 11, 2020 at 12:40 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:
> > On Wed, Nov 11, 2020 at 02:14:17AM +0100, Linus Walleij wrote:
> 
> > > +     } else if (brightness < RT8515_TORCH_MAX) {
> > > +             /* Step it up to movie mode brightness using the flash pin */
> > > +             rt8515_gpio_brightness_commit(rt->ent, brightness);
> >
> > What's the unit of brightness here? If you don't know the unit, you could
> > still assume something and fix it later if needed. Or the current could be
> > just measured.
> >
> > It's usually linear but if the number of steps is small then logarithmic
> > scale is also not unforeseen.
> 
> I will try to come up with something...
> 
> > > +     } else {
> > > +             /* Max torch brightness requested */
> > > +             gpiod_set_value(rt->ent, 1);
> >
> > What's the current in this case? The maximum really should come from DT to
> > avoid frying components.
> 
> The way I understand it is that this component contains its own
> current regulation electronic. You request a brightness
> between 1-100 and it will support this range (no external
> current boost). And as a user that is "all you need to know".
> 
> Isn't this problem more prevalent when you have some kind of
> external current-regulator that you need to program?
> 
> This component draws its power directly from VBAT (the main
> battery) so regulating how much of that it takes is up to the
> component.
> 
> I could think of the component brightness being a problem if
> the flash is embedded in some kind of plastic that cannot
> take the heat though, but I haven't seen any code trying to
> hold it down for this reason. I suppose the component
> datasheet (that I don't have) specifies all these things...

The LED is different from the LED driver. If you happen to have a LED with
smaller maximum current than the LED driver can provide, the software has
to limit the current the driver provides, or hardware damage will result.

This is why virtually all flash LED drivers have these properties.

I guess you could use the maximum as it is known the driver uses the
maximum current on those devices? How about the torch mode, does that use
maximum as well?

A (safe) way forward now, without knowing the current in various
configurations, could be to document the said properties in DT bindings,
but the driver would only work if it gets the maximum values from the DT.
Or use the lowest setting otherwise.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11 16:55       ` Sakari Ailus
@ 2020-11-11 22:07         ` Linus Walleij
  2020-11-12 10:24           ` Sakari Ailus
  2020-11-25 19:35           ` Pavel Machek
  0 siblings, 2 replies; 11+ messages in thread
From: Linus Walleij @ 2020-11-11 22:07 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold

On Wed, Nov 11, 2020 at 5:56 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:
> On Wed, Nov 11, 2020 at 05:34:58PM +0100, Linus Walleij wrote:

> > The way I understand it is that this component contains its own
> > current regulation electronic. You request a brightness
> > between 1-100 and it will support this range (no external
> > current boost). And as a user that is "all you need to know".
> >
> > Isn't this problem more prevalent when you have some kind of
> > external current-regulator that you need to program?
> >
> > This component draws its power directly from VBAT (the main
> > battery) so regulating how much of that it takes is up to the
> > component.
> >
> > I could think of the component brightness being a problem if
> > the flash is embedded in some kind of plastic that cannot
> > take the heat though, but I haven't seen any code trying to
> > hold it down for this reason. I suppose the component
> > datasheet (that I don't have) specifies all these things...
>
> The LED is different from the LED driver. If you happen to have a LED with
> smaller maximum current than the LED driver can provide, the software has
> to limit the current the driver provides, or hardware damage will result.
>
> This is why virtually all flash LED drivers have these properties.

Hm you're right of course.

I did some research, the flash driver in the RT8515
appears to be somewhat clever.

Here is a schematic picture from the LG P970 service
manual where you can see the connections from the RT8515
to the LED:
https://dflund.se/~triad/images/rt8515.jpg

On this image you can see that there are two resistors connected
from the pins "RFS" and "RTS" to ground.

RFS (resistance flash setting?) is 20 kOhm
RTS (resistance torch setting?) is 39 kOhm

Some sleuthing finds us the RT9387A which we have a datasheet for:
https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf
This apparently works the same way so now we have a
RT9387A driver as well.

The two resistances control the max current for flash
and torch, with I = 5500 / R, up to 700 mA.
For 20 and 39 kOhm this means

ImaxFlash = 275 mA
ImaxTorch = 141 mA

So the max current is actually hardwired into the
circuit.

The setting of brightness is done with the pulse train,
but it is a PWM dimmer setting on top of the max
current.

So I'll just put in these max currents (assuming they
are using the same equation).

Yours,
Linus Walleij

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11 22:07         ` Linus Walleij
@ 2020-11-12 10:24           ` Sakari Ailus
  2020-11-25 19:35           ` Pavel Machek
  1 sibling, 0 replies; 11+ messages in thread
From: Sakari Ailus @ 2020-11-12 10:24 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold, linux-media

Hi Linus,

On Wed, Nov 11, 2020 at 11:07:53PM +0100, Linus Walleij wrote:
> On Wed, Nov 11, 2020 at 5:56 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:
> > On Wed, Nov 11, 2020 at 05:34:58PM +0100, Linus Walleij wrote:
> 
> > > The way I understand it is that this component contains its own
> > > current regulation electronic. You request a brightness
> > > between 1-100 and it will support this range (no external
> > > current boost). And as a user that is "all you need to know".
> > >
> > > Isn't this problem more prevalent when you have some kind of
> > > external current-regulator that you need to program?
> > >
> > > This component draws its power directly from VBAT (the main
> > > battery) so regulating how much of that it takes is up to the
> > > component.
> > >
> > > I could think of the component brightness being a problem if
> > > the flash is embedded in some kind of plastic that cannot
> > > take the heat though, but I haven't seen any code trying to
> > > hold it down for this reason. I suppose the component
> > > datasheet (that I don't have) specifies all these things...
> >
> > The LED is different from the LED driver. If you happen to have a LED with
> > smaller maximum current than the LED driver can provide, the software has
> > to limit the current the driver provides, or hardware damage will result.
> >
> > This is why virtually all flash LED drivers have these properties.
> 
> Hm you're right of course.
> 
> I did some research, the flash driver in the RT8515
> appears to be somewhat clever.
> 
> Here is a schematic picture from the LG P970 service
> manual where you can see the connections from the RT8515
> to the LED:
> https://dflund.se/~triad/images/rt8515.jpg
> 
> On this image you can see that there are two resistors connected
> from the pins "RFS" and "RTS" to ground.
> 
> RFS (resistance flash setting?) is 20 kOhm
> RTS (resistance torch setting?) is 39 kOhm
> 
> Some sleuthing finds us the RT9387A which we have a datasheet for:
> https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf
> This apparently works the same way so now we have a
> RT9387A driver as well.
> 
> The two resistances control the max current for flash
> and torch, with I = 5500 / R, up to 700 mA.
> For 20 and 39 kOhm this means
> 
> ImaxFlash = 275 mA
> ImaxTorch = 141 mA
> 
> So the max current is actually hardwired into the
> circuit.

Nice; thanks for digging into this! Interesting indeed, I have to admit
I've only seen software limited implementations up to now.

So here it's indeed not necessary to know the limits to operate the device
safely, and the limits would (or could) remain for the user interface's
purpose only (from driver PoV).

> 
> The setting of brightness is done with the pulse train,
> but it is a PWM dimmer setting on top of the max
> current.
> 
> So I'll just put in these max currents (assuming they
> are using the same equation).

Sounds good.

I think it'd be nice to have the limits, but they could be optional --- it
might not be always possible to know them in general case. I wonder if
anyone else has thoughts on this.

Cc'ing also linux-media.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-11 22:07         ` Linus Walleij
  2020-11-12 10:24           ` Sakari Ailus
@ 2020-11-25 19:35           ` Pavel Machek
  1 sibling, 0 replies; 11+ messages in thread
From: Pavel Machek @ 2020-11-25 19:35 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Sakari Ailus, Jacek Anaszewski, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold

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

Hi!

> Here is a schematic picture from the LG P970 service
> manual where you can see the connections from the RT8515
> to the LED:
> https://dflund.se/~triad/images/rt8515.jpg
> 
> On this image you can see that there are two resistors connected
> from the pins "RFS" and "RTS" to ground.
> 
> RFS (resistance flash setting?) is 20 kOhm
> RTS (resistance torch setting?) is 39 kOhm
> 
> Some sleuthing finds us the RT9387A which we have a datasheet for:
> https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf
> This apparently works the same way so now we have a
> RT9387A driver as well.

These links and RT9387A would be useful to mention in a comment in a
driver...

Best regards,
								Pavel

-- 
http://www.livejournal.com/~pavelmachek

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

end of thread, other threads:[~2020-11-25 19:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-11  1:14 [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
2020-11-11  1:14 ` [PATCH 2/2 v3] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
2020-11-11  7:59   ` Pavel Machek
2020-11-11 11:38   ` Sakari Ailus
2020-11-11 16:34     ` Linus Walleij
2020-11-11 16:55       ` Sakari Ailus
2020-11-11 22:07         ` Linus Walleij
2020-11-12 10:24           ` Sakari Ailus
2020-11-25 19:35           ` Pavel Machek
2020-11-11 11:04 ` [PATCH 1/2 v3] dt-bindings: leds: Add DT binding for Richtek RT8515 Sakari Ailus
2020-11-11 13:44   ` Linus Walleij

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.