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