1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2018 Intel Corporation 7 // 8 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9 // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 10 // Rander Wang <rander.wang@intel.com> 11 // Keyon Jie <yang.jie@linux.intel.com> 12 // 13 14 /* 15 * Hardware interface for generic Intel audio DSP HDA IP 16 */ 17 18 #include <linux/module.h> 19 #include <sound/hdaudio_ext.h> 20 #include <sound/hda_register.h> 21 #include <sound/hda_component.h> 22 #include <sound/hda-mlink.h> 23 #include "../ops.h" 24 #include "hda.h" 25 26 /* 27 * HDA Operations. 28 */ 29 30 int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset) 31 { 32 unsigned long timeout; 33 u32 gctl = 0; 34 u32 val; 35 36 /* 0 to enter reset and 1 to exit reset */ 37 val = reset ? 0 : SOF_HDA_GCTL_RESET; 38 39 /* enter/exit HDA controller reset */ 40 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL, 41 SOF_HDA_GCTL_RESET, val); 42 43 /* wait to enter/exit reset */ 44 timeout = jiffies + msecs_to_jiffies(HDA_DSP_CTRL_RESET_TIMEOUT); 45 while (time_before(jiffies, timeout)) { 46 gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL); 47 if ((gctl & SOF_HDA_GCTL_RESET) == val) 48 return 0; 49 usleep_range(500, 1000); 50 } 51 52 /* enter/exit reset failed */ 53 dev_err(sdev->dev, "error: failed to %s HDA controller gctl 0x%x\n", 54 reset ? "reset" : "ready", gctl); 55 return -EIO; 56 } 57 58 int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) 59 { 60 struct hdac_bus *bus = sof_to_bus(sdev); 61 u32 cap, offset, feature; 62 int count = 0; 63 int ret; 64 65 /* 66 * On some devices, one reset cycle is necessary before reading 67 * capabilities 68 */ 69 ret = hda_dsp_ctrl_link_reset(sdev, true); 70 if (ret < 0) 71 return ret; 72 ret = hda_dsp_ctrl_link_reset(sdev, false); 73 if (ret < 0) 74 return ret; 75 76 offset = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_LLCH); 77 78 do { 79 dev_dbg(sdev->dev, "checking for capabilities at offset 0x%x\n", 80 offset & SOF_HDA_CAP_NEXT_MASK); 81 82 cap = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, offset); 83 84 if (cap == -1) { 85 dev_dbg(bus->dev, "Invalid capability reg read\n"); 86 break; 87 } 88 89 feature = (cap & SOF_HDA_CAP_ID_MASK) >> SOF_HDA_CAP_ID_OFF; 90 91 switch (feature) { 92 case SOF_HDA_PP_CAP_ID: 93 dev_dbg(sdev->dev, "found DSP capability at 0x%x\n", 94 offset); 95 bus->ppcap = bus->remap_addr + offset; 96 sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap; 97 break; 98 case SOF_HDA_SPIB_CAP_ID: 99 dev_dbg(sdev->dev, "found SPIB capability at 0x%x\n", 100 offset); 101 bus->spbcap = bus->remap_addr + offset; 102 sdev->bar[HDA_DSP_SPIB_BAR] = bus->spbcap; 103 break; 104 case SOF_HDA_DRSM_CAP_ID: 105 dev_dbg(sdev->dev, "found DRSM capability at 0x%x\n", 106 offset); 107 bus->drsmcap = bus->remap_addr + offset; 108 sdev->bar[HDA_DSP_DRSM_BAR] = bus->drsmcap; 109 break; 110 case SOF_HDA_GTS_CAP_ID: 111 dev_dbg(sdev->dev, "found GTS capability at 0x%x\n", 112 offset); 113 bus->gtscap = bus->remap_addr + offset; 114 break; 115 case SOF_HDA_ML_CAP_ID: 116 dev_dbg(sdev->dev, "found ML capability at 0x%x\n", 117 offset); 118 bus->mlcap = bus->remap_addr + offset; 119 break; 120 default: 121 dev_dbg(sdev->dev, "found capability %d at 0x%x\n", 122 feature, offset); 123 break; 124 } 125 126 offset = cap & SOF_HDA_CAP_NEXT_MASK; 127 } while (count++ <= SOF_HDA_MAX_CAPS && offset); 128 129 return 0; 130 } 131 EXPORT_SYMBOL_NS(hda_dsp_ctrl_get_caps, "SND_SOC_SOF_INTEL_HDA_COMMON"); 132 133 void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) 134 { 135 u32 val = enable ? SOF_HDA_PPCTL_GPROCEN : 0; 136 137 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, 138 SOF_HDA_PPCTL_GPROCEN, val); 139 } 140 EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_enable, "SND_SOC_SOF_INTEL_HDA_COMMON"); 141 142 void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) 143 { 144 u32 val = enable ? SOF_HDA_PPCTL_PIE : 0; 145 146 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, 147 SOF_HDA_PPCTL_PIE, val); 148 } 149 EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_int_enable, "SND_SOC_SOF_INTEL_HDA_COMMON"); 150 151 void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) 152 { 153 u32 val = enable ? PCI_CGCTL_MISCBDCGE_MASK : 0; 154 155 snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_MISCBDCGE_MASK, val); 156 } 157 158 /* 159 * enable/disable audio dsp clock gating and power gating bits. 160 * This allows the HW to opportunistically power and clock gate 161 * the audio dsp when it is idle 162 */ 163 int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) 164 { 165 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 166 u32 val; 167 168 /* enable/disable audio dsp clock gating */ 169 val = enable ? PCI_CGCTL_ADSPDCGE : 0; 170 snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); 171 172 /* disable the DMI link when requested. But enable only if it wasn't disabled previously */ 173 val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; 174 if (!enable || !hda->l1_disabled) 175 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, 176 HDA_VS_INTEL_EM2_L1SEN, val); 177 178 /* enable/disable audio dsp power gating */ 179 val = enable ? 0 : PCI_PGCTL_ADSPPGD; 180 snd_sof_pci_update_bits(sdev, PCI_PGCTL, PCI_PGCTL_ADSPPGD, val); 181 182 return 0; 183 } 184 EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, "SND_SOC_SOF_INTEL_HDA_COMMON"); 185 186 int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool detect_codec) 187 { 188 struct hdac_bus *bus = sof_to_bus(sdev); 189 struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); 190 struct hdac_stream *stream; 191 int sd_offset, ret = 0; 192 u32 gctl; 193 194 if (bus->chip_init) 195 return 0; 196 197 /* 198 * The controller reset clears the ACE2+ link DMA stream allocation 199 * constraints; reset the masks to reflect this. 200 */ 201 memset(sof_hda->link_dma_active_sdw_mask, 0, 202 sizeof(sof_hda->link_dma_active_sdw_mask)); 203 memset(sof_hda->link_dma_active_multi_mask, 0, 204 sizeof(sof_hda->link_dma_active_multi_mask)); 205 sof_hda->link_dma_out_hda_used_mask = 0; 206 207 hda_codec_set_codec_wakeup(sdev, true); 208 209 hda_dsp_ctrl_misc_clock_gating(sdev, false); 210 211 /* clear WAKE_STS if not in reset */ 212 gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL); 213 if (gctl & SOF_HDA_GCTL_RESET) 214 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 215 SOF_HDA_WAKESTS, SOF_HDA_WAKESTS_INT_MASK); 216 217 /* reset HDA controller */ 218 ret = hda_dsp_ctrl_link_reset(sdev, true); 219 if (ret < 0) { 220 dev_err(sdev->dev, "error: failed to reset HDA controller\n"); 221 goto err; 222 } 223 224 usleep_range(500, 1000); 225 226 /* exit HDA controller reset */ 227 ret = hda_dsp_ctrl_link_reset(sdev, false); 228 if (ret < 0) { 229 dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); 230 goto err; 231 } 232 usleep_range(1000, 1200); 233 234 /* Accept unsolicited responses */ 235 snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); 236 237 /* Perform a one-time enumeration of the Multi-Link capability */ 238 ret = hda_bus_ml_init(bus); 239 if (ret < 0) { 240 dev_err(sdev->dev, "%s: failed to enumerate multi-links\n", 241 __func__); 242 goto err; 243 } 244 245 if (detect_codec) 246 hda_codec_detect_mask(sdev); 247 248 /* clear stream status */ 249 list_for_each_entry(stream, &bus->stream_list, list) { 250 sd_offset = SOF_STREAM_SD_OFFSET(stream); 251 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 252 sd_offset + SOF_HDA_ADSP_REG_SD_STS, 253 SOF_HDA_CL_DMA_SD_INT_MASK); 254 } 255 256 /* clear WAKESTS */ 257 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, 258 bus->codec_mask); 259 260 hda_codec_rirb_status_clear(sdev); 261 262 /* clear interrupt status register */ 263 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, 264 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); 265 266 hda_codec_init_cmd_io(sdev); 267 268 /* enable CIE and GIE interrupts */ 269 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 270 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 271 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); 272 273 /* program the position buffer */ 274 if (bus->use_posbuf && bus->posbuf.addr) { 275 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE, 276 (u32)bus->posbuf.addr); 277 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE, 278 upper_32_bits(bus->posbuf.addr)); 279 } 280 281 hda_bus_ml_reset_losidv(bus); 282 283 bus->chip_init = true; 284 285 err: 286 hda_dsp_ctrl_misc_clock_gating(sdev, true); 287 288 hda_codec_set_codec_wakeup(sdev, false); 289 290 return ret; 291 } 292 EXPORT_SYMBOL_NS(hda_dsp_ctrl_init_chip, "SND_SOC_SOF_INTEL_HDA_COMMON"); 293 294 void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) 295 { 296 struct hdac_bus *bus = sof_to_bus(sdev); 297 struct hdac_stream *stream; 298 int sd_offset; 299 300 if (!bus->chip_init) 301 return; 302 303 /* disable interrupts in stream descriptor */ 304 list_for_each_entry(stream, &bus->stream_list, list) { 305 sd_offset = SOF_STREAM_SD_OFFSET(stream); 306 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, 307 sd_offset + 308 SOF_HDA_ADSP_REG_SD_CTL, 309 SOF_HDA_CL_DMA_SD_INT_MASK, 310 0); 311 } 312 313 /* disable SIE for all streams */ 314 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 315 SOF_HDA_INT_ALL_STREAM, 0); 316 317 /* disable controller CIE and GIE */ 318 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 319 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 320 0); 321 322 /* clear stream status */ 323 list_for_each_entry(stream, &bus->stream_list, list) { 324 sd_offset = SOF_STREAM_SD_OFFSET(stream); 325 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 326 sd_offset + SOF_HDA_ADSP_REG_SD_STS, 327 SOF_HDA_CL_DMA_SD_INT_MASK); 328 } 329 330 /* clear WAKESTS */ 331 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, 332 SOF_HDA_WAKESTS_INT_MASK); 333 334 hda_codec_rirb_status_clear(sdev); 335 336 /* clear interrupt status register */ 337 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, 338 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); 339 340 hda_codec_stop_cmd_io(sdev); 341 342 /* disable position buffer */ 343 if (bus->use_posbuf && bus->posbuf.addr) { 344 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 345 SOF_HDA_ADSP_DPLBASE, 0); 346 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 347 SOF_HDA_ADSP_DPUBASE, 0); 348 } 349 350 bus->chip_init = false; 351 } 352 353 MODULE_LICENSE("Dual BSD/GPL"); 354 MODULE_DESCRIPTION("SOF helpers for HDaudio platforms"); 355 MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); 356 MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC"); 357 MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC_I915"); 358