summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-03-26 22:04:31 +0300
committerMark Brown <broonie@kernel.org>2020-03-26 22:04:31 +0300
commit7e37c5cf555f525ed84167c26d514476cca46893 (patch)
tree955ac9ed66c51c3859be66db1ad0d8d50a84a50e
parent27821f4ddedcaea0f16d03ee3432bddb729daba5 (diff)
parent7e26df0ced1643679922d197e798d469ac3bf9c0 (diff)
downloadlinux-7e37c5cf555f525ed84167c26d514476cca46893.tar.xz
Merge series "ASoC: SOF: cleanups and improvements" from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:
Couple of small patches to improve error handling, inits, logs. Hope we can have this for 5.7? Guennadi Liakhovetski (2): ASoC: SOF: (cosmetic) use for_each_pcm_streams() in sof_dai_load() ASoC: SOF: fix uninitialised "work" with VirtIO Kai Vehmanen (2): ASoC: SOF: Intel: hda: do not leave clock gating off upon error ASoC: SOF: Intel: hda: call codec wake at chip init Ranjani Sridharan (1): ASoC: SOF: Intel: hda: Improve DSP state logging sound/soc/sof/intel/hda-ctrl.c | 15 +++++++++--- sound/soc/sof/intel/hda-dsp.c | 43 ++++++++++++++++++++++++++++++++-- sound/soc/sof/pcm.c | 4 +--- sound/soc/sof/sof-audio.h | 3 +++ sound/soc/sof/topology.c | 17 ++++++++++---- 5 files changed, 69 insertions(+), 13 deletions(-) -- 2.20.1
-rw-r--r--sound/soc/sof/intel/hda-ctrl.c15
-rw-r--r--sound/soc/sof/intel/hda-dsp.c43
-rw-r--r--sound/soc/sof/pcm.c4
-rw-r--r--sound/soc/sof/sof-audio.h3
-rw-r--r--sound/soc/sof/topology.c17
5 files changed, 69 insertions, 13 deletions
diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c
index 871b71a15a63..f88dbcc4ba66 100644
--- a/sound/soc/sof/intel/hda-ctrl.c
+++ b/sound/soc/sof/intel/hda-ctrl.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
+#include <sound/hda_component.h>
#include "../ops.h"
#include "hda.h"
@@ -176,6 +177,9 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
if (bus->chip_init)
return 0;
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+ snd_hdac_set_codec_wakeup(bus, true);
+#endif
hda_dsp_ctrl_misc_clock_gating(sdev, false);
if (full_reset) {
@@ -183,7 +187,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
ret = hda_dsp_ctrl_link_reset(sdev, true);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to reset HDA controller\n");
- return ret;
+ goto err;
}
usleep_range(500, 1000);
@@ -192,7 +196,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
ret = hda_dsp_ctrl_link_reset(sdev, false);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
- return ret;
+ goto err;
}
usleep_range(1000, 1200);
@@ -202,7 +206,8 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
/* check to see if controller is ready */
if (!snd_hdac_chip_readb(bus, GCTL)) {
dev_dbg(bus->dev, "controller not ready!\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto err;
}
/* Accept unsolicited responses */
@@ -268,7 +273,11 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
bus->chip_init = true;
+err:
hda_dsp_ctrl_misc_clock_gating(sdev, true);
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+ snd_hdac_set_codec_wakeup(bus, false);
+#endif
return ret;
}
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 79ce52c32ef1..c396b7ef0328 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -452,6 +452,46 @@ revert:
return ret;
}
+/* helper to log DSP state */
+static void hda_dsp_state_log(struct snd_sof_dev *sdev)
+{
+ switch (sdev->dsp_power_state.state) {
+ case SOF_DSP_PM_D0:
+ switch (sdev->dsp_power_state.substate) {
+ case SOF_HDA_DSP_PM_D0I0:
+ dev_dbg(sdev->dev, "Current DSP power state: D0I0\n");
+ break;
+ case SOF_HDA_DSP_PM_D0I3:
+ dev_dbg(sdev->dev, "Current DSP power state: D0I3\n");
+ break;
+ default:
+ dev_dbg(sdev->dev, "Unknown DSP D0 substate: %d\n",
+ sdev->dsp_power_state.substate);
+ break;
+ }
+ break;
+ case SOF_DSP_PM_D1:
+ dev_dbg(sdev->dev, "Current DSP power state: D1\n");
+ break;
+ case SOF_DSP_PM_D2:
+ dev_dbg(sdev->dev, "Current DSP power state: D2\n");
+ break;
+ case SOF_DSP_PM_D3_HOT:
+ dev_dbg(sdev->dev, "Current DSP power state: D3_HOT\n");
+ break;
+ case SOF_DSP_PM_D3:
+ dev_dbg(sdev->dev, "Current DSP power state: D3\n");
+ break;
+ case SOF_DSP_PM_D3_COLD:
+ dev_dbg(sdev->dev, "Current DSP power state: D3_COLD\n");
+ break;
+ default:
+ dev_dbg(sdev->dev, "Unknown DSP power state: %d\n",
+ sdev->dsp_power_state.state);
+ break;
+ }
+}
+
/*
* All DSP power state transitions are initiated by the driver.
* If the requested state change fails, the error is simply returned.
@@ -511,8 +551,7 @@ set_state:
}
sdev->dsp_power_state = *target_state;
- dev_dbg(sdev->dev, "New DSP state %d substate %d\n",
- target_state->state, target_state->substate);
+ hda_dsp_state_log(sdev);
return ret;
}
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index f4769e19965a..47cd741f2a8c 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -57,7 +57,7 @@ static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream
/*
* sof pcm period elapse work
*/
-static void sof_pcm_period_elapsed_work(struct work_struct *work)
+void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
{
struct snd_sof_pcm_stream *sps =
container_of(work, struct snd_sof_pcm_stream,
@@ -475,8 +475,6 @@ static int sof_pcm_open(struct snd_soc_component *component,
dev_dbg(component->dev, "pcm: open stream %d dir %d\n",
spcm->pcm.pcm_id, substream->stream);
- INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
- sof_pcm_period_elapsed_work);
caps = &spcm->pcm.caps[substream->stream];
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index eacd10e4da11..bf65f31af858 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -11,6 +11,8 @@
#ifndef __SOUND_SOC_SOF_AUDIO_H
#define __SOUND_SOC_SOF_AUDIO_H
+#include <linux/workqueue.h>
+
#include <sound/soc.h>
#include <sound/control.h>
#include <sound/sof/stream.h> /* needs to be included before control.h */
@@ -189,6 +191,7 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp,
struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
unsigned int pcm_id);
void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
+void snd_sof_pcm_period_elapsed_work(struct work_struct *work);
/*
* Mixer IPC
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 058de94fb8cf..fe8ba3e05e08 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -9,6 +9,7 @@
//
#include <linux/firmware.h>
+#include <linux/workqueue.h>
#include <sound/tlv.h>
#include <sound/pcm_params.h>
#include <uapi/sound/sof/tokens.h>
@@ -2448,7 +2449,7 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
struct snd_soc_tplg_stream_caps *caps;
struct snd_soc_tplg_private *private = &pcm->priv;
struct snd_sof_pcm *spcm;
- int stream = SNDRV_PCM_STREAM_PLAYBACK;
+ int stream;
int ret = 0;
/* nothing to do for BEs atm */
@@ -2460,8 +2461,12 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
return -ENOMEM;
spcm->scomp = scomp;
- spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id = COMP_ID_UNASSIGNED;
- spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id = COMP_ID_UNASSIGNED;
+
+ for_each_pcm_streams(stream) {
+ spcm->stream[stream].comp_id = COMP_ID_UNASSIGNED;
+ INIT_WORK(&spcm->stream[stream].period_elapsed_work,
+ snd_sof_pcm_period_elapsed_work);
+ }
spcm->pcm = *pcm;
dev_dbg(scomp->dev, "tplg: load pcm %s\n", pcm->dai_name);
@@ -2482,8 +2487,10 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
if (!spcm->pcm.playback)
goto capture;
+ stream = SNDRV_PCM_STREAM_PLAYBACK;
+
dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n",
- spcm->pcm.pcm_name, spcm->stream[0].d0i3_compatible);
+ spcm->pcm.pcm_name, spcm->stream[stream].d0i3_compatible);
caps = &spcm->pcm.caps[stream];
@@ -2513,7 +2520,7 @@ capture:
return ret;
dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n",
- spcm->pcm.pcm_name, spcm->stream[1].d0i3_compatible);
+ spcm->pcm.pcm_name, spcm->stream[stream].d0i3_compatible);
caps = &spcm->pcm.caps[stream];