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