diff options
Diffstat (limited to 'sound/soc/sof/intel/hda-ctrl.c')
| -rw-r--r-- | sound/soc/sof/intel/hda-ctrl.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 3aea36c077c9..8332d4bda558 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> @@ -19,6 +19,7 @@ #include <sound/hdaudio_ext.h> #include <sound/hda_register.h> #include <sound/hda_component.h> +#include <sound/hda-mlink.h> #include "../ops.h" #include "hda.h" @@ -127,6 +128,7 @@ int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_get_caps, "SND_SOC_SOF_INTEL_HDA_COMMON"); void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) { @@ -135,6 +137,7 @@ void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_GPROCEN, val); } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_enable, "SND_SOC_SOF_INTEL_HDA_COMMON"); void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) { @@ -143,6 +146,7 @@ void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_PIE, val); } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_int_enable, "SND_SOC_SOF_INTEL_HDA_COMMON"); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) { @@ -158,16 +162,18 @@ 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) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; u32 val; /* enable/disable audio dsp clock gating */ val = enable ? PCI_CGCTL_ADSPDCGE : 0; snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); - /* enable/disable DMI Link L1 support */ + /* disable the DMI link when requested. But enable only if it wasn't disabled previously */ val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, val); + if (!enable || !hda->l1_disabled) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, val); /* enable/disable audio dsp power gating */ val = enable ? 0 : PCI_PGCTL_ADSPPGD; @@ -175,12 +181,14 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, "SND_SOC_SOF_INTEL_HDA_COMMON"); -int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) +int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool detect_codec) { struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_stream *stream; int sd_offset, ret = 0; + u32 gctl; if (bus->chip_init) return 0; @@ -189,6 +197,12 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) hda_dsp_ctrl_misc_clock_gating(sdev, false); + /* clear WAKE_STS if not in reset */ + gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL); + if (gctl & SOF_HDA_GCTL_RESET) + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_WAKESTS, SOF_HDA_WAKESTS_INT_MASK); + /* reset HDA controller */ ret = hda_dsp_ctrl_link_reset(sdev, true); if (ret < 0) { @@ -196,14 +210,21 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) goto err; } + usleep_range(500, 1000); + /* exit HDA controller reset */ ret = hda_dsp_ctrl_link_reset(sdev, false); if (ret < 0) { dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); goto err; } + usleep_range(1000, 1200); - hda_codec_detect_mask(sdev); + /* Accept unsolicited responses */ + snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); + + if (detect_codec) + hda_codec_detect_mask(sdev); /* clear stream status */ list_for_each_entry(stream, &bus->stream_list, list) { @@ -215,7 +236,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) /* clear WAKESTS */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK); + bus->codec_mask); hda_codec_rirb_status_clear(sdev); @@ -249,6 +270,7 @@ err: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_init_chip, "SND_SOC_SOF_INTEL_HDA_COMMON"); void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) { @@ -308,3 +330,9 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) bus->chip_init = false; } + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("SOF helpers for HDaudio platforms"); +MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); +MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC"); +MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC_I915"); |
