1*747503b1SLiam Girdwood // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2*747503b1SLiam Girdwood // 3*747503b1SLiam Girdwood // This file is provided under a dual BSD/GPLv2 license. When using or 4*747503b1SLiam Girdwood // redistributing this file, you may do so under either license. 5*747503b1SLiam Girdwood // 6*747503b1SLiam Girdwood // Copyright(c) 2018 Intel Corporation. All rights reserved. 7*747503b1SLiam Girdwood // 8*747503b1SLiam Girdwood // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9*747503b1SLiam Girdwood // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 10*747503b1SLiam Girdwood // Rander Wang <rander.wang@intel.com> 11*747503b1SLiam Girdwood // Keyon Jie <yang.jie@linux.intel.com> 12*747503b1SLiam Girdwood // 13*747503b1SLiam Girdwood 14*747503b1SLiam Girdwood /* 15*747503b1SLiam Girdwood * Hardware interface for generic Intel audio DSP HDA IP 16*747503b1SLiam Girdwood */ 17*747503b1SLiam Girdwood 18*747503b1SLiam Girdwood #include <sound/hdaudio_ext.h> 19*747503b1SLiam Girdwood #include <sound/hda_register.h> 20*747503b1SLiam Girdwood #include "../ops.h" 21*747503b1SLiam Girdwood #include "hda.h" 22*747503b1SLiam Girdwood 23*747503b1SLiam Girdwood /* 24*747503b1SLiam Girdwood * DSP Core control. 25*747503b1SLiam Girdwood */ 26*747503b1SLiam Girdwood 27*747503b1SLiam Girdwood int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask) 28*747503b1SLiam Girdwood { 29*747503b1SLiam Girdwood u32 adspcs; 30*747503b1SLiam Girdwood u32 reset; 31*747503b1SLiam Girdwood int ret; 32*747503b1SLiam Girdwood 33*747503b1SLiam Girdwood /* set reset bits for cores */ 34*747503b1SLiam Girdwood reset = HDA_DSP_ADSPCS_CRST_MASK(core_mask); 35*747503b1SLiam Girdwood snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, 36*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, 37*747503b1SLiam Girdwood reset, reset), 38*747503b1SLiam Girdwood 39*747503b1SLiam Girdwood /* poll with timeout to check if operation successful */ 40*747503b1SLiam Girdwood ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, 41*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, adspcs, 42*747503b1SLiam Girdwood ((adspcs & reset) == reset), 43*747503b1SLiam Girdwood HDA_DSP_REG_POLL_INTERVAL_US, 44*747503b1SLiam Girdwood HDA_DSP_RESET_TIMEOUT_US); 45*747503b1SLiam Girdwood 46*747503b1SLiam Girdwood /* has core entered reset ? */ 47*747503b1SLiam Girdwood adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, 48*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS); 49*747503b1SLiam Girdwood if ((adspcs & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) != 50*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CRST_MASK(core_mask)) { 51*747503b1SLiam Girdwood dev_err(sdev->dev, 52*747503b1SLiam Girdwood "error: reset enter failed: core_mask %x adspcs 0x%x\n", 53*747503b1SLiam Girdwood core_mask, adspcs); 54*747503b1SLiam Girdwood ret = -EIO; 55*747503b1SLiam Girdwood } 56*747503b1SLiam Girdwood 57*747503b1SLiam Girdwood return ret; 58*747503b1SLiam Girdwood } 59*747503b1SLiam Girdwood 60*747503b1SLiam Girdwood int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask) 61*747503b1SLiam Girdwood { 62*747503b1SLiam Girdwood unsigned int crst; 63*747503b1SLiam Girdwood u32 adspcs; 64*747503b1SLiam Girdwood int ret; 65*747503b1SLiam Girdwood 66*747503b1SLiam Girdwood /* clear reset bits for cores */ 67*747503b1SLiam Girdwood snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, 68*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, 69*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CRST_MASK(core_mask), 70*747503b1SLiam Girdwood 0); 71*747503b1SLiam Girdwood 72*747503b1SLiam Girdwood /* poll with timeout to check if operation successful */ 73*747503b1SLiam Girdwood crst = HDA_DSP_ADSPCS_CRST_MASK(core_mask); 74*747503b1SLiam Girdwood ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, 75*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, adspcs, 76*747503b1SLiam Girdwood !(adspcs & crst), 77*747503b1SLiam Girdwood HDA_DSP_REG_POLL_INTERVAL_US, 78*747503b1SLiam Girdwood HDA_DSP_RESET_TIMEOUT_US); 79*747503b1SLiam Girdwood 80*747503b1SLiam Girdwood /* has core left reset ? */ 81*747503b1SLiam Girdwood adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, 82*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS); 83*747503b1SLiam Girdwood if ((adspcs & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) != 0) { 84*747503b1SLiam Girdwood dev_err(sdev->dev, 85*747503b1SLiam Girdwood "error: reset leave failed: core_mask %x adspcs 0x%x\n", 86*747503b1SLiam Girdwood core_mask, adspcs); 87*747503b1SLiam Girdwood ret = -EIO; 88*747503b1SLiam Girdwood } 89*747503b1SLiam Girdwood 90*747503b1SLiam Girdwood return ret; 91*747503b1SLiam Girdwood } 92*747503b1SLiam Girdwood 93*747503b1SLiam Girdwood int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask) 94*747503b1SLiam Girdwood { 95*747503b1SLiam Girdwood /* stall core */ 96*747503b1SLiam Girdwood snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, 97*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, 98*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CSTALL_MASK(core_mask), 99*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CSTALL_MASK(core_mask)); 100*747503b1SLiam Girdwood 101*747503b1SLiam Girdwood /* set reset state */ 102*747503b1SLiam Girdwood return hda_dsp_core_reset_enter(sdev, core_mask); 103*747503b1SLiam Girdwood } 104*747503b1SLiam Girdwood 105*747503b1SLiam Girdwood int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) 106*747503b1SLiam Girdwood { 107*747503b1SLiam Girdwood int ret; 108*747503b1SLiam Girdwood 109*747503b1SLiam Girdwood /* leave reset state */ 110*747503b1SLiam Girdwood ret = hda_dsp_core_reset_leave(sdev, core_mask); 111*747503b1SLiam Girdwood if (ret < 0) 112*747503b1SLiam Girdwood return ret; 113*747503b1SLiam Girdwood 114*747503b1SLiam Girdwood /* run core */ 115*747503b1SLiam Girdwood dev_dbg(sdev->dev, "unstall/run core: core_mask = %x\n", core_mask); 116*747503b1SLiam Girdwood snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, 117*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, 118*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CSTALL_MASK(core_mask), 119*747503b1SLiam Girdwood 0); 120*747503b1SLiam Girdwood 121*747503b1SLiam Girdwood /* is core now running ? */ 122*747503b1SLiam Girdwood if (!hda_dsp_core_is_enabled(sdev, core_mask)) { 123*747503b1SLiam Girdwood hda_dsp_core_stall_reset(sdev, core_mask); 124*747503b1SLiam Girdwood dev_err(sdev->dev, "error: DSP start core failed: core_mask %x\n", 125*747503b1SLiam Girdwood core_mask); 126*747503b1SLiam Girdwood ret = -EIO; 127*747503b1SLiam Girdwood } 128*747503b1SLiam Girdwood 129*747503b1SLiam Girdwood return ret; 130*747503b1SLiam Girdwood } 131*747503b1SLiam Girdwood 132*747503b1SLiam Girdwood /* 133*747503b1SLiam Girdwood * Power Management. 134*747503b1SLiam Girdwood */ 135*747503b1SLiam Girdwood 136*747503b1SLiam Girdwood int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) 137*747503b1SLiam Girdwood { 138*747503b1SLiam Girdwood unsigned int cpa; 139*747503b1SLiam Girdwood u32 adspcs; 140*747503b1SLiam Girdwood int ret; 141*747503b1SLiam Girdwood 142*747503b1SLiam Girdwood /* update bits */ 143*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, 144*747503b1SLiam Girdwood HDA_DSP_ADSPCS_SPA_MASK(core_mask), 145*747503b1SLiam Girdwood HDA_DSP_ADSPCS_SPA_MASK(core_mask)); 146*747503b1SLiam Girdwood 147*747503b1SLiam Girdwood /* poll with timeout to check if operation successful */ 148*747503b1SLiam Girdwood cpa = HDA_DSP_ADSPCS_CPA_MASK(core_mask); 149*747503b1SLiam Girdwood ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, 150*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, adspcs, 151*747503b1SLiam Girdwood (adspcs & cpa) == cpa, 152*747503b1SLiam Girdwood HDA_DSP_REG_POLL_INTERVAL_US, 153*747503b1SLiam Girdwood HDA_DSP_RESET_TIMEOUT_US); 154*747503b1SLiam Girdwood if (ret < 0) 155*747503b1SLiam Girdwood dev_err(sdev->dev, "error: timeout on core powerup\n"); 156*747503b1SLiam Girdwood 157*747503b1SLiam Girdwood /* did core power up ? */ 158*747503b1SLiam Girdwood adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, 159*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS); 160*747503b1SLiam Girdwood if ((adspcs & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) != 161*747503b1SLiam Girdwood HDA_DSP_ADSPCS_CPA_MASK(core_mask)) { 162*747503b1SLiam Girdwood dev_err(sdev->dev, 163*747503b1SLiam Girdwood "error: power up core failed core_mask %xadspcs 0x%x\n", 164*747503b1SLiam Girdwood core_mask, adspcs); 165*747503b1SLiam Girdwood ret = -EIO; 166*747503b1SLiam Girdwood } 167*747503b1SLiam Girdwood 168*747503b1SLiam Girdwood return ret; 169*747503b1SLiam Girdwood } 170*747503b1SLiam Girdwood 171*747503b1SLiam Girdwood int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) 172*747503b1SLiam Girdwood { 173*747503b1SLiam Girdwood u32 adspcs; 174*747503b1SLiam Girdwood 175*747503b1SLiam Girdwood /* update bits */ 176*747503b1SLiam Girdwood snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, 177*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, 178*747503b1SLiam Girdwood HDA_DSP_ADSPCS_SPA_MASK(core_mask), 0); 179*747503b1SLiam Girdwood 180*747503b1SLiam Girdwood return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, 181*747503b1SLiam Girdwood HDA_DSP_REG_ADSPCS, adspcs, 182*747503b1SLiam Girdwood !(adspcs & HDA_DSP_ADSPCS_SPA_MASK(core_mask)), 183*747503b1SLiam Girdwood HDA_DSP_REG_POLL_INTERVAL_US, 184*747503b1SLiam Girdwood HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC); 185*747503b1SLiam Girdwood } 186*747503b1SLiam Girdwood 187*747503b1SLiam Girdwood bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, 188*747503b1SLiam Girdwood unsigned int core_mask) 189*747503b1SLiam Girdwood { 190*747503b1SLiam Girdwood int val; 191*747503b1SLiam Girdwood bool is_enable; 192*747503b1SLiam Girdwood 193*747503b1SLiam Girdwood val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS); 194*747503b1SLiam Girdwood 195*747503b1SLiam Girdwood is_enable = ((val & HDA_DSP_ADSPCS_CPA_MASK(core_mask)) && 196*747503b1SLiam Girdwood (val & HDA_DSP_ADSPCS_SPA_MASK(core_mask)) && 197*747503b1SLiam Girdwood !(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) && 198*747503b1SLiam Girdwood !(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask))); 199*747503b1SLiam Girdwood 200*747503b1SLiam Girdwood dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n", 201*747503b1SLiam Girdwood is_enable, core_mask); 202*747503b1SLiam Girdwood 203*747503b1SLiam Girdwood return is_enable; 204*747503b1SLiam Girdwood } 205*747503b1SLiam Girdwood 206*747503b1SLiam Girdwood int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask) 207*747503b1SLiam Girdwood { 208*747503b1SLiam Girdwood int ret; 209*747503b1SLiam Girdwood 210*747503b1SLiam Girdwood /* return if core is already enabled */ 211*747503b1SLiam Girdwood if (hda_dsp_core_is_enabled(sdev, core_mask)) 212*747503b1SLiam Girdwood return 0; 213*747503b1SLiam Girdwood 214*747503b1SLiam Girdwood /* power up */ 215*747503b1SLiam Girdwood ret = hda_dsp_core_power_up(sdev, core_mask); 216*747503b1SLiam Girdwood if (ret < 0) { 217*747503b1SLiam Girdwood dev_err(sdev->dev, "error: dsp core power up failed: core_mask %x\n", 218*747503b1SLiam Girdwood core_mask); 219*747503b1SLiam Girdwood return ret; 220*747503b1SLiam Girdwood } 221*747503b1SLiam Girdwood 222*747503b1SLiam Girdwood return hda_dsp_core_run(sdev, core_mask); 223*747503b1SLiam Girdwood } 224*747503b1SLiam Girdwood 225*747503b1SLiam Girdwood int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, 226*747503b1SLiam Girdwood unsigned int core_mask) 227*747503b1SLiam Girdwood { 228*747503b1SLiam Girdwood int ret; 229*747503b1SLiam Girdwood 230*747503b1SLiam Girdwood /* place core in reset prior to power down */ 231*747503b1SLiam Girdwood ret = hda_dsp_core_stall_reset(sdev, core_mask); 232*747503b1SLiam Girdwood if (ret < 0) { 233*747503b1SLiam Girdwood dev_err(sdev->dev, "error: dsp core reset failed: core_mask %x\n", 234*747503b1SLiam Girdwood core_mask); 235*747503b1SLiam Girdwood return ret; 236*747503b1SLiam Girdwood } 237*747503b1SLiam Girdwood 238*747503b1SLiam Girdwood /* power down core */ 239*747503b1SLiam Girdwood ret = hda_dsp_core_power_down(sdev, core_mask); 240*747503b1SLiam Girdwood if (ret < 0) { 241*747503b1SLiam Girdwood dev_err(sdev->dev, "error: dsp core power down fail mask %x: %d\n", 242*747503b1SLiam Girdwood core_mask, ret); 243*747503b1SLiam Girdwood return ret; 244*747503b1SLiam Girdwood } 245*747503b1SLiam Girdwood 246*747503b1SLiam Girdwood /* make sure we are in OFF state */ 247*747503b1SLiam Girdwood if (hda_dsp_core_is_enabled(sdev, core_mask)) { 248*747503b1SLiam Girdwood dev_err(sdev->dev, "error: dsp core disable fail mask %x: %d\n", 249*747503b1SLiam Girdwood core_mask, ret); 250*747503b1SLiam Girdwood ret = -EIO; 251*747503b1SLiam Girdwood } 252*747503b1SLiam Girdwood 253*747503b1SLiam Girdwood return ret; 254*747503b1SLiam Girdwood } 255*747503b1SLiam Girdwood 256*747503b1SLiam Girdwood void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev) 257*747503b1SLiam Girdwood { 258*747503b1SLiam Girdwood struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 259*747503b1SLiam Girdwood const struct sof_intel_dsp_desc *chip = hda->desc; 260*747503b1SLiam Girdwood 261*747503b1SLiam Girdwood /* enable IPC DONE and BUSY interrupts */ 262*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, 263*747503b1SLiam Girdwood HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY, 264*747503b1SLiam Girdwood HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY); 265*747503b1SLiam Girdwood 266*747503b1SLiam Girdwood /* enable IPC interrupt */ 267*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, 268*747503b1SLiam Girdwood HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); 269*747503b1SLiam Girdwood } 270*747503b1SLiam Girdwood 271*747503b1SLiam Girdwood void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) 272*747503b1SLiam Girdwood { 273*747503b1SLiam Girdwood struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 274*747503b1SLiam Girdwood const struct sof_intel_dsp_desc *chip = hda->desc; 275*747503b1SLiam Girdwood 276*747503b1SLiam Girdwood /* disable IPC interrupt */ 277*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, 278*747503b1SLiam Girdwood HDA_DSP_ADSPIC_IPC, 0); 279*747503b1SLiam Girdwood 280*747503b1SLiam Girdwood /* disable IPC BUSY and DONE interrupt */ 281*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, 282*747503b1SLiam Girdwood HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); 283*747503b1SLiam Girdwood } 284*747503b1SLiam Girdwood 285*747503b1SLiam Girdwood static int hda_suspend(struct snd_sof_dev *sdev, int state) 286*747503b1SLiam Girdwood { 287*747503b1SLiam Girdwood struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 288*747503b1SLiam Girdwood const struct sof_intel_dsp_desc *chip = hda->desc; 289*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 290*747503b1SLiam Girdwood struct hdac_bus *bus = sof_to_bus(sdev); 291*747503b1SLiam Girdwood #endif 292*747503b1SLiam Girdwood int ret; 293*747503b1SLiam Girdwood 294*747503b1SLiam Girdwood /* disable IPC interrupts */ 295*747503b1SLiam Girdwood hda_dsp_ipc_int_disable(sdev); 296*747503b1SLiam Girdwood 297*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 298*747503b1SLiam Girdwood /* power down all hda link */ 299*747503b1SLiam Girdwood snd_hdac_ext_bus_link_power_down_all(bus); 300*747503b1SLiam Girdwood #endif 301*747503b1SLiam Girdwood 302*747503b1SLiam Girdwood /* power down DSP */ 303*747503b1SLiam Girdwood ret = hda_dsp_core_reset_power_down(sdev, chip->cores_mask); 304*747503b1SLiam Girdwood if (ret < 0) { 305*747503b1SLiam Girdwood dev_err(sdev->dev, 306*747503b1SLiam Girdwood "error: failed to power down core during suspend\n"); 307*747503b1SLiam Girdwood return ret; 308*747503b1SLiam Girdwood } 309*747503b1SLiam Girdwood 310*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 311*747503b1SLiam Girdwood /* disable ppcap interrupt */ 312*747503b1SLiam Girdwood snd_hdac_ext_bus_ppcap_int_enable(bus, false); 313*747503b1SLiam Girdwood snd_hdac_ext_bus_ppcap_enable(bus, false); 314*747503b1SLiam Girdwood 315*747503b1SLiam Girdwood /* disable hda bus irq and i/o */ 316*747503b1SLiam Girdwood snd_hdac_bus_stop_chip(bus); 317*747503b1SLiam Girdwood #else 318*747503b1SLiam Girdwood /* disable ppcap interrupt */ 319*747503b1SLiam Girdwood hda_dsp_ctrl_ppcap_enable(sdev, false); 320*747503b1SLiam Girdwood hda_dsp_ctrl_ppcap_int_enable(sdev, false); 321*747503b1SLiam Girdwood 322*747503b1SLiam Girdwood /* disable hda bus irq */ 323*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 324*747503b1SLiam Girdwood SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 325*747503b1SLiam Girdwood 0); 326*747503b1SLiam Girdwood #endif 327*747503b1SLiam Girdwood 328*747503b1SLiam Girdwood /* disable LP retention mode */ 329*747503b1SLiam Girdwood snd_sof_pci_update_bits(sdev, PCI_PGCTL, 330*747503b1SLiam Girdwood PCI_PGCTL_LSRMD_MASK, PCI_PGCTL_LSRMD_MASK); 331*747503b1SLiam Girdwood 332*747503b1SLiam Girdwood /* reset controller */ 333*747503b1SLiam Girdwood ret = hda_dsp_ctrl_link_reset(sdev, true); 334*747503b1SLiam Girdwood if (ret < 0) { 335*747503b1SLiam Girdwood dev_err(sdev->dev, 336*747503b1SLiam Girdwood "error: failed to reset controller during suspend\n"); 337*747503b1SLiam Girdwood return ret; 338*747503b1SLiam Girdwood } 339*747503b1SLiam Girdwood 340*747503b1SLiam Girdwood return 0; 341*747503b1SLiam Girdwood } 342*747503b1SLiam Girdwood 343*747503b1SLiam Girdwood static int hda_resume(struct snd_sof_dev *sdev) 344*747503b1SLiam Girdwood { 345*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 346*747503b1SLiam Girdwood struct hdac_bus *bus = sof_to_bus(sdev); 347*747503b1SLiam Girdwood struct hdac_ext_link *hlink = NULL; 348*747503b1SLiam Girdwood #endif 349*747503b1SLiam Girdwood int ret; 350*747503b1SLiam Girdwood 351*747503b1SLiam Girdwood /* 352*747503b1SLiam Girdwood * clear TCSEL to clear playback on some HD Audio 353*747503b1SLiam Girdwood * codecs. PCI TCSEL is defined in the Intel manuals. 354*747503b1SLiam Girdwood */ 355*747503b1SLiam Girdwood snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); 356*747503b1SLiam Girdwood 357*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 358*747503b1SLiam Girdwood /* reset and start hda controller */ 359*747503b1SLiam Girdwood ret = hda_dsp_ctrl_init_chip(sdev, true); 360*747503b1SLiam Girdwood if (ret < 0) { 361*747503b1SLiam Girdwood dev_err(sdev->dev, 362*747503b1SLiam Girdwood "error: failed to start controller after resume\n"); 363*747503b1SLiam Girdwood return ret; 364*747503b1SLiam Girdwood } 365*747503b1SLiam Girdwood 366*747503b1SLiam Girdwood hda_dsp_ctrl_misc_clock_gating(sdev, false); 367*747503b1SLiam Girdwood 368*747503b1SLiam Girdwood /* Reset stream-to-link mapping */ 369*747503b1SLiam Girdwood list_for_each_entry(hlink, &bus->hlink_list, list) 370*747503b1SLiam Girdwood bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); 371*747503b1SLiam Girdwood 372*747503b1SLiam Girdwood hda_dsp_ctrl_misc_clock_gating(sdev, true); 373*747503b1SLiam Girdwood 374*747503b1SLiam Girdwood /* enable ppcap interrupt */ 375*747503b1SLiam Girdwood snd_hdac_ext_bus_ppcap_enable(bus, true); 376*747503b1SLiam Girdwood snd_hdac_ext_bus_ppcap_int_enable(bus, true); 377*747503b1SLiam Girdwood #else 378*747503b1SLiam Girdwood 379*747503b1SLiam Girdwood hda_dsp_ctrl_misc_clock_gating(sdev, false); 380*747503b1SLiam Girdwood 381*747503b1SLiam Girdwood /* reset controller */ 382*747503b1SLiam Girdwood ret = hda_dsp_ctrl_link_reset(sdev, true); 383*747503b1SLiam Girdwood if (ret < 0) { 384*747503b1SLiam Girdwood dev_err(sdev->dev, 385*747503b1SLiam Girdwood "error: failed to reset controller during resume\n"); 386*747503b1SLiam Girdwood return ret; 387*747503b1SLiam Girdwood } 388*747503b1SLiam Girdwood 389*747503b1SLiam Girdwood /* take controller out of reset */ 390*747503b1SLiam Girdwood ret = hda_dsp_ctrl_link_reset(sdev, false); 391*747503b1SLiam Girdwood if (ret < 0) { 392*747503b1SLiam Girdwood dev_err(sdev->dev, 393*747503b1SLiam Girdwood "error: failed to ready controller during resume\n"); 394*747503b1SLiam Girdwood return ret; 395*747503b1SLiam Girdwood } 396*747503b1SLiam Girdwood 397*747503b1SLiam Girdwood /* enable hda bus irq */ 398*747503b1SLiam Girdwood snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 399*747503b1SLiam Girdwood SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 400*747503b1SLiam Girdwood SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); 401*747503b1SLiam Girdwood 402*747503b1SLiam Girdwood hda_dsp_ctrl_misc_clock_gating(sdev, true); 403*747503b1SLiam Girdwood 404*747503b1SLiam Girdwood /* enable ppcap interrupt */ 405*747503b1SLiam Girdwood hda_dsp_ctrl_ppcap_enable(sdev, true); 406*747503b1SLiam Girdwood hda_dsp_ctrl_ppcap_int_enable(sdev, true); 407*747503b1SLiam Girdwood #endif 408*747503b1SLiam Girdwood 409*747503b1SLiam Girdwood #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 410*747503b1SLiam Girdwood /* turn off the links that were off before suspend */ 411*747503b1SLiam Girdwood list_for_each_entry(hlink, &bus->hlink_list, list) { 412*747503b1SLiam Girdwood if (!hlink->ref_count) 413*747503b1SLiam Girdwood snd_hdac_ext_bus_link_power_down(hlink); 414*747503b1SLiam Girdwood } 415*747503b1SLiam Girdwood 416*747503b1SLiam Girdwood /* check dma status and clean up CORB/RIRB buffers */ 417*747503b1SLiam Girdwood if (!bus->cmd_dma_state) 418*747503b1SLiam Girdwood snd_hdac_bus_stop_cmd_io(bus); 419*747503b1SLiam Girdwood #endif 420*747503b1SLiam Girdwood 421*747503b1SLiam Girdwood return 0; 422*747503b1SLiam Girdwood } 423*747503b1SLiam Girdwood 424*747503b1SLiam Girdwood int hda_dsp_resume(struct snd_sof_dev *sdev) 425*747503b1SLiam Girdwood { 426*747503b1SLiam Girdwood /* init hda controller. DSP cores will be powered up during fw boot */ 427*747503b1SLiam Girdwood return hda_resume(sdev); 428*747503b1SLiam Girdwood } 429*747503b1SLiam Girdwood 430*747503b1SLiam Girdwood int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) 431*747503b1SLiam Girdwood { 432*747503b1SLiam Girdwood /* init hda controller. DSP cores will be powered up during fw boot */ 433*747503b1SLiam Girdwood return hda_resume(sdev); 434*747503b1SLiam Girdwood } 435*747503b1SLiam Girdwood 436*747503b1SLiam Girdwood int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state) 437*747503b1SLiam Girdwood { 438*747503b1SLiam Girdwood /* stop hda controller and power dsp off */ 439*747503b1SLiam Girdwood return hda_suspend(sdev, state); 440*747503b1SLiam Girdwood } 441*747503b1SLiam Girdwood 442*747503b1SLiam Girdwood int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) 443*747503b1SLiam Girdwood { 444*747503b1SLiam Girdwood struct hdac_bus *bus = sof_to_bus(sdev); 445*747503b1SLiam Girdwood int ret; 446*747503b1SLiam Girdwood 447*747503b1SLiam Girdwood /* stop hda controller and power dsp off */ 448*747503b1SLiam Girdwood ret = hda_suspend(sdev, state); 449*747503b1SLiam Girdwood if (ret < 0) { 450*747503b1SLiam Girdwood dev_err(bus->dev, "error: suspending dsp\n"); 451*747503b1SLiam Girdwood return ret; 452*747503b1SLiam Girdwood } 453*747503b1SLiam Girdwood 454*747503b1SLiam Girdwood return 0; 455*747503b1SLiam Girdwood } 456