diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 07bc123112c9ba..688ab8d895a974 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -263,3 +263,70 @@ 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 controller CIE and GIE */ + 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); +#endif + /* disable position buffer */ + if (bus->posbuf.addr) { + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_ADSP_DPLBASE, 0); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_ADSP_DPUBASE, 0); + } + + bus->chip_init = false; +} diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 5b73115a0b7873..d1577cac76a2ed 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -307,23 +307,12 @@ 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); - - /* 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, - 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, @@ -370,10 +359,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 +385,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 */ 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. */