ASoC: SOF: Intel: hda: reserve host DMA channel for hostless streams
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Wed, 12 Jun 2019 17:23:37 +0000 (12:23 -0500)
committerMark Brown <broonie@kernel.org>
Mon, 17 Jun 2019 12:43:22 +0000 (13:43 +0100)
Due to the HW programming sequence requirement that the host
and link DMA channels need to be coupled/decoupled during pcm
hw_params, the host DMA channel corresponding to the link
DMA channel in use for hostless streams needs to be reserved.
This is achieved by adding a host_reserved flag in the
sof_intel_hda_stream structure which is checked when assigning
a host DMA channel.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/intel/hda-dai.c
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/intel/hda.h

index c270fd7..a514f9c 100644 (file)
@@ -75,7 +75,7 @@ static struct hdac_ext_stream *
 
                hda_stream = hstream_to_sof_hda_stream(hstream);
 
-               /* check if available */
+               /* check if link is available */
                if (!hstream->link_locked) {
                        if (stream->opened) {
                                /*
@@ -89,6 +89,12 @@ static struct hdac_ext_stream *
                                }
                        } else {
                                res = hstream;
+
+                               /*
+                                * This must be a hostless stream.
+                                * So reserve the host DMA channel.
+                                */
+                               hda_stream->host_reserved = 1;
                                break;
                        }
                }
@@ -368,6 +374,9 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
        snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
        link_dev->link_prepared = 0;
 
+       /* free the host DMA channel reserved by hostless streams */
+       hda_stream->host_reserved = 0;
+
        return 0;
 }
 
index 1cd94e7..a3f7c91 100644 (file)
@@ -155,6 +155,7 @@ struct hdac_ext_stream *
 hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
+       struct sof_intel_hda_stream *hda_stream;
        struct hdac_ext_stream *stream = NULL;
        struct hdac_stream *s;
 
@@ -163,8 +164,15 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
        /* get an unused stream */
        list_for_each_entry(s, &bus->stream_list, list) {
                if (s->direction == direction && !s->opened) {
-                       s->opened = true;
                        stream = stream_to_hdac_ext_stream(s);
+                       hda_stream = container_of(stream,
+                                                 struct sof_intel_hda_stream,
+                                                 hda_stream);
+                       /* check if the host DMA channel is reserved */
+                       if (hda_stream->host_reserved)
+                               continue;
+
+                       s->opened = true;
                        break;
                }
        }
index 376b1ca..2862b4b 100644 (file)
@@ -413,6 +413,7 @@ struct sof_intel_hda_stream {
        struct hdac_ext_stream hda_stream;
        struct sof_intel_stream stream;
        int hw_params_upon_resume; /* set up hw_params upon resume */
+       int host_reserved; /* reserve host DMA channel */
 };
 
 #define hstream_to_sof_hda_stream(hstream) \