All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515
@ 2020-11-13 12:42 Linus Walleij
  2020-11-13 12:42 ` [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
  2020-11-21 13:27 ` [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Rob Herring
  0 siblings, 2 replies; 7+ messages in thread
From: Linus Walleij @ 2020-11-13 12:42 UTC (permalink / raw)
  To: Jacek Anaszewski, Pavel Machek, Dan Murphy
  Cc: linux-leds, Linus Walleij, Sakari Ailus, newbytee,
	Stephan Gerhold, phone-devel, linux-media, 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: phone-devel@vger.kernel.org
Cc: linux-media@vger.kernel.org
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v4->v5:
- Fix the RFS/RTS resistors to reference the u32 schema.
- Fix resisitor speling error.
ChangeLog v3->v4:
- Add DT attributes for the RFS and RTS resistors, so that
  the hardware-defined maximum current can be determined.
- Add torch-max-microamp to the common bindings so we can
  set an attribute for the max microamp in torch mode.
- Add flash-max-microamp and torch-max-microamp as optional
  to the LED node.
- Slot in some elabortative descriptions of the new
  properties and describe what the hardware is doing.
- Cc phone-devel@vger.kernel.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.
---
 .../devicetree/bindings/leds/common.yaml      |   6 +
 .../bindings/leds/richtek,rt8515.yaml         | 111 ++++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/richtek,rt8515.yaml

diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml
index f1211e7045f1..92fa90b4a671 100644
--- a/Documentation/devicetree/bindings/leds/common.yaml
+++ b/Documentation/devicetree/bindings/leds/common.yaml
@@ -151,6 +151,12 @@ properties:
       Maximum flash LED supply current in microamperes. Required for flash LED
       nodes with configurable current.
 
+  torch-max-microamp:
+    description:
+      Maximum flash LED supply current in microamperes, when the flash LED is
+      used as a torch (flashlight). This is usually lower than the flash mode
+      maximum current, if the LED supports torch mode.
+
   flash-max-timeout-us:
     description:
       Maximum timeout in microseconds after which the flash LED is turned off.
diff --git a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
new file mode 100644
index 000000000000..b1f69277c5d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
@@ -0,0 +1,111 @@
+# 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. The maximum
+  current for each mode is defined in hardware using two resistors
+  RFS and RTS.
+
+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.
+
+  richtek,rfs:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 7680
+    maximum: 367000
+    description: The resistance value of the RFS resistor. This
+      resistors limits the maximum flash current. This must be set
+      for the property flash-max-microamp to work, the RFS resistor
+      defines the range of the dimmer setting (brightness) of the
+      flash LED.
+
+  richtek,rts:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 7680
+    maximum: 367000
+    description: The resistance value of the RTS resistor. This
+      resistors limits the maximum torch current. This must be set
+      for the property torch-max-microamp to work, the RTS resistor
+      defines the range of the dimmer setting (brightness) of the
+      torch LED.
+
+  led:
+    type: object
+    $ref: common.yaml#
+    properties:
+      function: true
+      color: true
+      flash-max-timeout-us: true
+
+      flash-max-microamp:
+        maximum: 700000
+        description: The maximum current for flash mode
+          is hardwired to the component using the RFS resistor to
+          ground. The maximum hardware current setting is calculated
+          according to the formula Imax = 5500 / RFS. The lowest
+          allowed resistance value is 7.86 kOhm giving an absolute
+          maximum current of 700mA. By setting this attribute in
+          the device tree, you can further restrict the maximum
+          current below the hardware limit. This requires the RFS
+          to be defined as it defines the maximum range.
+
+      torch-max-microamp:
+        maximum: 700000
+        description: The maximum current for torch mode
+          is hardwired to the component using the RTS resistor to
+          ground. The maximum hardware current setting is calculated
+          according to the formula Imax = 5500 / RTS. The lowest
+          allowed resistance value is 7.86 kOhm giving an absolute
+          maximum current of 700mA. By setting this attribute in
+          the device tree, you can further restrict the maximum
+          current below the hardware limit. This requires the RTS
+          to be defined as it defines the maximum range.
+
+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>;
+        richtek,rfs = <16000>;
+        richtek,rts = <100000>;
+
+        led {
+            function = LED_FUNCTION_FLASH;
+            color = <LED_COLOR_ID_WHITE>;
+            flash-max-timeout-us = <250000>;
+            flash-max-microamp = <150000>;
+            torch-max-microamp = <25000>;
+        };
+    };
+
+...
-- 
2.26.2


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

* [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-13 12:42 [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
@ 2020-11-13 12:42 ` Linus Walleij
  2020-11-22 11:50   ` Sakari Ailus
  2020-11-21 13:27 ` [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Rob Herring
  1 sibling, 1 reply; 7+ messages in thread
From: Linus Walleij @ 2020-11-13 12:42 UTC (permalink / raw)
  To: Jacek Anaszewski, Pavel Machek, Dan Murphy
  Cc: linux-leds, Linus Walleij, Sakari Ailus, newbytee,
	Stephan Gerhold, linux-media, phone-devel

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.

We do not have a proper datasheet for the RT8515 but
it turns out that RT9387A has a public datasheet and
is essentially the same chip. We designed the driver
in accordance with this datasheet. The day someone
needs to drive a RT9387A this driver can probably
easily be augmented to handle that chip too.

Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: newbytee@protonmail.com
Cc: Stephan Gerhold <stephan@gerhold.net>
Cc: linux-media@vger.kernel.org
Cc: phone-devel@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v4->v5:
- Fix a missing static keyword, complaint from the kernel
  autobuilder robot.
ChangeLog v3->v4:
- Create a new subdirectory for flash LEDs under
  drivers/leds/flash as requested by Pavel, move the
  driver there and set up a kbuild structure for pure
  flash LEDs.
  (Others can follow the established pattern.)
- Handle the new richtek,rfs and richtek,rts resistor
  values that make it possible to determine the current
  range configured in the hardware.
- Handle the new flash-max-microamp and torch-max-microamp
  if present and optionally further restrict the current
  range using these. Otherwise fall back on the hardware
  defaults as specified by the RFS and RTS resistors.
- Cc phone-devel@vger.kernel.org
- License as GPL-2.0-or-later
- Renable ent and enf gpio descriptors to enable_torch
  and enable_flash
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             |   3 +
 drivers/leds/Makefile            |   3 +
 drivers/leds/flash/Kconfig       |  15 ++
 drivers/leds/flash/Makefile      |   3 +
 drivers/leds/flash/leds-rt8515.c | 373 +++++++++++++++++++++++++++++++
 5 files changed, 397 insertions(+)
 create mode 100644 drivers/leds/flash/Kconfig
 create mode 100644 drivers/leds/flash/Makefile
 create mode 100644 drivers/leds/flash/leds-rt8515.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 849d3c5f908e..6c1d8b69a465 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -928,6 +928,9 @@ config LEDS_ACER_A500
 	  This option enables support for the Power Button LED of
 	  Acer Iconia Tab A500.
 
+comment "Flash and Torch LED drivers"
+source "drivers/leds/flash/Kconfig"
+
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
 
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 73e603e1727e..156c0b4e60d9 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -103,5 +103,8 @@ obj-$(CONFIG_LEDS_SPI_BYTE)		+= leds-spi-byte.o
 # LED Userspace Drivers
 obj-$(CONFIG_LEDS_USER)			+= uleds.o
 
+# Flash and Torch LED Drivers
+obj-$(CONFIG_LEDS_CLASS_FLASH)		+= flash/
+
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig
new file mode 100644
index 000000000000..d21d273ef3da
--- /dev/null
+++ b/drivers/leds/flash/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if LEDS_CLASS_FLASH
+
+config LEDS_RT8515
+	tristate "LED support for Richtek RT8515 flash/torch LED"
+	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.
+
+endif # LEDS_CLASS_FLASH
diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile
new file mode 100644
index 000000000000..e990e257f4d7
--- /dev/null
+++ b/drivers/leds/flash/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_LEDS_RT8515)	+= leds-rt8515.o
diff --git a/drivers/leds/flash/leds-rt8515.c b/drivers/leds/flash/leds-rt8515.c
new file mode 100644
index 000000000000..f092a661480d
--- /dev/null
+++ b/drivers/leds/flash/leds-rt8515.c
@@ -0,0 +1,373 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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>
+
+/* We can provide 15-700 mA out to the LED */
+#define RT8515_MIN_IOUT_MA	15
+#define RT8515_MAX_IOUT_MA	700
+/* The maximum intensity is 1-16 for flash and 1-100 for torch */
+#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 device *dev;
+	struct led_classdev_flash fled;
+	struct v4l2_flash *v4l2_flash;
+	struct mutex lock;
+	struct regulator *reg;
+	struct gpio_desc *enable_torch;
+	struct gpio_desc *enable_flash;
+	struct timer_list powerdown_timer;
+	u32 max_timeout; /* Flash max timeout */
+	int flash_max_intensity;
+	int torch_max_intensity;
+};
+
+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->enable_flash, 0);
+		gpiod_set_value(rt->enable_torch, 0);
+	} else if (brightness < RT8515_TORCH_MAX) {
+		/* Step it up to movie mode brightness using the flash pin */
+		rt8515_gpio_brightness_commit(rt->enable_torch, brightness);
+	} else {
+		/* Max torch brightness requested */
+		gpiod_set_value(rt->enable_torch, 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->enable_flash, 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->enable_flash, 0);
+		gpiod_set_value(rt->enable_torch, 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->enable_flash, 0);
+	gpiod_set_value(rt->enable_torch, 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: this is a linear scale
+	 * capped from the device tree max intensity setting
+	 * 1..flash_max_intensity
+	 */
+	s = &v4l2_sd_cfg->intensity;
+	s->min = 1;
+	s->max = rt->flash_max_intensity;
+	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 void rt8515_determine_max_intensity(struct rt8515 *rt,
+					   struct fwnode_handle *led,
+					   const char *resistance,
+					   const char *max_ua_prop, int hw_max,
+					   int *max_intensity_setting)
+{
+	u32 res;
+	u32 ua;
+	u32 max_ma;
+	int max_intensity;
+	int ret1, ret2;
+
+
+	ret1 = fwnode_property_read_u32(rt->dev->fwnode, resistance, &res);
+	ret2 = fwnode_property_read_u32(led, max_ua_prop, &ua);
+
+	/* No info in DT, OK go with hardware maxima */
+	if (ret1 && ret2) {
+		max_ma = RT8515_MAX_IOUT_MA;
+		max_intensity = hw_max;
+		goto out_assign_max;
+	}
+
+	if (ret1 || ret2) {
+		dev_err(rt->dev,
+			"either %s or %s missing from DT, using HW max\n",
+			resistance, max_ua_prop);
+		max_ma = RT8515_MAX_IOUT_MA;
+		max_intensity = hw_max;
+		goto out_assign_max;
+	}
+
+	/*
+	 * Formula from datasheet, this is the maximum current
+	 * defined by the hardware.
+	 */
+	max_ma = (5500 * 1000) / res;
+	/*
+	 * Calculate max intensity (linear scaling)
+	 * Formula is ((ua / 1000) / max_ma) * 100, then simplified
+	 */
+	max_intensity = (ua / 10) / max_ma;
+
+	dev_info(rt->dev,
+		 "current restricted from %u to %u mA, max intensity %d/100\n",
+		 max_ma, (ua / 1000), max_intensity);
+
+out_assign_max:
+	dev_info(rt->dev, "max intensity %d/%d = %d mA\n",
+		 max_intensity, hw_max, max_ma);
+	*max_intensity_setting = max_intensity;
+}
+
+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;
+
+	rt->dev = dev;
+	fled = &rt->fled;
+	led = &fled->led_cdev;
+
+	/* ENF - Enable Flash line */
+	rt->enable_flash = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW);
+	if (IS_ERR(rt->enable_flash)) {
+		dev_err(dev, "cannot get ENF (enable flash) GPIO\n");
+		return PTR_ERR(rt->enable_flash);
+	}
+
+	/* ENT - Enable Torch line */
+	rt->enable_torch = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW);
+	if (IS_ERR(rt->enable_torch)) {
+		dev_err(dev, "cannot get ENT (enable torch) GPIO\n");
+		return PTR_ERR(rt->enable_torch);
+	}
+
+	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;
+
+	rt8515_determine_max_intensity(rt, child, "richtek,rfs", "flash-max-microamp",
+				       RT8515_FLASH_MAX, &rt->flash_max_intensity);
+	rt8515_determine_max_intensity(rt, child, "richtek,rts", "torch-max-microamp",
+				       RT8515_TORCH_MAX, &rt->torch_max_intensity);
+
+	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 = rt->torch_max_intensity;
+	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] 7+ messages in thread

* Re: [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515
  2020-11-13 12:42 [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
  2020-11-13 12:42 ` [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
@ 2020-11-21 13:27 ` Rob Herring
  2020-11-21 15:25   ` Linus Walleij
  1 sibling, 1 reply; 7+ messages in thread
From: Rob Herring @ 2020-11-21 13:27 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, linux-leds,
	Sakari Ailus, newbytee, Stephan Gerhold, phone-devel,
	linux-media, devicetree

On Fri, Nov 13, 2020 at 01:42:38PM +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: phone-devel@vger.kernel.org
> Cc: linux-media@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v4->v5:
> - Fix the RFS/RTS resistors to reference the u32 schema.
> - Fix resisitor speling error.
> ChangeLog v3->v4:
> - Add DT attributes for the RFS and RTS resistors, so that
>   the hardware-defined maximum current can be determined.
> - Add torch-max-microamp to the common bindings so we can
>   set an attribute for the max microamp in torch mode.
> - Add flash-max-microamp and torch-max-microamp as optional
>   to the LED node.
> - Slot in some elabortative descriptions of the new
>   properties and describe what the hardware is doing.
> - Cc phone-devel@vger.kernel.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.
> ---
>  .../devicetree/bindings/leds/common.yaml      |   6 +
>  .../bindings/leds/richtek,rt8515.yaml         | 111 ++++++++++++++++++
>  2 files changed, 117 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> 
> diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml
> index f1211e7045f1..92fa90b4a671 100644
> --- a/Documentation/devicetree/bindings/leds/common.yaml
> +++ b/Documentation/devicetree/bindings/leds/common.yaml
> @@ -151,6 +151,12 @@ properties:
>        Maximum flash LED supply current in microamperes. Required for flash LED
>        nodes with configurable current.
>  
> +  torch-max-microamp:
> +    description:
> +      Maximum flash LED supply current in microamperes, when the flash LED is
> +      used as a torch (flashlight). This is usually lower than the flash mode
> +      maximum current, if the LED supports torch mode.
> +
>    flash-max-timeout-us:
>      description:
>        Maximum timeout in microseconds after which the flash LED is turned off.
> diff --git a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> new file mode 100644
> index 000000000000..b1f69277c5d3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
> @@ -0,0 +1,111 @@
> +# 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. The maximum
> +  current for each mode is defined in hardware using two resistors
> +  RFS and RTS.
> +
> +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.
> +
> +  richtek,rfs:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 7680
> +    maximum: 367000
> +    description: The resistance value of the RFS resistor. This

Units? Add a defined unit suffix to the property name and you can drop 
the type.

> +      resistors limits the maximum flash current. This must be set
> +      for the property flash-max-microamp to work, the RFS resistor
> +      defines the range of the dimmer setting (brightness) of the
> +      flash LED.
> +
> +  richtek,rts:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 7680
> +    maximum: 367000
> +    description: The resistance value of the RTS resistor. This
> +      resistors limits the maximum torch current. This must be set
> +      for the property torch-max-microamp to work, the RTS resistor
> +      defines the range of the dimmer setting (brightness) of the
> +      torch LED.
> +
> +  led:
> +    type: object
> +    $ref: common.yaml#
> +    properties:
> +      function: true
> +      color: true
> +      flash-max-timeout-us: true
> +
> +      flash-max-microamp:
> +        maximum: 700000
> +        description: The maximum current for flash mode
> +          is hardwired to the component using the RFS resistor to
> +          ground. The maximum hardware current setting is calculated
> +          according to the formula Imax = 5500 / RFS. The lowest
> +          allowed resistance value is 7.86 kOhm giving an absolute
> +          maximum current of 700mA. By setting this attribute in
> +          the device tree, you can further restrict the maximum
> +          current below the hardware limit. This requires the RFS
> +          to be defined as it defines the maximum range.
> +
> +      torch-max-microamp:
> +        maximum: 700000
> +        description: The maximum current for torch mode
> +          is hardwired to the component using the RTS resistor to
> +          ground. The maximum hardware current setting is calculated
> +          according to the formula Imax = 5500 / RTS. The lowest
> +          allowed resistance value is 7.86 kOhm giving an absolute
> +          maximum current of 700mA. By setting this attribute in
> +          the device tree, you can further restrict the maximum
> +          current below the hardware limit. This requires the RTS
> +          to be defined as it defines the maximum range.
> +
> +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>;
> +        richtek,rfs = <16000>;
> +        richtek,rts = <100000>;
> +
> +        led {
> +            function = LED_FUNCTION_FLASH;
> +            color = <LED_COLOR_ID_WHITE>;
> +            flash-max-timeout-us = <250000>;
> +            flash-max-microamp = <150000>;
> +            torch-max-microamp = <25000>;
> +        };
> +    };
> +
> +...
> -- 
> 2.26.2
> 

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

* Re: [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515
  2020-11-21 13:27 ` [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Rob Herring
@ 2020-11-21 15:25   ` Linus Walleij
  2020-11-23 21:23     ` Linus Walleij
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Walleij @ 2020-11-21 15:25 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	Sakari Ailus, newbytee, Stephan Gerhold, phone-devel,
	Linux Media Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Sat, Nov 21, 2020 at 2:27 PM Rob Herring <robh@kernel.org> wrote:
> On Fri, Nov 13, 2020 at 01:42:38PM +0100, Linus Walleij wrote:

> > +  richtek,rfs:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 7680
> > +    maximum: 367000
> > +    description: The resistance value of the RFS resistor. This
>
> Units? Add a defined unit suffix to the property name and you can drop
> the type.

Do you mean that if I rename this property as:

richtek,rfs-ohms

there will be some automagic machinery in dtschema that checks that
it is an uint32?

Is there a list of these magic suffixes somewhere?

Yours,
Linus Walleij

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

* Re: [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-13 12:42 ` [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
@ 2020-11-22 11:50   ` Sakari Ailus
  2020-11-23 13:49     ` Linus Walleij
  0 siblings, 1 reply; 7+ messages in thread
From: Sakari Ailus @ 2020-11-22 11:50 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, linux-leds, newbytee,
	Stephan Gerhold, linux-media, phone-devel

Hi Linus,

Thanks for the update.

On Fri, Nov 13, 2020 at 01:42:39PM +0100, Linus Walleij wrote:
...
> +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 */

Just a question on the unit --- did the other spec shed any light on what
the relation between this setting and the current might be?

But if it's not known, or even estimated, then I guess you could use these
values.

4 seems like a random number though. I'd use maximum as the default.

-- 
Sakari Ailus

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

* Re: [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver
  2020-11-22 11:50   ` Sakari Ailus
@ 2020-11-23 13:49     ` Linus Walleij
  0 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2020-11-23 13:49 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	newbytee, Stephan Gerhold, Linux Media Mailing List, phone-devel

On Sun, Nov 22, 2020 at 12:50 PM Sakari Ailus <sakari.ailus@iki.fi> wrote:

> > +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 */
>
> Just a question on the unit --- did the other spec shed any light on what
> the relation between this setting and the current might be?

They just say:
"There are a total of 16 steps of current
level which can be set by users."

They do not say whether this is linear or not. So I have
assumed linear. The above is just a bug, it should should be
the configured max or max available of course. I'll fix!

Yours,
Linus Walleij

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

* Re: [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515
  2020-11-21 15:25   ` Linus Walleij
@ 2020-11-23 21:23     ` Linus Walleij
  0 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2020-11-23 21:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Linux LED Subsystem,
	Sakari Ailus, newbytee, Stephan Gerhold, phone-devel,
	Linux Media Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS

On Sat, Nov 21, 2020 at 4:25 PM Linus Walleij <linus.walleij@linaro.org> wrote:

> > Units? Add a defined unit suffix to the property name and you can drop
> > the type.
>
> Do you mean that if I rename this property as:
>
> richtek,rfs-ohms
>
> there will be some automagic machinery in dtschema that checks that
> it is an uint32?
>
> Is there a list of these magic suffixes somewhere?

Got impatient and grepped around myself :D
So schemas/property-units.yaml and meta-schemas/vendor-props.yaml
explains a lot!

Clever, we should add these example tweaks to the example schema
as illustration of available intrinsics.

Okidoki, respinning tagging on -ohms!

Yours,
Linus Walleij

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

end of thread, other threads:[~2020-11-23 21:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-13 12:42 [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Linus Walleij
2020-11-13 12:42 ` [PATCH 2/2 v5] leds: rt8515: Add Richtek RT8515 LED driver Linus Walleij
2020-11-22 11:50   ` Sakari Ailus
2020-11-23 13:49     ` Linus Walleij
2020-11-21 13:27 ` [PATCH 1/2 v5] dt-bindings: leds: Add DT binding for Richtek RT8515 Rob Herring
2020-11-21 15:25   ` Linus Walleij
2020-11-23 21:23     ` 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.