diff mbox series

[v3,1/4] ALSA: hda: Poll SDxFIFOS after programming SDxFMT

Message ID 20230926080623.43927-2-cezary.rojewski@intel.com (mailing list archive)
State New, archived
Headers show
Series ALSA: hda: Abstract and update HOST-stream setup procedure | expand

Commit Message

Cezary Rojewski Sept. 26, 2023, 8:06 a.m. UTC
Software shall read SDxFIFOS calculated by the hardware and notify if
invalid value is programmed before continuing the stream preparation.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 include/sound/hda_register.h | 2 ++
 include/sound/hdaudio.h      | 3 +++
 sound/hda/hdac_stream.c      | 8 ++++++++
 3 files changed, 13 insertions(+)

Comments

Cezary Rojewski Sept. 28, 2023, 4:37 p.m. UTC | #1
On 2023-09-26 10:06 AM, Cezary Rojewski wrote:
> Software shall read SDxFIFOS calculated by the hardware and notify if
> invalid value is programmed before continuing the stream preparation.

...

> @@ -300,6 +302,12 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
>   	/* set the interrupt enable bits in the descriptor control register */
>   	snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK);
>   
> +	/* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */
> +	ret = snd_hdac_stream_readw_poll(azx_dev, SD_FIFOSIZE, reg, reg & AZX_SD_FIFOSIZE_MASK,
> +					 3, 300);
> +	if (ret)
> +		dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n",
> +			AZX_REG_SD_FIFOSIZE, ret);

There is one (negligible?) side effect. AudioDSP firmware is the one who 
kicks SDxFIFOS calculation when a stream is decoupled mode. During 
firmware bring up procedure, there is no firmware running _and_ the 
code-loading stream is always a decoupled one. So, there is none to 
trigger the calculation and we end up with debug -110 messages. It looks 
like to do this in complete fashion some refactoring is needed in 
hdac_stream.c/hdac_ext_stream.c.

Czarek

>   	azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1;
>   
>   	/* when LPIB delay correction gives a small negative value,
diff mbox series

Patch

diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
index 9c7872c0ca79..55958711d697 100644
--- a/include/sound/hda_register.h
+++ b/include/sound/hda_register.h
@@ -91,6 +91,8 @@  enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_REG_SD_BDLPL		0x18
 #define AZX_REG_SD_BDLPU		0x1c
 
+#define AZX_SD_FIFOSIZE_MASK		GENMASK(15, 0)
+
 /* GTS registers */
 #define AZX_REG_LLCH			0x14
 
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 32c59053b48e..41d725babf53 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -624,6 +624,9 @@  int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);
 #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
 	read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
 				 false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
+#define snd_hdac_stream_readw_poll(dev, reg, val, cond, delay_us, timeout_us) \
+	read_poll_timeout_atomic(snd_hdac_reg_readw, val, cond, delay_us, timeout_us, \
+				 false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
 	read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
 				 false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index 2633a4bb1d85..5382894bebab 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -258,6 +258,8 @@  int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
 	struct hdac_bus *bus = azx_dev->bus;
 	struct snd_pcm_runtime *runtime;
 	unsigned int val;
+	u16 reg;
+	int ret;
 
 	if (azx_dev->substream)
 		runtime = azx_dev->substream->runtime;
@@ -300,6 +302,12 @@  int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
 	/* set the interrupt enable bits in the descriptor control register */
 	snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK);
 
+	/* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */
+	ret = snd_hdac_stream_readw_poll(azx_dev, SD_FIFOSIZE, reg, reg & AZX_SD_FIFOSIZE_MASK,
+					 3, 300);
+	if (ret)
+		dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n",
+			AZX_REG_SD_FIFOSIZE, ret);
 	azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1;
 
 	/* when LPIB delay correction gives a small negative value,