]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ALSA: hda: Introduce HOST stream setup mechanism
authorCezary Rojewski <cezary.rojewski@intel.com>
Tue, 26 Sep 2023 08:06:21 +0000 (10:06 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 6 Oct 2023 09:11:39 +0000 (11:11 +0200)
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>
Link: https://lore.kernel.org/r/20230926080623.43927-3-cezary.rojewski@intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/hdaudio_ext.h
sound/hda/ext/hdac_ext_stream.c

index 511211f4a2b66fa94f97f91c5223387789d286ad..d32959cb71d27f366c66d8f05df62be413b34288 100644 (file)
@@ -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;
index 11b7119cc47e631892cec7bb8ed8c0958908266a..186e95bffb2828999ffba48d611375e8a5686e23 100644 (file)
  */
 
 #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_apl_host_stream_setup;
+       else
+               setup_op = snd_hdac_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;