[alsa-devel] [PATCH v4 0/9] ASoC: Intel: Skylake: Driver updates
From: Jeeja KP jeeja.kp@intel.com
This patch series includes driver updates for the handling scenarios during System S0/S3 transitions when audio stream is stopped during system. o move DMA configuration in DSP Gateway Module widget event handler to ensure DMA is configured after resume. o Enable SSP MLCK using Supply widget. This will ensure the MCLK is enabled when the widget is power on. o Check DMA decouple register state before coupling/decoupling the DMA. o In case of HDMI pass-through pipe, reset only the FE Pipe when stream in in XRUN state. o Resume the stream from HW renderer position. o HDMI Codec pin and converter state need to be restored when stream is resumed.
Changes in v2: - Addressed Mark's comment on patch 1, split this into 2 as this had additional changes other than configuring the DMA. - Addressed Takashi's comment on the usage of snd_hdac_updatel()
Changes in v3: - Addressed Takashi's comment on superfluous shift used in reading the value of PPCTL register and also cleaned the condition for updating the reg value.
Changes in v4: - Acked by Takashi for patch "ALSA: hda: check stream decoupled register state". - Removed compilation warning in patch "ASoC: hdac_hdmi: Enable pin and converter in prepare". - Remove 4 patches which are already applied.
Jeeja KP (9): ALSA: hda: check stream decoupled register state ASoC: Intel: Skylake: Add set_tristate DAI ops to enable SSP MCLK ASoC: Intel: Skylake: Remove unused SSP BE prepare DAI ops ASoC: Intel: Skylake: Add supply widget as non DSP widget ASoC: Intel: Skylake: Add supply widget in skl_nau_max machine ASoC: Intel: Skylake: Add supply widget in bxt_da_max machine ASoC: Intel: Skylake: Don't reset pass-through pipe in BE prepare ASoC: Intel: Skylake: set the resume point to LPIB ASoC: hdac_hdmi: Enable pin and converter in prepare
sound/hda/ext/hdac_ext_stream.c | 15 ++++--- sound/soc/codecs/hdac_hdmi.c | 37 ++++++++---------- sound/soc/intel/boards/bxt_da7219_max98357a.c | 34 ++++++++++++++++ sound/soc/intel/boards/skl_nau88l25_max98357a.c | 34 ++++++++++++++++ sound/soc/intel/skylake/skl-pcm.c | 52 +++++++++++++++---------- sound/soc/intel/skylake/skl-topology.c | 6 ++- 6 files changed, 130 insertions(+), 48 deletions(-)
From: Jeeja KP jeeja.kp@intel.com
Check stream decoupled register value with requested value before decoupling/coupling the stream.
Signed-off-by: Jeeja KP jeeja.kp@intel.com Acked-by: Takashi Iwai tiwai@suse.de --- sound/hda/ext/hdac_ext_stream.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 3be051ab5..c96d7a7 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -128,14 +128,17 @@ void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, { struct hdac_stream *hstream = &stream->hstream; struct hdac_bus *bus = &ebus->bus; + u32 val; + int mask = AZX_PPCTL_PROCEN(hstream->index);
spin_lock_irq(&bus->reg_lock); - if (decouple) - snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, - AZX_PPCTL_PROCEN(hstream->index)); - else - snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, - AZX_PPCTL_PROCEN(hstream->index), 0); + val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask; + + if (decouple && !val) + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, mask); + else if (!decouple && val) + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0); + stream->decoupled = decouple; spin_unlock_irq(&bus->reg_lock); }
From: Jeeja KP jeeja.kp@intel.com
Some machine requires MCLK to be enabled before SSP start up, so add set_tristate() DAI ops to enable/disable SSP MCLK. This ops will be called from machine which requires early MCLK and removes the usage of enabling early MLCK in platform DAI prepare by default which is not machine specific.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 10fa10d..3c16d41 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -396,6 +396,33 @@ static int skl_be_hw_params(struct snd_pcm_substream *substream, return skl_tplg_be_update_params(dai, &p_params); }
+static int skl_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + struct skl *skl = get_skl_ctx(dai->dev); + struct skl_sst *ctx = skl->skl_sst; + struct skl_module_cfg *mconfig; + int stream; + + if (dai->playback_active) + stream = SNDRV_PCM_STREAM_PLAYBACK; + else + stream = SNDRV_PCM_STREAM_CAPTURE; + + mconfig = skl_tplg_be_get_cpr_module(dai, stream); + if (!mconfig) + return -EINVAL; + + /* + * To enable ssp clk explicitly before gateway copier is configured, + * need to use dma control IPC. + * Disable will be done when DSP gateway copier modules are deleted. + */ + if (!tristate) + return skl_dsp_set_dma_control(ctx, mconfig); + + return 0; +} + static int skl_decoupled_trigger(struct snd_pcm_substream *substream, int cmd) { @@ -646,7 +673,7 @@ static struct snd_soc_dai_ops skl_dmic_dai_ops = {
static struct snd_soc_dai_ops skl_be_ssp_dai_ops = { .hw_params = skl_be_hw_params, - .prepare = skl_be_prepare, + .set_tristate = skl_soc_dai_set_tristate, };
static struct snd_soc_dai_ops skl_link_dai_ops = {
On Mon, Jan 02, 2017 at 12:44:29PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
Some machine requires MCLK to be enabled before SSP start up, so add set_tristate() DAI ops to enable/disable SSP MCLK. This ops will be called from machine which requires early MCLK and removes the usage of enabling early MLCK in platform DAI prepare by default which is not machine specific.
This isn't an *obvious* use of the tristate operation...
- /*
* To enable ssp clk explicitly before gateway copier is configured,
* need to use dma control IPC.
* Disable will be done when DSP gateway copier modules are deleted.
*/
- if (!tristate)
return skl_dsp_set_dma_control(ctx, mconfig);
So we never clear this? And to be frank I'd have no idea looking at this that it's doing anything to do with clocks though that's a bit of a separate thing. It feels like DAPM might be a more natural place to do this, have a clock widget supplying the AIF widget for the interface. That'd be a bit more idiomatic.
On Fri, Jan 06, 2017 at 06:32:33PM +0000, Mark Brown wrote:
On Mon, Jan 02, 2017 at 12:44:29PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
Some machine requires MCLK to be enabled before SSP start up, so add set_tristate() DAI ops to enable/disable SSP MCLK. This ops will be called from machine which requires early MCLK and removes the usage of enabling early MLCK in platform DAI prepare by default which is not machine specific.
This isn't an *obvious* use of the tristate operation...
- /*
* To enable ssp clk explicitly before gateway copier is configured,
* need to use dma control IPC.
* Disable will be done when DSP gateway copier modules are deleted.
*/
- if (!tristate)
return skl_dsp_set_dma_control(ctx, mconfig);
So we never clear this? And to be frank I'd have no idea looking at this that it's doing anything to do with clocks though that's a bit of a separate thing. It feels like DAPM might be a more natural place to do this, have a clock widget supplying the AIF widget for the interface. That'd be a bit more idiomatic.
The clk will be cleared, when DSP pipeline is deleted, that is when audio device is closed. My bad, yes this is not the correct usage of tristate operation, we need to model it as a clock supply widget, will rework on this patch. --
From: Jeeja KP jeeja.kp@intel.com
Removed unused prepare DAI ops as previous patch uses set_tristate ops and this is no longer in use so remove the BE DAI prepare opd.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 3c16d41..688d6f7 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -259,23 +259,6 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, return 0; }
-static int skl_be_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct skl *skl = get_skl_ctx(dai->dev); - struct skl_sst *ctx = skl->skl_sst; - struct skl_module_cfg *mconfig; - - if (dai->playback_widget->power || dai->capture_widget->power) - return 0; - - mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); - if (mconfig == NULL) - return -EINVAL; - - return skl_dsp_set_dma_control(ctx, mconfig); -} - static int skl_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) {
From: Jeeja KP jeeja.kp@intel.com
Supply widgets to model clock supplies for SSP and add this widget type dapm supply widget as non DSP widget to bypass while parsing the source and sink dapm widget list.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/skylake/skl-topology.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 9cf8c51..edd0c60 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -87,6 +87,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w) case snd_soc_dapm_aif_out: case snd_soc_dapm_dai_out: case snd_soc_dapm_switch: + case snd_soc_dapm_supply: return false; default: return true; @@ -1484,12 +1485,13 @@ static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, snd_soc_dapm_widget_for_each_source_path(w, p) { if (p->connect && is_skl_dsp_widget_type(p->source) && p->source->priv) { - ret = skl_tplg_be_fill_pipe_params(dai, p->source->priv, params); if (ret < 0) return ret; } else { + if (p->source->id == snd_soc_dapm_supply) + continue; ret = skl_tplg_be_set_src_pipe_params(dai, p->source, params); if (ret < 0) @@ -1515,6 +1517,8 @@ static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, if (ret < 0) return ret; } else { + if (p->sink->id == snd_soc_dapm_supply) + continue; ret = skl_tplg_be_set_sink_pipe_params( dai, p->sink, params); if (ret < 0)
From: Jeeja KP jeeja.kp@intel.com
Maxim codec needs clock to be configured before the SSP startup, so we need to model the MLCK from SSP0 and turn it on before SSP port is enabled, so model this in DSP widget parsing.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 25db5be..06abdf1 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -100,6 +100,36 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, return ret; }
+static struct snd_soc_dai *skl_get_dai_widget(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p = NULL; + + snd_soc_dapm_widget_for_each_sink_path(w, p) { + if (p->sink->id == snd_soc_dapm_dai_in) + return p->sink->priv; + + return skl_get_dai_widget(p->sink); + } + + return NULL; +} + +static int ssp_set_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dai *cpu_dai = NULL; + + cpu_dai = skl_get_dai_widget(w); + if (!cpu_dai) + return -EIO; + + /* Enable/Disable the SSP clk */ + if (SND_SOC_DAPM_EVENT_ON(event)) + return snd_soc_dai_set_tristate(cpu_dai, 0); + else + return snd_soc_dai_set_tristate(cpu_dai, 1); +} + static const struct snd_kcontrol_new skylake_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -113,6 +143,9 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_SPK("DP", NULL), SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SUPPLY("ssp0 mclk", SND_SOC_NOPM, 0, 0, + ssp_set_clk, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -136,6 +169,7 @@ static const struct snd_soc_dapm_route skylake_map[] = { /* CODEC BE connections */ { "HiFi Playback", NULL, "ssp0 Tx" }, { "ssp0 Tx", NULL, "codec0_out" }, + { "codec0_out", NULL, "ssp0 mclk"},
{ "Playback", NULL, "ssp1 Tx" }, { "ssp1 Tx", NULL, "codec1_out" },
From: Jeeja KP jeeja.kp@intel.com
Maxim codec needs clock to be configured before the SSP startup, so we need to model the MLCK from SSP5 and turn it on before SSP port is enabled, so model this in DSP widget parsing.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index bff80b4..c702967 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -43,6 +43,36 @@ enum { BXT_DPCM_AUDIO_HDMI3_PB, };
+static struct snd_soc_dai *skl_get_dai_widget(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p = NULL; + + snd_soc_dapm_widget_for_each_sink_path(w, p) { + if (p->sink->id == snd_soc_dapm_dai_in) + return p->sink->priv; + + return skl_get_dai_widget(p->sink); + } + + return NULL; +} + +static int ssp_set_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dai *cpu_dai = NULL; + + cpu_dai = skl_get_dai_widget(w); + if (!cpu_dai) + return -EIO; + + /* Enable/Disable the SSP clk */ + if (SND_SOC_DAPM_EVENT_ON(event)) + return snd_soc_dai_set_tristate(cpu_dai, 0); + else + return snd_soc_dai_set_tristate(cpu_dai, 1); +} + static const struct snd_kcontrol_new broxton_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -57,6 +87,9 @@ static const struct snd_soc_dapm_widget broxton_widgets[] = { SND_SOC_DAPM_SPK("HDMI1", NULL), SND_SOC_DAPM_SPK("HDMI2", NULL), SND_SOC_DAPM_SPK("HDMI3", NULL), + SND_SOC_DAPM_SUPPLY("ssp5 mclk", SND_SOC_NOPM, 0, 0, + ssp_set_clk, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), };
static const struct snd_soc_dapm_route broxton_map[] = { @@ -76,6 +109,7 @@ static const struct snd_soc_dapm_route broxton_map[] = { /* CODEC BE connections */ {"HiFi Playback", NULL, "ssp5 Tx"}, {"ssp5 Tx", NULL, "codec0_out"}, + { "codec0_out", NULL, "ssp5 mclk"},
{"Playback", NULL, "ssp1 Tx"}, {"ssp1 Tx", NULL, "codec1_out"},
On Mon, Jan 02, 2017 at 12:44:33PM +0530, jeeja.kp@intel.com wrote:
+static int ssp_set_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
+{
- struct snd_soc_dai *cpu_dai = NULL;
- cpu_dai = skl_get_dai_widget(w);
- if (!cpu_dai)
return -EIO;
- /* Enable/Disable the SSP clk */
- if (SND_SOC_DAPM_EVENT_ON(event))
return snd_soc_dai_set_tristate(cpu_dai, 0);
- else
return snd_soc_dai_set_tristate(cpu_dai, 1);
+}
Erk, no - you definitely want to just move the whole thing to DAPM I think. We shoudn't be manually fiddling with the tristating from driver code when the core will also try to manage tristating, at some point this widget and the core will inevitably end up fighting with each other.
From: Jeeja KP jeeja.kp@intel.com
When pipe is pass-through, BE and FE modules are defined inside a pipe, reset of pipe will be done in FE DAI prepare. So don't reset in the BE prepare.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 688d6f7..800fdad 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -582,8 +582,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
/* In case of XRUN recovery, reset the FW pipe to clean state */ mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); - if (mconfig && (substream->runtime->status->state == - SNDRV_PCM_STATE_XRUN)) + if (mconfig && !mconfig->pipe->passthru && + (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) skl_reset_pipe(skl->skl_sst, mconfig->pipe);
return 0;
From: Jeeja KP jeeja.kp@intel.com
In system suspend, the firmware pipelines will be deleted and there is no need to save the pipeline context. Driver will save the DPIB and LPIB pointers in suspend.
In system resume, the firmware pipelines will be created again and the RD/RW pointers in the Firmware buffer points to the base address. So need to fetch the non-played data again to firmware buffer. LPIB indicates the HW rendered position.
Instead of setting DPIB as resume point, set it to LPIB to restore from the HW render position so that DMA would fetch the non-played data one more time.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 800fdad..508144b 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -484,7 +484,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, snd_hdac_ext_stream_drsm_enable(ebus, true, hdac_stream(stream)->index); snd_hdac_ext_stream_set_dpibr(ebus, stream, - stream->dpib); + stream->lpib); snd_hdac_ext_stream_set_lpib(stream, stream->lpib); }
From: Jeeja KP jeeja.kp@intel.com
Instead of enabling pin and cvt in pcm_open(), need to restore pin and cvt state after system resume to restart the playback which is paused/stopped before system suspend. So enable pin and cvt in playback_prepare and call prepare when trigger cmd is paused/started and resume to reconfigure pin and cvt.
Signed-off-by: Sachin Mokashi sachinx.mokashi@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c602c49..1da4405 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -114,6 +114,12 @@ struct hdac_hdmi_priv { struct hdac_chmap chmap; };
+static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev, + struct hdac_hdmi_dai_pin_map *dai_map); + +static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac, + struct hdac_hdmi_dai_pin_map *dai_map); + static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, int pcm_idx) { @@ -411,6 +417,10 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream, dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n", dd->stream_tag, dd->format);
+ hdac_hdmi_enable_cvt(hdac, dai_map); + ret = hdac_hdmi_enable_pin(hdac, dai_map); + if (ret < 0) + return ret; mutex_lock(&pin->lock); pin->channels = substream->runtime->channels;
@@ -464,12 +474,7 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); struct hdac_ext_dma_params *dd; - struct hdac_hdmi_priv *hdmi = edev->private_data; - struct hdac_hdmi_dai_pin_map *dai_map; - - dai_map = &hdmi->dai_map[dai->id];
dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
@@ -622,11 +627,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
dai_map->pin = pin;
- hdac_hdmi_enable_cvt(hdac, dai_map); - ret = hdac_hdmi_enable_pin(hdac, dai_map); - if (ret < 0) - return ret; - ret = hdac_hdmi_eld_limit_formats(substream->runtime, pin->eld.eld_buffer); if (ret < 0) @@ -639,18 +639,15 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct hdac_hdmi_dai_pin_map *dai_map; - struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdac->private_data; - int ret; - - dai_map = &hdmi->dai_map[dai->id]; - if (cmd == SNDRV_PCM_TRIGGER_RESUME) { - ret = hdac_hdmi_enable_pin(hdac, dai_map); - if (ret < 0) - return ret;
+ switch (cmd) { + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: return hdac_hdmi_playback_prepare(substream, dai); + + default: + return 0; }
return 0;
The patch
ASoC: hdac_hdmi: Enable pin and converter in prepare
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 1de777fed54dfa93e166a3c934c5846920b86f0c Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Tue, 10 Jan 2017 17:57:48 +0530 Subject: [PATCH] ASoC: hdac_hdmi: Enable pin and converter in prepare
Instead of enabling pin and cvt in pcm_open(), need to restore pin and cvt state after system resume to restart the playback which is paused/stopped before system suspend. So enable pin and cvt in playback_prepare and call prepare when trigger cmd is paused/started and resume to reconfigure pin and cvt.
Signed-off-by: Sachin Mokashi sachinx.mokashi@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/hdac_hdmi.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c602c4960924..1da4405ee435 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -114,6 +114,12 @@ struct hdac_hdmi_priv { struct hdac_chmap chmap; };
+static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev, + struct hdac_hdmi_dai_pin_map *dai_map); + +static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac, + struct hdac_hdmi_dai_pin_map *dai_map); + static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, int pcm_idx) { @@ -411,6 +417,10 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream, dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n", dd->stream_tag, dd->format);
+ hdac_hdmi_enable_cvt(hdac, dai_map); + ret = hdac_hdmi_enable_pin(hdac, dai_map); + if (ret < 0) + return ret; mutex_lock(&pin->lock); pin->channels = substream->runtime->channels;
@@ -464,12 +474,7 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); struct hdac_ext_dma_params *dd; - struct hdac_hdmi_priv *hdmi = edev->private_data; - struct hdac_hdmi_dai_pin_map *dai_map; - - dai_map = &hdmi->dai_map[dai->id];
dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
@@ -622,11 +627,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
dai_map->pin = pin;
- hdac_hdmi_enable_cvt(hdac, dai_map); - ret = hdac_hdmi_enable_pin(hdac, dai_map); - if (ret < 0) - return ret; - ret = hdac_hdmi_eld_limit_formats(substream->runtime, pin->eld.eld_buffer); if (ret < 0) @@ -639,18 +639,15 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct hdac_hdmi_dai_pin_map *dai_map; - struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdac->private_data; - int ret; - - dai_map = &hdmi->dai_map[dai->id]; - if (cmd == SNDRV_PCM_TRIGGER_RESUME) { - ret = hdac_hdmi_enable_pin(hdac, dai_map); - if (ret < 0) - return ret;
+ switch (cmd) { + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: return hdac_hdmi_playback_prepare(substream, dai); + + default: + return 0; }
return 0;
On Mon, Jan 02, 2017 at 12:44:27PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
This patch series includes driver updates for the handling scenarios during System S0/S3 transitions when audio stream is stopped during system. o move DMA configuration in DSP Gateway Module widget event handler to ensure DMA is configured after resume. o Enable SSP MLCK using Supply widget. This will ensure the MCLK is enabled when the widget is power on. o Check DMA decouple register state before coupling/decoupling the DMA. o In case of HDMI pass-through pipe, reset only the FE Pipe when stream in in XRUN state. o Resume the stream from HW renderer position. o HDMI Codec pin and converter state need to be restored when stream is resumed.
Full series:
Acked-by: Vinod Koul vinod.koul@intel.com
participants (4)
-
Jeeja KP
-
jeeja.kp@intel.com
-
Mark Brown
-
Vinod Koul