Re: [PATCH v2 2/2] media: synopsys: hdmirx: add HDMI audio capture support
From: Igor Paunovic
Date: Wed Jul 15 2026 - 19:46:18 EST
> Does this code incorrectly parse the ACR N and CTS values?
No -- but the variable naming makes it look like it does, so this is
worth cleaning up. The packet decoder stores the ACR subpacket bytes
with packet byte 0 in register bits [7:0], so the byte swap is what
lines the bytes up for extraction: CTS is packet bytes 1-3 (register
PKTDEC_ACR_PB3_0) and N is packet bytes 4-6 (PKTDEC_ACR_PB7_4), and
the masks then take exactly the 20-bit fields. The two locals are
named after the wrong registers (inherited from the vendor driver),
which is confusing but has no functional effect.
The path is also validated on hardware: with a 44.1 kHz source the
card reports 44.1 kHz rather than falling back to the 48 kHz default,
and sample rate switches are followed -- neither would work if the
parsing were broken. I'll rename the locals and add a comment about
the byte packing in the next revision.
> Could this dummy callback simply be removed to allow the core to
> map the reg property to the correct DAI ID naturally?
The #sound-dai-cells path is not affected -- there the DAI index
comes from the phandle cell, so <&hdmirx 1> still reaches the S/PDIF
DAI and gets the intended -EOPNOTSUPP. But you're right that the stub
is unnecessary and would wrongly force DAI 0 for an OF-graph card, so
I'll drop it in the next revision.
Igor
On Wed, Jul 15, 2026 at 10:22 PM <sashiko-bot@xxxxxxxxxx> wrote:
>
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] Severe logical and mathematical errors in Audio Clock Regeneration (ACR) N and CTS parsing, leading to hardware clock recovery failure.
> - [High] Dummy `hdmirx_audio_get_dai_id` callback unconditionally returns 0, breaking S/PDIF DAI OF graph mapping.
> --
>
> --- Patch [2]: [PATCH v2 2/2] media: synopsys: hdmirx: add HDMI audio capture support ---
> commit c4b60dd6e2a0b110adfab2b5a2ccf3d214ed0d05
> Author: Igor Paunovic <royalnet026@xxxxxxxxx>
>
> media: synopsys: hdmirx: add HDMI audio capture support
>
> The Synopsys DesignWare HDMI RX controller extracts the audio stream
> embedded in the incoming HDMI signal and feeds it to an on-SoC I2S
> controller. Expose it as an ALSA capture device by registering the
> generic hdmi-codec as a child of the controller, so that a
> simple-audio-card in the device tree can bind the HDMI RX audio DAI.
>
> > diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c
> > index 25f8ca0d6d946..acabd43664c10 100644
> > --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c
> > +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c
>
> [ ... ]
>
> > @@ -2646,6 +2662,255 @@ static int hdmirx_register_cec(struct snps_hdmirx_dev *hdmirx_dev,
>
> [ ... ]
>
> > +/* Recover the incoming audio sample rate from the ACR N/CTS + TMDS clock. */
> > +static u32 hdmirx_audio_fs(struct snps_hdmirx_dev *hdmirx_dev)
> > +{
> > + u64 tmds_clk, fs_audio = 0;
> > + u32 acr_cts, acr_n, tmdsqpclk_freq;
> > + u32 acr_pb7_4, acr_pb3_0;
> > +
> > + tmdsqpclk_freq = hdmirx_readl(hdmirx_dev, CMU_TMDSQPCLK_FREQ);
> > + hdmirx_readl(hdmirx_dev, PKTDEC_ACR_PH2_1);
> > + acr_pb7_4 = hdmirx_readl(hdmirx_dev, PKTDEC_ACR_PB3_0);
> > + acr_pb3_0 = hdmirx_readl(hdmirx_dev, PKTDEC_ACR_PB7_4);
> > + acr_cts = be32_to_cpu((__force __be32)acr_pb7_4) & 0xfffff;
> > + acr_n = (be32_to_cpu((__force __be32)acr_pb3_0) & 0x0fffff00) >> 8;
>
> [Severity: High]
> Does this code incorrectly parse the ACR N and CTS values?
>
> The variables acr_pb7_4 and acr_pb3_0 are assigned the swapped register
> contents (PKTDEC_ACR_PB3_0 is assigned to acr_pb7_4, and vice versa).
>
> Additionally, applying be32_to_cpu() to the native-endian result of
> hdmirx_readl() will cause big-endian byte-swapping on little-endian
> architectures. Because of the swapped assignment and byte reversal, the
> bitwise shift operations extract completely incorrect bytes.
>
> Will this cause hardware clock regeneration to fail and silently fall back
> to the ALSA default sample rate (48kHz)?
>
> > + tmds_clk = tmdsqpclk_freq * 4 * 1000U;
> > + if (acr_cts != 0) {
> > + fs_audio = div_u64((tmds_clk * acr_n), acr_cts);
> > + fs_audio /= 128;
> > + fs_audio = hdmirx_audio_closest_fs(fs_audio);
> > + }
> > + return (u32)fs_audio;
> > +}
>
> [ ... ]
>
> > +static int hdmirx_audio_get_dai_id(struct snd_soc_component *component,
> > + struct device_node *endpoint,
> > + void *data)
> > +{
> > + return 0;
> > +}
>
> [Severity: High]
> Does this dummy callback break the S/PDIF DAI OF graph mapping?
>
> The driver registers two audio DAIs (0 for I2S, 1 for S/PDIF) to match the
> DT binding. However, this callback unconditionally returns 0, which overrides
> the standard DAI index parsing in the ASoC core.
>
> Consequently, any DT endpoint requesting S/PDIF (reg = <1>) will be
> incorrectly forced to map to DAI 0 (I2S). This bypasses the intended
> -EOPNOTSUPP rejection in hdmirx_audio_hw_params() and erroneously configures
> the hardware for I2S when S/PDIF was requested.
>
> Could this dummy callback simply be removed to allow the core to map the reg
> property to the correct DAI ID naturally?
>
> > +
> > +static const struct hdmi_codec_ops hdmirx_audio_codec_ops = {
> > + .hw_params = hdmirx_audio_hw_params,
> > + .audio_shutdown = hdmirx_audio_shutdown,
> > + .get_dai_id = hdmirx_audio_get_dai_id,
> > +};
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260715200834.8486-1-royalnet026@xxxxxxxxx?part=2