linux/sound/soc/sof/intel/hda-dsp.c
<<
>>
Prefs
   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
  27int 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
  60int 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
  93int 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
 105int 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
 136int 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
 171int 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
 187bool 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
 206int 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
 225int 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
 256void 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
 271void 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
 285static int hda_suspend(struct snd_sof_dev *sdev, int state)
 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        /* power down all hda link */
 299        snd_hdac_ext_bus_link_power_down_all(bus);
 300#endif
 301
 302        /* power down DSP */
 303        ret = hda_dsp_core_reset_power_down(sdev, chip->cores_mask);
 304        if (ret < 0) {
 305                dev_err(sdev->dev,
 306                        "error: failed to power down core during suspend\n");
 307                return ret;
 308        }
 309
 310#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
 311        /* disable ppcap interrupt */
 312        snd_hdac_ext_bus_ppcap_int_enable(bus, false);
 313        snd_hdac_ext_bus_ppcap_enable(bus, false);
 314
 315        /* disable hda bus irq and i/o */
 316        snd_hdac_bus_stop_chip(bus);
 317#else
 318        /* disable ppcap interrupt */
 319        hda_dsp_ctrl_ppcap_enable(sdev, false);
 320        hda_dsp_ctrl_ppcap_int_enable(sdev, false);
 321
 322        /* disable hda bus irq */
 323        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
 324                                SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
 325                                0);
 326#endif
 327
 328        /* disable LP retention mode */
 329        snd_sof_pci_update_bits(sdev, PCI_PGCTL,
 330                                PCI_PGCTL_LSRMD_MASK, PCI_PGCTL_LSRMD_MASK);
 331
 332        /* reset controller */
 333        ret = hda_dsp_ctrl_link_reset(sdev, true);
 334        if (ret < 0) {
 335                dev_err(sdev->dev,
 336                        "error: failed to reset controller during suspend\n");
 337                return ret;
 338        }
 339
 340        return 0;
 341}
 342
 343static int hda_resume(struct snd_sof_dev *sdev)
 344{
 345#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
 346        struct hdac_bus *bus = sof_to_bus(sdev);
 347        struct hdac_ext_link *hlink = NULL;
 348#endif
 349        int ret;
 350
 351        /*
 352         * clear TCSEL to clear playback on some HD Audio
 353         * codecs. PCI TCSEL is defined in the Intel manuals.
 354         */
 355        snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0);
 356
 357#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
 358        /* reset and start hda controller */
 359        ret = hda_dsp_ctrl_init_chip(sdev, true);
 360        if (ret < 0) {
 361                dev_err(sdev->dev,
 362                        "error: failed to start controller after resume\n");
 363                return ret;
 364        }
 365
 366        hda_dsp_ctrl_misc_clock_gating(sdev, false);
 367
 368        /* Reset stream-to-link mapping */
 369        list_for_each_entry(hlink, &bus->hlink_list, list)
 370                bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
 371
 372        hda_dsp_ctrl_misc_clock_gating(sdev, true);
 373
 374        /* enable ppcap interrupt */
 375        snd_hdac_ext_bus_ppcap_enable(bus, true);
 376        snd_hdac_ext_bus_ppcap_int_enable(bus, true);
 377#else
 378
 379        hda_dsp_ctrl_misc_clock_gating(sdev, false);
 380
 381        /* reset controller */
 382        ret = hda_dsp_ctrl_link_reset(sdev, true);
 383        if (ret < 0) {
 384                dev_err(sdev->dev,
 385                        "error: failed to reset controller during resume\n");
 386                return ret;
 387        }
 388
 389        /* take controller out of reset */
 390        ret = hda_dsp_ctrl_link_reset(sdev, false);
 391        if (ret < 0) {
 392                dev_err(sdev->dev,
 393                        "error: failed to ready controller during resume\n");
 394                return ret;
 395        }
 396
 397        /* enable hda bus irq */
 398        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
 399                                SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
 400                                SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
 401
 402        hda_dsp_ctrl_misc_clock_gating(sdev, true);
 403
 404        /* enable ppcap interrupt */
 405        hda_dsp_ctrl_ppcap_enable(sdev, true);
 406        hda_dsp_ctrl_ppcap_int_enable(sdev, true);
 407#endif
 408
 409#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
 410        /* turn off the links that were off before suspend */
 411        list_for_each_entry(hlink, &bus->hlink_list, list) {
 412                if (!hlink->ref_count)
 413                        snd_hdac_ext_bus_link_power_down(hlink);
 414        }
 415
 416        /* check dma status and clean up CORB/RIRB buffers */
 417        if (!bus->cmd_dma_state)
 418                snd_hdac_bus_stop_cmd_io(bus);
 419#endif
 420
 421        return 0;
 422}
 423
 424int hda_dsp_resume(struct snd_sof_dev *sdev)
 425{
 426        /* init hda controller. DSP cores will be powered up during fw boot */
 427        return hda_resume(sdev);
 428}
 429
 430int hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
 431{
 432        /* init hda controller. DSP cores will be powered up during fw boot */
 433        return hda_resume(sdev);
 434}
 435
 436int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state)
 437{
 438        /* stop hda controller and power dsp off */
 439        return hda_suspend(sdev, state);
 440}
 441
 442int hda_dsp_suspend(struct snd_sof_dev *sdev, int state)
 443{
 444        struct hdac_bus *bus = sof_to_bus(sdev);
 445        int ret;
 446
 447        /* stop hda controller and power dsp off */
 448        ret = hda_suspend(sdev, state);
 449        if (ret < 0) {
 450                dev_err(bus->dev, "error: suspending dsp\n");
 451                return ret;
 452        }
 453
 454        return 0;
 455}
 456
 457void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
 458{
 459        struct hdac_bus *bus = sof_to_bus(sdev);
 460        struct sof_intel_hda_stream *hda_stream;
 461        struct hdac_ext_stream *stream;
 462        struct hdac_stream *s;
 463
 464        /* set internal flag for BE */
 465        list_for_each_entry(s, &bus->stream_list, list) {
 466                stream = stream_to_hdac_ext_stream(s);
 467                hda_stream = container_of(stream, struct sof_intel_hda_stream,
 468                                          hda_stream);
 469                hda_stream->hw_params_upon_resume = 1;
 470        }
 471}
 472