Am Freitag, dem 24.07.2026 um 10:59 +0200 schrieb Lajosházi László Gergely:
> Hi Srinivas, all,
>
> With the help of Claude Code it has been solved, playback works in the
> headset.
> Fixable in the kernel - no TZ/PIL-internal change. The last difference
> wasn't a PHY-pad or
> xPU precondition, it's a single AP-writable bit in the ADSP CSR:
>
> QDSP6SS 0x0c20002c, bit 3 (c200000.remoteproc aperture)
> downstream PIL leaves it clear (0x103); mainline PAS leaves it set (0x10b)
>
> With bit3 set the framer never gets frame-sync (the INTF_STAT +0x604 = 0
> loop I quoted); clear it and +0x604 reads 0x3e04, NGD capability completes,
> the WCD9335 gets a logical address.
>
> Timing subtlety that hid it: right after pas_auth_and_reset the bit already
> reads clear, so clearing it there is a no-op - the ADSP re-sets it during
> its own init. The clear has to land in the NGD path just before the
> capability exchange. I do it in qcom_slim_ngd_power_up() before NGD_INT_EN,
> gated by a DT property carrying the register address.
>
> Verified on msm8953-mainline, 6.13 through 7.0.9, Fairphone 3: codec
> enumerates, ALSA card comes up, and playback now reaches the headphone/
> earpiece output (clean audio). A first-attempt capability timeout remains
> (ADSP needs ~3 s; the existing NGD retry recovers it).
>
> Two things I'd value your steer on before a series:
>
> (1) Where should the register address live - per-board DT property on the
> NGD node (what I have), a soc-data quirk keyed off compatible, or the
> remoteproc side? This should help the whole SDM632/msm8953 + WCD9335
> family.
> (2) Do you know what bit3 actually gates? A proper name/comment would turn
> it from a magic poke into a described fix - it behaves like something
> PIL ungates for the framer that PAS leaves gated.
>
> WIP branch (personal fork, not for upstream as-is): github.com/llg179/linux,
> branch fp3-709.
>
> Thanks - and to Bert Karwatzki, whose working FP3 config was my reference.
>
> Best regards,
> László
>
>
> Lajosházi László Gergely <[email protected]> ezt írta (időpont:
> 2026. júl. 20., H, 2:16):
> >
> > Hi Srinivas, all,
> >
> > On the Fairphone 3 (SDM632/msm8953, WCD9326 codec) mainline SLIMbus audio
> > is silent: the NGD reports "capability exchange timed-out STATUS=0x40c
> > CFG=0x0 INT_STAT=0x0" and the codec never gets a logical address. Same
> > hardware works on the downstream 4.9 stack (A/B slots, same phone). With
> > Claude
> > code I've localized it to one register-level difference and I'm stuck
> > on the last step.
> >
> > The only variable is the ADSP boot method: downstream subsys-pil-tz vs
> > mainline qcom_q6v5_pas. adsp.mbn and its devcfg are byte-identical; the
> > AP-side QMI sequence is byte-identical and ACKed in both cases; current
> > mainline HEAD (including the merged qcom-ngd-ctrl fix series) reproduces
> > it, cold-boot retested.
> >
> > Reading the SLIMbus block (0x0c140000) and LPASS-CC (0x0c000000) via
> > /dev/mem on both slots:
> >
> > reg (0x0c140000 +off) downstream/PIL mainline/PAS
> > FRM_CFG +0x400 0x000D0C83 0x000D0C83 identical
> > INTF_CFG +0x600 0x00000001 0x00000001 identical
> > FRM_STAT +0x404 0x060D1901 0x00000000
> > INTF_STAT +0x604 0x00003E04 0x00000000
> >
> > LPASS-CC is byte-identical over the whole aperture (SLIMbus root RCGR
> > CFG=0x509, branch CLK_OFF=0 on both -- the 24.576 MHz root clock runs on
> > the dead side too). So the framer is configured and clocked identically;
> > only the status registers read 0 under PAS: INTF_STAT bits FS/SFS/MS
> > (frame/super-frame/master sync) never set -- the interface never acquires
> > sync on the physical bus. The stock firmware's own bring-up confirms it
> > waits on hardware: it polls the FS bit, times out ("Hardware failed to
> > enumerate ... (FS:0)(SFS:0)(MS:0)"), and its subsequent HW reset succeeds,
> > so ADSP register access is fine. The firmware maps no separate PHY/analog
> > block. On msm8953 I find no AP-side lever either: no lpasscc, nothing
> > SLIMbus in gcc, no LPASS GDSC (unlike msm8996, which frames the same codec
> > family under PAS).
> >
> > Two questions:
> >
> > (1) What physical precondition (rail / reset-deassert / pad / LPASS-internal
> > enable) must hold for the SLIMbus interface to acquire frame-sync on
> > SDM632, and where does the pil-tz path establish it that q6v5_pas does not?
> >
> > (2) Is that step AP-reachable from mainline (SCM call, reset, regulator
> > vote, clock, DT), or only TZ/PIL-internal -- i.e. is this fixable with a
> > kernel patch at all, or does it need a vendor-side change?
> >
> > Full write-up, two-sided register dumps, binary diffs and the annotated
> > firmware disassembly: https://github.com/msm8953-mainline/linux/issues/255
> >
> > Thanks for any pointer,
> > László
Now I finally got to test your kernel (with arm64 debian stable/trixie as
userspace)
on my Fairphone3. I'm currently running
commit 5bc4d5ebb7c0 ("ASoC: wcd9335: drop a stray blank line this series
added") as
HEAD (with two patches I'll explain below)
1. Congratulation to you (and Claude ;-)). Call audio works great!
2. My Fairphone3 is the model with the lc898127 actuator (which by the way
needs two
regulators, otherwise i2c transaction time out) and also has the imx363 camera
on
a different i2c address. To address this issues I'm using the
following patch (this disables your camera configuratoin, to address this
issue properly one could probably use individual device trees including
a comon Fairphone3 device tree):
commit 8dc38ed9807fba7a70bd0f947b09b9bcad2a1dc7
Author: Bert Karwatzki <[email protected]>
Date: Mon Aug 31 00:35:52 2026 +0200
i2c/lc898217: fix camera address and lc898217 supplies for older Fairphone 3
This sets up the camera sensors and actuator for the older version
of the Fairphone 3. If we want to support both cameras, do we
need two (or three with the Fairphone 3+) device trees (each
device specific devicce tree including a sdm632-fairphone-common.dtsi)?
Signed-off-by: Bert Karwatzki <[email protected]>
diff --git a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
index 3abd4b0f89f0..5f682f576e83 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
@@ -223,6 +223,51 @@ &cci {
};
&cci_i2c0 {
+/* Sony IMX363 (rear) @ 0x10 This is the older(?) version
+ * paired with lens actuator LC898217XC */
+ camera@10 {
+ compatible = "sony,imx363";
+ reg = <0x10>;
+
+ /* Rear (world-facing) sensor, mounted rotated 270 degrees. */
+ orientation = <1>;
+ rotation = <270>;
+
+ reset-gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>;
+
+ clocks = <&gcc GCC_CAMSS_MCLK0_CLK>;
+ assigned-clocks = <&gcc GCC_CAMSS_MCLK0_CLK>;
+ assigned-clock-rates = <24000000>;
+ clock-frequency = <24000000>;
+
+ vana-supply = <&pm8953_l22>; /* 2.8V analog */
+ vdig-supply = <&pm8953_l2>; /* 1.2V digital core */
+ vif-supply = <&vreg_cam_io_1p8>; /* 1.8V IO */
+
+ lens-focus = <&camera_lens>;
+
+ port {
+ imx363_ep: endpoint {
+ data-lanes = <0 1 2 3>;
+ link-frequencies = /bits/ 64
+ <636000000 321000000>;
+ remote-endpoint = <&csiphy0_ep>;
+ };
+ };
+ };
+
+ camera_lens: camera-lens@72 {
+ compatible = "onnn,lc898217xc";
+ reg = <0x72>;
+
+ vaf-supply = <&vreg_cam_af_2p85>;
+ /* The vio supply is needed because when probing the
+ * actuator the camera sensor has already powered down
+ * again causing i2c transactions to time out.
+ */
+ vio-supply = <&vreg_cam_io_1p8>; /* 1.8V IO */
+ };
+#if 0
/* Sony IMX363 (rear) @ 0x1a (SLASEL strapped high on FP3) */
camera@1a {
compatible = "sony,imx363";
@@ -255,13 +300,6 @@ imx363_ep: endpoint {
};
};
- eeprom@50 {
- compatible = "belling,bl24s64", "atmel,24c64";
- reg = <0x50>;
- vcc-supply = <&vreg_cam_io_1p8>;
- read-only;
- };
-
/*
* Fairphone ships this phone with two different rear camera modules,
* and they do not carry the same focus actuator: the vendor camera
@@ -278,6 +316,13 @@ camera_lens: camera-lens@c {
vdd-supply = <&vreg_cam_af_2p85>;
vio-supply = <&vreg_cam_io_1p8>;
};
+#endif
+ eeprom@50 {
+ compatible = "belling,bl24s64", "atmel,24c64";
+ reg = <0x50>;
+ vcc-supply = <&vreg_cam_io_1p8>;
+ read-only;
+ };
};
&cci_i2c1 {
diff --git a/drivers/media/i2c/lc898217.c b/drivers/media/i2c/lc898217.c
index 650c4146c0ef..b3dea1b41355 100644
--- a/drivers/media/i2c/lc898217.c
+++ b/drivers/media/i2c/lc898217.c
@@ -49,11 +49,16 @@ static inline u16 lc898217_position_to_code(s32 position)
return LC898217_FOCUS_MAX - position;
}
+static const char * const lc898217_supply_names[] = {
+ "vaf",
+ "vio",
+};
+
struct lc898217 {
struct v4l2_ctrl_handler ctrls;
struct v4l2_subdev sd;
struct v4l2_ctrl *focus;
- struct regulator *vcc;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(lc898217_supply_names)];
};
static inline struct lc898217 *ctrl_to_lc898217(struct v4l2_ctrl *ctrl)
@@ -82,7 +87,6 @@ static int lc898217_write(struct lc898217 *lc898217, u8 reg,
u16 val, u8 size)
return ret;
if (ret != size + 1)
return -EIO;
-
return 0;
}
@@ -153,10 +157,16 @@ static int lc898217_probe(struct i2c_client *client)
if (!lc898217)
return -ENOMEM;
- lc898217->vcc = devm_regulator_get(dev, "vcc");
- if (IS_ERR(lc898217->vcc))
- return dev_err_probe(dev, PTR_ERR(lc898217->vcc),
- "failed to get the vcc regulator\n");
+ for (int i = 0; i < ARRAY_SIZE(lc898217_supply_names); i++)
+ lc898217->supplies[i].supply = lc898217_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(lc898217_supply_names),
+ lc898217->supplies);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to get regulators\n");
+ return ret;
+ }
v4l2_i2c_subdev_init(&lc898217->sd, client, &lc898217_ops);
lc898217->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -192,7 +202,8 @@ static int lc898217_runtime_suspend(struct device *dev)
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct lc898217 *lc898217 = sd_to_lc898217(sd);
- return regulator_disable(lc898217->vcc);
+ return regulator_bulk_disable(ARRAY_SIZE(lc898217_supply_names),
+ lc898217->supplies);
}
static int lc898217_runtime_resume(struct device *dev)
@@ -202,7 +213,8 @@ static int lc898217_runtime_resume(struct device *dev)
unsigned int tries;
int ret;
- ret = regulator_enable(lc898217->vcc);
+ ret = regulator_bulk_enable(ARRAY_SIZE(lc898217_supply_names),
+ lc898217->supplies);
if (ret)
return ret;
@@ -218,7 +230,7 @@ static int lc898217_runtime_resume(struct device *dev)
}
if (ret) {
dev_err(dev, "failed to enable the actuator: %d\n", ret);
- goto err_disable_vcc;
+ goto err_disable_regulators;
}
usleep_range(LC898217_ENABLE_DELAY_US, LC898217_ENABLE_DELAY_US + 500);
@@ -226,13 +238,15 @@ static int lc898217_runtime_resume(struct device *dev)
ret = lc898217_set_position(lc898217, lc898217->focus->val);
if (ret) {
dev_err(dev, "failed to set the lens position: %d\n", ret);
- goto err_disable_vcc;
+ goto err_disable_regulators;
}
+ dev_info(dev, "lc898217 regulator resumed successfully\n");
return 0;
-err_disable_vcc:
- regulator_disable(lc898217->vcc);
+err_disable_regulators:
+ regulator_bulk_disable(ARRAY_SIZE(lc898217_supply_names),
+ lc898217->supplies);
return ret;
}
3. Commit
1ac2e21fbf3a ("arm64: dts: qcom: msm8953: name the right affinity level for
system-pc")
breaks my touchscreen, after resuming from suspend i2c transcaction will time
out making
the device unusable (ssh'ing into the device works fine)
Error messages:
[ T128] Himax-hx83112b-TS 0-0048: Failed to read input event: -110
[ T128] Himax-hx83112b-TS 0-0048: Failed to read input event: -6
Reverting this commit fixes the issue.
4. Waking up from suspend by an incomming call or sms works, but there are also
a
lot of unwanted wakeup (especially with mobile data enabled). The time between
those
unwanted wakeups is a few seconds up to an hour. This was expected and can be
worked
around like this (this also declares smd edges as wakeup capable, but instead of
declaring the edge irq as a wakeup irq, the wakeup is initiated by
qcom_smd_qrtr_callback()
which checks the ports relating the call and sms services first (the portnumber
for these service come from the qrtr-lookup tool, but could also be read from a
socket with AF_QIPCRTR (this is how qrtr-lookup gets these numbers))):
https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/694#note_2648210
This is rather hacky though, I have not yet figured out how the downstream
kernel
avoid unwanted wakeups.
5. Is it possible to add an issues tab to your github repo, these issue could
be discussed?
Bert Karwatzki