linux/sound/soc/sof/ops.h
<<
>>
Prefs
   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 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
   9 */
  10
  11#ifndef __SOUND_SOC_SOF_IO_H
  12#define __SOUND_SOC_SOF_IO_H
  13
  14#include <linux/device.h>
  15#include <linux/interrupt.h>
  16#include <linux/kernel.h>
  17#include <linux/types.h>
  18#include <sound/pcm.h>
  19#include "sof-priv.h"
  20
  21#define sof_ops(sdev) \
  22        ((sdev)->pdata->desc->ops)
  23
  24/* Mandatory operations are verified during probing */
  25
  26/* init */
  27static inline int snd_sof_probe(struct snd_sof_dev *sdev)
  28{
  29        return sof_ops(sdev)->probe(sdev);
  30}
  31
  32static inline int snd_sof_remove(struct snd_sof_dev *sdev)
  33{
  34        if (sof_ops(sdev)->remove)
  35                return sof_ops(sdev)->remove(sdev);
  36
  37        return 0;
  38}
  39
  40static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
  41{
  42        if (sof_ops(sdev)->shutdown)
  43                return sof_ops(sdev)->shutdown(sdev);
  44
  45        return 0;
  46}
  47
  48/* control */
  49
  50/*
  51 * snd_sof_dsp_run returns the core mask of the cores that are available
  52 * after successful fw boot
  53 */
  54static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
  55{
  56        return sof_ops(sdev)->run(sdev);
  57}
  58
  59static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask)
  60{
  61        if (sof_ops(sdev)->stall)
  62                return sof_ops(sdev)->stall(sdev, core_mask);
  63
  64        return 0;
  65}
  66
  67static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
  68{
  69        if (sof_ops(sdev)->reset)
  70                return sof_ops(sdev)->reset(sdev);
  71
  72        return 0;
  73}
  74
  75/* dsp core power up/power down */
  76static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
  77                                            unsigned int core_mask)
  78{
  79        int ret = 0;
  80
  81        core_mask &= ~sdev->enabled_cores_mask;
  82        if (sof_ops(sdev)->core_power_up && core_mask) {
  83                ret = sof_ops(sdev)->core_power_up(sdev, core_mask);
  84                if (!ret)
  85                        sdev->enabled_cores_mask |= core_mask;
  86        }
  87
  88        return ret;
  89}
  90
  91static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
  92                                              unsigned int core_mask)
  93{
  94        int ret = 0;
  95
  96        core_mask &= sdev->enabled_cores_mask;
  97        if (sof_ops(sdev)->core_power_down && core_mask) {
  98                ret = sof_ops(sdev)->core_power_down(sdev, core_mask);
  99                if (!ret)
 100                        sdev->enabled_cores_mask &= ~core_mask;
 101        }
 102
 103        return ret;
 104}
 105
 106/* pre/post fw load */
 107static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
 108{
 109        if (sof_ops(sdev)->pre_fw_run)
 110                return sof_ops(sdev)->pre_fw_run(sdev);
 111
 112        return 0;
 113}
 114
 115static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
 116{
 117        if (sof_ops(sdev)->post_fw_run)
 118                return sof_ops(sdev)->post_fw_run(sdev);
 119
 120        return 0;
 121}
 122
 123/* parse platform specific extended manifest */
 124static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev,
 125                                                          const struct sof_ext_man_elem_header *hdr)
 126{
 127        if (sof_ops(sdev)->parse_platform_ext_manifest)
 128                return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr);
 129
 130        return 0;
 131}
 132
 133/* misc */
 134
 135/**
 136 * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
 137 *
 138 * @sdev: sof device
 139 * @type: section type as described by snd_sof_fw_blk_type
 140 *
 141 * Returns the corresponding BAR index (a positive integer) or -EINVAL
 142 * in case there is no mapping
 143 */
 144static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
 145{
 146        if (sof_ops(sdev)->get_bar_index)
 147                return sof_ops(sdev)->get_bar_index(sdev, type);
 148
 149        return sdev->mmio_bar;
 150}
 151
 152static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
 153{
 154        if (sof_ops(sdev)->get_mailbox_offset)
 155                return sof_ops(sdev)->get_mailbox_offset(sdev);
 156
 157        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 158        return -ENOTSUPP;
 159}
 160
 161static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
 162                                                u32 id)
 163{
 164        if (sof_ops(sdev)->get_window_offset)
 165                return sof_ops(sdev)->get_window_offset(sdev, id);
 166
 167        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 168        return -ENOTSUPP;
 169}
 170/* power management */
 171static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
 172{
 173        if (sof_ops(sdev)->resume)
 174                return sof_ops(sdev)->resume(sdev);
 175
 176        return 0;
 177}
 178
 179static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev,
 180                                      u32 target_state)
 181{
 182        if (sof_ops(sdev)->suspend)
 183                return sof_ops(sdev)->suspend(sdev, target_state);
 184
 185        return 0;
 186}
 187
 188static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
 189{
 190        if (sof_ops(sdev)->runtime_resume)
 191                return sof_ops(sdev)->runtime_resume(sdev);
 192
 193        return 0;
 194}
 195
 196static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
 197{
 198        if (sof_ops(sdev)->runtime_suspend)
 199                return sof_ops(sdev)->runtime_suspend(sdev);
 200
 201        return 0;
 202}
 203
 204static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
 205{
 206        if (sof_ops(sdev)->runtime_idle)
 207                return sof_ops(sdev)->runtime_idle(sdev);
 208
 209        return 0;
 210}
 211
 212static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
 213{
 214        if (sof_ops(sdev)->set_hw_params_upon_resume)
 215                return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
 216        return 0;
 217}
 218
 219static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
 220{
 221        if (sof_ops(sdev)->set_clk)
 222                return sof_ops(sdev)->set_clk(sdev, freq);
 223
 224        return 0;
 225}
 226
 227static inline int
 228snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
 229                            const struct sof_dsp_power_state *target_state)
 230{
 231        int ret = 0;
 232
 233        mutex_lock(&sdev->power_state_access);
 234
 235        if (sof_ops(sdev)->set_power_state)
 236                ret = sof_ops(sdev)->set_power_state(sdev, target_state);
 237
 238        mutex_unlock(&sdev->power_state_access);
 239
 240        return ret;
 241}
 242
 243/* debug */
 244static inline void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags)
 245{
 246        if (sof_ops(sdev)->dbg_dump)
 247                sof_ops(sdev)->dbg_dump(sdev, flags);
 248}
 249
 250static inline void snd_sof_ipc_dump(struct snd_sof_dev *sdev)
 251{
 252        if (sof_ops(sdev)->ipc_dump)
 253                sof_ops(sdev)->ipc_dump(sdev);
 254}
 255
 256/* register IO */
 257static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
 258                                     u32 offset, u32 value)
 259{
 260        if (sof_ops(sdev)->write) {
 261                sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
 262                return;
 263        }
 264
 265        dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
 266}
 267
 268static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
 269                                       u32 offset, u64 value)
 270{
 271        if (sof_ops(sdev)->write64) {
 272                sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
 273                return;
 274        }
 275
 276        dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
 277}
 278
 279static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
 280                                   u32 offset)
 281{
 282        if (sof_ops(sdev)->read)
 283                return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
 284
 285        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 286        return -ENOTSUPP;
 287}
 288
 289static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
 290                                     u32 offset)
 291{
 292        if (sof_ops(sdev)->read64)
 293                return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
 294
 295        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 296        return -ENOTSUPP;
 297}
 298
 299/* block IO */
 300static inline void snd_sof_dsp_block_read(struct snd_sof_dev *sdev, u32 bar,
 301                                          u32 offset, void *dest, size_t bytes)
 302{
 303        sof_ops(sdev)->block_read(sdev, bar, offset, dest, bytes);
 304}
 305
 306static inline void snd_sof_dsp_block_write(struct snd_sof_dev *sdev, u32 bar,
 307                                           u32 offset, void *src, size_t bytes)
 308{
 309        sof_ops(sdev)->block_write(sdev, bar, offset, src, bytes);
 310}
 311
 312/* ipc */
 313static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
 314                                       struct snd_sof_ipc_msg *msg)
 315{
 316        return sof_ops(sdev)->send_msg(sdev, msg);
 317}
 318
 319/* host DMA trace */
 320static inline int snd_sof_dma_trace_init(struct snd_sof_dev *sdev,
 321                                         u32 *stream_tag)
 322{
 323        if (sof_ops(sdev)->trace_init)
 324                return sof_ops(sdev)->trace_init(sdev, stream_tag);
 325
 326        return 0;
 327}
 328
 329static inline int snd_sof_dma_trace_release(struct snd_sof_dev *sdev)
 330{
 331        if (sof_ops(sdev)->trace_release)
 332                return sof_ops(sdev)->trace_release(sdev);
 333
 334        return 0;
 335}
 336
 337static inline int snd_sof_dma_trace_trigger(struct snd_sof_dev *sdev, int cmd)
 338{
 339        if (sof_ops(sdev)->trace_trigger)
 340                return sof_ops(sdev)->trace_trigger(sdev, cmd);
 341
 342        return 0;
 343}
 344
 345/* host PCM ops */
 346static inline int
 347snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
 348                          struct snd_pcm_substream *substream)
 349{
 350        if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
 351                return sof_ops(sdev)->pcm_open(sdev, substream);
 352
 353        return 0;
 354}
 355
 356/* disconnect pcm substream to a host stream */
 357static inline int
 358snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
 359                           struct snd_pcm_substream *substream)
 360{
 361        if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
 362                return sof_ops(sdev)->pcm_close(sdev, substream);
 363
 364        return 0;
 365}
 366
 367/* host stream hw params */
 368static inline int
 369snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
 370                               struct snd_pcm_substream *substream,
 371                               struct snd_pcm_hw_params *params,
 372                               struct sof_ipc_stream_params *ipc_params)
 373{
 374        if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
 375                return sof_ops(sdev)->pcm_hw_params(sdev, substream,
 376                                                    params, ipc_params);
 377
 378        return 0;
 379}
 380
 381/* host stream hw free */
 382static inline int
 383snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
 384                             struct snd_pcm_substream *substream)
 385{
 386        if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
 387                return sof_ops(sdev)->pcm_hw_free(sdev, substream);
 388
 389        return 0;
 390}
 391
 392/* host stream trigger */
 393static inline int
 394snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
 395                             struct snd_pcm_substream *substream, int cmd)
 396{
 397        if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
 398                return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
 399
 400        return 0;
 401}
 402
 403/* host DSP message data */
 404static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
 405                                        struct snd_pcm_substream *substream,
 406                                        void *p, size_t sz)
 407{
 408        sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
 409}
 410
 411/* host configure DSP HW parameters */
 412static inline int
 413snd_sof_ipc_pcm_params(struct snd_sof_dev *sdev,
 414                       struct snd_pcm_substream *substream,
 415                       const struct sof_ipc_pcm_params_reply *reply)
 416{
 417        return sof_ops(sdev)->ipc_pcm_params(sdev, substream, reply);
 418}
 419
 420/* host stream pointer */
 421static inline snd_pcm_uframes_t
 422snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
 423                             struct snd_pcm_substream *substream)
 424{
 425        if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
 426                return sof_ops(sdev)->pcm_pointer(sdev, substream);
 427
 428        return 0;
 429}
 430
 431#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
 432static inline int
 433snd_sof_probe_compr_assign(struct snd_sof_dev *sdev,
 434                struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
 435{
 436        return sof_ops(sdev)->probe_assign(sdev, cstream, dai);
 437}
 438
 439static inline int
 440snd_sof_probe_compr_free(struct snd_sof_dev *sdev,
 441                struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
 442{
 443        return sof_ops(sdev)->probe_free(sdev, cstream, dai);
 444}
 445
 446static inline int
 447snd_sof_probe_compr_set_params(struct snd_sof_dev *sdev,
 448                struct snd_compr_stream *cstream,
 449                struct snd_compr_params *params, struct snd_soc_dai *dai)
 450{
 451        return sof_ops(sdev)->probe_set_params(sdev, cstream, params, dai);
 452}
 453
 454static inline int
 455snd_sof_probe_compr_trigger(struct snd_sof_dev *sdev,
 456                struct snd_compr_stream *cstream, int cmd,
 457                struct snd_soc_dai *dai)
 458{
 459        return sof_ops(sdev)->probe_trigger(sdev, cstream, cmd, dai);
 460}
 461
 462static inline int
 463snd_sof_probe_compr_pointer(struct snd_sof_dev *sdev,
 464                struct snd_compr_stream *cstream,
 465                struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
 466{
 467        if (sof_ops(sdev) && sof_ops(sdev)->probe_pointer)
 468                return sof_ops(sdev)->probe_pointer(sdev, cstream, tstamp, dai);
 469
 470        return 0;
 471}
 472#endif
 473
 474/* machine driver */
 475static inline int
 476snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
 477{
 478        if (sof_ops(sdev) && sof_ops(sdev)->machine_register)
 479                return sof_ops(sdev)->machine_register(sdev, pdata);
 480
 481        return 0;
 482}
 483
 484static inline void
 485snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
 486{
 487        if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister)
 488                sof_ops(sdev)->machine_unregister(sdev, pdata);
 489}
 490
 491static inline void
 492snd_sof_machine_select(struct snd_sof_dev *sdev)
 493{
 494        if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
 495                sof_ops(sdev)->machine_select(sdev);
 496}
 497
 498static inline void
 499snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach,
 500                        struct snd_sof_dev *sdev)
 501{
 502        if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
 503                sof_ops(sdev)->set_mach_params(mach, sdev);
 504}
 505
 506static inline const struct snd_sof_dsp_ops
 507*sof_get_ops(const struct sof_dev_desc *d,
 508             const struct sof_ops_table mach_ops[], int asize)
 509{
 510        int i;
 511
 512        for (i = 0; i < asize; i++) {
 513                if (d == mach_ops[i].desc)
 514                        return mach_ops[i].ops;
 515        }
 516
 517        /* not found */
 518        return NULL;
 519}
 520
 521/**
 522 * snd_sof_dsp_register_poll_timeout - Periodically poll an address
 523 * until a condition is met or a timeout occurs
 524 * @op: accessor function (takes @addr as its only argument)
 525 * @addr: Address to poll
 526 * @val: Variable to read the value into
 527 * @cond: Break condition (usually involving @val)
 528 * @sleep_us: Maximum time to sleep between reads in us (0
 529 *            tight-loops).  Should be less than ~20ms since usleep_range
 530 *            is used (see Documentation/timers/timers-howto.rst).
 531 * @timeout_us: Timeout in us, 0 means never timeout
 532 *
 533 * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
 534 * case, the last read value at @addr is stored in @val. Must not
 535 * be called from atomic context if sleep_us or timeout_us are used.
 536 *
 537 * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
 538 */
 539#define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
 540({ \
 541        u64 __timeout_us = (timeout_us); \
 542        unsigned long __sleep_us = (sleep_us); \
 543        ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
 544        might_sleep_if((__sleep_us) != 0); \
 545        for (;;) {                                                      \
 546                (val) = snd_sof_dsp_read(sdev, bar, offset);            \
 547                if (cond) { \
 548                        dev_dbg(sdev->dev, \
 549                                "FW Poll Status: reg[%#x]=%#x successful\n", \
 550                                (offset), (val)); \
 551                        break; \
 552                } \
 553                if (__timeout_us && \
 554                    ktime_compare(ktime_get(), __timeout) > 0) { \
 555                        (val) = snd_sof_dsp_read(sdev, bar, offset); \
 556                        dev_dbg(sdev->dev, \
 557                                "FW Poll Status: reg[%#x]=%#x timedout\n", \
 558                                (offset), (val)); \
 559                        break; \
 560                } \
 561                if (__sleep_us) \
 562                        usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
 563        } \
 564        (cond) ? 0 : -ETIMEDOUT; \
 565})
 566
 567/* This is for registers bits with attribute RWC */
 568bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
 569                             u32 mask, u32 value);
 570
 571bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
 572                                      u32 offset, u32 mask, u32 value);
 573
 574bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
 575                                        u32 offset, u64 mask, u64 value);
 576
 577bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
 578                             u32 mask, u32 value);
 579
 580bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
 581                               u32 offset, u64 mask, u64 value);
 582
 583void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
 584                                    u32 offset, u32 mask, u32 value);
 585
 586int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
 587                              u32 mask, u32 target, u32 timeout_ms,
 588                              u32 interval_us);
 589
 590void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset);
 591#endif
 592