From e27abf20ae0516290db87d94daa36d10ee21a4f5 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Tue, 21 May 2019 17:04:48 +0800 Subject: [PATCH 1/4] ASoC: SOF: Intel: hda: use the SOF defined ppcap functions Use the SOF defined ppcap functions for both HDA and none-HDA in hda_suspend and hda_resume. Signed-off-by: Zhu Yingjiang --- sound/soc/sof/intel/hda-dsp.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 5b73115a0b7873..3faa7f648b3ded 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -307,18 +307,14 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) return ret; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(bus, false); - snd_hdac_ext_bus_ppcap_enable(bus, false); + hda_dsp_ctrl_ppcap_enable(sdev, false); + hda_dsp_ctrl_ppcap_int_enable(sdev, false); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* disable hda bus irq and i/o */ snd_hdac_bus_stop_chip(bus); #else - /* disable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, false); - hda_dsp_ctrl_ppcap_int_enable(sdev, false); - /* disable hda bus irq */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, @@ -370,10 +366,6 @@ static int hda_resume(struct snd_sof_dev *sdev) bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); hda_dsp_ctrl_misc_clock_gating(sdev, true); - - /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(bus, true); - snd_hdac_ext_bus_ppcap_int_enable(bus, true); #else hda_dsp_ctrl_misc_clock_gating(sdev, false); @@ -400,11 +392,11 @@ static int hda_resume(struct snd_sof_dev *sdev) SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); hda_dsp_ctrl_misc_clock_gating(sdev, true); +#endif /* enable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, true); hda_dsp_ctrl_ppcap_int_enable(sdev, true); -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* turn off the links that were off before suspend */ From 51c7a506e12c902c1abd3cdf3e0c3ee350e70591 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Tue, 21 May 2019 16:50:39 +0800 Subject: [PATCH 2/4] ASoC: SOF: Intel: hda: add function for hda stop chip Add hda_dsp_ctrl_stop_chip, so stop hda irq and streams irq sequence will be called by hda_suspend. Whether CONFIG_SND_SOC_SOF_HDA is defined or not. This function is used to disable the whole IRQ and I/Os. Signed-off-by: Zhu Yingjiang --- sound/soc/sof/intel/hda-ctrl.c | 65 ++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 07bc123112c9ba..9035b67ce224fa 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -263,3 +263,68 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) return ret; } + +void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *stream; + int sd_offset; + + if (!bus->chip_init) + return; + + /* disable interrupts in stream descriptor */ + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_CTL, + SOF_HDA_CL_DMA_SD_INT_MASK, + 0); + } + + /* disable SIE for all streams */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_ALL_STREAM, 0); + + /* disable hda bus irq */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, + 0); + + /* clear stream status */ + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK, + SOF_HDA_CL_DMA_SD_INT_MASK); + } + + /* clear WAKESTS */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK, + SOF_HDA_WAKESTS_INT_MASK); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* clear rirb status */ + snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); +#endif + + /* clear interrupt status register */ + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* disable CORB/RIRB */ + snd_hdac_bus_stop_cmd_io(bus); + + /* disable position buffer */ + if (bus->posbuf.addr) { + snd_hdac_chip_writel(bus, DPLBASE, 0); + snd_hdac_chip_writel(bus, DPUBASE, 0); + } +#endif + bus->chip_init = false; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 455046612b9494..b1cb5d8d5c9e08 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -529,7 +529,7 @@ int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset); - +void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); /* * HDA bus operations. */ From dd6992889f9088a1e21b5e4b49066720c2ee98cd Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Tue, 21 May 2019 17:42:05 +0800 Subject: [PATCH 3/4] ASoC: SOF: Intel: hda: use the defined stop chip in suspend The SOF defined hda_dsp_ctrl_stop_chip can handle both cases for whether CONFIG_SND_SOC_SOF_HDA is defined. Disable the interrupts for HDA controller and streams. If CONFIG_SND_SOC_SOF_HDA is defined, also disable the CORB/RIRB, and stop i/o. Signed-off-by: Zhu Yingjiang --- sound/soc/sof/intel/hda-dsp.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 3faa7f648b3ded..d1577cac76a2ed 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -311,15 +311,8 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) hda_dsp_ctrl_ppcap_enable(sdev, false); hda_dsp_ctrl_ppcap_int_enable(sdev, false); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* disable hda bus irq and i/o */ - snd_hdac_bus_stop_chip(bus); -#else - /* disable hda bus irq */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - 0); -#endif + /* disable hda bus irq and streams */ + hda_dsp_ctrl_stop_chip(sdev); /* disable LP retention mode */ snd_sof_pci_update_bits(sdev, PCI_PGCTL, From eee6e438e7a5a0e74c41c2d8cab97f66aec3c54f Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Tue, 21 May 2019 18:24:40 +0800 Subject: [PATCH 4/4] ASoC: SOF: Intel: hda: use SOF defined init chip in resume The SOF defined hda_dsp_ctrl_init_chip function can handle both case whether CONFIG_SND_SOC_SOF_HDA is defined, so make it common codes. Move reset stream-to-link mapping into hda_dsp_ctrl_init_chip. So only one misc clock gating disable/enable is needed. Signed-off-by: Zhu Yingjiang --- sound/soc/sof/intel/hda-ctrl.c | 4 ++++ sound/soc/sof/intel/hda-dsp.c | 36 ---------------------------------- 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 9035b67ce224fa..c8b01b3ad56887 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -255,6 +255,10 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr)); } + + /* Reset stream-to-link mapping */ + list_for_each_entry(hlink, &bus->hlink_list, list) + bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); #endif bus->chip_init = true; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index d1577cac76a2ed..d63e93dc17643d 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -343,7 +343,6 @@ static int hda_resume(struct snd_sof_dev *sdev) */ snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* reset and start hda controller */ ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { @@ -352,41 +351,6 @@ static int hda_resume(struct snd_sof_dev *sdev) return ret; } - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* Reset stream-to-link mapping */ - list_for_each_entry(hlink, &bus->hlink_list, list) - bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); -#else - - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* reset controller */ - ret = hda_dsp_ctrl_link_reset(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to reset controller during resume\n"); - return ret; - } - - /* take controller out of reset */ - ret = hda_dsp_ctrl_link_reset(sdev, false); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to ready controller during resume\n"); - return ret; - } - - /* enable hda bus irq */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); -#endif - /* enable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, true); hda_dsp_ctrl_ppcap_int_enable(sdev, true);