Re: [BUG] hda/conexant: SN6140 (0x14f11f87) loses widget state across suspend ― silent capture + dead speaker, no resume callback
Takashi Iwai <[email protected]>
| Newsgroups | org.alsa-project.alsa-devel |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 05 Aug 2026 11:29:35 +0200,
Attila Hudecz wrote:
>
>
> Follow-up with three weeks of monitoring data (a watchdog samples the ALSA
> PCM state every 5s and snapshots context on each failure), plus a specific
> question for Bo Liu about the codec's internal power behaviour.
>
> == New findings since the original report ==
>
> 1. The failures are NOT limited to suspend/resume. Of ~30 logged events,
> roughly half occurred with no suspend at all typically on the first
> capture after 1-3 h of capture-idle, and occasionally mid-stream (hw_ptr
> advancing, then frozen). A resume-only fix therefore would not cover all
> cases.
>
> 2. In the failed state the widgets read "Power: setting=D3, actual=D3"
> i.e. the codec's power-state register itself holds D3 as the *set* value
> while on the software side nobody requested it:
> - snd_hda_intel power_save=0 power_save_controller=N (verified live),
> - kernel log completely silent at the moment of failure,
> - PCI device and codec stay in D0 / runtime-active,
> - userspace (PipeWire/WirePlumber) ruled out.
> Codec re-init via /sys/.../reconfig always restores the silent variant;
> the spurious-response/single_cmd variant needs a controller reset (reboot).
>
> 3. Event frequency wanders (0-6/day) and has worsened over the three weeks,
> independent of kernel (6.17.0-122035 6.17.0-124040), PipeWire and other
> userspace changes so a platform/firmware factor may be involved. An
> EC/BIOS update recommended by the vendor (TUXEDO) is pending on our side;
> I will report its effect on the thread.
>
> == Question for Bo Liu ==
>
> Does the SN61xx family implement an internal / autonomous power-down (or
> power-state controller) that is meant to be configured or disabled through
> vendor init verbs? The observed behaviour widgets ending up with
> setting=D3 with no driver activity, recoverable only by re-running codec
> init looks like un-configured codec-internal power logic rather than
> driver-initiated PM.
>
> Your SN6186 work adds senary_init_verb() and an init-verb/fixup framework.
> Does the SN6140 need an equivalent vendor init-verb table, and could you
> share the appropriate verbs/coefficients? (conexant.c already writes one
> vendor coefficient for this family the 0x320/0x010 micbias comparator
> setting on nid 0x1c so I assume more such coefs exist.)
>
> == Candidate patch, and offer to test ==
>
> I drafted a minimal resume callback for conexant.c mirroring the pending
> senarytech one (below). It builds and loads fine on 6.17, but per finding
> (1) it cannot address the no-suspend cases, so I have reverted it pending
> your guidance on the init-verb question. I have a ready build/test pipeline
> for this machine and can turn any test patch around within a day.
>
> --- a/sound/hda/codecs/conexant.c
> +++ b/sound/hda/codecs/conexant.c
> @@ -1269,6 +1269,21 @@
> return err;
> }
>
> +/*
> + * The generic HDA resume path restores the register cache but does not
> re-run
> + * the codec's init sequence, so vendor-specific hardware state (widget
> power,
> + * converter/pin setup) can be lost after S3 resume, leaving capture and the
> + * internal speaker silent with the codec stuck in D3. Mirror the senarytech
> + * fix: on resume, re-sync the register cache, re-run init, and resync jacks.
> + */
> +static int cx_resume(struct hda_codec *codec)
> +{
> + regcache_sync(codec->core.regmap);
> + cx_init(codec);
> + snd_hda_jack_report_sync(codec);
> + return 0;
> +}
> +
> static const struct hda_codec_ops cx_codec_ops = {
> .probe = cx_probe,
> .remove = cx_remove,
> @@ -1277,6 +1292,7 @@
> .init = cx_init,
> .unsol_event = snd_hda_jack_unsol_event,
> .suspend = cx_suspend,
> + .resume = cx_resume,
> .check_power_status = snd_hda_gen_check_power_status,
> .stream_pm = snd_hda_gen_stream_pm,
> };
This patch shouldn't improve things, I suppose. Basically it's as
same as the behavior without NULL resume callback; see
hda_codec_runtime_resume() in sound/hda/common/codec.c.
Takashi