root/sound/soc/sof/intel/hda-dsp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hda_dsp_core_reset_enter
  2. hda_dsp_core_reset_leave
  3. hda_dsp_core_stall_reset
  4. hda_dsp_core_run
  5. hda_dsp_core_power_up
  6. hda_dsp_core_power_down
  7. hda_dsp_core_is_enabled
  8. hda_dsp_enable_core
  9. hda_dsp_core_reset_power_down
  10. hda_dsp_ipc_int_enable
  11. hda_dsp_ipc_int_disable
  12. hda_suspend
  13. hda_resume
  14. hda_dsp_resume
  15. hda_dsp_runtime_resume
  16. hda_dsp_runtime_idle
  17. hda_dsp_runtime_suspend
  18. hda_dsp_suspend
  19. hda_dsp_set_hw_params_upon_resume

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

/* [<][>][^][v][top][bottom][index][help] */