ASoC: SOF: intel: hda: add hw_params_upon_resume flag for hda stream
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Tue, 30 Apr 2019 23:09:31 +0000 (18:09 -0500)
committerMark Brown <broonie@kernel.org>
Fri, 3 May 2019 06:01:45 +0000 (15:01 +0900)
The prepare() ioctl for BE dai link gets called both
when the stream is started and when it is resumed from
suspend. SOF uses this ioctl to set the hw params
again only if the stream has been suspended.

When the stream is started, the hw_params ioctl gets called
before prepare() and hw_params is set for the BE dai link.
So the prepare call does not need to do anything further.

When the stream resumes after system suspend, SOF requires
that the hw_params be set again for the BE dai. In order
to determine which streams should set the hw params
during prepare(), an internal flag called "hw_params_upon_resume"
is introduced in struct sof_intel_hda_stream. The flag is set
for hda streams when the sof device suspends and is
cleared after hw_params is set.

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/apl.c
sound/soc/sof/intel/cnl.c
sound/soc/sof/intel/hda-dai.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/hda.h
sound/soc/sof/ops.h
sound/soc/sof/pm.c
sound/soc/sof/sof-priv.h

index 026dde83962186f856b1ffecc67851471775e485..d1fb2f2ba1e1cc88c3b5b0928a9c87516f1001cf 100644 (file)
@@ -91,6 +91,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
        .resume                 = hda_dsp_resume,
        .runtime_suspend        = hda_dsp_runtime_suspend,
        .runtime_resume         = hda_dsp_runtime_resume,
+       .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
 };
 EXPORT_SYMBOL(sof_apl_ops);
 
index d128839b24504bf682ecdee3b52e930333e96462..2eac20bbcaea0314ddb191f6a3151cc145a23f2a 100644 (file)
@@ -225,6 +225,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
        .resume                 = hda_dsp_resume,
        .runtime_suspend        = hda_dsp_runtime_suspend,
        .runtime_resume         = hda_dsp_runtime_resume,
+       .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
 };
 EXPORT_SYMBOL(sof_cnl_ops);
 
index 830328af19c5ef52e3499b37347767c06901b315..e1decf25aeace3c2474648219d5fb9044c6998a4 100644 (file)
@@ -131,12 +131,17 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
        struct hdac_ext_stream *link_dev;
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct sof_intel_hda_stream *hda_stream;
        struct hda_pipe_params p_params = {0};
        struct hdac_ext_link *link;
        int stream_tag;
 
        link_dev = snd_soc_dai_get_dma_data(dai, substream);
 
+       hda_stream = container_of(link_dev, struct sof_intel_hda_stream,
+                                 hda_stream);
+       hda_stream->hw_params_upon_resume = 0;
+
        link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
        if (!link)
                return -EINVAL;
@@ -168,22 +173,22 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
 static int hda_link_pcm_prepare(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct hdac_ext_stream *link_dev =
+                               snd_soc_dai_get_dma_data(dai, substream);
+       struct sof_intel_hda_stream *hda_stream;
        struct snd_sof_dev *sdev =
-               snd_soc_component_get_drvdata(dai->component);
-       struct snd_sof_pcm *spcm;
+                               snd_soc_component_get_drvdata(dai->component);
+       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
        int stream = substream->stream;
 
-       spcm = snd_sof_find_spcm_dai(sdev, rtd);
-       if (!spcm)
-               return -EINVAL;
+       hda_stream = container_of(link_dev, struct sof_intel_hda_stream,
+                                 hda_stream);
 
        /* setup hw_params again only if resuming from system suspend */
-       if (!spcm->hw_params_upon_resume[stream])
+       if (!hda_stream->hw_params_upon_resume)
                return 0;
 
-       dev_dbg(sdev->dev, "hda: prepare stream %d dir %d\n",
-               spcm->pcm.pcm_id, substream->stream);
+       dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream);
 
        return hda_link_hw_params(substream, &rtd->dpcm[stream].hw_params,
                                  dai);
index 311fed502e09fc4e38817030ae55305be240552d..5b73115a0b787352c443cbcf37db532691f58652 100644 (file)
@@ -453,3 +453,19 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state)
 
        return 0;
 }
+
+void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
+{
+       struct hdac_bus *bus = sof_to_bus(sdev);
+       struct sof_intel_hda_stream *hda_stream;
+       struct hdac_ext_stream *stream;
+       struct hdac_stream *s;
+
+       /* set internal flag for BE */
+       list_for_each_entry(s, &bus->stream_list, list) {
+               stream = stream_to_hdac_ext_stream(s);
+               hda_stream = container_of(stream, struct sof_intel_hda_stream,
+                                         hda_stream);
+               hda_stream->hw_params_upon_resume = 1;
+       }
+}
index 7cb2fb92c4eba25584344dd2c7ad3e1532796037..4b00e5d88565e3f85269f437b5e0d47b3c192b5c 100644 (file)
@@ -409,6 +409,7 @@ static inline struct hda_bus *sof_to_hbus(struct snd_sof_dev *s)
 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 */
 };
 
 #define bus_to_sof_hda(bus) \
@@ -443,6 +444,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state);
 int hda_dsp_resume(struct snd_sof_dev *sdev);
 int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state);
 int hda_dsp_runtime_resume(struct snd_sof_dev *sdev);
+void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
 void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags);
 void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
 
index 2a5d4c63f160f899d09b5103fa22203a1cdffdb0..b8e2bf1fee2474b871e80c31d3fd77fcd48d6205 100644 (file)
@@ -134,6 +134,12 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev,
        return 0;
 }
 
+static inline void snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
+{
+       if (sof_ops(sdev)->set_hw_params_upon_resume)
+               sof_ops(sdev)->set_hw_params_upon_resume(sdev);
+}
+
 static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
 {
        if (sof_ops(sdev)->set_clk)
index fc599e1b6f65e643780a249e44b6ef82fb1e5308..8ef1d51025d8bb0929644691a21421a94d126c95 100644 (file)
@@ -227,6 +227,9 @@ static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
                                spcm->hw_params_upon_resume[dir] = 1;
                }
        }
+
+       /* set internal flag for BE */
+       snd_sof_dsp_hw_params_upon_resume(sdev);
 }
 
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
index bbc285018f9a729e7ac9882218d1862cabbb4bfb..170adc21ef1753063cba51969ad6986c12099260 100644 (file)
@@ -166,6 +166,7 @@ struct snd_sof_dsp_ops {
        int (*runtime_suspend)(struct snd_sof_dev *sof_dev,
                               int state); /* optional */
        int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */
+       void (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */
 
        /* DSP clocking */
        int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */