In message: [linux-yocto][v5.15/standard/preempt-rt/sdkv5.15/xlnx-soc][PATCH] 
sound: xilinx: use hdmi-codec as dp audio codec
on 13/03/2024 quanyang.w...@windriver.com wrote:

> From: Quanyang Wang <quanyang.w...@windriver.com>
> 
> According to the description in the section "Audio Management" of
> Chapter 33 in "Zynq UltraScale+ Device Technical Reference Manual",
> A set/clr operation to TX_AUDIO_CONTROL register is needed when we
> start/stop audio play. It means that when we stop playing audio,
> TX_AUDIO_CONTROL register should be cleared. Now the dp codec driver
> xilinx-dp-codec.c can't access DP Tx registers and it has no control
> of DP Tx Audio registers. This results that even if we close the audio
> device after playing audio, Tx Audio is still working and it triggers
> numerous underflow interrupts (bit 17 in DP_INT_STATUS).
> 
> zcu102-zynqmp:~$ cat /proc/interrupts | grep display
>  52:    1063792    0    0    0   GICv2 151 Level   fd4a0000.display
> 
> zcu102-zynqmp:~$ top
> Mem: 158168K used, 3864792K free, 9992K shrd, 0K buff, 36500K cached
> CPU:  0.0% usr  1.0% sys  0.0% nic 98.9% idle  0.0% io  0.0% irq  0.0% sirq
> Load average: 0.03 0.03 0.01 1/122 391
>   PID  PPID USER    STAT   VSZ %VSZ CPU %CPU COMMAND
>   223     2 root    SW       0  0.0   0  0.9 [irq/52-fd4a0000]
>   352     1 root    S    94148  2.3   0  0.0 /usr/sbin/tcf-agent -d -L- -l0
> 
> So we register a HDMI codec device and use callbacks in hdmi_codec_ops
> to set/clr TX_AUDIO_CONTROL.
> 
> Signed-off-by: Quanyang Wang <quanyang.w...@windriver.com>
> ---
> Hi Bruce,
> Would you please help merge this patch to the branches:
>       v5.15/standard/preempt-rt/sdkv5.15/xlnx-soc
>       v5.15/standard/sdkv5.15/xlnx-soc

merged.

Bruce

> Thanks,
> Quanyang
> ---
>  drivers/gpu/drm/xlnx/zynqmp_dp.c  | 55 +++++++++++++++++++++++++++++++
>  sound/soc/xilinx/Kconfig          |  1 +
>  sound/soc/xilinx/xilinx-dp-card.c | 14 ++------
>  3 files changed, 59 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c 
> b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index 308404f122957..c9badbfe5b566 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -26,6 +26,7 @@
>  #include <linux/phy/phy.h>
>  #include <linux/reset.h>
>  #include <linux/uaccess.h>
> +#include <sound/hdmi-codec.h>
>  
>  #include "zynqmp_disp.h"
>  #include "zynqmp_dp.h"
> @@ -329,6 +330,7 @@ struct zynqmp_dp {
>       void __iomem *iomem;
>       struct reset_control *reset;
>       int irq;
> +     struct platform_device *audio_pdev;
>  
>       struct zynqmp_dp_config config;
>       struct drm_dp_aux aux;
> @@ -375,6 +377,53 @@ static void zynqmp_dp_set(void __iomem *base, int 
> offset, u32 set)
>       zynqmp_dp_write(base, offset, zynqmp_dp_read(base, offset) | set);
>  }
>  
> +static int zynqmp_dp_audio_hw_params(struct device *dev,  void *data,
> +                                struct hdmi_codec_daifmt *daifmt,
> +                                struct hdmi_codec_params *params)
> +{
> +     return 0;
> +}
> +
> +static int zynqmp_dp_audio_startup(struct device *dev, void *data)
> +{
> +     struct zynqmp_dp *dp = data;
> +
> +     if (zynqmp_disp_aud_enabled(dp->dpsub->disp))
> +             zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
> +
> +     return 0;
> +}
> +
> +static void zynqmp_dp_audio_shutdown(struct device *dev, void *data)
> +{
> +     struct zynqmp_dp *dp = data;
> +
> +     if (zynqmp_disp_aud_enabled(dp->dpsub->disp))
> +             zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
> +}
> +
> +static const struct hdmi_codec_ops audio_codec_ops = {
> +     .hw_params = zynqmp_dp_audio_hw_params,
> +     .audio_shutdown = zynqmp_dp_audio_shutdown,
> +     .audio_startup = zynqmp_dp_audio_startup,
> +};
> +
> +static int zynqmp_dp_audio_init(struct zynqmp_dp *dp,
> +                                struct device *dev)
> +{
> +     struct hdmi_codec_pdata codec_data = {
> +             .ops = &audio_codec_ops,
> +             .spdif = 1,
> +             .data = dp,
> +     };
> +
> +     dp->audio_pdev = platform_device_register_data(
> +                      dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE,
> +                      &codec_data, sizeof(codec_data));
> +
> +     return PTR_ERR_OR_ZERO(dp->audio_pdev);
> +}
> +
>  /* 
> -----------------------------------------------------------------------------
>   * PHY Handling
>   */
> @@ -1950,6 +1999,12 @@ int zynqmp_dp_probe(struct platform_device *pdev)
>               goto error;
>       }
>  
> +     ret = zynqmp_dp_audio_init(dp, dp->dev);
> +     if (ret < 0) {
> +             dev_err(dp->dev, "failed to initialize DP audio codec\n");
> +             goto error;
> +     }
> +
>       irq = platform_get_irq(pdev, 0);
>       if (irq < 0) {
>               ret = irq;
> diff --git a/sound/soc/xilinx/Kconfig b/sound/soc/xilinx/Kconfig
> index ade55b32a8cc6..787b92a406a23 100644
> --- a/sound/soc/xilinx/Kconfig
> +++ b/sound/soc/xilinx/Kconfig
> @@ -3,6 +3,7 @@ config SND_SOC_XILINX_DP
>       tristate "Audio support for the the Xilinx DisplayPort"
>       select SND_DMAENGINE_PCM
>       select SND_SOC_GENERIC_DMAENGINE_PCM
> +     select SND_SOC_HDMI_CODEC
>       help
>         Audio support the for Xilinx DisplayPort.
>  
> diff --git a/sound/soc/xilinx/xilinx-dp-card.c 
> b/sound/soc/xilinx/xilinx-dp-card.c
> index 396a87d56394f..ec0682f2a7a6c 100644
> --- a/sound/soc/xilinx/xilinx-dp-card.c
> +++ b/sound/soc/xilinx/xilinx-dp-card.c
> @@ -36,12 +36,12 @@ static const struct snd_soc_ops xilinx_dp_ops = {
>  
>  SND_SOC_DAILINK_DEFS(xilinx_dp0,
>               DAILINK_COMP_ARRAY(COMP_CPU("xilinx-dp-snd-codec-dai")),
> -             DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "xilinx-dp-snd-codec-dai")),
> +             DAILINK_COMP_ARRAY(COMP_CODEC("hdmi-audio-codec", 
> "spdif-hifi")),
>               DAILINK_COMP_ARRAY(COMP_PLATFORM(NULL)));
>  
>  SND_SOC_DAILINK_DEFS(xilinx_dp1,
>               DAILINK_COMP_ARRAY(COMP_CPU("xilinx-dp-snd-codec-dai")),
> -             DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "xilinx-dp-snd-codec-dai")),
> +             DAILINK_COMP_ARRAY(COMP_CODEC("hdmi-audio-codec", 
> "spdif-hifi")),
>               DAILINK_COMP_ARRAY(COMP_PLATFORM(NULL)));
>  
>  static struct snd_soc_dai_link xilinx_dp_dai_links[] = {
> @@ -71,28 +71,20 @@ static int xilinx_dp_probe(struct platform_device *pdev)
>  {
>       struct snd_soc_card *card = &xilinx_dp_card;
>       struct device_node *node = pdev->dev.of_node;
> -     struct device_node *codec, *pcm;
> +     struct device_node *pcm;
>       int ret;
>  
>       card->dev = &pdev->dev;
>  
> -     codec = of_parse_phandle(node, "xlnx,dp-snd-codec", 0);
> -     if (!codec)
> -             return -ENODEV;
> -
>       pcm = of_parse_phandle(node, "xlnx,dp-snd-pcm", 0);
>       if (!pcm)
>               return -ENODEV;
>       xilinx_dp_dai_links[0].platforms->of_node = pcm;
> -     xilinx_dp_dai_links[0].cpus->of_node = codec;
> -     xilinx_dp_dai_links[0].codecs->of_node = codec;
>  
>       pcm = of_parse_phandle(node, "xlnx,dp-snd-pcm", 1);
>       if (!pcm)
>               return -ENODEV;
>       xilinx_dp_dai_links[1].platforms->of_node = pcm;
> -     xilinx_dp_dai_links[1].cpus->of_node = codec;
> -     xilinx_dp_dai_links[1].codecs->of_node = codec;
>  
>       ret = devm_snd_soc_register_card(&pdev->dev, card);
>       if (ret)
> -- 
> 2.36.1
> 
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#13685): 
https://lists.yoctoproject.org/g/linux-yocto/message/13685
Mute This Topic: https://lists.yoctoproject.org/mt/104902291/21656
Group Owner: linux-yocto+ow...@lists.yoctoproject.org
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to