* [RFC PATCH 0/2] media: synopsys: hdmirx: add HDMI audio capture support @ 2026-07-15 5:19 Igor Paunovic 2026-07-15 5:19 ` [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells Igor Paunovic 2026-07-15 5:19 ` [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 0 siblings, 2 replies; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 5:19 UTC (permalink / raw) To: Dmitry Osipenko, Mauro Carvalho Chehab Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-media, kernel, devicetree, linux-kernel, Igor Paunovic This series adds audio capture support to the Synopsys DesignWare HDMI RX driver, which currently handles video only. The controller already extracts the audio stream embedded in the incoming HDMI signal and can feed it to an on-SoC I2S interface. Patch 1 documents #sound-dai-cells in the binding. Patch 2 registers the generic hdmi-codec as a child device of the controller so that a simple-audio-card in the device tree can bind the HDMI RX audio DAI. The audio sample rate is recovered from the ACR N/CTS values together with the measured TMDS character rate, and a periodic worker keeps the local audio reference clock locked to the source by nudging it in small ppm steps to hold the audio FIFO fill level near its target, avoiding FIFO under/overflow and dropped samples. Tested on an Orange Pi 5 Plus (RK3588, i2s7_8ch as the capture DAI) with several HDMI sources: stable capture at 44.1 kHz and 48 kHz, sample rate switching, long recordings with no drift-related drops, and live A/V monitoring alongside the existing video capture. Sent as RFC to ask whether this is the preferred shape for the RX driver: the hdmi-codec child + DT sound card plumbing follows the pattern used on the TX side by dw-hdmi. The board-side DT changes (enabling the I2S interface and adding the sound card) are not part of this series and would go through the SoC tree separately. Igor Paunovic (2): dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells media: synopsys: hdmirx: add HDMI audio capture support .../bindings/media/snps,dw-hdmi-rx.yaml | 7 + .../platform/synopsys/hdmirx/snps_hdmirx.c | 244 ++++++++++++++++++ .../platform/synopsys/hdmirx/snps_hdmirx.h | 8 + 3 files changed, 259 insertions(+) -- 2.53.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 5:19 [RFC PATCH 0/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic @ 2026-07-15 5:19 ` Igor Paunovic 2026-07-15 5:54 ` sashiko-bot 2026-07-15 5:19 ` [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 1 sibling, 1 reply; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 5:19 UTC (permalink / raw) To: Dmitry Osipenko, Mauro Carvalho Chehab Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-media, kernel, devicetree, linux-kernel, Igor Paunovic The HDMI RX controller can expose the audio embedded in the incoming HDMI stream as an ALSA capture device. Document the #sound-dai-cells property so that a sound card can reference the HDMI RX audio DAI. Signed-off-by: Igor Paunovic <royalnet026@gmail.com> --- .../devicetree/bindings/media/snps,dw-hdmi-rx.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml index b7f6c87..83c10d9 100644 --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml @@ -78,6 +78,13 @@ properties: The phandle of the syscon node for the Video Output GRF register to enable EDID transfer through SDAIN and SCLIN. + "#sound-dai-cells": + const: 1 + description: + The HDMI RX controller registers a generic HDMI audio codec so the + audio embedded in the incoming stream can be captured. A value of 1 + lets a sound card reference the audio DAI as <&hdmirx 0>. + required: - compatible - reg -- 2.53.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 5:19 ` [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells Igor Paunovic @ 2026-07-15 5:54 ` sashiko-bot 2026-07-15 6:55 ` Royal Net 0 siblings, 1 reply; 14+ messages in thread From: sashiko-bot @ 2026-07-15 5:54 UTC (permalink / raw) To: Igor Paunovic; +Cc: conor+dt, devicetree, robh Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] Incorrect cell count constraint for single-DAI provider. -- --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 Author: Igor Paunovic <royalnet026@gmail.com> dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells This commit adds the #sound-dai-cells property to the HDMI RX controller bindings, enabling a generic audio codec to capture incoming embedded audio. > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > index b7f6c87d0e06a..83c10d9997c8e 100644 > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > @@ -78,6 +78,13 @@ properties: > The phandle of the syscon node for the Video Output GRF register > to enable EDID transfer through SDAIN and SCLIN. > > + "#sound-dai-cells": > + const: 1 > + description: > + The HDMI RX controller registers a generic HDMI audio codec so the > + audio embedded in the incoming stream can be captured. A value of 1 > + lets a sound card reference the audio DAI as <&hdmirx 0>. [Severity: Medium] Is this cell count constraint correct for a single-DAI provider? Looking at properties:#sound-dai-cells, the hardware exposes only a single generic audio DAI. Requiring a cell count of 1 forces device tree nodes to use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a single resource. Should the constraint be set to 0 to follow standard device tree norms? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 5:54 ` sashiko-bot @ 2026-07-15 6:55 ` Royal Net 2026-07-15 12:59 ` Sebastian Reichel 0 siblings, 1 reply; 14+ messages in thread From: Royal Net @ 2026-07-15 6:55 UTC (permalink / raw) To: sashiko-reviews Cc: conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel > Should the constraint be set to 0 to follow standard device tree > norms? Fair point. The current RFC wires up a single I2S DAI, and for a single-DAI provider 0 is indeed the norm -- rockchip,dw-hdmi does exactly that for its one DAI on the TX side. The reason I picked 1 is that the controller also has an S/PDIF audio output path (the vendor driver exposes both I2S and S/PDIF DAIs through hdmi-codec), so a DAI index becomes meaningful if that second path is wired up later. Unless the DT maintainers prefer keeping 1 from the start to avoid changing the cell count if/when the S/PDIF DAI is added, I'll switch to const: 0 in the next revision -- please let me know which you'd prefer. Igor On Wed, Jul 15, 2026 at 7:54 AM <sashiko-bot@kernel.org> wrote: > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > - [Medium] Incorrect cell count constraint for single-DAI provider. > -- > > --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- > commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 > Author: Igor Paunovic <royalnet026@gmail.com> > dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells > > This commit adds the #sound-dai-cells property to the HDMI RX controller > bindings, enabling a generic audio codec to capture incoming embedded audio. > > > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > index b7f6c87d0e06a..83c10d9997c8e 100644 > > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > @@ -78,6 +78,13 @@ properties: > > The phandle of the syscon node for the Video Output GRF register > > to enable EDID transfer through SDAIN and SCLIN. > > > > + "#sound-dai-cells": > > + const: 1 > > + description: > > + The HDMI RX controller registers a generic HDMI audio codec so the > > + audio embedded in the incoming stream can be captured. A value of 1 > > + lets a sound card reference the audio DAI as <&hdmirx 0>. > > [Severity: Medium] > Is this cell count constraint correct for a single-DAI provider? > > Looking at properties:#sound-dai-cells, the hardware exposes only a single > generic audio DAI. Requiring a cell count of 1 forces device tree nodes to > use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a > single resource. > > Should the constraint be set to 0 to follow standard device tree norms? > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 6:55 ` Royal Net @ 2026-07-15 12:59 ` Sebastian Reichel 2026-07-15 13:19 ` Igor Paunovic 0 siblings, 1 reply; 14+ messages in thread From: Sebastian Reichel @ 2026-07-15 12:59 UTC (permalink / raw) To: Royal Net Cc: sashiko-reviews, conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 3774 bytes --] Hello Igor, On Wed, Jul 15, 2026 at 08:55:37AM +0200, Royal Net wrote: > > Should the constraint be set to 0 to follow standard device tree > > norms? > > Fair point. The current RFC wires up a single I2S DAI, and for a > single-DAI provider 0 is indeed the norm -- rockchip,dw-hdmi does > exactly that for its one DAI on the TX side. > > The reason I picked 1 is that the controller also has an S/PDIF > audio output path (the vendor driver exposes both I2S and S/PDIF > DAIs through hdmi-codec), so a DAI index becomes meaningful if that > second path is wired up later. > > Unless the DT maintainers prefer keeping 1 from the start to avoid > changing the cell count if/when the S/PDIF DAI is added, I'll switch > to const: 0 in the next revision -- please let me know which you'd > prefer. It should be 1 from the start as the DT binding is supposed to describe the hardware and be stable. But in the next version you should look into updating the commit descriptions to be less about the kernel driver and more about the hardware. Maybe something like > The HDMI RX controller has two digital audio interfaces, one for > I2S and one for S/PDIF. Allow referencing connections from audio > codecs to these interfaces by documenting the missing #sound-dai-cells > property. Apart from that it makes sense to document that argument 0 means I2S and argument 1 means S/PDIF interface in the property description. Last but not least drop "A value of 1 lets a sound card reference the audio DAI as <&hdmirx 0>.". Instead you can add this to the example section at the end of the file. Greetings, -- Sebastian > > Igor > > On Wed, Jul 15, 2026 at 7:54 AM <sashiko-bot@kernel.org> wrote: > > > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > - [Medium] Incorrect cell count constraint for single-DAI provider. > > -- > > > > --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- > > commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 > > Author: Igor Paunovic <royalnet026@gmail.com> > > dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells > > > > This commit adds the #sound-dai-cells property to the HDMI RX controller > > bindings, enabling a generic audio codec to capture incoming embedded audio. > > > > > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > index b7f6c87d0e06a..83c10d9997c8e 100644 > > > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > @@ -78,6 +78,13 @@ properties: > > > The phandle of the syscon node for the Video Output GRF register > > > to enable EDID transfer through SDAIN and SCLIN. > > > > > > + "#sound-dai-cells": > > > + const: 1 > > > + description: > > > + The HDMI RX controller registers a generic HDMI audio codec so the > > > + audio embedded in the incoming stream can be captured. A value of 1 > > > + lets a sound card reference the audio DAI as <&hdmirx 0>. > > > > [Severity: Medium] > > Is this cell count constraint correct for a single-DAI provider? > > > > Looking at properties:#sound-dai-cells, the hardware exposes only a single > > generic audio DAI. Requiring a cell count of 1 forces device tree nodes to > > use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a > > single resource. > > > > Should the constraint be set to 0 to follow standard device tree norms? > > > > -- > > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 12:59 ` Sebastian Reichel @ 2026-07-15 13:19 ` Igor Paunovic 2026-07-15 17:27 ` Sebastian Reichel 0 siblings, 1 reply; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 13:19 UTC (permalink / raw) To: Sebastian Reichel Cc: sashiko-reviews, conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel Hello Sebastian, > It should be 1 from the start as the DT binding is supposed to > describe the hardware and be stable. Thanks -- keeping const: 1 then. > But in the next version you should look into updating the commit > descriptions to be less about the kernel driver and more about > the hardware. Will do. I'll use your wording as the base for the v2 commit message, document that argument 0 is the I2S and 1 the S/PDIF interface in the property description, and move the consumer reference (sound-dai = <&hdmi_receiver 0>) into the example section. For completeness: the driver part of the series currently wires up only the I2S interface (DAI 0); the binding now describes both interfaces as per the hardware. Thanks for the review! Igor On Wed, Jul 15, 2026 at 3:00 PM Sebastian Reichel <sebastian.reichel@collabora.com> wrote: > > Hello Igor, > > On Wed, Jul 15, 2026 at 08:55:37AM +0200, Royal Net wrote: > > > Should the constraint be set to 0 to follow standard device tree > > > norms? > > > > Fair point. The current RFC wires up a single I2S DAI, and for a > > single-DAI provider 0 is indeed the norm -- rockchip,dw-hdmi does > > exactly that for its one DAI on the TX side. > > > > The reason I picked 1 is that the controller also has an S/PDIF > > audio output path (the vendor driver exposes both I2S and S/PDIF > > DAIs through hdmi-codec), so a DAI index becomes meaningful if that > > second path is wired up later. > > > > Unless the DT maintainers prefer keeping 1 from the start to avoid > > changing the cell count if/when the S/PDIF DAI is added, I'll switch > > to const: 0 in the next revision -- please let me know which you'd > > prefer. > > It should be 1 from the start as the DT binding is supposed to > describe the hardware and be stable. But in the next version you > should look into updating the commit descriptions to be less about > the kernel driver and more about the hardware. Maybe something like > > > The HDMI RX controller has two digital audio interfaces, one for > > I2S and one for S/PDIF. Allow referencing connections from audio > > codecs to these interfaces by documenting the missing #sound-dai-cells > > property. > > Apart from that it makes sense to document that argument 0 means > I2S and argument 1 means S/PDIF interface in the property description. > > Last but not least drop "A value of 1 lets a sound card reference > the audio DAI as <&hdmirx 0>.". Instead you can add this to the > example section at the end of the file. > > Greetings, > > -- Sebastian > > > > > Igor > > > > On Wed, Jul 15, 2026 at 7:54 AM <sashiko-bot@kernel.org> wrote: > > > > > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > > - [Medium] Incorrect cell count constraint for single-DAI provider. > > > -- > > > > > > --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- > > > commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 > > > Author: Igor Paunovic <royalnet026@gmail.com> > > > dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells > > > > > > This commit adds the #sound-dai-cells property to the HDMI RX controller > > > bindings, enabling a generic audio codec to capture incoming embedded audio. > > > > > > > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > index b7f6c87d0e06a..83c10d9997c8e 100644 > > > > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > @@ -78,6 +78,13 @@ properties: > > > > The phandle of the syscon node for the Video Output GRF register > > > > to enable EDID transfer through SDAIN and SCLIN. > > > > > > > > + "#sound-dai-cells": > > > > + const: 1 > > > > + description: > > > > + The HDMI RX controller registers a generic HDMI audio codec so the > > > > + audio embedded in the incoming stream can be captured. A value of 1 > > > > + lets a sound card reference the audio DAI as <&hdmirx 0>. > > > > > > [Severity: Medium] > > > Is this cell count constraint correct for a single-DAI provider? > > > > > > Looking at properties:#sound-dai-cells, the hardware exposes only a single > > > generic audio DAI. Requiring a cell count of 1 forces device tree nodes to > > > use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a > > > single resource. > > > > > > Should the constraint be set to 0 to follow standard device tree norms? > > > > > > -- > > > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 13:19 ` Igor Paunovic @ 2026-07-15 17:27 ` Sebastian Reichel 2026-07-15 17:41 ` Igor Paunovic 0 siblings, 1 reply; 14+ messages in thread From: Sebastian Reichel @ 2026-07-15 17:27 UTC (permalink / raw) To: Igor Paunovic Cc: sashiko-reviews, conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel Hi, On Wed, Jul 15, 2026 at 03:19:54PM +0200, Igor Paunovic wrote: > For completeness: the driver part of the series currently wires > up only the I2S interface (DAI 0); the binding now describes both > interfaces as per the hardware. Not implementing all features in the driver is perfectly fine. Ideally you return -ENOTSUP if somebody tries to use the S/PDIF DAI interface instead of I2S. Greetings, -- Sebastian > > Thanks for the review! > > Igor > > On Wed, Jul 15, 2026 at 3:00 PM Sebastian Reichel > <sebastian.reichel@collabora.com> wrote: > > > > Hello Igor, > > > > On Wed, Jul 15, 2026 at 08:55:37AM +0200, Royal Net wrote: > > > > Should the constraint be set to 0 to follow standard device tree > > > > norms? > > > > > > Fair point. The current RFC wires up a single I2S DAI, and for a > > > single-DAI provider 0 is indeed the norm -- rockchip,dw-hdmi does > > > exactly that for its one DAI on the TX side. > > > > > > The reason I picked 1 is that the controller also has an S/PDIF > > > audio output path (the vendor driver exposes both I2S and S/PDIF > > > DAIs through hdmi-codec), so a DAI index becomes meaningful if that > > > second path is wired up later. > > > > > > Unless the DT maintainers prefer keeping 1 from the start to avoid > > > changing the cell count if/when the S/PDIF DAI is added, I'll switch > > > to const: 0 in the next revision -- please let me know which you'd > > > prefer. > > > > It should be 1 from the start as the DT binding is supposed to > > describe the hardware and be stable. But in the next version you > > should look into updating the commit descriptions to be less about > > the kernel driver and more about the hardware. Maybe something like > > > > > The HDMI RX controller has two digital audio interfaces, one for > > > I2S and one for S/PDIF. Allow referencing connections from audio > > > codecs to these interfaces by documenting the missing #sound-dai-cells > > > property. > > > > Apart from that it makes sense to document that argument 0 means > > I2S and argument 1 means S/PDIF interface in the property description. > > > > Last but not least drop "A value of 1 lets a sound card reference > > the audio DAI as <&hdmirx 0>.". Instead you can add this to the > > example section at the end of the file. > > > > Greetings, > > > > -- Sebastian > > > > > > > > Igor > > > > > > On Wed, Jul 15, 2026 at 7:54 AM <sashiko-bot@kernel.org> wrote: > > > > > > > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > > > - [Medium] Incorrect cell count constraint for single-DAI provider. > > > > -- > > > > > > > > --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- > > > > commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 > > > > Author: Igor Paunovic <royalnet026@gmail.com> > > > > dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells > > > > > > > > This commit adds the #sound-dai-cells property to the HDMI RX controller > > > > bindings, enabling a generic audio codec to capture incoming embedded audio. > > > > > > > > > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > index b7f6c87d0e06a..83c10d9997c8e 100644 > > > > > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > @@ -78,6 +78,13 @@ properties: > > > > > The phandle of the syscon node for the Video Output GRF register > > > > > to enable EDID transfer through SDAIN and SCLIN. > > > > > > > > > > + "#sound-dai-cells": > > > > > + const: 1 > > > > > + description: > > > > > + The HDMI RX controller registers a generic HDMI audio codec so the > > > > > + audio embedded in the incoming stream can be captured. A value of 1 > > > > > + lets a sound card reference the audio DAI as <&hdmirx 0>. > > > > > > > > [Severity: Medium] > > > > Is this cell count constraint correct for a single-DAI provider? > > > > > > > > Looking at properties:#sound-dai-cells, the hardware exposes only a single > > > > generic audio DAI. Requiring a cell count of 1 forces device tree nodes to > > > > use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a > > > > single resource. > > > > > > > > Should the constraint be set to 0 to follow standard device tree norms? > > > > > > > > -- > > > > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 17:27 ` Sebastian Reichel @ 2026-07-15 17:41 ` Igor Paunovic 2026-07-15 19:20 ` Sebastian Reichel 0 siblings, 1 reply; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 17:41 UTC (permalink / raw) To: Sebastian Reichel Cc: sashiko-reviews, conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel Hello Sebastian, > Not implementing all features in the driver is perfectly fine. > Ideally you return -ENOTSUP if somebody tries to use the S/PDIF > DAI interface instead of I2S. Done for v2: the codec registration now exposes the S/PDIF DAI as well, so the DAI indexes match the binding (0 = I2S, 1 = S/PDIF), and hw_params() rejects the S/PDIF interface with -EOPNOTSUPP until that path is actually wired up. Thanks! Igor On Wed, Jul 15, 2026 at 7:28 PM Sebastian Reichel <sebastian.reichel@collabora.com> wrote: > > Hi, > > On Wed, Jul 15, 2026 at 03:19:54PM +0200, Igor Paunovic wrote: > > For completeness: the driver part of the series currently wires > > up only the I2S interface (DAI 0); the binding now describes both > > interfaces as per the hardware. > > Not implementing all features in the driver is perfectly fine. > Ideally you return -ENOTSUP if somebody tries to use the S/PDIF > DAI interface instead of I2S. > > Greetings, > > -- Sebastian > > > > > Thanks for the review! > > > > Igor > > > > On Wed, Jul 15, 2026 at 3:00 PM Sebastian Reichel > > <sebastian.reichel@collabora.com> wrote: > > > > > > Hello Igor, > > > > > > On Wed, Jul 15, 2026 at 08:55:37AM +0200, Royal Net wrote: > > > > > Should the constraint be set to 0 to follow standard device tree > > > > > norms? > > > > > > > > Fair point. The current RFC wires up a single I2S DAI, and for a > > > > single-DAI provider 0 is indeed the norm -- rockchip,dw-hdmi does > > > > exactly that for its one DAI on the TX side. > > > > > > > > The reason I picked 1 is that the controller also has an S/PDIF > > > > audio output path (the vendor driver exposes both I2S and S/PDIF > > > > DAIs through hdmi-codec), so a DAI index becomes meaningful if that > > > > second path is wired up later. > > > > > > > > Unless the DT maintainers prefer keeping 1 from the start to avoid > > > > changing the cell count if/when the S/PDIF DAI is added, I'll switch > > > > to const: 0 in the next revision -- please let me know which you'd > > > > prefer. > > > > > > It should be 1 from the start as the DT binding is supposed to > > > describe the hardware and be stable. But in the next version you > > > should look into updating the commit descriptions to be less about > > > the kernel driver and more about the hardware. Maybe something like > > > > > > > The HDMI RX controller has two digital audio interfaces, one for > > > > I2S and one for S/PDIF. Allow referencing connections from audio > > > > codecs to these interfaces by documenting the missing #sound-dai-cells > > > > property. > > > > > > Apart from that it makes sense to document that argument 0 means > > > I2S and argument 1 means S/PDIF interface in the property description. > > > > > > Last but not least drop "A value of 1 lets a sound card reference > > > the audio DAI as <&hdmirx 0>.". Instead you can add this to the > > > example section at the end of the file. > > > > > > Greetings, > > > > > > -- Sebastian > > > > > > > > > > > Igor > > > > > > > > On Wed, Jul 15, 2026 at 7:54 AM <sashiko-bot@kernel.org> wrote: > > > > > > > > > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > > > > - [Medium] Incorrect cell count constraint for single-DAI provider. > > > > > -- > > > > > > > > > > --- Patch [1]: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells --- > > > > > commit e6b0bac0b97f568ce749084e6c1e728bcd258b10 > > > > > Author: Igor Paunovic <royalnet026@gmail.com> > > > > > dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells > > > > > > > > > > This commit adds the #sound-dai-cells property to the HDMI RX controller > > > > > bindings, enabling a generic audio codec to capture incoming embedded audio. > > > > > > > > > > > diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > > index b7f6c87d0e06a..83c10d9997c8e 100644 > > > > > > --- a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > > +++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml > > > > > > @@ -78,6 +78,13 @@ properties: > > > > > > The phandle of the syscon node for the Video Output GRF register > > > > > > to enable EDID transfer through SDAIN and SCLIN. > > > > > > > > > > > > + "#sound-dai-cells": > > > > > > + const: 1 > > > > > > + description: > > > > > > + The HDMI RX controller registers a generic HDMI audio codec so the > > > > > > + audio embedded in the incoming stream can be captured. A value of 1 > > > > > > + lets a sound card reference the audio DAI as <&hdmirx 0>. > > > > > > > > > > [Severity: Medium] > > > > > Is this cell count constraint correct for a single-DAI provider? > > > > > > > > > > Looking at properties:#sound-dai-cells, the hardware exposes only a single > > > > > generic audio DAI. Requiring a cell count of 1 forces device tree nodes to > > > > > use a non-standard syntax like <&hdmirx 0> instead of just <&hdmirx> for a > > > > > single resource. > > > > > > > > > > Should the constraint be set to 0 to follow standard device tree norms? > > > > > > > > > > -- > > > > > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells 2026-07-15 17:41 ` Igor Paunovic @ 2026-07-15 19:20 ` Sebastian Reichel 0 siblings, 0 replies; 14+ messages in thread From: Sebastian Reichel @ 2026-07-15 19:20 UTC (permalink / raw) To: Igor Paunovic Cc: sashiko-reviews, conor+dt, devicetree, robh, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media, kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 572 bytes --] Hi Igor, On Wed, Jul 15, 2026 at 07:41:22PM +0200, Igor Paunovic wrote: > Hello Sebastian, > > > Not implementing all features in the driver is perfectly fine. > > Ideally you return -ENOTSUP if somebody tries to use the S/PDIF > > DAI interface instead of I2S. > > Done for v2: the codec registration now exposes the S/PDIF DAI as > well, so the DAI indexes match the binding (0 = I2S, 1 = S/PDIF), > and hw_params() rejects the S/PDIF interface with -EOPNOTSUPP until > that path is actually wired up. Sounds good to me. Greetings, -- Sebastian [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support 2026-07-15 5:19 [RFC PATCH 0/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 2026-07-15 5:19 ` [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells Igor Paunovic @ 2026-07-15 5:19 ` Igor Paunovic 2026-07-15 5:48 ` sashiko-bot 2026-07-15 19:07 ` Dmitry Osipenko 1 sibling, 2 replies; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 5:19 UTC (permalink / raw) To: Dmitry Osipenko, Mauro Carvalho Chehab Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-media, kernel, devicetree, linux-kernel, Igor Paunovic 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. The sample rate is recovered from the ACR N/CTS values together with the measured TMDS character rate. A periodic worker keeps the local audio reference clock locked to the source by nudging it in small ppm steps to hold the audio FIFO fill level near its target, which avoids FIFO under/overflow and the resulting dropped samples. Signed-off-by: Igor Paunovic <royalnet026@gmail.com> --- .../platform/synopsys/hdmirx/snps_hdmirx.c | 244 ++++++++++++++++++ .../platform/synopsys/hdmirx/snps_hdmirx.h | 8 + 2 files changed, 252 insertions(+) diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c index 9cceffa..f536d17 100644 --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c @@ -41,6 +41,8 @@ #include <media/videobuf2-dma-contig.h> #include <media/videobuf2-v4l2.h> +#include <sound/hdmi-codec.h> + #include "snps_hdmirx.h" #include "snps_hdmirx_cec.h" @@ -132,6 +134,12 @@ struct snps_hdmirx_dev { struct delayed_work delayed_work_hotplug; struct delayed_work delayed_work_res_change; struct hdmirx_cec *cec; + struct platform_device *audio_pdev; + struct delayed_work audio_work; + u32 audio_clkrate; + u32 audio_fs; + int audio_pre_state; + bool audio_streaming; struct mutex phy_rw_lock; /* to protect phy r/w configuration */ struct mutex stream_lock; /* to lock video stream capture */ struct mutex work_lock; /* to lock the critical section of hotplug event */ @@ -2650,6 +2658,233 @@ static int hdmirx_register_cec(struct snps_hdmirx_dev *hdmirx_dev, return 0; } +#define HDMIRX_AUDIO_INIT_FIFO_STATE 128 +#define HDMIRX_AUDIO_INIT_STATE (HDMIRX_AUDIO_INIT_FIFO_STATE * 4) + +static const int hdmirx_supported_fs[] = { + 32000, 44100, 48000, 88200, 96000, 176400, 192000, 768000, -1 +}; + +static int hdmirx_audio_closest_fs(int fs) +{ + int i = 0, fs_t = hdmirx_supported_fs[0]; + + while (fs_t > 0) { + if (abs(fs - fs_t) <= 2000) + return fs_t; + fs_t = hdmirx_supported_fs[++i]; + } + return 0; +} + +/* 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(acr_pb7_4) & 0xfffff; + acr_n = (__be32_to_cpu(acr_pb3_0) & 0x0fffff00) >> 8; + 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; +} + +/* Nudge the audio reference clock by +/- ppm to keep the FIFO balanced. */ +static void hdmirx_audio_clk_ppm_inc(struct snps_hdmirx_dev *hdmirx_dev, int ppm) +{ + int delta, inc; + long rate = hdmirx_dev->audio_clkrate; + + if (ppm < 0) { + ppm = -ppm; + inc = -1; + } else { + inc = 1; + } + delta = (int)div64_u64((u64)rate * ppm + 500000, 1000000); + delta *= inc; + rate = hdmirx_dev->audio_clkrate + delta; + clk_set_rate(hdmirx_dev->clks[1].clk, rate); + hdmirx_dev->audio_clkrate = rate; +} + +static int hdmirx_audio_clk_adjust(struct snps_hdmirx_dev *hdmirx_dev, + int total_offset, int single_offset) +{ + int schedule_time = 500; + int ppm = 10; + u32 offset_abs = abs(total_offset); + + if (offset_abs > 200) { + ppm += 200; + schedule_time -= 100; + } + if (offset_abs > 100) { + ppm += 200; + schedule_time -= 100; + } + if (offset_abs > 32) { + ppm += 20; + schedule_time -= 100; + } + if (offset_abs > 16) + ppm += 20; + if (total_offset > 16 && single_offset > 0) + hdmirx_audio_clk_ppm_inc(hdmirx_dev, ppm); + else if (total_offset < -16 && single_offset < 0) + hdmirx_audio_clk_ppm_inc(hdmirx_dev, -ppm); + return schedule_time; +} + +static void hdmirx_audio_fifo_reinit(struct snps_hdmirx_dev *hdmirx_dev) +{ + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_CONTROL, 1); + usleep_range(200, 210); + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_CONTROL, 0); +} + +/* + * Periodic worker that locks the local audio clock to the source by keeping + * the audio FIFO fill level close to its target, avoiding under/overflow. + */ +static void hdmirx_audio_work(struct work_struct *work) +{ + struct snps_hdmirx_dev *hdmirx_dev = + container_of(to_delayed_work(work), struct snps_hdmirx_dev, audio_work); + unsigned long delay = 200; + int cur, total, single; + u32 fifo, fs; + + fs = hdmirx_audio_fs(hdmirx_dev); + fifo = hdmirx_readl(hdmirx_dev, AUDIO_FIFO_STATUS2); + + if (fifo & (AFIFO_UNDERFLOW_ST | AFIFO_OVERFLOW_ST)) { + if (fs) { + clk_set_rate(hdmirx_dev->clks[1].clk, fs * 128); + hdmirx_dev->audio_clkrate = fs * 128; + hdmirx_dev->audio_fs = fs; + } + hdmirx_audio_fifo_reinit(hdmirx_dev); + hdmirx_dev->audio_pre_state = 0; + goto out; + } + + cur = fifo & 0xffff; + total = cur - HDMIRX_AUDIO_INIT_STATE; + single = cur - hdmirx_dev->audio_pre_state; + + if (fs && abs((int)fs - (int)hdmirx_dev->audio_fs) > 1000) { + clk_set_rate(hdmirx_dev->clks[1].clk, fs * 128); + hdmirx_dev->audio_clkrate = fs * 128; + hdmirx_dev->audio_fs = fs; + hdmirx_audio_fifo_reinit(hdmirx_dev); + hdmirx_dev->audio_pre_state = 0; + goto out; + } + + if (cur != 0) + delay = hdmirx_audio_clk_adjust(hdmirx_dev, total, single); + hdmirx_dev->audio_pre_state = cur; +out: + /* Only re-arm while streaming; avoids a self-reschedule race with + * cancel_delayed_work_sync() in audio_shutdown(). + */ + if (READ_ONCE(hdmirx_dev->audio_streaming)) + schedule_delayed_work(&hdmirx_dev->audio_work, + msecs_to_jiffies(delay)); +} + +static int hdmirx_audio_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); + u32 fs; + + fs = hdmirx_audio_fs(hdmirx_dev); + if (!fs) + fs = hparms ? hparms->sample_rate : 48000; + if (!fs) + fs = 48000; + + hdmirx_dev->audio_fs = fs; + hdmirx_dev->audio_clkrate = fs * 128; + clk_set_rate(hdmirx_dev->clks[1].clk, fs * 128); + + hdmirx_audio_fifo_reinit(hdmirx_dev); + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR_PASS, HDMIRX_AUDIO_INIT_FIFO_STATE); + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR, + AFIFO_THR_LOW_QST(0x20) | AFIFO_THR_HIGH_QST(0x160)); + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_MUTE_THR, + AFIFO_THR_MUTE_LOW_QST(0x8) | AFIFO_THR_MUTE_HIGH_QST(0x178)); + + hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, I2S_EN); + hdmirx_update_bits(hdmirx_dev, GLOBAL_SWENABLE, AUDIO_ENABLE, AUDIO_ENABLE); + + hdmirx_dev->audio_pre_state = 0; + WRITE_ONCE(hdmirx_dev->audio_streaming, true); + mod_delayed_work(system_unbound_wq, &hdmirx_dev->audio_work, + msecs_to_jiffies(200)); + + dev_dbg(dev, "audio hw_params: fs=%u\n", fs); + return 0; +} + +static void hdmirx_audio_shutdown(struct device *dev, void *data) +{ + struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); + + WRITE_ONCE(hdmirx_dev->audio_streaming, false); + cancel_delayed_work_sync(&hdmirx_dev->audio_work); + hdmirx_update_bits(hdmirx_dev, GLOBAL_SWENABLE, AUDIO_ENABLE, 0); +} + +static int hdmirx_audio_get_dai_id(struct snd_soc_component *component, + struct device_node *endpoint, + void *data) +{ + return 0; +} + +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, +}; + +static int hdmirx_register_audio_device(struct snps_hdmirx_dev *hdmirx_dev) +{ + struct hdmi_codec_pdata codec_data = { + .ops = &hdmirx_audio_codec_ops, + .i2s = 1, + .no_i2s_playback = 1, + .max_i2s_channels = 8, + .data = hdmirx_dev, + }; + struct platform_device_info pdevinfo = { + .parent = hdmirx_dev->dev, + .id = PLATFORM_DEVID_AUTO, + .name = HDMI_CODEC_DRV_NAME, + .data = &codec_data, + .size_data = sizeof(codec_data), + .dma_mask = DMA_BIT_MASK(32), + }; + + hdmirx_dev->audio_pdev = platform_device_register_full(&pdevinfo); + + return PTR_ERR_OR_ZERO(hdmirx_dev->audio_pdev); +} + static int hdmirx_probe(struct platform_device *pdev) { struct snps_hdmirx_dev *hdmirx_dev; @@ -2701,6 +2936,7 @@ static int hdmirx_probe(struct platform_device *pdev) hdmirx_delayed_work_hotplug); INIT_DELAYED_WORK(&hdmirx_dev->delayed_work_res_change, hdmirx_delayed_work_res_change); + INIT_DELAYED_WORK(&hdmirx_dev->audio_work, hdmirx_audio_work); hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24; hdmirx_dev->timings = cea640x480; @@ -2769,6 +3005,10 @@ static int hdmirx_probe(struct platform_device *pdev) V4L2_DEBUGFS_IF_AVI, hdmirx_dev, hdmirx_debugfs_if_read); + ret = hdmirx_register_audio_device(hdmirx_dev); + if (ret) + dev_warn(dev, "failed to register HDMI audio codec: %d\n", ret); + return 0; err_unreg_video_dev: @@ -2788,6 +3028,10 @@ static void hdmirx_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); + cancel_delayed_work_sync(&hdmirx_dev->audio_work); + if (hdmirx_dev->audio_pdev) + platform_device_unregister(hdmirx_dev->audio_pdev); + v4l2_debugfs_if_free(hdmirx_dev->infoframes); debugfs_remove_recursive(hdmirx_dev->debugfs_dir); diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h index 31b887e..a99f54f 100644 --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h @@ -81,6 +81,7 @@ #define DATAPATH_ENABLE BIT(12) #define PKTFIFO_ENABLE BIT(11) #define AVPUNIT_ENABLE BIT(8) +#define AUDIO_ENABLE BIT(9) #define MAIN_ENABLE BIT(0) #define GLOBAL_TIMER_REF_BASE 0x0028 #define CORE_CONFIG 0x0050 @@ -177,20 +178,27 @@ #define VPROC_FMT_OVR_VALUE(x) UPDATE(x, 6, 4) #define VPROC_FMT_OVR_EN BIT(0) +#define AUDIO_FIFO_CONFIG 0x0460 #define AFIFO_FILL_RESTART BIT(0) +#define AUDIO_FIFO_CONTROL 0x0464 #define AFIFO_INIT_P BIT(0) +#define AUDIO_FIFO_THR_PASS 0x0468 +#define AUDIO_FIFO_THR 0x046c #define AFIFO_THR_LOW_QST_MASK GENMASK(25, 16) #define AFIFO_THR_LOW_QST(x) UPDATE(x, 25, 16) #define AFIFO_THR_HIGH_QST_MASK GENMASK(9, 0) #define AFIFO_THR_HIGH_QST(x) UPDATE(x, 9, 0) +#define AUDIO_FIFO_MUTE_THR 0x0470 #define AFIFO_THR_MUTE_LOW_QST_MASK GENMASK(25, 16) #define AFIFO_THR_MUTE_LOW_QST(x) UPDATE(x, 25, 16) #define AFIFO_THR_MUTE_HIGH_QST_MASK GENMASK(9, 0) #define AFIFO_THR_MUTE_HIGH_QST(x) UPDATE(x, 9, 0) +#define AUDIO_FIFO_STATUS2 0x0478 #define AFIFO_UNDERFLOW_ST BIT(25) #define AFIFO_OVERFLOW_ST BIT(24) +#define AUDIO_PROC_CONFIG0 0x0480 #define SPEAKER_ALLOC_OVR_EN BIT(16) #define I2S_BPCUV_EN BIT(4) #define SPDIF_EN BIT(2) -- 2.53.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support 2026-07-15 5:19 ` [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic @ 2026-07-15 5:48 ` sashiko-bot 2026-07-15 6:42 ` Royal Net 2026-07-15 19:07 ` Dmitry Osipenko 1 sibling, 1 reply; 14+ messages in thread From: sashiko-bot @ 2026-07-15 5:48 UTC (permalink / raw) To: Igor Paunovic; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] Passing an ERR_PTR to platform_device_unregister() causes a kernel panic during module removal. - [High] Flawed teardown ordering and failure to clear the audio_streaming flag in hdmirx_remove() allows the delayed work to re-arm, leading to a Use-After-Free. - [High] Concurrent unprotected access to shared audio state variables between ALSA `hw_params` and the background worker. - [Medium] Unconditional access to `clks[1]` causes an out-of-bounds read if the Device Tree specifies only one clock. - [Low] The audio worker item silently migrates from an unbound workqueue to the default CPU-bound workqueue after its first execution. -- --- Patch [2]: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support --- commit a0cbe815be5692f1b4e770ef5f613ff1fa0b7862 Author: Igor Paunovic <royalnet026@gmail.com> 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. > diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c > --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c > +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c [ ... ] > +static void hdmirx_audio_clk_ppm_inc(struct snps_hdmirx_dev *hdmirx_dev, int ppm) > +{ > + int delta, inc; > + long rate = hdmirx_dev->audio_clkrate; > + > + if (ppm < 0) { > + ppm = -ppm; > + inc = -1; > + } else { > + inc = 1; > + } > + delta = (int)div64_u64((u64)rate * ppm + 500000, 1000000); > + delta *= inc; > + rate = hdmirx_dev->audio_clkrate + delta; > + clk_set_rate(hdmirx_dev->clks[1].clk, rate); [Severity: Medium] Does this code access the clock array out of bounds if the device tree only provides one clock? The probe function uses devm_clk_bulk_get_all() which only guarantees num_clks >= 1, but this unconditionally accesses index 1. > + hdmirx_dev->audio_clkrate = rate; > +} [ ... ] > +static void hdmirx_audio_work(struct work_struct *work) > +{ [ ... ] > + /* Only re-arm while streaming; avoids a self-reschedule race with > + * cancel_delayed_work_sync() in audio_shutdown(). > + */ > + if (READ_ONCE(hdmirx_dev->audio_streaming)) > + schedule_delayed_work(&hdmirx_dev->audio_work, > + msecs_to_jiffies(delay)); [Severity: Low] Does this cause the worker to silently migrate to the default system_wq? The worker is initially queued on system_unbound_wq using mod_delayed_work(), but schedule_delayed_work() implicitly targets the default CPU-bound workqueue. > +} > + > +static int hdmirx_audio_hw_params(struct device *dev, void *data, > + struct hdmi_codec_daifmt *fmt, > + struct hdmi_codec_params *hparms) > +{ > + struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); > + u32 fs; > + > + fs = hdmirx_audio_fs(hdmirx_dev); > + if (!fs) > + fs = hparms ? hparms->sample_rate : 48000; > + if (!fs) > + fs = 48000; > + > + hdmirx_dev->audio_fs = fs; > + hdmirx_dev->audio_clkrate = fs * 128; [Severity: High] Can concurrent ALSA hw_params ioctl calls race with the background worker here? ALSA allows consecutive hw_params calls, which could modify audio_fs, audio_clkrate, and audio_pre_state locklessly while the worker is already executing on another CPU. Could this concurrent access result in an invalid clock frequency calculation? > + clk_set_rate(hdmirx_dev->clks[1].clk, fs * 128); > + > + hdmirx_audio_fifo_reinit(hdmirx_dev); > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR_PASS, HDMIRX_AUDIO_INIT_FIFO_STATE); > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR, > + AFIFO_THR_LOW_QST(0x20) | AFIFO_THR_HIGH_QST(0x160)); > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_MUTE_THR, > + AFIFO_THR_MUTE_LOW_QST(0x8) | AFIFO_THR_MUTE_HIGH_QST(0x178)); > + > + hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, I2S_EN); > + hdmirx_update_bits(hdmirx_dev, GLOBAL_SWENABLE, AUDIO_ENABLE, AUDIO_ENABLE); > + > + hdmirx_dev->audio_pre_state = 0; > + WRITE_ONCE(hdmirx_dev->audio_streaming, true); > + mod_delayed_work(system_unbound_wq, &hdmirx_dev->audio_work, > + msecs_to_jiffies(200)); > + > + dev_dbg(dev, "audio hw_params: fs=%u\n", fs); > + return 0; > +} [ ... ] > @@ -2765,6 +3001,10 @@ static int hdmirx_probe(struct platform_device *pdev) > V4L2_DEBUGFS_IF_AVI, hdmirx_dev, > hdmirx_debugfs_if_read); > > + ret = hdmirx_register_audio_device(hdmirx_dev); > + if (ret) > + dev_warn(dev, "failed to register HDMI audio codec: %d\n", ret); > + [Severity: High] If platform_device_register_full() fails in hdmirx_register_audio_device(), it returns an ERR_PTR which is stored in hdmirx_dev->audio_pdev. Since this failure only logs a warning and allows the probe to succeed, won't the check in hdmirx_remove() evaluate to true? if (hdmirx_dev->audio_pdev) platform_device_unregister(hdmirx_dev->audio_pdev); Will this cause a kernel panic when platform_device_unregister() attempts to dereference the ERR_PTR? > return 0; > > err_unreg_video_dev: > @@ -2784,6 +3024,10 @@ static void hdmirx_remove(struct platform_device *pdev) > struct device *dev = &pdev->dev; > struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); > > + cancel_delayed_work_sync(&hdmirx_dev->audio_work); > + if (hdmirx_dev->audio_pdev) > + platform_device_unregister(hdmirx_dev->audio_pdev); > + [Severity: High] Could the worker re-arm itself after this cancelation? If the worker is running during removal, cancel_delayed_work_sync() waits for it to finish. However, because audio_streaming is not set to false prior to this call, the worker will see audio_streaming == true and re-arm itself. Additionally, since platform_device_unregister() is called after the timer cancelation, could userspace trigger a concurrent hw_params ioctl and re-arm the timer through that path? Will the re-armed timer execute on freed memory after the device is removed? > v4l2_debugfs_if_free(hdmirx_dev->infoframes); > debugfs_remove_recursive(hdmirx_dev->debugfs_dir); -- Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=2 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support 2026-07-15 5:48 ` sashiko-bot @ 2026-07-15 6:42 ` Royal Net 0 siblings, 0 replies; 14+ messages in thread From: Royal Net @ 2026-07-15 6:42 UTC (permalink / raw) To: sashiko-reviews; +Cc: robh, conor+dt, devicetree Thanks for the thorough pass -- all five are in the new code, so all five are mine to fix. Ack on each: > - [High] Passing an ERR_PTR to platform_device_unregister() causes > a kernel panic during module removal. Confirmed. hdmirx_register_audio_device() leaves the ERR_PTR in audio_pdev when registration fails (probe intentionally only warns), and the NULL check in hdmirx_remove() doesn't catch an ERR_PTR. Will store NULL on failure so the existing check works. > - [High] Flawed teardown ordering and failure to clear the > audio_streaming flag in hdmirx_remove() allows the delayed work > to re-arm, leading to a Use-After-Free. Confirmed. The self-rearm guard was added for audio_shutdown() but remove() never clears audio_streaming, so a worker instance running at removal time can re-arm after cancel_delayed_work_sync() returns. Will clear the flag first, unregister the codec device (tearing down the stream), and cancel the work last. > - [High] Concurrent unprotected access to shared audio state > variables between ALSA `hw_params` and the background worker. Confirmed. A repeated hw_params without an intervening shutdown can race the worker over audio_fs/audio_clkrate/audio_pre_state. Plan is to stop the worker (clear the flag + cancel_delayed_work_sync) at the top of hw_params before touching shared state, which keeps the worker the only writer while it is armed and avoids introducing a lock. > - [Medium] Unconditional access to `clks[1]` causes an > out-of-bounds read if the Device Tree specifies only one clock. Agreed -- index-based access is fragile even though the binding lists the audio clock. Will resolve the "audio" clock by name from the bulk clock data once at probe time and cache the pointer. > - [Low] The audio worker item silently migrates from an unbound > workqueue to the default CPU-bound workqueue after its first > execution. Confirmed; the re-arm path uses schedule_delayed_work() while the initial queueing uses system_unbound_wq. Will use queue_delayed_work(system_unbound_wq, ...) consistently. All five will be addressed in the next revision, together with any design-level feedback on the RFC itself. Igor On Wed, Jul 15, 2026 at 7:48 AM <sashiko-bot@kernel.org> wrote: > > Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: > - [High] Passing an ERR_PTR to platform_device_unregister() causes a kernel panic during module removal. > - [High] Flawed teardown ordering and failure to clear the audio_streaming flag in hdmirx_remove() allows the delayed work to re-arm, leading to a Use-After-Free. > - [High] Concurrent unprotected access to shared audio state variables between ALSA `hw_params` and the background worker. > - [Medium] Unconditional access to `clks[1]` causes an out-of-bounds read if the Device Tree specifies only one clock. > - [Low] The audio worker item silently migrates from an unbound workqueue to the default CPU-bound workqueue after its first execution. > -- > > --- Patch [2]: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support --- > commit a0cbe815be5692f1b4e770ef5f613ff1fa0b7862 > Author: Igor Paunovic <royalnet026@gmail.com> > > 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. > > > diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c > > --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c > > +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c > > [ ... ] > > > +static void hdmirx_audio_clk_ppm_inc(struct snps_hdmirx_dev *hdmirx_dev, int ppm) > > +{ > > + int delta, inc; > > + long rate = hdmirx_dev->audio_clkrate; > > + > > + if (ppm < 0) { > > + ppm = -ppm; > > + inc = -1; > > + } else { > > + inc = 1; > > + } > > + delta = (int)div64_u64((u64)rate * ppm + 500000, 1000000); > > + delta *= inc; > > + rate = hdmirx_dev->audio_clkrate + delta; > > + clk_set_rate(hdmirx_dev->clks[1].clk, rate); > > [Severity: Medium] > Does this code access the clock array out of bounds if the device tree only > provides one clock? > > The probe function uses devm_clk_bulk_get_all() which only guarantees > num_clks >= 1, but this unconditionally accesses index 1. > > > + hdmirx_dev->audio_clkrate = rate; > > +} > > [ ... ] > > > +static void hdmirx_audio_work(struct work_struct *work) > > +{ > > [ ... ] > > > + /* Only re-arm while streaming; avoids a self-reschedule race with > > + * cancel_delayed_work_sync() in audio_shutdown(). > > + */ > > + if (READ_ONCE(hdmirx_dev->audio_streaming)) > > + schedule_delayed_work(&hdmirx_dev->audio_work, > > + msecs_to_jiffies(delay)); > > [Severity: Low] > Does this cause the worker to silently migrate to the default system_wq? > > The worker is initially queued on system_unbound_wq using mod_delayed_work(), > but schedule_delayed_work() implicitly targets the default CPU-bound > workqueue. > > > +} > > + > > +static int hdmirx_audio_hw_params(struct device *dev, void *data, > > + struct hdmi_codec_daifmt *fmt, > > + struct hdmi_codec_params *hparms) > > +{ > > + struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); > > + u32 fs; > > + > > + fs = hdmirx_audio_fs(hdmirx_dev); > > + if (!fs) > > + fs = hparms ? hparms->sample_rate : 48000; > > + if (!fs) > > + fs = 48000; > > + > > + hdmirx_dev->audio_fs = fs; > > + hdmirx_dev->audio_clkrate = fs * 128; > > [Severity: High] > Can concurrent ALSA hw_params ioctl calls race with the background worker here? > > ALSA allows consecutive hw_params calls, which could modify audio_fs, > audio_clkrate, and audio_pre_state locklessly while the worker is already > executing on another CPU. > > Could this concurrent access result in an invalid clock frequency calculation? > > > + clk_set_rate(hdmirx_dev->clks[1].clk, fs * 128); > > + > > + hdmirx_audio_fifo_reinit(hdmirx_dev); > > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR_PASS, HDMIRX_AUDIO_INIT_FIFO_STATE); > > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR, > > + AFIFO_THR_LOW_QST(0x20) | AFIFO_THR_HIGH_QST(0x160)); > > + hdmirx_writel(hdmirx_dev, AUDIO_FIFO_MUTE_THR, > > + AFIFO_THR_MUTE_LOW_QST(0x8) | AFIFO_THR_MUTE_HIGH_QST(0x178)); > > + > > + hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, I2S_EN); > > + hdmirx_update_bits(hdmirx_dev, GLOBAL_SWENABLE, AUDIO_ENABLE, AUDIO_ENABLE); > > + > > + hdmirx_dev->audio_pre_state = 0; > > + WRITE_ONCE(hdmirx_dev->audio_streaming, true); > > + mod_delayed_work(system_unbound_wq, &hdmirx_dev->audio_work, > > + msecs_to_jiffies(200)); > > + > > + dev_dbg(dev, "audio hw_params: fs=%u\n", fs); > > + return 0; > > +} > > [ ... ] > > > @@ -2765,6 +3001,10 @@ static int hdmirx_probe(struct platform_device *pdev) > > V4L2_DEBUGFS_IF_AVI, hdmirx_dev, > > hdmirx_debugfs_if_read); > > > > + ret = hdmirx_register_audio_device(hdmirx_dev); > > + if (ret) > > + dev_warn(dev, "failed to register HDMI audio codec: %d\n", ret); > > + > > [Severity: High] > If platform_device_register_full() fails in hdmirx_register_audio_device(), > it returns an ERR_PTR which is stored in hdmirx_dev->audio_pdev. > > Since this failure only logs a warning and allows the probe to succeed, won't > the check in hdmirx_remove() evaluate to true? > > if (hdmirx_dev->audio_pdev) > platform_device_unregister(hdmirx_dev->audio_pdev); > > Will this cause a kernel panic when platform_device_unregister() attempts to > dereference the ERR_PTR? > > > return 0; > > > > err_unreg_video_dev: > > @@ -2784,6 +3024,10 @@ static void hdmirx_remove(struct platform_device *pdev) > > struct device *dev = &pdev->dev; > > struct snps_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); > > > > + cancel_delayed_work_sync(&hdmirx_dev->audio_work); > > + if (hdmirx_dev->audio_pdev) > > + platform_device_unregister(hdmirx_dev->audio_pdev); > > + > > [Severity: High] > Could the worker re-arm itself after this cancelation? > > If the worker is running during removal, cancel_delayed_work_sync() waits for > it to finish. However, because audio_streaming is not set to false prior to > this call, the worker will see audio_streaming == true and re-arm itself. > > Additionally, since platform_device_unregister() is called after the timer > cancelation, could userspace trigger a concurrent hw_params ioctl and re-arm > the timer through that path? > > Will the re-armed timer execute on freed memory after the device is removed? > > > v4l2_debugfs_if_free(hdmirx_dev->infoframes); > > debugfs_remove_recursive(hdmirx_dev->debugfs_dir); > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/20260715051939.64652-1-royalnet026@gmail.com?part=2 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support 2026-07-15 5:19 ` [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 2026-07-15 5:48 ` sashiko-bot @ 2026-07-15 19:07 ` Dmitry Osipenko 2026-07-15 19:27 ` Igor Paunovic 1 sibling, 1 reply; 14+ messages in thread From: Dmitry Osipenko @ 2026-07-15 19:07 UTC (permalink / raw) To: Igor Paunovic, Mauro Carvalho Chehab Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-media, kernel, devicetree, linux-kernel Hi, 15.07.2026 08:19, Igor Paunovic пишет: > +static int hdmirx_register_audio_device(struct snps_hdmirx_dev *hdmirx_dev) > +{ > + struct hdmi_codec_pdata codec_data = { > + .ops = &hdmirx_audio_codec_ops, > + .i2s = 1, > + .no_i2s_playback = 1, > + .max_i2s_channels = 8, > + .data = hdmirx_dev, > + }; > + struct platform_device_info pdevinfo = { > + .parent = hdmirx_dev->dev, > + .id = PLATFORM_DEVID_AUTO, > + .name = HDMI_CODEC_DRV_NAME, > + .data = &codec_data, > + .size_data = sizeof(codec_data), > + .dma_mask = DMA_BIT_MASK(32), > + }; > + > + hdmirx_dev->audio_pdev = platform_device_register_full(&pdevinfo); Nit: platform_device_register_data() should work too. The specified DMA mask should be unused by the codec driver and even if it was used, it should be inherited from the parent dev and not fixed to 32bit. Please either remove .dma_mask or use platform_device_register_data(). Please fix Sashiko bug reports for v2. Otherwise, the patch looks okay. Thanks for working on it. -- Best regards, Dmitry ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support 2026-07-15 19:07 ` Dmitry Osipenko @ 2026-07-15 19:27 ` Igor Paunovic 0 siblings, 0 replies; 14+ messages in thread From: Igor Paunovic @ 2026-07-15 19:27 UTC (permalink / raw) To: Dmitry Osipenko Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-media, kernel, devicetree, linux-kernel Hello Dmitry, > Nit: platform_device_register_data() should work too. The specified > DMA mask should be unused by the codec driver and even if it was > used, it should be inherited from the parent dev and not fixed to > 32bit. Please either remove .dma_mask or use > platform_device_register_data(). Switched to platform_device_register_data() for v2 -- you're right, the codec doesn't do DMA, so the mask (a leftover from the vendor driver) is gone together with the pdevinfo boilerplate. > Please fix Sashiko bug reports for v2. Otherwise, the patch looks > okay. Thanks for working on it. All five driver findings from that review are already fixed in my tree (ERR_PTR handling, remove() teardown ordering, hw_params/worker race, named clock lookup, consistent workqueue), along with the Media CI sparse warnings and Sebastian's binding and S/PDIF DAI comments. Re-validated on the Orange Pi 5 Plus. I'll send v2 with all of it shortly. Thanks for the review! Igor -------------------------------------------------------- ============================================================= On Wed, Jul 15, 2026 at 9:08 PM Dmitry Osipenko <dmitry.osipenko@collabora.com> wrote: > > Hi, > > 15.07.2026 08:19, Igor Paunovic пишет: > > +static int hdmirx_register_audio_device(struct snps_hdmirx_dev *hdmirx_dev) > > +{ > > + struct hdmi_codec_pdata codec_data = { > > + .ops = &hdmirx_audio_codec_ops, > > + .i2s = 1, > > + .no_i2s_playback = 1, > > + .max_i2s_channels = 8, > > + .data = hdmirx_dev, > > + }; > > + struct platform_device_info pdevinfo = { > > + .parent = hdmirx_dev->dev, > > + .id = PLATFORM_DEVID_AUTO, > > + .name = HDMI_CODEC_DRV_NAME, > > + .data = &codec_data, > > + .size_data = sizeof(codec_data), > > + .dma_mask = DMA_BIT_MASK(32), > > + }; > > + > > + hdmirx_dev->audio_pdev = platform_device_register_full(&pdevinfo); > Nit: platform_device_register_data() should work too. The specified DMA > mask should be unused by the codec driver and even if it was used, it > should be inherited from the parent dev and not fixed to 32bit. Please > either remove .dma_mask or use platform_device_register_data(). > > Please fix Sashiko bug reports for v2. Otherwise, the patch looks okay. > Thanks for working on it. > > -- > Best regards, > Dmitry ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-07-15 19:27 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-15 5:19 [RFC PATCH 0/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 2026-07-15 5:19 ` [RFC PATCH 1/2] dt-bindings: media: snps,dw-hdmi-rx: add #sound-dai-cells Igor Paunovic 2026-07-15 5:54 ` sashiko-bot 2026-07-15 6:55 ` Royal Net 2026-07-15 12:59 ` Sebastian Reichel 2026-07-15 13:19 ` Igor Paunovic 2026-07-15 17:27 ` Sebastian Reichel 2026-07-15 17:41 ` Igor Paunovic 2026-07-15 19:20 ` Sebastian Reichel 2026-07-15 5:19 ` [RFC PATCH 2/2] media: synopsys: hdmirx: add HDMI audio capture support Igor Paunovic 2026-07-15 5:48 ` sashiko-bot 2026-07-15 6:42 ` Royal Net 2026-07-15 19:07 ` Dmitry Osipenko 2026-07-15 19:27 ` Igor Paunovic
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.