[PATCH 0/4] ALSA: hda: Abstract and update HOST-stream setup procedure
The patchset targets two intertwined topics:
The driver shall poll SDxFIFOS to ensure a valid value is set by the controller after programming SDxFMT. Due to amount of users and limited-number of configuration available in our CI when compared to overall possibilities on the market, the check is non-blocking.
Second topic relates to stream setup procedure. The procedure differs between HDAudio controller device revisions. Right now those differences are handled directly by a platform driver. Existing top-level 'if (pci->device == APL)' could be replaced by a abstraction in lower parts of the code instead.
With that done, the two users are updated accordingly. In avs-driver case, this updates the flow to the recommended one.
Cezary Rojewski (4): ALSA: hda: Poll SDxFIFOS after programming SDxFMT ALSA: hda: Introduce HOST stream setup mechanism ASoC: Intel: avs: Use helper to setup HOST stream ASoC: Intel: Skylake: Use helper to setup HOST stream
include/sound/hda_register.h | 2 ++ include/sound/hdaudio.h | 3 +++ include/sound/hdaudio_ext.h | 3 +++ sound/hda/ext/hdac_ext_stream.c | 41 +++++++++++++++++++++++++++++++ sound/hda/hdac_stream.c | 8 ++++++ sound/soc/intel/avs/pcm.c | 2 +- sound/soc/intel/skylake/skl-pcm.c | 14 +---------- 7 files changed, 59 insertions(+), 14 deletions(-)
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(+)
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,
HDAudio stream setup procedure differs between revisions of the controller device. Currently the differences are handled directly within AudioDSP platform drivers with if-statements. Implement a more generic approach and expose a function that a platform driver may use to ensure the correct procedure is followed each time.
Signed-off-by: Cezary Rojewski cezary.rojewski@intel.com --- include/sound/hdaudio_ext.h | 3 +++ sound/hda/ext/hdac_ext_stream.c | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 511211f4a2b6..d32959cb71d2 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -60,6 +60,8 @@ struct hdac_ext_stream { bool link_locked:1; bool link_prepared;
+ int (*host_setup)(struct hdac_stream *); + struct snd_pcm_substream *link_substream; };
@@ -86,6 +88,7 @@ void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream); void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream); void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream); int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt); +int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream);
struct hdac_ext_link { struct hdac_bus *bus; diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 11b7119cc47e..292bbf91acd0 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -10,12 +10,45 @@ */
#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> #include <linux/slab.h> #include <sound/pcm.h> #include <sound/hda_register.h> #include <sound/hdaudio_ext.h> #include <sound/compress_driver.h>
+/** + * snd_hdac_ext_host_stream_setup - Setup a HOST stream. + * @hext_stream - HDAudio stream to set up. + * + * Return: Zero on success or negative error code. + */ +int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream) +{ + return hext_stream->host_setup(hdac_stream(hext_stream)); +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_host_stream_setup); + +/** + * snd_hdac_apl_host_stream_setup - Setup a HOST stream following procedure + * recommended for ApolloLake devices. + * @hstream - HDAudio stream to set up. + * + * Return: Zero on success or negative error code. + */ +static int snd_hdac_apl_host_stream_setup(struct hdac_stream *hstream) +{ + struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); + int ret; + + snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, false); + ret = snd_hdac_stream_setup(hstream); + snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, true); + + return ret; +} + /** * snd_hdac_ext_stream_init - initialize each stream (aka device) * @bus: HD-audio core bus @@ -55,9 +88,16 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus, int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir) { + struct pci_dev *pci = to_pci_dev(bus->dev); + int (*setup_op)(struct hdac_stream *); int stream_tag = 0; int i, tag, idx = start_idx;
+ if (pci->device == PCI_DEVICE_ID_INTEL_HDA_APL) + setup_op = snd_hdac_stream_setup; + else + setup_op = snd_hdac_apl_host_stream_setup; + for (i = 0; i < num_stream; i++) { struct hdac_ext_stream *hext_stream = kzalloc(sizeof(*hext_stream), GFP_KERNEL); @@ -66,6 +106,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, tag = ++stream_tag; snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag); idx++; + hext_stream->host_setup = setup_op; }
return 0;
On 2023-09-25 1:58 PM, Cezary Rojewski wrote:
HDAudio stream setup procedure differs between revisions of the controller device. Currently the differences are handled directly within AudioDSP platform drivers with if-statements. Implement a more generic approach and expose a function that a platform driver may use to ensure the correct procedure is followed each time.
...
@@ -55,9 +88,16 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus, int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir) {
struct pci_dev *pci = to_pci_dev(bus->dev);
int (*setup_op)(struct hdac_stream *); int stream_tag = 0; int i, tag, idx = start_idx;
if (pci->device == PCI_DEVICE_ID_INTEL_HDA_APL)
setup_op = snd_hdac_stream_setup;
else
setup_op = snd_hdac_apl_host_stream_setup;
Sorry for this, due to renaming I did send incorrect revision of patchset. The if-statement was "negative" previously. Will send v2.
for (i = 0; i < num_stream; i++) { struct hdac_ext_stream *hext_stream = kzalloc(sizeof(*hext_stream), GFP_KERNEL); @@ -66,6 +106,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, tag = ++stream_tag; snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag); idx++;
hext_stream->host_setup = setup_op;
}
return 0;
Hi Cezary,
kernel test robot noticed the following build warnings:
[auto build test WARNING on tiwai-sound/for-next] [also build test WARNING on tiwai-sound/for-linus broonie-sound/for-next linus/master v6.6-rc3 next-20230925] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Cezary-Rojewski/ALSA-hda-Poll... base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next patch link: https://lore.kernel.org/r/20230925115844.18795-3-cezary.rojewski%40intel.com patch subject: [PATCH 2/4] ALSA: hda: Introduce HOST stream setup mechanism config: x86_64-buildonly-randconfig-002-20230925 (https://download.01.org/0day-ci/archive/20230925/202309252200.gnjksNmD-lkp@i...) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230925/202309252200.gnjksNmD-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202309252200.gnjksNmD-lkp@intel.com/
All warnings (new ones prefixed by >>):
sound/hda/ext/hdac_ext_stream.c:28: warning: Function parameter or member 'hext_stream' not described in 'snd_hdac_ext_host_stream_setup' sound/hda/ext/hdac_ext_stream.c:41: warning: Function parameter or member 'hstream' not described in 'snd_hdac_apl_host_stream_setup'
vim +28 sound/hda/ext/hdac_ext_stream.c
20 21 /** 22 * snd_hdac_ext_host_stream_setup - Setup a HOST stream. 23 * @hext_stream - HDAudio stream to set up. 24 * 25 * Return: Zero on success or negative error code. 26 */ 27 int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream)
28 {
29 return hext_stream->host_setup(hdac_stream(hext_stream)); 30 } 31 EXPORT_SYMBOL_GPL(snd_hdac_ext_host_stream_setup); 32 33 /** 34 * snd_hdac_apl_host_stream_setup - Setup a HOST stream following procedure 35 * recommended for ApolloLake devices. 36 * @hstream - HDAudio stream to set up. 37 * 38 * Return: Zero on success or negative error code. 39 */ 40 static int snd_hdac_apl_host_stream_setup(struct hdac_stream *hstream)
41 {
42 struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); 43 int ret; 44 45 snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, false); 46 ret = snd_hdac_stream_setup(hstream); 47 snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, true); 48 49 return ret; 50 } 51
snd_hdac_ext_host_stream_setup() abstracts the procedure details away. Simplify the code by using it.
Signed-off-by: Cezary Rojewski cezary.rojewski@intel.com --- sound/soc/intel/avs/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 8565a530706d..e628fdfdc018 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -625,7 +625,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (ret < 0) return ret;
- ret = snd_hdac_stream_setup(hdac_stream(host_stream)); + ret = snd_hdac_ext_host_stream_setup(host_stream); if (ret < 0) return ret;
On Mon, Sep 25, 2023 at 01:58:43PM +0200, Cezary Rojewski wrote:
snd_hdac_ext_host_stream_setup() abstracts the procedure details away. Simplify the code by using it.
Acked-by: Mark Brown broonie@kernel.org
snd_hdac_ext_host_stream_setup() abstracts the procedure details away. Simplify the code by using it.
Signed-off-by: Cezary Rojewski cezary.rojewski@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index ac3dc8c63c26..7502b2e70e46 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -124,7 +124,6 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) { struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl_dev *skl = bus_to_skl(bus); unsigned int format_val; struct hdac_stream *hstream; struct hdac_ext_stream *stream; @@ -149,18 +148,7 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) if (err < 0) return err;
- /* - * The recommended SDxFMT programming sequence for BXT - * platforms is to couple the stream before writing the format - */ - if (HDA_CONTROLLER_IS_APL(skl->pci)) { - snd_hdac_ext_stream_decouple(bus, stream, false); - err = snd_hdac_stream_setup(hdac_stream(stream)); - snd_hdac_ext_stream_decouple(bus, stream, true); - } else { - err = snd_hdac_stream_setup(hdac_stream(stream)); - } - + err = snd_hdac_ext_host_stream_setup(stream); if (err < 0) return err;
On Mon, Sep 25, 2023 at 01:58:44PM +0200, Cezary Rojewski wrote:
snd_hdac_ext_host_stream_setup() abstracts the procedure details away. Simplify the code by using it.
Acked-by: Mark Brown broonie@kernel.org
participants (3)
-
Cezary Rojewski
-
kernel test robot
-
Mark Brown