Re: [linux-yocto][v5.15/standard/preempt-rt/sdkv5.15/xlnx-soc][PATCH] sound: xilinx: use hdmi-codec as dp audio codec

2024-03-13 Thread Bruce Ashfield
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 
> 
> 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:1063792000   GICv2 151 Level   fd4a.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 USERSTAT   VSZ %VSZ CPU %CPU COMMAND
>   223 2 rootSW   0  0.0   0  0.9 [irq/52-fd4a]
>   352 1 rootS94148  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 
> ---
> 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 
>  #include 
>  #include 
> +#include 
>  
>  #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 = _codec_ops,
> + .spdif = 1,
> + .data = dp,
> + };
> +
> + dp->audio_pdev = platform_device_register_data(
> +  dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE,
> +  _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, 

[linux-yocto][v5.15/standard/preempt-rt/sdkv5.15/xlnx-soc][PATCH] sound: xilinx: use hdmi-codec as dp audio codec

2024-03-13 Thread quanyang.wang via lists.yoctoproject.org
From: Quanyang Wang 

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:1063792000   GICv2 151 Level   fd4a.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 USERSTAT   VSZ %VSZ CPU %CPU COMMAND
  223 2 rootSW   0  0.0   0  0.9 [irq/52-fd4a]
  352 1 rootS94148  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 
---
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
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 
 #include 
 #include 
+#include 
 
 #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 = _codec_ops,
+   .spdif = 1,
+   .data = dp,
+   };
+
+   dp->audio_pdev = platform_device_register_data(
+dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE,
+_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
+++