diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 82edc77eeac1f7..55be5a6ff2cc47 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -103,5 +103,6 @@ struct snd_sof_dsp_ops sof_apl_ops = { .resume = hda_dsp_resume, .runtime_suspend = hda_dsp_runtime_suspend, .runtime_resume = hda_dsp_runtime_resume, + .clock_power_gating = hda_dsp_ctrl_clock_power_gating, }; EXPORT_SYMBOL(sof_apl_ops); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 867bc3c4c7d3e9..ab8d88c6435b48 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "../sof-priv.h" #include "../ops.h" @@ -148,6 +149,24 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_MISCBDCGE_MASK, val); } +void hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + u32 val; + + /* Update PDCGE bit of CGCTL register */ + val = enable ? PCI_CGCTL_ADSPDCGE : 0; + snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); + + /* Update L1SEN bit of EM2 register */ + val = enable ? SOF_HDA_VS_EM2_L1SEN : 0; + snd_hdac_chip_updatel(bus, VS_EM2, SOF_HDA_VS_EM2_L1SEN, val); + + /* Update ADSPPGD bit of PGCTL register */ + val = enable ? 0 : PCI_TCSEL_ADSPPGD; + snd_sof_pci_update_bits(sdev, PCI_TCSEL, PCI_TCSEL_ADSPPGD, val); +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* * While performing reset, controller may not come back properly and causing diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index c9c3e52508f00f..b53d88d0c9af95 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -17,9 +17,13 @@ #define PCI_TCSEL 0x44 #define PCI_CGCTL 0x48 +/* PCI_TVSEL bits */ +#define PCI_TCSEL_ADSPPGD BIT(2) + /* PCI_CGCTL bits */ #define PCI_CGCTL_MISCBDCGE_MASK BIT(6) #define PCI_CGCTL_LSRMD_MASK BIT(4) +#define PCI_CGCTL_ADSPDCGE BIT(1) /* Legacy HDA registers and bits used - widths are variable */ #define SOF_HDA_GCAP 0x0 @@ -32,6 +36,7 @@ #define SOF_HDA_WAKESTS 0x0E #define SOF_HDA_WAKESTS_INT_MASK ((1 << 8) - 1) #define SOF_HDA_RIRBSTS 0x5d +#define SOF_HDA_VS_EM2_L1SEN BIT(13) /* SOF_HDA_GCTL register bist */ #define SOF_HDA_GCTL_RESET BIT(0) @@ -490,6 +495,7 @@ int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev); int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev); int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable); +void 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); /* diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index e30531026209e9..031c1493bcc233 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -286,6 +286,9 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "booting DSP firmware\n"); + /* disable clock power gating */ + snd_sof_dsp_clock_power_gating(sdev, false); + /* boot the firmware on the DSP */ ret = snd_sof_dsp_run(sdev); if (ret < 0) { @@ -305,6 +308,9 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) dev_info(sdev->dev, "firmware boot complete\n"); + /* enable clock power gating */ + snd_sof_dsp_clock_power_gating(sdev, true); + return 0; } EXPORT_SYMBOL(snd_sof_run_firmware); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 5bd6e3921b5510..a970eafeb07310 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -95,6 +95,13 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, return 0; } +static inline void snd_sof_dsp_clock_power_gating(struct snd_sof_dev *sdev, + bool enable) +{ + if (sdev->ops->clock_power_gating) + sdev->ops->clock_power_gating(sdev, enable); +} + static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) { if (sdev->ops->set_clk) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 0f7ddf19bf8a15..2bc81e05ba5842 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -83,6 +83,7 @@ struct snd_sof_dsp_ops { int (*resume)(struct snd_sof_dev *sof_dev); int (*runtime_suspend)(struct snd_sof_dev *sof_dev, int state); int (*runtime_resume)(struct snd_sof_dev *sof_dev); + void (*clock_power_gating)(struct snd_sof_dev *sof_dev, bool enable); /* DSP clocking */ int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq);