* [PATCH v3 0/5] media: lm3560: convert to use OF bindings
@ 2026-04-24 7:22 Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 1/5] dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver Svyatoslav Ryhel
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
Add missing HWEN input pin and IN supply. Fix v4l2 subdev registration.
Remove platform data and switch to OF device tree bindings.
---
Changes in v3:
- added note regarding lm3559 in the schema commit
- lm3560 power on/off functions converted to be part of PM,
dropped redundant wrappers
Changes in v2:
- vendor properties swapped with generic LED properties
- added mutex lock usage optimization
- power supply and enable gpio commits squashed into PM
configuration since they are both required in making
proper on/off sequence.
---
Svyatoslav Ryhel (5):
dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver
media: i2c: lm3560: Fix v4l2 subdev registration
media: i2c: lm3560: Optimize mutex lock usage
media: i2c: lm3560: Convert to use OF bindings
media: i2c: lm3560: Add support for PM features
.../devicetree/bindings/leds/ti,lm3560.yaml | 131 +++++++++
drivers/media/i2c/lm3560.c | 250 ++++++++++++++----
include/media/i2c/lm3560.h | 15 --
3 files changed, 328 insertions(+), 68 deletions(-)
create mode 100644 Documentation/devicetree/bindings/leds/ti,lm3560.yaml
--
2.51.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/5] dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
@ 2026-04-24 7:22 ` Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 2/5] media: i2c: lm3560: Fix v4l2 subdev registration Svyatoslav Ryhel
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
Document TI LM3560 Synchronous Boost Flash Driver used for camera flash
LEDs.
The TI LM3559 documented in this schema requires a separate compatible, as
it utilizes a different programming model — specifically regarding the
handling of voltage ranges.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
.../devicetree/bindings/leds/ti,lm3560.yaml | 131 ++++++++++++++++++
1 file changed, 131 insertions(+)
create mode 100644 Documentation/devicetree/bindings/leds/ti,lm3560.yaml
diff --git a/Documentation/devicetree/bindings/leds/ti,lm3560.yaml b/Documentation/devicetree/bindings/leds/ti,lm3560.yaml
new file mode 100644
index 000000000000..c6c553ad23f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/ti,lm3560.yaml
@@ -0,0 +1,131 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/ti,lm3560.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI LM3560 Synchronous Boost Flash Driver
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+
+description:
+ The LM3560 is a 2-MHz fixed frequency synchronous boost converter with two
+ 1000-mA constant current drivers for high-current white LEDs. The dual high-
+ side current sources allow for grounded cathode LED operation and can be
+ tied together for providing flash currents at up to 2 A through a single LED.
+ An adaptive regulation method ensures the current for each LED remains in
+ regulation and maximizes efficiency.
+
+allOf:
+ - $ref: /schemas/leds/common.yaml
+
+properties:
+ compatible:
+ enum:
+ - ti,lm3559
+ - ti,lm3560
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ enable-gpios:
+ description: GPIO connected to the HWEN pin.
+ maxItems: 1
+
+ vin-supply:
+ description: Supply connected to the IN line.
+
+ flash-max-timeout-us:
+ minimum: 32000
+ maximum: 1024000
+ default: 32000
+
+ ti,peak-current-microamp:
+ description:
+ The LM3560 features 4 selectable current limits 1.6A, 2.3A, 3A, and 3.6A.
+ When the current limit is reached, the LM3560 stops switching for the
+ remainder of the switching cycle.
+ enum: [16000000, 23000000, 30000000, 36000000]
+ default: 16000000
+
+patternProperties:
+ '^led@[01]$':
+ description: LED control bank nodes.
+ $ref: /schemas/leds/common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description: Control bank selection (0 = bank A, 1 = bank B).
+ maximum: 1
+
+ flash-max-microamp:
+ minimum: 62500
+ maximum: 1000000
+
+ led-max-microamp:
+ minimum: 31250
+ maximum: 250000
+
+ required:
+ - reg
+ - flash-max-microamp
+ - led-max-microamp
+
+required:
+ - compatible
+ - reg
+ - '#address-cells'
+ - '#size-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led-controller@53 {
+ compatible = "ti,lm3560";
+ reg = <0x53>;
+
+ enable-gpios = <&gpio 28 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vdd_3v3_sys>;
+
+ flash-max-timeout-us = <1024000>;
+ ti,peak-current-microamp = <16000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+
+ label = "white::flash";
+ linux,default-trigger = "flash";
+
+ flash-max-microamp = <562500>;
+ led-max-microamp = <156250>;
+ };
+
+ led@1 {
+ reg = <1>;
+
+ label = "yellow::flash";
+ linux,default-trigger = "flash";
+
+ flash-max-microamp = <562500>;
+ led-max-microamp = <156250>;
+ };
+ };
+ };
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/5] media: i2c: lm3560: Fix v4l2 subdev registration
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 1/5] dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver Svyatoslav Ryhel
@ 2026-04-24 7:22 ` Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 3/5] media: i2c: lm3560: Optimize mutex lock usage Svyatoslav Ryhel
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
The existing driver does not call media subdev registration, making it
invisible to the media framework. Since the LM3560 supports two
independent LEDs, register each LED as a separate media entity.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/media/i2c/lm3560.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index f4cc844f4e3c..085a0ef70e39 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -364,8 +364,15 @@ static int lm3560_subdev_init(struct lm3560_flash *flash,
goto err_out;
flash->subdev_led[led_no].entity.function = MEDIA_ENT_F_FLASH;
- return rval;
+ rval = v4l2_async_register_subdev(&flash->subdev_led[led_no]);
+ if (rval < 0) {
+ dev_err(flash->dev, "failed to register V4L2 subdev");
+ goto error_out_media;
+ }
+ return rval;
+error_out_media:
+ media_entity_cleanup(&flash->subdev_led[led_no].entity);
err_out:
v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]);
return rval;
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/5] media: i2c: lm3560: Optimize mutex lock usage
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 1/5] dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 2/5] media: i2c: lm3560: Fix v4l2 subdev registration Svyatoslav Ryhel
@ 2026-04-24 7:22 ` Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 4/5] media: i2c: lm3560: Convert to use OF bindings Svyatoslav Ryhel
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
Pass the device's own mutex lock to the control handler so that the media
framework can handle control access instead of managing it manually. The
lock must be common to both sub-devices, so the individual sub-device
locks will not work here.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/media/i2c/lm3560.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 085a0ef70e39..5cd22c2fbb64 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -162,14 +162,12 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
int rval = -EINVAL;
- mutex_lock(&flash->lock);
-
if (ctrl->id == V4L2_CID_FLASH_FAULT) {
s32 fault = 0;
unsigned int reg_val;
rval = regmap_read(flash->regmap, REG_FLAG, ®_val);
if (rval < 0)
- goto out;
+ return rval;
if (reg_val & FAULT_SHORT_CIRCUIT)
fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
if (reg_val & FAULT_OVERTEMP)
@@ -179,8 +177,6 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
ctrl->cur.val = fault;
}
-out:
- mutex_unlock(&flash->lock);
return rval;
}
@@ -190,8 +186,6 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
u8 tout_bits;
int rval = -EINVAL;
- mutex_lock(&flash->lock);
-
switch (ctrl->id) {
case V4L2_CID_FLASH_LED_MODE:
flash->led_mode = ctrl->val;
@@ -202,14 +196,12 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
case V4L2_CID_FLASH_STROBE_SOURCE:
rval = regmap_update_bits(flash->regmap,
REG_CONFIG1, 0x04, (ctrl->val) << 2);
- if (rval < 0)
- goto err_out;
break;
case V4L2_CID_FLASH_STROBE:
if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
rval = -EBUSY;
- goto err_out;
+ break;
}
flash->led_mode = V4L2_FLASH_LED_MODE_FLASH;
rval = lm3560_mode_ctrl(flash);
@@ -218,7 +210,7 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
case V4L2_CID_FLASH_STROBE_STOP:
if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
rval = -EBUSY;
- goto err_out;
+ break;
}
flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
rval = lm3560_mode_ctrl(flash);
@@ -239,8 +231,6 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
break;
}
-err_out:
- mutex_unlock(&flash->lock);
return rval;
}
@@ -332,6 +322,8 @@ static int lm3560_init_controls(struct lm3560_flash *flash,
return hdl->error;
flash->subdev_led[led_no].ctrl_handler = hdl;
+ flash->subdev_led[led_no].ctrl_handler->lock = &flash->lock;
+
return 0;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/5] media: i2c: lm3560: Convert to use OF bindings
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
` (2 preceding siblings ...)
2026-04-24 7:22 ` [PATCH v3 3/5] media: i2c: lm3560: Optimize mutex lock usage Svyatoslav Ryhel
@ 2026-04-24 7:22 ` Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 5/5] media: i2c: lm3560: Add support for PM features Svyatoslav Ryhel
2026-04-24 16:14 ` [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
5 siblings, 0 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
Since there are no users of this driver via platform data, remove platform
data and switch to using device tree bindings.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/media/i2c/lm3560.c | 112 ++++++++++++++++++++++++++-----------
include/media/i2c/lm3560.h | 15 -----
2 files changed, 79 insertions(+), 48 deletions(-)
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 5cd22c2fbb64..022a6a76befb 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -13,7 +13,9 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/videodev2.h>
#include <media/i2c/lm3560.h>
@@ -43,22 +45,30 @@ enum led_enable {
* struct lm3560_flash
*
* @dev: pointer to &struct device
- * @pdata: platform data
* @regmap: reg. map for i2c
* @lock: muxtex for serial access.
* @led_mode: V4L2 LED mode
* @ctrls_led: V4L2 controls
* @subdev_led: V4L2 subdev
+ * @peak: peak current
+ * @max_flash_timeout: flash timeout
+ * @max_flash_brt: flash mode led brightness
+ * @max_torch_brt: torch mode led brightness
*/
struct lm3560_flash {
struct device *dev;
- struct lm3560_platform_data *pdata;
struct regmap *regmap;
struct mutex lock;
enum v4l2_flash_led_mode led_mode;
struct v4l2_ctrl_handler ctrls_led[LM3560_LED_MAX];
struct v4l2_subdev subdev_led[LM3560_LED_MAX];
+
+ enum lm3560_peak_current peak;
+ u32 max_flash_timeout;
+
+ u32 max_flash_brt[LM3560_LED_MAX];
+ u32 max_torch_brt[LM3560_LED_MAX];
};
#define to_lm3560_flash(_ctrl, _no) \
@@ -269,8 +279,8 @@ static int lm3560_init_controls(struct lm3560_flash *flash,
enum lm3560_led_id led_no)
{
struct v4l2_ctrl *fault;
- u32 max_flash_brt = flash->pdata->max_flash_brt[led_no];
- u32 max_torch_brt = flash->pdata->max_torch_brt[led_no];
+ u32 max_flash_brt = flash->max_flash_brt[led_no];
+ u32 max_torch_brt = flash->max_torch_brt[led_no];
struct v4l2_ctrl_handler *hdl = &flash->ctrls_led[led_no];
const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no];
@@ -295,9 +305,9 @@ static int lm3560_init_controls(struct lm3560_flash *flash,
/* flash strobe timeout */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
LM3560_FLASH_TOUT_MIN,
- flash->pdata->max_flash_timeout,
+ flash->max_flash_timeout,
LM3560_FLASH_TOUT_STEP,
- flash->pdata->max_flash_timeout);
+ flash->max_flash_timeout);
/* flash brt */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
@@ -339,15 +349,18 @@ static const struct regmap_config lm3560_regmap = {
};
static int lm3560_subdev_init(struct lm3560_flash *flash,
- enum lm3560_led_id led_no, char *led_name)
+ enum lm3560_led_id led_no,
+ struct fwnode_handle *fwnode)
{
struct i2c_client *client = to_i2c_client(flash->dev);
int rval;
v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops);
flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- strscpy(flash->subdev_led[led_no].name, led_name,
- sizeof(flash->subdev_led[led_no].name));
+ snprintf(flash->subdev_led[led_no].name,
+ sizeof(flash->subdev_led[led_no].name),
+ "lm3560-led%d", led_no);
+ flash->subdev_led[led_no].fwnode = fwnode;
rval = lm3560_init_controls(flash, led_no);
if (rval)
goto err_out;
@@ -377,7 +390,7 @@ static int lm3560_init_device(struct lm3560_flash *flash)
/* set peak current */
rval = regmap_update_bits(flash->regmap,
- REG_FLASH_TOUT, 0x60, flash->pdata->peak);
+ REG_FLASH_TOUT, 0x60, flash->peak);
if (rval < 0)
return rval;
/* output disable */
@@ -393,8 +406,9 @@ static int lm3560_init_device(struct lm3560_flash *flash)
static int lm3560_probe(struct i2c_client *client)
{
struct lm3560_flash *flash;
- struct lm3560_platform_data *pdata = dev_get_platdata(&client->dev);
- int rval;
+ struct fwnode_handle *node;
+ u32 peak_ua;
+ int rval, reg;
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL)
@@ -406,36 +420,60 @@ static int lm3560_probe(struct i2c_client *client)
return rval;
}
- /* if there is no platform data, use chip default value */
- if (pdata == NULL) {
- pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (pdata == NULL)
- return -ENODEV;
- pdata->peak = LM3560_PEAK_3600mA;
- pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
- /* led 1 */
- pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX;
- pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX;
- /* led 2 */
- pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX;
- pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX;
- }
- flash->pdata = pdata;
flash->dev = &client->dev;
mutex_init(&flash->lock);
- rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
- if (rval < 0)
- return rval;
+ flash->peak = LM3560_PEAK_1600mA;
+ rval = device_property_read_u32(flash->dev,
+ "ti,peak-current-microamp", &peak_ua);
+ if (!rval) {
+ switch (peak_ua) {
+ case 16000000:
+ flash->peak = LM3560_PEAK_1600mA;
+ break;
+ case 23000000:
+ flash->peak = LM3560_PEAK_2300mA;
+ break;
+ case 30000000:
+ flash->peak = LM3560_PEAK_3000mA;
+ break;
+ case 36000000:
+ flash->peak = LM3560_PEAK_3600mA;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
- rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
- if (rval < 0)
- return rval;
+ flash->max_flash_timeout = LM3560_FLASH_TOUT_MIN * 1000;
+ device_property_read_u32(flash->dev, "flash-max-timeout-us",
+ &flash->max_flash_timeout);
+ flash->max_flash_timeout /= 1000;
rval = lm3560_init_device(flash);
if (rval < 0)
return rval;
+ device_for_each_child_node(flash->dev, node) {
+ fwnode_property_read_u32(node, "reg", ®);
+
+ if (reg == LM3560_LED0 || reg == LM3560_LED1) {
+ flash->max_flash_brt[reg] = LM3560_FLASH_BRT_MIN;
+ fwnode_property_read_u32(node, "flash-max-microamp",
+ &flash->max_flash_brt[reg]);
+
+ flash->max_torch_brt[reg] = LM3560_TORCH_BRT_MIN;
+ fwnode_property_read_u32(node, "led-max-microamp",
+ &flash->max_torch_brt[reg]);
+
+ rval = lm3560_subdev_init(flash, reg, node);
+ if (rval < 0)
+ return dev_err_probe(flash->dev, rval,
+ "failed to register led%d\n",
+ reg);
+ }
+ }
+
i2c_set_clientdata(client, flash);
return 0;
@@ -453,6 +491,13 @@ static void lm3560_remove(struct i2c_client *client)
}
}
+static const struct of_device_id lm3560_of_match[] = {
+ { .compatible = "ti,lm3559" },
+ { .compatible = "ti,lm3560" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lm3560_of_match);
+
static const struct i2c_device_id lm3560_id_table[] = {
{ LM3559_NAME },
{ LM3560_NAME },
@@ -465,6 +510,7 @@ static struct i2c_driver lm3560_i2c_driver = {
.driver = {
.name = LM3560_NAME,
.pm = NULL,
+ .of_match_table = lm3560_of_match,
},
.probe = lm3560_probe,
.remove = lm3560_remove,
diff --git a/include/media/i2c/lm3560.h b/include/media/i2c/lm3560.h
index 770d8c72c94a..b56c1ff8fd49 100644
--- a/include/media/i2c/lm3560.h
+++ b/include/media/i2c/lm3560.h
@@ -66,19 +66,4 @@ enum lm3560_peak_current {
LM3560_PEAK_3600mA = 0x60
};
-/* struct lm3560_platform_data
- *
- * @peak : peak current
- * @max_flash_timeout: flash timeout
- * @max_flash_brt: flash mode led brightness
- * @max_torch_brt: torch mode led brightness
- */
-struct lm3560_platform_data {
- enum lm3560_peak_current peak;
-
- u32 max_flash_timeout;
- u32 max_flash_brt[LM3560_LED_MAX];
- u32 max_torch_brt[LM3560_LED_MAX];
-};
-
#endif /* __LM3560_H__ */
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 5/5] media: i2c: lm3560: Add support for PM features
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
` (3 preceding siblings ...)
2026-04-24 7:22 ` [PATCH v3 4/5] media: i2c: lm3560: Convert to use OF bindings Svyatoslav Ryhel
@ 2026-04-24 7:22 ` Svyatoslav Ryhel
2026-04-24 16:14 ` [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
5 siblings, 0 replies; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 7:22 UTC (permalink / raw)
To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus, Mauro Carvalho Chehab,
Svyatoslav Ryhel
Cc: linux-leds, devicetree, linux-kernel, linux-media
Add support for power management features to better control the LM3560
within the media framework. To achieve the desired PM support, the HWEN
GPIO and VIN power supply were added and configured into power on/off
sequences. Media device deregistration helpers were grouped into a
separate function to simplify the probe/remove process. Added PM
operations along with the PM configuration setup.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/media/i2c/lm3560.c | 123 +++++++++++++++++++++++++++++++++----
1 file changed, 111 insertions(+), 12 deletions(-)
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 022a6a76befb..ebb30d45fdfe 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -11,12 +11,15 @@
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/videodev2.h>
#include <media/i2c/lm3560.h>
#include <media/v4l2-ctrls.h>
@@ -47,6 +50,8 @@ enum led_enable {
* @dev: pointer to &struct device
* @regmap: reg. map for i2c
* @lock: muxtex for serial access.
+ * @hwen_gpio: line connected to HWEN pin
+ * @vin_supply: line connected to IN supply (2.5V - 5.5V)
* @led_mode: V4L2 LED mode
* @ctrls_led: V4L2 controls
* @subdev_led: V4L2 subdev
@@ -60,6 +65,9 @@ struct lm3560_flash {
struct regmap *regmap;
struct mutex lock;
+ struct gpio_desc *hwen_gpio;
+ struct regulator *vin_supply;
+
enum v4l2_flash_led_mode led_mode;
struct v4l2_ctrl_handler ctrls_led[LM3560_LED_MAX];
struct v4l2_subdev subdev_led[LM3560_LED_MAX];
@@ -172,12 +180,17 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
int rval = -EINVAL;
+ if (!pm_runtime_get_if_in_use(flash->dev))
+ return 0;
+
if (ctrl->id == V4L2_CID_FLASH_FAULT) {
s32 fault = 0;
unsigned int reg_val;
rval = regmap_read(flash->regmap, REG_FLAG, ®_val);
- if (rval < 0)
+ if (rval < 0) {
+ pm_runtime_put(flash->dev);
return rval;
+ }
if (reg_val & FAULT_SHORT_CIRCUIT)
fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
if (reg_val & FAULT_OVERTEMP)
@@ -187,6 +200,8 @@ static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
ctrl->cur.val = fault;
}
+ pm_runtime_put(flash->dev);
+
return rval;
}
@@ -196,6 +211,9 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
u8 tout_bits;
int rval = -EINVAL;
+ if (!pm_runtime_get_if_in_use(flash->dev))
+ return 0;
+
switch (ctrl->id) {
case V4L2_CID_FLASH_LED_MODE:
flash->led_mode = ctrl->val;
@@ -241,6 +259,8 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
break;
}
+ pm_runtime_put(flash->dev);
+
return rval;
}
@@ -403,6 +423,49 @@ static int lm3560_init_device(struct lm3560_flash *flash)
return rval;
}
+static int lm3560_power_off(struct device *dev)
+{
+ struct lm3560_flash *flash = dev_get_drvdata(dev);
+
+ gpiod_set_value_cansleep(flash->hwen_gpio, 0);
+ regulator_disable(flash->vin_supply);
+
+ return 0;
+}
+
+static int lm3560_power_on(struct device *dev)
+{
+ struct lm3560_flash *flash = dev_get_drvdata(dev);
+ int rval;
+
+ rval = regulator_enable(flash->vin_supply);
+ if (rval < 0) {
+ dev_err(flash->dev, "failed to enable vin power supply\n");
+ return rval;
+ }
+
+ gpiod_set_value_cansleep(flash->hwen_gpio, 1);
+
+ rval = lm3560_init_device(flash);
+ if (rval < 0) {
+ lm3560_power_off(dev);
+ return rval;
+ }
+
+ return 0;
+}
+
+static void lm3560_subdev_cleanup(struct lm3560_flash *flash)
+{
+ unsigned int i;
+
+ for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) {
+ v4l2_device_unregister_subdev(&flash->subdev_led[i]);
+ v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
+ media_entity_cleanup(&flash->subdev_led[i].entity);
+ }
+}
+
static int lm3560_probe(struct i2c_client *client)
{
struct lm3560_flash *flash;
@@ -423,6 +486,17 @@ static int lm3560_probe(struct i2c_client *client)
flash->dev = &client->dev;
mutex_init(&flash->lock);
+ flash->hwen_gpio = devm_gpiod_get_optional(&client->dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(flash->hwen_gpio))
+ return dev_err_probe(&client->dev, PTR_ERR(flash->hwen_gpio),
+ "failed to get hwen gpio\n");
+
+ flash->vin_supply = devm_regulator_get(&client->dev, "vin");
+ if (IS_ERR(flash->vin_supply))
+ return dev_err_probe(&client->dev, PTR_ERR(flash->vin_supply),
+ "failed to get vin-supply\n");
+
flash->peak = LM3560_PEAK_1600mA;
rval = device_property_read_u32(flash->dev,
"ti,peak-current-microamp", &peak_ua);
@@ -450,10 +524,13 @@ static int lm3560_probe(struct i2c_client *client)
&flash->max_flash_timeout);
flash->max_flash_timeout /= 1000;
- rval = lm3560_init_device(flash);
+ rval = lm3560_power_on(flash->dev);
if (rval < 0)
return rval;
+ pm_runtime_set_active(flash->dev);
+ pm_runtime_enable(flash->dev);
+
device_for_each_child_node(flash->dev, node) {
fwnode_property_read_u32(node, "reg", ®);
@@ -467,30 +544,52 @@ static int lm3560_probe(struct i2c_client *client)
&flash->max_torch_brt[reg]);
rval = lm3560_subdev_init(flash, reg, node);
- if (rval < 0)
- return dev_err_probe(flash->dev, rval,
- "failed to register led%d\n",
- reg);
+ if (rval < 0) {
+ dev_err(flash->dev,
+ "failed to register led%d\n", reg);
+ goto error_clean;
+ }
}
}
i2c_set_clientdata(client, flash);
+ pm_runtime_set_autosuspend_delay(flash->dev, 1000);
+ pm_runtime_use_autosuspend(flash->dev);
+ pm_runtime_idle(flash->dev);
+
return 0;
+
+error_clean:
+ pm_runtime_disable(flash->dev);
+ pm_runtime_set_suspended(flash->dev);
+ lm3560_subdev_cleanup(flash);
+ lm3560_power_off(flash->dev);
+
+ return rval;
}
static void lm3560_remove(struct i2c_client *client)
{
struct lm3560_flash *flash = i2c_get_clientdata(client);
- unsigned int i;
- for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) {
- v4l2_device_unregister_subdev(&flash->subdev_led[i]);
- v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
- media_entity_cleanup(&flash->subdev_led[i].entity);
+ lm3560_subdev_cleanup(flash);
+
+ /*
+ * Disable runtime PM. In case runtime PM is disabled in the kernel,
+ * make sure to turn power off manually.
+ */
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev)) {
+ lm3560_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
}
}
+static const struct dev_pm_ops lm3560_pm_ops = {
+ SET_RUNTIME_PM_OPS(lm3560_power_off, lm3560_power_on, NULL)
+};
+
static const struct of_device_id lm3560_of_match[] = {
{ .compatible = "ti,lm3559" },
{ .compatible = "ti,lm3560" },
@@ -509,7 +608,7 @@ MODULE_DEVICE_TABLE(i2c, lm3560_id_table);
static struct i2c_driver lm3560_i2c_driver = {
.driver = {
.name = LM3560_NAME,
- .pm = NULL,
+ .pm = &lm3560_pm_ops,
.of_match_table = lm3560_of_match,
},
.probe = lm3560_probe,
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/5] media: lm3560: convert to use OF bindings
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
` (4 preceding siblings ...)
2026-04-24 7:22 ` [PATCH v3 5/5] media: i2c: lm3560: Add support for PM features Svyatoslav Ryhel
@ 2026-04-24 16:14 ` Svyatoslav Ryhel
2026-04-27 6:35 ` Sakari Ailus
5 siblings, 1 reply; 8+ messages in thread
From: Svyatoslav Ryhel @ 2026-04-24 16:14 UTC (permalink / raw)
To: Sakari Ailus
Cc: Rob Herring, Lee Jones, Krzysztof Kozlowski, Conor Dooley,
Svyatoslav Ryhel, Mauro Carvalho Chehab, linux-leds, devicetree,
linux-kernel, linux-media
пт, 24 квіт. 2026 р. о 10:22 Svyatoslav Ryhel <clamor95@gmail.com> пише:
>
> Add missing HWEN input pin and IN supply. Fix v4l2 subdev registration.
> Remove platform data and switch to OF device tree bindings.
>
> ---
> Changes in v3:
> - added note regarding lm3559 in the schema commit
> - lm3560 power on/off functions converted to be part of PM,
> dropped redundant wrappers
>
> Changes in v2:
> - vendor properties swapped with generic LED properties
> - added mutex lock usage optimization
> - power supply and enable gpio commits squashed into PM
> configuration since they are both required in making
> proper on/off sequence.
> ---
>
> Svyatoslav Ryhel (5):
> dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver
> media: i2c: lm3560: Fix v4l2 subdev registration
> media: i2c: lm3560: Optimize mutex lock usage
> media: i2c: lm3560: Convert to use OF bindings
> media: i2c: lm3560: Add support for PM features
>
> .../devicetree/bindings/leds/ti,lm3560.yaml | 131 +++++++++
> drivers/media/i2c/lm3560.c | 250 ++++++++++++++----
> include/media/i2c/lm3560.h | 15 --
> 3 files changed, 328 insertions(+), 68 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/leds/ti,lm3560.yaml
>
> --
> 2.51.0
>
Hello Sakari! May you please not yet pick this patchset if you had
such intention. It has a few slight flaws I would like to address in
v4 next week. Thank you.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/5] media: lm3560: convert to use OF bindings
2026-04-24 16:14 ` [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
@ 2026-04-27 6:35 ` Sakari Ailus
0 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2026-04-27 6:35 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Rob Herring, Lee Jones, Krzysztof Kozlowski, Conor Dooley,
Mauro Carvalho Chehab, linux-leds, devicetree, linux-kernel,
linux-media
On Fri, Apr 24, 2026 at 07:14:06PM +0300, Svyatoslav Ryhel wrote:
> Hello Sakari! May you please not yet pick this patchset if you had
> such intention. It has a few slight flaws I would like to address in
> v4 next week. Thank you.
Ack, thanks for the info!
--
Sakari Ailus
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-04-27 6:35 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-24 7:22 [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 1/5] dt-bindings: leds: Document TI LM3560 Synchronous Boost Flash Driver Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 2/5] media: i2c: lm3560: Fix v4l2 subdev registration Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 3/5] media: i2c: lm3560: Optimize mutex lock usage Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 4/5] media: i2c: lm3560: Convert to use OF bindings Svyatoslav Ryhel
2026-04-24 7:22 ` [PATCH v3 5/5] media: i2c: lm3560: Add support for PM features Svyatoslav Ryhel
2026-04-24 16:14 ` [PATCH v3 0/5] media: lm3560: convert to use OF bindings Svyatoslav Ryhel
2026-04-27 6:35 ` Sakari Ailus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox