hda-ctrl.c (9858B)
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. All rights reserved. 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 "../ops.h" 23#include "hda.h" 24 25#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 26static int hda_codec_mask = -1; 27module_param_named(codec_mask, hda_codec_mask, int, 0444); 28MODULE_PARM_DESC(codec_mask, "SOF HDA codec mask for probing"); 29#endif 30 31/* 32 * HDA Operations. 33 */ 34 35int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev, bool reset) 36{ 37 unsigned long timeout; 38 u32 gctl = 0; 39 u32 val; 40 41 /* 0 to enter reset and 1 to exit reset */ 42 val = reset ? 0 : SOF_HDA_GCTL_RESET; 43 44 /* enter/exit HDA controller reset */ 45 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL, 46 SOF_HDA_GCTL_RESET, val); 47 48 /* wait to enter/exit reset */ 49 timeout = jiffies + msecs_to_jiffies(HDA_DSP_CTRL_RESET_TIMEOUT); 50 while (time_before(jiffies, timeout)) { 51 gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL); 52 if ((gctl & SOF_HDA_GCTL_RESET) == val) 53 return 0; 54 usleep_range(500, 1000); 55 } 56 57 /* enter/exit reset failed */ 58 dev_err(sdev->dev, "error: failed to %s HDA controller gctl 0x%x\n", 59 reset ? "reset" : "ready", gctl); 60 return -EIO; 61} 62 63int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) 64{ 65 struct hdac_bus *bus = sof_to_bus(sdev); 66 u32 cap, offset, feature; 67 int count = 0; 68 int ret; 69 70 /* 71 * On some devices, one reset cycle is necessary before reading 72 * capabilities 73 */ 74 ret = hda_dsp_ctrl_link_reset(sdev, true); 75 if (ret < 0) 76 return ret; 77 ret = hda_dsp_ctrl_link_reset(sdev, false); 78 if (ret < 0) 79 return ret; 80 81 offset = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_LLCH); 82 83 do { 84 dev_dbg(sdev->dev, "checking for capabilities at offset 0x%x\n", 85 offset & SOF_HDA_CAP_NEXT_MASK); 86 87 cap = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, offset); 88 89 if (cap == -1) { 90 dev_dbg(bus->dev, "Invalid capability reg read\n"); 91 break; 92 } 93 94 feature = (cap & SOF_HDA_CAP_ID_MASK) >> SOF_HDA_CAP_ID_OFF; 95 96 switch (feature) { 97 case SOF_HDA_PP_CAP_ID: 98 dev_dbg(sdev->dev, "found DSP capability at 0x%x\n", 99 offset); 100 bus->ppcap = bus->remap_addr + offset; 101 sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap; 102 break; 103 case SOF_HDA_SPIB_CAP_ID: 104 dev_dbg(sdev->dev, "found SPIB capability at 0x%x\n", 105 offset); 106 bus->spbcap = bus->remap_addr + offset; 107 sdev->bar[HDA_DSP_SPIB_BAR] = bus->spbcap; 108 break; 109 case SOF_HDA_DRSM_CAP_ID: 110 dev_dbg(sdev->dev, "found DRSM capability at 0x%x\n", 111 offset); 112 bus->drsmcap = bus->remap_addr + offset; 113 sdev->bar[HDA_DSP_DRSM_BAR] = bus->drsmcap; 114 break; 115 case SOF_HDA_GTS_CAP_ID: 116 dev_dbg(sdev->dev, "found GTS capability at 0x%x\n", 117 offset); 118 bus->gtscap = bus->remap_addr + offset; 119 break; 120 case SOF_HDA_ML_CAP_ID: 121 dev_dbg(sdev->dev, "found ML capability at 0x%x\n", 122 offset); 123 bus->mlcap = bus->remap_addr + offset; 124 break; 125 default: 126 dev_dbg(sdev->dev, "found capability %d at 0x%x\n", 127 feature, offset); 128 break; 129 } 130 131 offset = cap & SOF_HDA_CAP_NEXT_MASK; 132 } while (count++ <= SOF_HDA_MAX_CAPS && offset); 133 134 return 0; 135} 136 137void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) 138{ 139 u32 val = enable ? SOF_HDA_PPCTL_GPROCEN : 0; 140 141 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, 142 SOF_HDA_PPCTL_GPROCEN, val); 143} 144 145void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) 146{ 147 u32 val = enable ? SOF_HDA_PPCTL_PIE : 0; 148 149 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, 150 SOF_HDA_PPCTL_PIE, val); 151} 152 153void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) 154{ 155 u32 val = enable ? PCI_CGCTL_MISCBDCGE_MASK : 0; 156 157 snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_MISCBDCGE_MASK, val); 158} 159 160/* 161 * enable/disable audio dsp clock gating and power gating bits. 162 * This allows the HW to opportunistically power and clock gate 163 * the audio dsp when it is idle 164 */ 165int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) 166{ 167 u32 val; 168 169 /* enable/disable audio dsp clock gating */ 170 val = enable ? PCI_CGCTL_ADSPDCGE : 0; 171 snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); 172 173 /* enable/disable DMI Link L1 support */ 174 val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; 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 185int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) 186{ 187 struct hdac_bus *bus = sof_to_bus(sdev); 188#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 189 struct hdac_ext_link *hlink; 190#endif 191 struct hdac_stream *stream; 192 int sd_offset, ret = 0; 193 194 if (bus->chip_init) 195 return 0; 196 197#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 198 snd_hdac_set_codec_wakeup(bus, true); 199#endif 200 hda_dsp_ctrl_misc_clock_gating(sdev, false); 201 202 if (full_reset) { 203 /* reset HDA controller */ 204 ret = hda_dsp_ctrl_link_reset(sdev, true); 205 if (ret < 0) { 206 dev_err(sdev->dev, "error: failed to reset HDA controller\n"); 207 goto err; 208 } 209 210 usleep_range(500, 1000); 211 212 /* exit HDA controller reset */ 213 ret = hda_dsp_ctrl_link_reset(sdev, false); 214 if (ret < 0) { 215 dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); 216 goto err; 217 } 218 219 usleep_range(1000, 1200); 220 } 221 222#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 223 /* check to see if controller is ready */ 224 if (!snd_hdac_chip_readb(bus, GCTL)) { 225 dev_dbg(bus->dev, "controller not ready!\n"); 226 ret = -EBUSY; 227 goto err; 228 } 229 230 /* Accept unsolicited responses */ 231 snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); 232 233 /* detect codecs */ 234 if (!bus->codec_mask) { 235 bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); 236 dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); 237 } 238 239 if (hda_codec_mask != -1) { 240 bus->codec_mask &= hda_codec_mask; 241 dev_dbg(bus->dev, "filtered codec_mask = 0x%lx\n", 242 bus->codec_mask); 243 } 244#endif 245 246 /* clear stream status */ 247 list_for_each_entry(stream, &bus->stream_list, list) { 248 sd_offset = SOF_STREAM_SD_OFFSET(stream); 249 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 250 sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, 251 SOF_HDA_CL_DMA_SD_INT_MASK); 252 } 253 254 /* clear WAKESTS */ 255 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, 256 SOF_HDA_WAKESTS_INT_MASK); 257 258#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 259 /* clear rirb status */ 260 snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); 261#endif 262 263 /* clear interrupt status register */ 264 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, 265 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); 266 267#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 268 /* initialize the codec command I/O */ 269 snd_hdac_bus_init_cmd_io(bus); 270#endif 271 272 /* enable CIE and GIE interrupts */ 273 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 274 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 275 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); 276 277 /* program the position buffer */ 278 if (bus->use_posbuf && bus->posbuf.addr) { 279 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE, 280 (u32)bus->posbuf.addr); 281 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE, 282 upper_32_bits(bus->posbuf.addr)); 283 } 284 285#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 286 /* Reset stream-to-link mapping */ 287 list_for_each_entry(hlink, &bus->hlink_list, list) 288 writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); 289#endif 290 291 bus->chip_init = true; 292 293err: 294 hda_dsp_ctrl_misc_clock_gating(sdev, true); 295#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 296 snd_hdac_set_codec_wakeup(bus, false); 297#endif 298 299 return ret; 300} 301 302void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) 303{ 304 struct hdac_bus *bus = sof_to_bus(sdev); 305 struct hdac_stream *stream; 306 int sd_offset; 307 308 if (!bus->chip_init) 309 return; 310 311 /* disable interrupts in stream descriptor */ 312 list_for_each_entry(stream, &bus->stream_list, list) { 313 sd_offset = SOF_STREAM_SD_OFFSET(stream); 314 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, 315 sd_offset + 316 SOF_HDA_ADSP_REG_CL_SD_CTL, 317 SOF_HDA_CL_DMA_SD_INT_MASK, 318 0); 319 } 320 321 /* disable SIE for all streams */ 322 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 323 SOF_HDA_INT_ALL_STREAM, 0); 324 325 /* disable controller CIE and GIE */ 326 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 327 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 328 0); 329 330 /* clear stream status */ 331 list_for_each_entry(stream, &bus->stream_list, list) { 332 sd_offset = SOF_STREAM_SD_OFFSET(stream); 333 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 334 sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, 335 SOF_HDA_CL_DMA_SD_INT_MASK); 336 } 337 338 /* clear WAKESTS */ 339 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, 340 SOF_HDA_WAKESTS_INT_MASK); 341 342#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 343 /* clear rirb status */ 344 snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); 345#endif 346 347 /* clear interrupt status register */ 348 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, 349 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); 350 351#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 352 /* disable CORB/RIRB */ 353 snd_hdac_bus_stop_cmd_io(bus); 354#endif 355 /* disable position buffer */ 356 if (bus->use_posbuf && bus->posbuf.addr) { 357 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 358 SOF_HDA_ADSP_DPLBASE, 0); 359 snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, 360 SOF_HDA_ADSP_DPUBASE, 0); 361 } 362 363 bus->chip_init = false; 364}