* [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK
@ 2026-10-15 8:58 Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
` (8 more replies)
0 siblings, 9 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
The Qualcomm SM8150 HDK can be equipped with an optional display card
having the same panel as the display card for SDM845 HDK. Reuse the
driver submitted at [1] and enable display card support on this HDK.
Unlike SDM845, this also requires a new LCDB driver, providing voltage
for the panel and several fixes in the WLED driver. The FSA4480 address
fix is independent and can be applied earlier.
[1] https://lore.kernel.org/dri-devel/20261014-sdm845-hdk-v2-0-6d0b4b42f267@oss.qualcomm.com/
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Dmitry Baryshkov (9):
backlight: qcom-wled: fix unbalanced OVP interrupt enable
backlight: qcom-wled: fix string detection brightness on WLED5
dt-bindings: regulator: add Qualcomm LCDB regulator
dt-bindings: mfd: qcom,spmi-pmic: add LCDB
regulator: add Qualcomm LCDB driver
arm64: dts: qcom: pm8150l: add LCDB regulators
arm64: dts: qcom: sm8150: add MDSS reset
arm64: dts: qcom: sm8150-hdk: fix FSA4480 address
arm64: dts: qcom: sm8150-hdk: add display card overlay
.../devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 +
.../bindings/regulator/qcom,pm8150l-lcdb.yaml | 81 ++++
arch/arm64/boot/dts/qcom/Makefile | 4 +
arch/arm64/boot/dts/qcom/pm8150l.dtsi | 18 +
.../boot/dts/qcom/sm8150-hdk-display-card.dtso | 103 +++++
arch/arm64/boot/dts/qcom/sm8150-hdk.dts | 4 +-
arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 +
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/qcom-lcdb-regulator.c | 475 +++++++++++++++++++++
drivers/video/backlight/qcom-wled.c | 31 +-
11 files changed, 723 insertions(+), 7 deletions(-)
---
base-commit: 1fffefb00cc0b0da1f2ae24e3d33364530ea6515
change-id: 20261014-sm8150-display-card-e43ee5b08c61
prerequisite-change-id: 20260122-sdm845-hdk-9466530c4267:v4
prerequisite-patch-id: cb272273cdb260eb5049ba5cfffe13e7904e7a70
prerequisite-patch-id: 118ae0e92f82e1d5be7b75cd310509388e6f5606
prerequisite-patch-id: efe1cd41bd8c1ddf7c9491a6fca5aec877afce3d
prerequisite-patch-id: 8759433719a8151e1a8399fe88036844f60f2ec8
prerequisite-patch-id: e46e47c4d158362a382efc455438ef1fd5c95f42
Best regards,
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:11 ` Konrad Dybcio
2026-10-15 9:22 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5 Dmitry Baryshkov
` (7 subsequent siblings)
8 siblings, 2 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
If the bootloader leaves the WLED module enabled, the OVP interrupt is
left enabled at probe time. The first brightness update then schedules
wled_ovp_work(), which enables the interrupt for a second time and
triggers the "Unbalanced enable for IRQ" warning.
Track whether the driver has disabled the interrupt and only enable it
back in that case.
Fixes: 8663c188beea ("backlight: qcom-wled: Add auto string detection logic")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/video/backlight/qcom-wled.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
index 650dd95f06ef..f2e0430cccbc 100644
--- a/drivers/video/backlight/qcom-wled.c
+++ b/drivers/video/backlight/qcom-wled.c
@@ -199,6 +199,7 @@ struct wled {
bool cabc_disabled;
int short_irq;
int ovp_irq;
+ bool ovp_irq_disabled;
struct wled_config cfg;
struct delayed_work ovp_work;
@@ -294,7 +295,11 @@ static void wled_ovp_work(struct work_struct *work)
{
struct wled *wled = container_of(work,
struct wled, ovp_work.work);
- enable_irq(wled->ovp_irq);
+
+ if (wled->ovp_irq_disabled) {
+ enable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = false;
+ }
}
static int wled_module_enable(struct wled *wled, int val)
@@ -321,8 +326,11 @@ static int wled_module_enable(struct wled *wled, int val)
*/
schedule_delayed_work(&wled->ovp_work, HZ / 100);
} else {
- if (!cancel_delayed_work_sync(&wled->ovp_work))
+ cancel_delayed_work_sync(&wled->ovp_work);
+ if (!wled->ovp_irq_disabled) {
disable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = true;
+ }
}
}
@@ -1649,8 +1657,10 @@ static int wled_configure_ovp_irq(struct wled *wled,
return rc;
/* Keep OVP irq disabled until module is enabled */
- if (!(val & WLED3_CTRL_REG_MOD_EN_MASK))
+ if (!(val & WLED3_CTRL_REG_MOD_EN_MASK)) {
disable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = true;
+ }
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:13 ` Konrad Dybcio
2026-10-15 9:17 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator Dmitry Baryshkov
` (6 subsequent siblings)
8 siblings, 2 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
The string detection sets the test brightness through
wled4_set_brightness(). On WLED5 that writes to unrelated registers and
the detection runs with whatever brightness has been programmed before.
Use the per-version callback and latch the new value on WLED5.
Fixes: 62a1d3f623ac ("backlight: qcom-wled: Add support for WLED5 peripheral that is present on PM8150L PMICs")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/video/backlight/qcom-wled.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
index f2e0430cccbc..6fbac6a4c29b 100644
--- a/drivers/video/backlight/qcom-wled.c
+++ b/drivers/video/backlight/qcom-wled.c
@@ -577,6 +577,17 @@ static irqreturn_t wled_short_irq_handler(int irq, void *_wled)
#define AUTO_DETECT_BRIGHTNESS 200
+static int wled_auto_detect_set_brightness(struct wled *wled, u16 brightness)
+{
+ int rc;
+
+ rc = wled->wled_set_brightness(wled, brightness);
+ if (rc < 0 || wled->version < 5)
+ return rc;
+
+ return wled5_mod_sync_toggle(wled);
+}
+
static void wled_auto_string_detection(struct wled *wled)
{
int rc = 0, i, j, delay_time_us;
@@ -603,7 +614,7 @@ static void wled_auto_string_detection(struct wled *wled)
}
/* Set low brightness across all sinks */
- rc = wled4_set_brightness(wled, AUTO_DETECT_BRIGHTNESS);
+ rc = wled_auto_detect_set_brightness(wled, AUTO_DETECT_BRIGHTNESS);
if (rc < 0) {
dev_err(wled->dev, "Failed to set brightness for auto detection rc=%d\n",
rc);
@@ -743,7 +754,7 @@ static void wled_auto_string_detection(struct wled *wled)
}
/* Restore brightness */
- rc = wled4_set_brightness(wled, wled->brightness);
+ rc = wled_auto_detect_set_brightness(wled, wled->brightness);
if (rc < 0) {
dev_err(wled->dev, "Failed to set brightness after auto detection rc=%d\n",
rc);
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5 Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:14 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 4/9] dt-bindings: mfd: qcom,spmi-pmic: add LCDB Dmitry Baryshkov
` (5 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
Several Qualcomm PMICs have an LCDB block providing the positive and
negative bias rails for LCD panels. It is not supported by Linux, so
boards using it either model the rails as dummy fixed regulators and
depend on the state left by the bootloader.
Describe the LCDB regulator present on the PM8150L. Use it as a fallback
compatible for LCDB blocks on PMI632 and PM6150L. PM660L has a different
version of LCDB block, so it's not being covered.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../bindings/regulator/qcom,pm8150l-lcdb.yaml | 81 ++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/Documentation/devicetree/bindings/regulator/qcom,pm8150l-lcdb.yaml b/Documentation/devicetree/bindings/regulator/qcom,pm8150l-lcdb.yaml
new file mode 100644
index 000000000000..eb5014f86439
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/qcom,pm8150l-lcdb.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/qcom,pm8150l-lcdb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm LCDB (LCD Bias) regulator
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+
+description:
+ LCDB is the LCD panel bias supply found on Qualcomm PMICs such as PMI632,
+ PM6150L and PM8150L. It consists of a boost converter feeding an LDO, which
+ provides the positive bias rail, and an inverting charge pump (NCP), which
+ provides the negative one. Both rails are switched together by a single
+ module enable.
+
+properties:
+ compatible:
+ oneOf:
+ - const: qcom,pm8150l-lcdb
+ - items:
+ - enum:
+ - qcom,pm6150l-lcdb
+ - qcom,pmi632-lcdb
+ - const: qcom,pm8150l-lcdb
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: short circuit on one of the outputs
+
+ ldo:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+ description: Positive bias rail.
+
+ ncp:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ Negative bias rail. The voltage is specified as an absolute value.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ lcdb@ec00 {
+ compatible = "qcom,pm8150l-lcdb";
+ reg = <0xec00>;
+ interrupts = <0x5 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
+
+ ldo {
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+
+ ncp {
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+ };
+ };
+
+...
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/9] dt-bindings: mfd: qcom,spmi-pmic: add LCDB
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (2 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 5/9] regulator: add Qualcomm LCDB driver Dmitry Baryshkov
` (4 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
Allow the LCDB regulator block as a child of the SPMI PMIC node.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index f6534e9e9912..1894fd82cbda 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -171,6 +171,10 @@ patternProperties:
type: object
$ref: /schemas/input/qcom,spmi-haptics.yaml#
+ "^lcdb@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/regulator/qcom,pm8150l-lcdb.yaml#
+
"^led-controller@[0-9a-f]+$":
type: object
$ref: /schemas/leds/qcom,spmi-flash-led.yaml#
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 5/9] regulator: add Qualcomm LCDB driver
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (3 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 4/9] dt-bindings: mfd: qcom,spmi-pmic: add LCDB Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:31 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators Dmitry Baryshkov
` (3 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
LCD panels on boards with PMI632, PM6150L or PM8150L take their bias
rails from the LCDB block. Without a driver they only work as long as
the bootloader has enabled it and nothing turns it off.
Both rails sit behind a single module enable, so the module is kept on
while at least one of them is in use. The boost output is not exposed,
it follows the higher of the two rails plus the headroom. Enabling
starts at a lower voltage and ramps up in steps, and the LDO pull-down
is forced while disabling, both as done by the vendor driver.
Touch-to-wake, current limit and soft start tuning and PM660L are not
supported.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/qcom-lcdb-regulator.c | 475 ++++++++++++++++++++++++++++++++
3 files changed, 484 insertions(+)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index be6b72daa76f..9fd3f2c7e365 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1915,4 +1915,12 @@ config REGULATOR_QCOM_LABIBB
boost regulator and IBB can be used as a negative boost regulator
for LCD display panel.
+config REGULATOR_QCOM_LCDB
+ tristate "Qualcomm LCDB regulator support"
+ depends on SPMI || COMPILE_TEST
+ help
+ This driver supports the LCDB (LCD bias) block found on Qualcomm
+ PMICs such as PMI632, PM6150L and PM8150L. It provides the positive
+ (LDO) and negative (NCP) bias rails for LCD panels.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6aabcc54382a..84164d2b6c45 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
obj-$(CONFIG_REGULATOR_NEX10000UB) += nex10000ub-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
+obj-$(CONFIG_REGULATOR_QCOM_LCDB) += qcom-lcdb-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_PM8008) += qcom-pm8008-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_REFGEN) += qcom-refgen-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
diff --git a/drivers/regulator/qcom-lcdb-regulator.c b/drivers/regulator/qcom-lcdb-regulator.c
new file mode 100644
index 000000000000..45b3b7118e31
--- /dev/null
+++ b/drivers/regulator/qcom-lcdb-regulator.c
@@ -0,0 +1,475 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/ktime.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define LCDB_INT_RT_STS 0x10
+#define LCDB_VREG_OK_RT_STS BIT(0)
+#define LCDB_SC_ERROR_RT_STS BIT(1)
+
+#define LCDB_BST_OUTPUT_VOLTAGE 0x41
+#define LCDB_BST_OUTPUT_VOLTAGE_MASK GENMASK(5, 0)
+
+#define LCDB_MODULE_RDY 0x45
+#define LCDB_MODULE_RDY_BIT BIT(7)
+
+#define LCDB_ENABLE_CTL1 0x46
+#define LCDB_MODULE_EN BIT(7)
+
+#define LCDB_LDO_OUTPUT_VOLTAGE 0x71
+#define LCDB_LDO_FORCE_PD_CTL 0x79
+#define LCDB_LDO_FORCE_PD_EN BIT(0)
+#define LCDB_LDO_FORCE_PD_MODE BIT(7)
+
+#define LCDB_NCP_OUTPUT_VOLTAGE 0x81
+
+#define LCDB_OUTPUT_VOLTAGE_MASK GENMASK(4, 0)
+
+#define LCDB_MIN_UV 4000000
+#define LCDB_STEP_100MV_UV 100000
+#define LCDB_50MV_MIN_UV 4950000
+#define LCDB_STEP_50MV_UV 50000
+#define LCDB_50MV_MIN_SEL 10
+#define LCDB_N_VOLTAGES 32
+
+#define LCDB_BST_MIN_UV 4700000
+#define LCDB_BST_MAX_UV 6275000
+#define LCDB_BST_STEP_UV 25000
+#define LCDB_BST_HEADROOM_UV 150000
+
+#define LCDB_RAMP_START_UV 4500000
+#define LCDB_RAMP_STEP_UV 500000
+
+#define LCDB_OFF_ON_DELAY_US 20000
+#define LCDB_VREG_OK_TIMEOUT_US 50000
+
+#define LCDB_SC_RESET_CNT_DLY_US 1000000
+#define LCDB_SC_CNT_MAX 10
+
+enum {
+ LCDB_LDO,
+ LCDB_NCP,
+ LCDB_NUM_RAILS,
+};
+
+struct qcom_lcdb {
+ struct device *dev;
+ struct regmap *regmap;
+ u32 base;
+
+ struct mutex lock;
+ struct regulator_dev *rdev[LCDB_NUM_RAILS];
+ int uV[LCDB_NUM_RAILS];
+ unsigned int enabled_mask;
+ ktime_t off_time;
+
+ bool sc_disabled;
+ int sc_count;
+ ktime_t sc_time;
+};
+
+static const u8 qcom_lcdb_vreg[LCDB_NUM_RAILS] = {
+ [LCDB_LDO] = LCDB_LDO_OUTPUT_VOLTAGE,
+ [LCDB_NCP] = LCDB_NCP_OUTPUT_VOLTAGE,
+};
+
+static unsigned int qcom_lcdb_uV_to_sel(int uV)
+{
+ if (uV < LCDB_50MV_MIN_UV)
+ return (uV - LCDB_MIN_UV) / LCDB_STEP_100MV_UV;
+
+ return LCDB_50MV_MIN_SEL + (uV - LCDB_50MV_MIN_UV) / LCDB_STEP_50MV_UV;
+}
+
+static int qcom_lcdb_sel_to_uV(unsigned int sel)
+{
+ if (sel < LCDB_50MV_MIN_SEL)
+ return LCDB_MIN_UV + sel * LCDB_STEP_100MV_UV;
+
+ return LCDB_50MV_MIN_UV + (sel - LCDB_50MV_MIN_SEL) * LCDB_STEP_50MV_UV;
+}
+
+static int qcom_lcdb_write_voltages(struct qcom_lcdb *lcdb, int ldo_uV, int ncp_uV)
+{
+ const int uV[LCDB_NUM_RAILS] = { ldo_uV, ncp_uV };
+ unsigned int bst_sel, cur_sel;
+ int bst_uV, ret, i;
+
+ bst_uV = clamp(max(ldo_uV, ncp_uV) + LCDB_BST_HEADROOM_UV,
+ LCDB_BST_MIN_UV, LCDB_BST_MAX_UV);
+ bst_sel = DIV_ROUND_UP(bst_uV - LCDB_BST_MIN_UV, LCDB_BST_STEP_UV);
+
+ ret = regmap_read(lcdb->regmap, lcdb->base + LCDB_BST_OUTPUT_VOLTAGE, &cur_sel);
+ if (ret)
+ return ret;
+ cur_sel &= LCDB_BST_OUTPUT_VOLTAGE_MASK;
+
+ /* The boost has to stay above both outputs while they are changing */
+ if (bst_sel > cur_sel) {
+ ret = regmap_update_bits(lcdb->regmap,
+ lcdb->base + LCDB_BST_OUTPUT_VOLTAGE,
+ LCDB_BST_OUTPUT_VOLTAGE_MASK, bst_sel);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < LCDB_NUM_RAILS; i++) {
+ ret = regmap_update_bits(lcdb->regmap,
+ lcdb->base + qcom_lcdb_vreg[i],
+ LCDB_OUTPUT_VOLTAGE_MASK,
+ qcom_lcdb_uV_to_sel(uV[i]));
+ if (ret)
+ return ret;
+ }
+
+ if (bst_sel < cur_sel)
+ ret = regmap_update_bits(lcdb->regmap,
+ lcdb->base + LCDB_BST_OUTPUT_VOLTAGE,
+ LCDB_BST_OUTPUT_VOLTAGE_MASK, bst_sel);
+
+ return ret;
+}
+
+static int qcom_lcdb_write_limited(struct qcom_lcdb *lcdb, int limit_uV)
+{
+ return qcom_lcdb_write_voltages(lcdb,
+ min(lcdb->uV[LCDB_LDO], limit_uV),
+ min(lcdb->uV[LCDB_NCP], limit_uV));
+}
+
+static int qcom_lcdb_module_disable(struct qcom_lcdb *lcdb)
+{
+ int ret;
+
+ /* Force the LDO pull-down to discharge the output quickly */
+ ret = regmap_write(lcdb->regmap, lcdb->base + LCDB_LDO_FORCE_PD_CTL,
+ LCDB_LDO_FORCE_PD_EN | LCDB_LDO_FORCE_PD_MODE);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(lcdb->regmap, lcdb->base + LCDB_ENABLE_CTL1, 0);
+ if (ret)
+ return ret;
+
+ lcdb->off_time = ktime_get();
+
+ usleep_range(10000, 11000);
+
+ return regmap_write(lcdb->regmap, lcdb->base + LCDB_LDO_FORCE_PD_CTL, 0);
+}
+
+static int qcom_lcdb_module_enable(struct qcom_lcdb *lcdb)
+{
+ int target_uV = max(lcdb->uV[LCDB_LDO], lcdb->uV[LCDB_NCP]);
+ int uV = LCDB_RAMP_START_UV;
+ unsigned int val;
+ s64 off_us;
+ int ret;
+
+ off_us = ktime_us_delta(ktime_get(), lcdb->off_time);
+ if (off_us < LCDB_OFF_ON_DELAY_US)
+ usleep_range(LCDB_OFF_ON_DELAY_US - off_us,
+ LCDB_OFF_ON_DELAY_US - off_us + 1000);
+
+ /* Start low and ramp the outputs up in steps to limit the inrush current */
+ ret = qcom_lcdb_write_limited(lcdb, uV);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(lcdb->regmap, lcdb->base + LCDB_ENABLE_CTL1,
+ LCDB_MODULE_EN);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(lcdb->regmap,
+ lcdb->base + LCDB_INT_RT_STS, val,
+ val & LCDB_VREG_OK_RT_STS,
+ 1000, LCDB_VREG_OK_TIMEOUT_US);
+ if (ret) {
+ dev_err(lcdb->dev, "outputs failed to come up: %d\n", ret);
+ goto err_disable;
+ }
+
+ usleep_range(10000, 11000);
+
+ while (uV < target_uV) {
+ uV += LCDB_RAMP_STEP_UV;
+
+ ret = qcom_lcdb_write_limited(lcdb, uV);
+ if (ret)
+ goto err_disable;
+
+ usleep_range(1000, 1100);
+ }
+
+ return 0;
+
+err_disable:
+ qcom_lcdb_module_disable(lcdb);
+
+ return ret;
+}
+
+static int qcom_lcdb_enable(struct regulator_dev *rdev)
+{
+ struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
+ int ret = 0;
+
+ guard(mutex)(&lcdb->lock);
+
+ if (lcdb->sc_disabled)
+ return -EIO;
+
+ if (!lcdb->enabled_mask)
+ ret = qcom_lcdb_module_enable(lcdb);
+ if (ret)
+ return ret;
+
+ lcdb->enabled_mask |= BIT(rdev_get_id(rdev));
+
+ return 0;
+}
+
+static int qcom_lcdb_disable(struct regulator_dev *rdev)
+{
+ struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
+
+ guard(mutex)(&lcdb->lock);
+
+ lcdb->enabled_mask &= ~BIT(rdev_get_id(rdev));
+ if (lcdb->enabled_mask)
+ return 0;
+
+ return qcom_lcdb_module_disable(lcdb);
+}
+
+static int qcom_lcdb_is_enabled(struct regulator_dev *rdev)
+{
+ struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
+
+ guard(mutex)(&lcdb->lock);
+
+ return !!(lcdb->enabled_mask & BIT(rdev_get_id(rdev)));
+}
+
+static int qcom_lcdb_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
+
+ guard(mutex)(&lcdb->lock);
+
+ lcdb->uV[rdev_get_id(rdev)] = qcom_lcdb_sel_to_uV(sel);
+
+ return qcom_lcdb_write_voltages(lcdb, lcdb->uV[LCDB_LDO],
+ lcdb->uV[LCDB_NCP]);
+}
+
+static int qcom_lcdb_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
+
+ guard(mutex)(&lcdb->lock);
+
+ return qcom_lcdb_uV_to_sel(lcdb->uV[rdev_get_id(rdev)]);
+}
+
+static const struct regulator_ops qcom_lcdb_ops = {
+ .enable = qcom_lcdb_enable,
+ .disable = qcom_lcdb_disable,
+ .is_enabled = qcom_lcdb_is_enabled,
+ .set_voltage_sel = qcom_lcdb_set_voltage_sel,
+ .get_voltage_sel = qcom_lcdb_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
+static const struct linear_range qcom_lcdb_ranges[] = {
+ REGULATOR_LINEAR_RANGE(LCDB_MIN_UV, 0, LCDB_50MV_MIN_SEL - 1,
+ LCDB_STEP_100MV_UV),
+ REGULATOR_LINEAR_RANGE(LCDB_50MV_MIN_UV, LCDB_50MV_MIN_SEL,
+ LCDB_N_VOLTAGES - 1, LCDB_STEP_50MV_UV),
+};
+
+static const struct regulator_desc qcom_lcdb_descs[LCDB_NUM_RAILS] = {
+ [LCDB_LDO] = {
+ .name = "lcdb_ldo",
+ .of_match = "ldo",
+ .id = LCDB_LDO,
+ .ops = &qcom_lcdb_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = qcom_lcdb_ranges,
+ .n_linear_ranges = ARRAY_SIZE(qcom_lcdb_ranges),
+ .n_voltages = LCDB_N_VOLTAGES,
+ .owner = THIS_MODULE,
+ },
+ [LCDB_NCP] = {
+ .name = "lcdb_ncp",
+ .of_match = "ncp",
+ .id = LCDB_NCP,
+ .ops = &qcom_lcdb_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = qcom_lcdb_ranges,
+ .n_linear_ranges = ARRAY_SIZE(qcom_lcdb_ranges),
+ .n_voltages = LCDB_N_VOLTAGES,
+ .owner = THIS_MODULE,
+ },
+};
+
+static void qcom_lcdb_handle_sc(struct qcom_lcdb *lcdb)
+{
+ int i;
+
+ guard(mutex)(&lcdb->lock);
+
+ if (!lcdb->enabled_mask || lcdb->sc_disabled)
+ return;
+
+ qcom_lcdb_module_disable(lcdb);
+
+ if (ktime_us_delta(ktime_get(), lcdb->sc_time) > LCDB_SC_RESET_CNT_DLY_US) {
+ lcdb->sc_count = 0;
+ } else if (lcdb->sc_count > LCDB_SC_CNT_MAX) {
+ dev_err(lcdb->dev, "persistent short circuit, keeping the outputs off\n");
+ lcdb->sc_disabled = true;
+
+ for (i = 0; i < LCDB_NUM_RAILS; i++)
+ regulator_notifier_call_chain(lcdb->rdev[i],
+ REGULATOR_EVENT_FAIL, NULL);
+ return;
+ }
+
+ lcdb->sc_count++;
+ lcdb->sc_time = ktime_get();
+
+ if (qcom_lcdb_module_enable(lcdb))
+ dev_err(lcdb->dev, "failed to recover from a short circuit\n");
+}
+
+static irqreturn_t qcom_lcdb_sc_irq(int irq, void *data)
+{
+ struct qcom_lcdb *lcdb = data;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(lcdb->regmap, lcdb->base + LCDB_INT_RT_STS, &val);
+ if (ret || !(val & LCDB_SC_ERROR_RT_STS))
+ return IRQ_HANDLED;
+
+ /* Blanking time, a real short circuit is still reported afterwards */
+ usleep_range(2000, 2100);
+
+ ret = regmap_read(lcdb->regmap, lcdb->base + LCDB_INT_RT_STS, &val);
+ if (ret || !(val & LCDB_SC_ERROR_RT_STS))
+ return IRQ_HANDLED;
+
+ qcom_lcdb_handle_sc(lcdb);
+
+ return IRQ_HANDLED;
+}
+
+static int qcom_lcdb_hw_init(struct qcom_lcdb *lcdb)
+{
+ unsigned int val;
+ int ret, i;
+
+ for (i = 0; i < LCDB_NUM_RAILS; i++) {
+ ret = regmap_read(lcdb->regmap, lcdb->base + qcom_lcdb_vreg[i], &val);
+ if (ret)
+ return ret;
+
+ lcdb->uV[i] = qcom_lcdb_sel_to_uV(val & LCDB_OUTPUT_VOLTAGE_MASK);
+ }
+
+ ret = regmap_read(lcdb->regmap, lcdb->base + LCDB_ENABLE_CTL1, &val);
+ if (ret)
+ return ret;
+
+ if (val & LCDB_MODULE_EN) {
+ lcdb->enabled_mask = GENMASK(LCDB_NUM_RAILS - 1, 0);
+ return 0;
+ }
+
+ return regmap_set_bits(lcdb->regmap, lcdb->base + LCDB_MODULE_RDY,
+ LCDB_MODULE_RDY_BIT);
+}
+
+static int qcom_lcdb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regulator_config cfg = {};
+ struct qcom_lcdb *lcdb;
+ int irq, ret, i;
+
+ lcdb = devm_kzalloc(dev, sizeof(*lcdb), GFP_KERNEL);
+ if (!lcdb)
+ return -ENOMEM;
+
+ lcdb->dev = dev;
+
+ lcdb->regmap = dev_get_regmap(dev->parent, NULL);
+ if (!lcdb->regmap)
+ return dev_err_probe(dev, -ENODEV, "failed to get the parent regmap\n");
+
+ ret = device_property_read_u32(dev, "reg", &lcdb->base);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get the base address\n");
+
+ ret = devm_mutex_init(dev, &lcdb->lock);
+ if (ret)
+ return ret;
+
+ ret = qcom_lcdb_hw_init(lcdb);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to read the initial state\n");
+
+ cfg.dev = dev;
+ cfg.regmap = lcdb->regmap;
+ cfg.driver_data = lcdb;
+
+ for (i = 0; i < LCDB_NUM_RAILS; i++) {
+ lcdb->rdev[i] = devm_regulator_register(dev, &qcom_lcdb_descs[i], &cfg);
+ if (IS_ERR(lcdb->rdev[i]))
+ return dev_err_probe(dev, PTR_ERR(lcdb->rdev[i]),
+ "failed to register %s\n",
+ qcom_lcdb_descs[i].name);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ return devm_request_threaded_irq(dev, irq, NULL, qcom_lcdb_sc_irq,
+ IRQF_ONESHOT, "lcdb-sc", lcdb);
+}
+
+static const struct of_device_id qcom_lcdb_match[] = {
+ { .compatible = "qcom,pm8150l-lcdb" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_lcdb_match);
+
+static struct platform_driver qcom_lcdb_driver = {
+ .driver = {
+ .name = "qcom-lcdb-regulator",
+ .of_match_table = qcom_lcdb_match,
+ },
+ .probe = qcom_lcdb_probe,
+};
+module_platform_driver(qcom_lcdb_driver);
+
+MODULE_DESCRIPTION("Qualcomm LCDB (LCD bias) regulator driver");
+MODULE_LICENSE("GPL");
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (4 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 5/9] regulator: add Qualcomm LCDB driver Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:39 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset Dmitry Baryshkov
` (2 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
Describe the LCDB block providing the LCD bias rails.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/pm8150l.dtsi | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
index 3911d6d0d2e2..f54ddb6f7946 100644
--- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -141,5 +141,23 @@ pm8150l_wled: leds@d800 {
status = "disabled";
};
+
+ pm8150l_lcdb: lcdb@ec00 {
+ compatible = "qcom,pm8150l-lcdb";
+ reg = <0xec00>;
+ interrupts = <0x5 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ pm8150l_lcdb_ldo: ldo {
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+
+ pm8150l_lcdb_ncp: ncp {
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+ };
};
};
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (5 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:15 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 9/9] arm64: dts: qcom: sm8150-hdk: add display card overlay Dmitry Baryshkov
8 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
The bootloader can leave the display running, as it does on the SM8150
HDK with the display card attached. Describe the MDSS reset so that the
driver can bring the hardware into a known state before using it.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 293fcbacff34..a2d6e6947c4c 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -3817,6 +3817,7 @@ mdss: display-subsystem@ae00000 {
iommus = <&apps_smmu 0x800 0x420>;
+ resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
status = "disabled";
#address-cells = <2>;
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (6 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
2026-10-15 9:10 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 9/9] arm64: dts: qcom: sm8150-hdk: add display card overlay Dmitry Baryshkov
8 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
The FSA4480 on the SM8150 HDK responds at 0x43 rather than 0x42. With
the wrong address the mux driver fails to probe, the Type-C controller
and the DisplayPort controller keep waiting for it and the display
subsystem never binds.
Fixes: ba712fd55c7b ("arm64: dts: qcom: sm8150-hdk: enable DisplayPort and USB-C altmode")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sm8150-hdk.dts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sm8150-hdk.dts b/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
index cdced5c848d3..8f4ea981bb89 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
@@ -434,9 +434,9 @@ &i2c4 {
status = "okay";
- typec-mux@42 {
+ typec-mux@43 {
compatible = "fcs,fsa4480";
- reg = <0x42>;
+ reg = <0x43>;
interrupts-extended = <&tlmm 152 IRQ_TYPE_LEVEL_LOW>;
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 9/9] arm64: dts: qcom: sm8150-hdk: add display card overlay
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
` (7 preceding siblings ...)
2026-10-15 8:58 ` [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address Dmitry Baryshkov
@ 2026-10-15 8:58 ` Dmitry Baryshkov
8 siblings, 0 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 8:58 UTC (permalink / raw)
To: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
The SM8150 HDK can be fitted with a display card carrying a Truly
NT36850 WQHD dual-DSI panel. It uses the PM8150L WLED for the backlight
and LCDB for the bias rails, and it is mutually exclusive with the
on-board LT9611 HDMI bridge.
Only two of the three WLED strings are connected on the card: the
backlight stays dark and the boost runs into the overvoltage limit if
only the third string is driven.
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/Makefile | 4 +
.../boot/dts/qcom/sm8150-hdk-display-card.dtso | 103 +++++++++++++++++++++
2 files changed, 107 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 85d06a950b4a..571bda210d63 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -409,6 +409,10 @@ dtb-$(CONFIG_ARCH_QCOM) += sm7325-nothing-spacewar.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7325-xiaomi-lisa.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7325-xiaomi-taoyao.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
+
+sm8150-hdk-display-card-dtbs := sm8150-hdk.dtb sm8150-hdk-display-card.dtbo
+
+dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk-display-card.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-microsoft-surface-duo.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-sony-xperia-kumano-bahamut.dtb
diff --git a/arch/arm64/boot/dts/qcom/sm8150-hdk-display-card.dtso b/arch/arm64/boot/dts/qcom/sm8150-hdk-display-card.dtso
new file mode 100644
index 000000000000..205cd6d2cd71
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8150-hdk-display-card.dtso
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+/*
+ * Display Card kit overlay.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/dts-v1/;
+/plugin/;
+
+/* Disable HDMI bridge related nodes (mutually exclusive with the display card) */
+<9611_codec {
+ status = "disabled";
+};
+
+&mdss_dsi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "truly,wqhd60-nt36850";
+ reg = <0>;
+
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
+
+ vddio-supply = <&vreg_l14a_1p8>;
+ avdd-supply = <&pm8150l_lcdb_ldo>;
+ avee-supply = <&pm8150l_lcdb_ncp>;
+
+ backlight = <&pm8150l_wled>;
+
+ pinctrl-0 = <&disp0_reset_n_active>, <&mdp_vsync>;
+ pinctrl-1 = <&disp0_reset_n_suspend>, <&mdp_vsync>;
+ pinctrl-names = "default", "sleep";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ panel0_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ panel1_in: endpoint {
+ remote-endpoint = <&mdss_dsi1_out>;
+ };
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&panel0_in>;
+};
+
+&mdss_dsi1_out {
+ remote-endpoint = <&panel1_in>;
+};
+
+&pm8150l_lcdb {
+ status = "okay";
+};
+
+&pm8150l_wled {
+ qcom,num-strings = <2>;
+
+ status = "okay";
+};
+
+&tlmm {
+ disp0_reset_n_active: disp0-reset-n-active-state {
+ pins = "gpio6";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ disp0_reset_n_suspend: disp0-reset-n-suspend-state {
+ pins = "gpio6";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdp_vsync: mdp-vsync-state {
+ pins = "gpio8";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
--
2.47.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address
2026-10-15 8:58 ` [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address Dmitry Baryshkov
@ 2026-10-15 9:10 ` Konrad Dybcio
2026-10-15 9:11 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:10 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> The FSA4480 on the SM8150 HDK responds at 0x43 rather than 0x42. With
> the wrong address the mux driver fails to probe, the Type-C controller
> and the DisplayPort controller keep waiting for it and the display
> subsystem never binds.
>
> Fixes: ba712fd55c7b ("arm64: dts: qcom: sm8150-hdk: enable DisplayPort and USB-C altmode")
> Assisted-by: LLM
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
Hm, there's an ADDR pin on the FSA. I wonder if the previous guy had
an earlier revision of the board which routed that differently or
something.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address
2026-10-15 9:10 ` Konrad Dybcio
@ 2026-10-15 9:11 ` Konrad Dybcio
0 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:11 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 11:10 AM, Konrad Dybcio wrote:
> On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
>> The FSA4480 on the SM8150 HDK responds at 0x43 rather than 0x42. With
>> the wrong address the mux driver fails to probe, the Type-C controller
>> and the DisplayPort controller keep waiting for it and the display
>> subsystem never binds.
>>
>> Fixes: ba712fd55c7b ("arm64: dts: qcom: sm8150-hdk: enable DisplayPort and USB-C altmode")
>> Assisted-by: LLM
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
>> ---
>
> Hm, there's an ADDR pin on the FSA. I wonder if the previous guy had
> an earlier revision of the board which routed that differently or
> something.
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
oh wait.. the previous guy (author of the Fixes commit is you.. :D
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
@ 2026-10-15 9:11 ` Konrad Dybcio
2026-10-15 9:44 ` Dmitry Baryshkov
2026-10-15 9:22 ` sashiko-bot
1 sibling, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:11 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> If the bootloader leaves the WLED module enabled, the OVP interrupt is
> left enabled at probe time. The first brightness update then schedules
> wled_ovp_work(), which enables the interrupt for a second time and
> triggers the "Unbalanced enable for IRQ" warning.
>
> Track whether the driver has disabled the interrupt and only enable it
> back in that case.
>
> Fixes: 8663c188beea ("backlight: qcom-wled: Add auto string detection logic")
> Assisted-by: LLM
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
This was merged yesterday:
https://lore.kernel.org/lkml/20260921-qcom-wled-backlight-v4-0-bab8c7ef73cb@ixit.cz/
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5
2026-10-15 8:58 ` [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5 Dmitry Baryshkov
@ 2026-10-15 9:13 ` Konrad Dybcio
2026-10-15 9:17 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:13 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> The string detection sets the test brightness through
> wled4_set_brightness(). On WLED5 that writes to unrelated registers and
> the detection runs with whatever brightness has been programmed before.
>
> Use the per-version callback and latch the new value on WLED5.
>
> Fixes: 62a1d3f623ac ("backlight: qcom-wled: Add support for WLED5 peripheral that is present on PM8150L PMICs")
> Assisted-by: LLM
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator
2026-10-15 8:58 ` [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator Dmitry Baryshkov
@ 2026-10-15 9:14 ` Konrad Dybcio
0 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:14 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> Several Qualcomm PMICs have an LCDB block providing the positive and
> negative bias rails for LCD panels. It is not supported by Linux, so
> boards using it either model the rails as dummy fixed regulators and
> depend on the state left by the bootloader.
>
> Describe the LCDB regulator present on the PM8150L. Use it as a fallback
> compatible for LCDB blocks on PMI632 and PM6150L. PM660L has a different
> version of LCDB block, so it's not being covered.
>
> Assisted-by: LLM
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
[...]
> + lcdb@ec00 {
> + compatible = "qcom,pm8150l-lcdb";
> + reg = <0xec00>;
> + interrupts = <0x5 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
> +
> + ldo {
> + regulator-min-microvolt = <4000000>;
> + regulator-max-microvolt = <6000000>;
> + };
> +
> + ncp {
> + regulator-min-microvolt = <4000000>;
> + regulator-max-microvolt = <6000000>;
> + };
Let's tighten up the example to some specific voltage to reduce
room for poor copypastas
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset
2026-10-15 8:58 ` [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset Dmitry Baryshkov
@ 2026-10-15 9:15 ` Konrad Dybcio
0 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2026-10-15 9:15 UTC (permalink / raw)
To: Dmitry Baryshkov, Lee Jones, Daniel Thompson, Jingoo Han,
Helge Deller, Kiran Gunda, Subbaraman Narayanamurthy,
Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Bjorn Andersson, Konrad Dybcio,
Abel Vesa, Dmitry Baryshkov
Cc: linux-arm-msm, dri-devel, linux-fbdev, linux-kernel, devicetree,
mfd
On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> The bootloader can leave the display running, as it does on the SM8150
> HDK with the display card attached. Describe the MDSS reset so that the
> driver can bring the hardware into a known state before using it.
>
> Assisted-by: LLM
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> index 293fcbacff34..a2d6e6947c4c 100644
> --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> @@ -3817,6 +3817,7 @@ mdss: display-subsystem@ae00000 {
>
> iommus = <&apps_smmu 0x800 0x420>;
>
> + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
please put it under clocks like in other DTs
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5
2026-10-15 8:58 ` [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5 Dmitry Baryshkov
2026-10-15 9:13 ` Konrad Dybcio
@ 2026-10-15 9:17 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-10-15 9:17 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel, devicetree, mfd, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] qcom-wled: missing brightness sync toggle for WLED4
--
commit 80c30ca9ff45480f825b4f3ca26c694d9fa71acf
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
backlight: qcom-wled: fix string detection brightness on WLED5
This patch updates the auto string detection logic to properly latch new
brightness values for WLED5. It introduces a helper function to set the
brightness and apply the version-specific sync toggle.
> diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
> index f2e0430cccbca..6fbac6a4c29b8 100644
> --- a/drivers/video/backlight/qcom-wled.c
> +++ b/drivers/video/backlight/qcom-wled.c
> @@ -577,6 +577,17 @@ static irqreturn_t wled_short_irq_handler(int irq, void *_wled)
>
> #define AUTO_DETECT_BRIGHTNESS 200
>
> +static int wled_auto_detect_set_brightness(struct wled *wled, u16 brightness)
> +{
> + int rc;
> +
> + rc = wled->wled_set_brightness(wled, brightness);
> + if (rc < 0 || wled->version < 5)
> + return rc;
[Severity: Medium]
Does this code introduce a regression for WLED4 devices by missing the
brightness sync toggle?
During WLED4 auto string detection, the code updates the brightness to a low
test value, but it appears to return without latching it. Looking at the
standard brightness update path in wled_update_status(), WLED4 hardware
requires a sync toggle to apply brightness changes:
drivers/video/backlight/qcom-wled.c:wled_update_status() {
...
if (wled->version < 5) {
rc = wled->wled_sync_toggle(wled);
...
}
Without syncing the auto-detect test brightness, WLED4 might run the
detection with stale, potentially high brightness. Could this trigger false
over-voltage (OVP) faults and incorrectly mark valid LED strings as
disconnected?
> +
> + return wled5_mod_sync_toggle(wled);
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-sm8150-display-card-v1-0-5c14928cef29@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
2026-10-15 9:11 ` Konrad Dybcio
@ 2026-10-15 9:22 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-10-15 9:22 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel, devicetree, mfd, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] backlight: ABBA deadlock between wled->lock and ovp_irq handler
- [High] backlight: missing cancel_delayed_work_sync in wled_probe() error path
--
commit f07dcfad88603020539ad65ef60f36337093bf41
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
backlight: qcom-wled: fix unbalanced OVP interrupt enable
If the bootloader leaves the WLED module enabled, the OVP interrupt is
left enabled at probe time. The first brightness update then schedules
wled_ovp_work(), which enables the interrupt for a second time and
triggers the "Unbalanced enable for IRQ" warning.
Track whether the driver has disabled the interrupt and only enable it
back in that case.
Fixes: 8663c188beea ("backlight: qcom-wled: Add auto string detection logic")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
> index 650dd95f06ef5..f2e0430cccbca 100644
> --- a/drivers/video/backlight/qcom-wled.c
> +++ b/drivers/video/backlight/qcom-wled.c
[ ... ]
> @@ -321,8 +326,11 @@ static int wled_module_enable(struct wled *wled, int val)
> */
> schedule_delayed_work(&wled->ovp_work, HZ / 100);
[Severity: High]
Could this delayed work execution lead to a use-after-free if probe fails?
In wled_probe(), INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work) initializes
the delayed work without registering a devm action for cancellation.
wled_probe() then requests the short IRQ, making it active.
If a short IRQ triggers during probe, its handler calls wled_module_enable()
which reaches here and globally schedules ovp_work.
If wled_probe() subsequently returns an error (e.g., if
devm_backlight_device_register() fails), devres automatically frees the wled
structure without cancelling the scheduled work. When ovp_work executes, won't
it dereference the freed wled structure?
> } else {
> - if (!cancel_delayed_work_sync(&wled->ovp_work))
> + cancel_delayed_work_sync(&wled->ovp_work);
> + if (!wled->ovp_irq_disabled) {
> disable_irq(wled->ovp_irq);
[Severity: High]
Does this code introduce an ABBA deadlock with the OVP IRQ handler?
If wled_update_status() or wled_short_irq_handler() disables the module, it
holds wled->lock and calls wled_module_enable(wled, false), which reaches here
and blocks in disable_irq() waiting for any currently executing OVP IRQ handler
to complete.
Meanwhile, the threaded OVP IRQ handler tries to acquire wled->lock to perform
auto string detection:
drivers/video/backlight/qcom-wled.c:wled_ovp_irq_handler() {
...
if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) {
if (wled->wled_auto_detection_required(wled)) {
mutex_lock(&wled->lock);
wled_auto_string_detection(wled);
mutex_unlock(&wled->lock);
}
}
...
}
If the OVP IRQ fires concurrently, will disable_irq() wait forever while the
handler waits for wled->lock?
> + wled->ovp_irq_disabled = true;
> + }
> }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-sm8150-display-card-v1-0-5c14928cef29@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/9] regulator: add Qualcomm LCDB driver
2026-10-15 8:58 ` [PATCH 5/9] regulator: add Qualcomm LCDB driver Dmitry Baryshkov
@ 2026-10-15 9:31 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-10-15 9:31 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel, devicetree, mfd, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] regulator: qcom-lcdb: LDO pull-down left forced on after disable error
- [High] regulator: qcom-lcdb: self-deadlock in short-circuit notifier chain
- [High] regulator: qcom-lcdb: state desync on SC recovery failure
- [Medium] regulator: qcom-lcdb: internal state corrupted on hardware write failure
--
commit 5e78a1b6d6d6c5c217f997a1d7627dc506e8ba37
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
regulator: add Qualcomm LCDB driver
Adds a driver for the LCDB block found on Qualcomm PMICs (PMI632, PM6150L,
PM8150L) to provide positive and negative bias rails for LCD panels. The
driver supports enabling with voltage ramp-up and disabling with an LDO
pull-down.
> diff --git a/drivers/regulator/qcom-lcdb-regulator.c b/drivers/regulator/qcom-lcdb-regulator.c
> new file mode 100644
> index 0000000000000..45b3b7118e31d
> --- /dev/null
> +++ b/drivers/regulator/qcom-lcdb-regulator.c
[ ... ]
> +static int qcom_lcdb_module_disable(struct qcom_lcdb *lcdb)
> +{
> + int ret;
> +
> + /* Force the LDO pull-down to discharge the output quickly */
> + ret = regmap_write(lcdb->regmap, lcdb->base + LCDB_LDO_FORCE_PD_CTL,
> + LCDB_LDO_FORCE_PD_EN | LCDB_LDO_FORCE_PD_MODE);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(lcdb->regmap, lcdb->base + LCDB_ENABLE_CTL1, 0);
> + if (ret)
> + return ret;
[Severity: High]
If the regmap_write() to LCDB_ENABLE_CTL1 fails, the function returns
early without reverting the prior LCDB_LDO_FORCE_PD_CTL write. Will this
leave the physical regulator shorted to ground with the strong pull-down
resistor active while the LDO remains enabled?
> +
> + lcdb->off_time = ktime_get();
> +
> + usleep_range(10000, 11000);
> +
> + return regmap_write(lcdb->regmap, lcdb->base + LCDB_LDO_FORCE_PD_CTL, 0);
> +}
[ ... ]
> +static int qcom_lcdb_disable(struct regulator_dev *rdev)
> +{
> + struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
> +
> + guard(mutex)(&lcdb->lock);
> +
> + lcdb->enabled_mask &= ~BIT(rdev_get_id(rdev));
> + if (lcdb->enabled_mask)
> + return 0;
> +
> + return qcom_lcdb_module_disable(lcdb);
> +}
[Severity: Medium]
Does clearing lcdb->enabled_mask before qcom_lcdb_module_disable() completes
permanently desynchronize the software state if the hardware disablement
fails?
If the write fails, the mask will remain cleared, causing qcom_lcdb_is_enabled()
to return false even though the hardware is still active. This misalignment
might cause the next enable call to incorrectly execute the ramp-up sequence
on an already active rail.
[ ... ]
> +static int qcom_lcdb_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
> +{
> + struct qcom_lcdb *lcdb = rdev_get_drvdata(rdev);
> +
> + guard(mutex)(&lcdb->lock);
> +
> + lcdb->uV[rdev_get_id(rdev)] = qcom_lcdb_sel_to_uV(sel);
> +
> + return qcom_lcdb_write_voltages(lcdb, lcdb->uV[LCDB_LDO],
> + lcdb->uV[LCDB_NCP]);
> +}
[Severity: Medium]
If qcom_lcdb_write_voltages() fails, the cached lcdb->uV array will already
have been updated. Will this cause subsequent calls to qcom_lcdb_get_voltage_sel()
to return the new but unapplied voltage instead of the actual hardware
state?
[ ... ]
> +static void qcom_lcdb_handle_sc(struct qcom_lcdb *lcdb)
> +{
> + int i;
> +
> + guard(mutex)(&lcdb->lock);
> +
> + if (!lcdb->enabled_mask || lcdb->sc_disabled)
> + return;
> +
> + qcom_lcdb_module_disable(lcdb);
> +
> + if (ktime_us_delta(ktime_get(), lcdb->sc_time) > LCDB_SC_RESET_CNT_DLY_US) {
> + lcdb->sc_count = 0;
> + } else if (lcdb->sc_count > LCDB_SC_CNT_MAX) {
> + dev_err(lcdb->dev, "persistent short circuit, keeping the outputs off\n");
> + lcdb->sc_disabled = true;
> +
> + for (i = 0; i < LCDB_NUM_RAILS; i++)
> + regulator_notifier_call_chain(lcdb->rdev[i],
> + REGULATOR_EVENT_FAIL, NULL);
> + return;
> + }
[Severity: High]
Can calling the synchronous notifier chain with lcdb->lock held result in a
self-deadlock?
Consumers often react to REGULATOR_EVENT_FAIL by attempting to disable the
failing regulator via regulator_disable(). This acquires rdev->mutex and
then invokes the driver's disable callback:
regulator_disable()
qcom_lcdb_disable()
guard(mutex)(&lcdb->lock);
Since lcdb->lock is already held by qcom_lcdb_handle_sc(), wouldn't this
result in a self-deadlock?
> +
> + lcdb->sc_count++;
> + lcdb->sc_time = ktime_get();
> +
> + if (qcom_lcdb_module_enable(lcdb))
> + dev_err(lcdb->dev, "failed to recover from a short circuit\n");
> +}
[Severity: High]
If qcom_lcdb_module_enable() fails here, it returns an error and the
hardware is left off, but lcdb->enabled_mask is not cleared and
lcdb->sc_disabled is not set.
Does this create a state mismatch where future consumers might call
qcom_lcdb_enable() and falsely see a success without any actual physical
hardware enablement?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-sm8150-display-card-v1-0-5c14928cef29@oss.qualcomm.com?part=5
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators
2026-10-15 8:58 ` [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators Dmitry Baryshkov
@ 2026-10-15 9:39 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-10-15 9:39 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel, devicetree, mfd, robh, conor+dt, lee
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] regulator: qcom-lcdb: deadlock in qcom_lcdb_handle_sc() during notifier call
- [Medium] regulator: qcom-lcdb: hardware state desync on write failure in set_voltage_sel()
- [Medium] regulator: qcom-lcdb: state desync breaking subsequent enables after short-circuit
--
commit 4cf3328d99c41fa55695e4085137c0f502bbc641
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
arm64: dts: qcom: pm8150l: add LCDB regulators
This commit describes the LCDB block for the LCD bias rails in the pm8150l
device tree, enabling the qcom-lcdb-regulator driver on this hardware.
> diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
> index 3911d6d0d2e28..f54ddb6f7946f 100644
> --- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
> +++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
> @@ -141,5 +141,23 @@ pm8150l_wled: leds@d800 {
>
> status = "disabled";
> };
> +
> + pm8150l_lcdb: lcdb@ec00 {
> + compatible = "qcom,pm8150l-lcdb";
[Severity: High]
Can this result in a deadlock during a failure notifier call?
When the LCD bias short-circuits, qcom_lcdb_handle_sc() takes lcdb->lock
and makes a blocking notifier call:
drivers/regulator/qcom-lcdb-regulator.c:qcom_lcdb_handle_sc() {
...
guard(mutex)(&lcdb->lock);
...
for (i = 0; i < LCDB_NUM_RAILS; i++)
regulator_notifier_call_chain(lcdb->rdev[i],
REGULATOR_EVENT_FAIL, NULL);
...
}
Consumers commonly react to REGULATOR_EVENT_FAIL by invoking
regulator_disable(), which invokes qcom_lcdb_disable(). That also attempts
to acquire lcdb->lock:
drivers/regulator/qcom-lcdb-regulator.c:qcom_lcdb_disable() {
...
guard(mutex)(&lcdb->lock);
...
}
Will this cause a self-deadlock since the lock is already held by the notifier
caller?
[Severity: Medium]
Can a hardware update failure result in a desync between the driver's cached
voltage state and the actual hardware state?
When changing the voltage, the internal state lcdb->uV is eagerly updated
before writing to the hardware:
drivers/regulator/qcom-lcdb-regulator.c:qcom_lcdb_set_voltage_sel() {
...
lcdb->uV[rdev_get_id(rdev)] = qcom_lcdb_sel_to_uV(sel);
return qcom_lcdb_write_voltages(lcdb, lcdb->uV[LCDB_LDO],
lcdb->uV[LCDB_NCP]);
}
If qcom_lcdb_write_voltages() fails and returns an error, the cached state in
lcdb->uV isn't rolled back.
Since future operations rely on both cached voltages to compute the boost
voltage (bst_uV), could an unapplied lower voltage cache cause the driver to
calculate a boost voltage lower than physically required, leading to a
regulator collapse?
[Severity: Medium]
Does this code silently break subsequent regulator enables after a short circuit
recovery fails?
In qcom_lcdb_handle_sc(), the hardware is forced off by
qcom_lcdb_module_disable(), and then it attempts to recover:
drivers/regulator/qcom-lcdb-regulator.c:qcom_lcdb_handle_sc() {
...
if (qcom_lcdb_module_enable(lcdb))
dev_err(lcdb->dev, "failed to recover from a short circuit\n");
}
If qcom_lcdb_module_enable(lcdb) fails, it emits an error message and returns,
but leaves lcdb->enabled_mask untouched and non-zero.
If a consumer later tries to re-enable the regulator:
drivers/regulator/qcom-lcdb-regulator.c:qcom_lcdb_enable() {
...
if (lcdb->enabled_mask)
return 0;
lcdb->enabled_mask |= BIT(rdev_get_id(rdev));
return qcom_lcdb_module_enable(lcdb);
}
Since lcdb->enabled_mask is still non-zero, will qcom_lcdb_enable() silently
return success without actually enabling the hardware?
> + reg = <0xec00>;
> + interrupts = <0x5 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
> +
> + status = "disabled";
> +
> + pm8150l_lcdb_ldo: ldo {
> + regulator-min-microvolt = <4000000>;
> + regulator-max-microvolt = <6000000>;
> + };
> +
> + pm8150l_lcdb_ncp: ncp {
> + regulator-min-microvolt = <4000000>;
> + regulator-max-microvolt = <6000000>;
> + };
> + };
> };
> };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-sm8150-display-card-v1-0-5c14928cef29@oss.qualcomm.com?part=6
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable
2026-10-15 9:11 ` Konrad Dybcio
@ 2026-10-15 9:44 ` Dmitry Baryshkov
0 siblings, 0 replies; 21+ messages in thread
From: Dmitry Baryshkov @ 2026-10-15 9:44 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Lee Jones, Daniel Thompson, Jingoo Han, Helge Deller, Kiran Gunda,
Subbaraman Narayanamurthy, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, Abel Vesa, Dmitry Baryshkov, linux-arm-msm,
dri-devel, linux-fbdev, linux-kernel, devicetree, mfd
On Thu, Oct 15, 2026 at 11:11:58AM +0200, Konrad Dybcio wrote:
> On 10/15/26 10:58 AM, Dmitry Baryshkov wrote:
> > If the bootloader leaves the WLED module enabled, the OVP interrupt is
> > left enabled at probe time. The first brightness update then schedules
> > wled_ovp_work(), which enables the interrupt for a second time and
> > triggers the "Unbalanced enable for IRQ" warning.
> >
> > Track whether the driver has disabled the interrupt and only enable it
> > back in that case.
> >
> > Fixes: 8663c188beea ("backlight: qcom-wled: Add auto string detection logic")
> > Assisted-by: LLM
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> > ---
>
> This was merged yesterday:
>
> https://lore.kernel.org/lkml/20260921-qcom-wled-backlight-v4-0-bab8c7ef73cb@ixit.cz/
Nice!
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-10-15 9:45 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 8:58 [PATCH 0/9] arm64: qcom: enable display card support on SM8150 HDK Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 1/9] backlight: qcom-wled: fix unbalanced OVP interrupt enable Dmitry Baryshkov
2026-10-15 9:11 ` Konrad Dybcio
2026-10-15 9:44 ` Dmitry Baryshkov
2026-10-15 9:22 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 2/9] backlight: qcom-wled: fix string detection brightness on WLED5 Dmitry Baryshkov
2026-10-15 9:13 ` Konrad Dybcio
2026-10-15 9:17 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 3/9] dt-bindings: regulator: add Qualcomm LCDB regulator Dmitry Baryshkov
2026-10-15 9:14 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 4/9] dt-bindings: mfd: qcom,spmi-pmic: add LCDB Dmitry Baryshkov
2026-10-15 8:58 ` [PATCH 5/9] regulator: add Qualcomm LCDB driver Dmitry Baryshkov
2026-10-15 9:31 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 6/9] arm64: dts: qcom: pm8150l: add LCDB regulators Dmitry Baryshkov
2026-10-15 9:39 ` sashiko-bot
2026-10-15 8:58 ` [PATCH 7/9] arm64: dts: qcom: sm8150: add MDSS reset Dmitry Baryshkov
2026-10-15 9:15 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 8/9] arm64: dts: qcom: sm8150-hdk: fix FSA4480 address Dmitry Baryshkov
2026-10-15 9:10 ` Konrad Dybcio
2026-10-15 9:11 ` Konrad Dybcio
2026-10-15 8:58 ` [PATCH 9/9] arm64: dts: qcom: sm8150-hdk: add display card overlay Dmitry Baryshkov
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.