Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
0002 /*
0003  * This file is provided under a dual BSD/GPLv2 license.  When using or
0004  * redistributing this file, you may do so under either license.
0005  *
0006  * Copyright(c) 2018 Intel Corporation. All rights reserved.
0007  *
0008  * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
0009  */
0010 
0011 #ifndef __SOUND_SOC_SOF_IO_H
0012 #define __SOUND_SOC_SOF_IO_H
0013 
0014 #include <linux/device.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/kernel.h>
0017 #include <linux/types.h>
0018 #include <sound/pcm.h>
0019 #include "sof-priv.h"
0020 
0021 #define sof_ops(sdev) \
0022     ((sdev)->pdata->desc->ops)
0023 
0024 static inline int sof_ops_init(struct snd_sof_dev *sdev)
0025 {
0026     if (sdev->pdata->desc->ops_init)
0027         return sdev->pdata->desc->ops_init(sdev);
0028 
0029     return 0;
0030 }
0031 
0032 static inline void sof_ops_free(struct snd_sof_dev *sdev)
0033 {
0034     if (sdev->pdata->desc->ops_free)
0035         sdev->pdata->desc->ops_free(sdev);
0036 }
0037 
0038 /* Mandatory operations are verified during probing */
0039 
0040 /* init */
0041 static inline int snd_sof_probe(struct snd_sof_dev *sdev)
0042 {
0043     return sof_ops(sdev)->probe(sdev);
0044 }
0045 
0046 static inline int snd_sof_remove(struct snd_sof_dev *sdev)
0047 {
0048     if (sof_ops(sdev)->remove)
0049         return sof_ops(sdev)->remove(sdev);
0050 
0051     return 0;
0052 }
0053 
0054 static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
0055 {
0056     if (sof_ops(sdev)->shutdown)
0057         return sof_ops(sdev)->shutdown(sdev);
0058 
0059     return 0;
0060 }
0061 
0062 /* control */
0063 
0064 /*
0065  * snd_sof_dsp_run returns the core mask of the cores that are available
0066  * after successful fw boot
0067  */
0068 static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
0069 {
0070     return sof_ops(sdev)->run(sdev);
0071 }
0072 
0073 static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask)
0074 {
0075     if (sof_ops(sdev)->stall)
0076         return sof_ops(sdev)->stall(sdev, core_mask);
0077 
0078     return 0;
0079 }
0080 
0081 static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
0082 {
0083     if (sof_ops(sdev)->reset)
0084         return sof_ops(sdev)->reset(sdev);
0085 
0086     return 0;
0087 }
0088 
0089 /* dsp core get/put */
0090 static inline int snd_sof_dsp_core_get(struct snd_sof_dev *sdev, int core)
0091 {
0092     if (core > sdev->num_cores - 1) {
0093         dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core,
0094             sdev->num_cores);
0095         return -EINVAL;
0096     }
0097 
0098     if (sof_ops(sdev)->core_get) {
0099         int ret;
0100 
0101         /* if current ref_count is > 0, increment it and return */
0102         if (sdev->dsp_core_ref_count[core] > 0) {
0103             sdev->dsp_core_ref_count[core]++;
0104             return 0;
0105         }
0106 
0107         /* power up the core */
0108         ret = sof_ops(sdev)->core_get(sdev, core);
0109         if (ret < 0)
0110             return ret;
0111 
0112         /* increment ref_count */
0113         sdev->dsp_core_ref_count[core]++;
0114 
0115         /* and update enabled_cores_mask */
0116         sdev->enabled_cores_mask |= BIT(core);
0117 
0118         dev_dbg(sdev->dev, "Core %d powered up\n", core);
0119     }
0120 
0121     return 0;
0122 }
0123 
0124 static inline int snd_sof_dsp_core_put(struct snd_sof_dev *sdev, int core)
0125 {
0126     if (core > sdev->num_cores - 1) {
0127         dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core,
0128             sdev->num_cores);
0129         return -EINVAL;
0130     }
0131 
0132     if (sof_ops(sdev)->core_put) {
0133         int ret;
0134 
0135         /* decrement ref_count and return if it is > 0 */
0136         if (--(sdev->dsp_core_ref_count[core]) > 0)
0137             return 0;
0138 
0139         /* power down the core */
0140         ret = sof_ops(sdev)->core_put(sdev, core);
0141         if (ret < 0)
0142             return ret;
0143 
0144         /* and update enabled_cores_mask */
0145         sdev->enabled_cores_mask &= ~BIT(core);
0146 
0147         dev_dbg(sdev->dev, "Core %d powered down\n", core);
0148     }
0149 
0150     return 0;
0151 }
0152 
0153 /* pre/post fw load */
0154 static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
0155 {
0156     if (sof_ops(sdev)->pre_fw_run)
0157         return sof_ops(sdev)->pre_fw_run(sdev);
0158 
0159     return 0;
0160 }
0161 
0162 static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
0163 {
0164     if (sof_ops(sdev)->post_fw_run)
0165         return sof_ops(sdev)->post_fw_run(sdev);
0166 
0167     return 0;
0168 }
0169 
0170 /* parse platform specific extended manifest */
0171 static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev,
0172                               const struct sof_ext_man_elem_header *hdr)
0173 {
0174     if (sof_ops(sdev)->parse_platform_ext_manifest)
0175         return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr);
0176 
0177     return 0;
0178 }
0179 
0180 /* misc */
0181 
0182 /**
0183  * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
0184  *
0185  * @sdev: sof device
0186  * @type: section type as described by snd_sof_fw_blk_type
0187  *
0188  * Returns the corresponding BAR index (a positive integer) or -EINVAL
0189  * in case there is no mapping
0190  */
0191 static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
0192 {
0193     if (sof_ops(sdev)->get_bar_index)
0194         return sof_ops(sdev)->get_bar_index(sdev, type);
0195 
0196     return sdev->mmio_bar;
0197 }
0198 
0199 static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
0200 {
0201     if (sof_ops(sdev)->get_mailbox_offset)
0202         return sof_ops(sdev)->get_mailbox_offset(sdev);
0203 
0204     dev_err(sdev->dev, "error: %s not defined\n", __func__);
0205     return -ENOTSUPP;
0206 }
0207 
0208 static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
0209                         u32 id)
0210 {
0211     if (sof_ops(sdev)->get_window_offset)
0212         return sof_ops(sdev)->get_window_offset(sdev, id);
0213 
0214     dev_err(sdev->dev, "error: %s not defined\n", __func__);
0215     return -ENOTSUPP;
0216 }
0217 /* power management */
0218 static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
0219 {
0220     if (sof_ops(sdev)->resume)
0221         return sof_ops(sdev)->resume(sdev);
0222 
0223     return 0;
0224 }
0225 
0226 static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev,
0227                       u32 target_state)
0228 {
0229     if (sof_ops(sdev)->suspend)
0230         return sof_ops(sdev)->suspend(sdev, target_state);
0231 
0232     return 0;
0233 }
0234 
0235 static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
0236 {
0237     if (sof_ops(sdev)->runtime_resume)
0238         return sof_ops(sdev)->runtime_resume(sdev);
0239 
0240     return 0;
0241 }
0242 
0243 static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
0244 {
0245     if (sof_ops(sdev)->runtime_suspend)
0246         return sof_ops(sdev)->runtime_suspend(sdev);
0247 
0248     return 0;
0249 }
0250 
0251 static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
0252 {
0253     if (sof_ops(sdev)->runtime_idle)
0254         return sof_ops(sdev)->runtime_idle(sdev);
0255 
0256     return 0;
0257 }
0258 
0259 static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
0260 {
0261     if (sof_ops(sdev)->set_hw_params_upon_resume)
0262         return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
0263     return 0;
0264 }
0265 
0266 static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
0267 {
0268     if (sof_ops(sdev)->set_clk)
0269         return sof_ops(sdev)->set_clk(sdev, freq);
0270 
0271     return 0;
0272 }
0273 
0274 static inline int
0275 snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
0276                 const struct sof_dsp_power_state *target_state)
0277 {
0278     int ret = 0;
0279 
0280     mutex_lock(&sdev->power_state_access);
0281 
0282     if (sof_ops(sdev)->set_power_state)
0283         ret = sof_ops(sdev)->set_power_state(sdev, target_state);
0284 
0285     mutex_unlock(&sdev->power_state_access);
0286 
0287     return ret;
0288 }
0289 
0290 /* debug */
0291 void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, const char *msg, u32 flags);
0292 
0293 static inline int snd_sof_debugfs_add_region_item(struct snd_sof_dev *sdev,
0294         enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size,
0295         const char *name, enum sof_debugfs_access_type access_type)
0296 {
0297     if (sof_ops(sdev) && sof_ops(sdev)->debugfs_add_region_item)
0298         return sof_ops(sdev)->debugfs_add_region_item(sdev, blk_type, offset,
0299                                   size, name, access_type);
0300 
0301     return 0;
0302 }
0303 
0304 /* register IO */
0305 static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
0306                      u32 offset, u32 value)
0307 {
0308     if (sof_ops(sdev)->write) {
0309         sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
0310         return;
0311     }
0312 
0313     dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
0314 }
0315 
0316 static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
0317                        u32 offset, u64 value)
0318 {
0319     if (sof_ops(sdev)->write64) {
0320         sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
0321         return;
0322     }
0323 
0324     dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
0325 }
0326 
0327 static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
0328                    u32 offset)
0329 {
0330     if (sof_ops(sdev)->read)
0331         return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
0332 
0333     dev_err(sdev->dev, "error: %s not defined\n", __func__);
0334     return -ENOTSUPP;
0335 }
0336 
0337 static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
0338                      u32 offset)
0339 {
0340     if (sof_ops(sdev)->read64)
0341         return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
0342 
0343     dev_err(sdev->dev, "error: %s not defined\n", __func__);
0344     return -ENOTSUPP;
0345 }
0346 
0347 /* block IO */
0348 static inline int snd_sof_dsp_block_read(struct snd_sof_dev *sdev,
0349                      enum snd_sof_fw_blk_type blk_type,
0350                      u32 offset, void *dest, size_t bytes)
0351 {
0352     return sof_ops(sdev)->block_read(sdev, blk_type, offset, dest, bytes);
0353 }
0354 
0355 static inline int snd_sof_dsp_block_write(struct snd_sof_dev *sdev,
0356                       enum snd_sof_fw_blk_type blk_type,
0357                       u32 offset, void *src, size_t bytes)
0358 {
0359     return sof_ops(sdev)->block_write(sdev, blk_type, offset, src, bytes);
0360 }
0361 
0362 /* mailbox IO */
0363 static inline void snd_sof_dsp_mailbox_read(struct snd_sof_dev *sdev,
0364                         u32 offset, void *dest, size_t bytes)
0365 {
0366     if (sof_ops(sdev)->mailbox_read)
0367         sof_ops(sdev)->mailbox_read(sdev, offset, dest, bytes);
0368 }
0369 
0370 static inline void snd_sof_dsp_mailbox_write(struct snd_sof_dev *sdev,
0371                          u32 offset, void *src, size_t bytes)
0372 {
0373     if (sof_ops(sdev)->mailbox_write)
0374         sof_ops(sdev)->mailbox_write(sdev, offset, src, bytes);
0375 }
0376 
0377 /* ipc */
0378 static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
0379                        struct snd_sof_ipc_msg *msg)
0380 {
0381     return sof_ops(sdev)->send_msg(sdev, msg);
0382 }
0383 
0384 /* host PCM ops */
0385 static inline int
0386 snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
0387               struct snd_pcm_substream *substream)
0388 {
0389     if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
0390         return sof_ops(sdev)->pcm_open(sdev, substream);
0391 
0392     return 0;
0393 }
0394 
0395 /* disconnect pcm substream to a host stream */
0396 static inline int
0397 snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
0398                struct snd_pcm_substream *substream)
0399 {
0400     if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
0401         return sof_ops(sdev)->pcm_close(sdev, substream);
0402 
0403     return 0;
0404 }
0405 
0406 /* host stream hw params */
0407 static inline int
0408 snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
0409                    struct snd_pcm_substream *substream,
0410                    struct snd_pcm_hw_params *params,
0411                    struct snd_sof_platform_stream_params *platform_params)
0412 {
0413     if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
0414         return sof_ops(sdev)->pcm_hw_params(sdev, substream, params,
0415                             platform_params);
0416 
0417     return 0;
0418 }
0419 
0420 /* host stream hw free */
0421 static inline int
0422 snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
0423                  struct snd_pcm_substream *substream)
0424 {
0425     if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
0426         return sof_ops(sdev)->pcm_hw_free(sdev, substream);
0427 
0428     return 0;
0429 }
0430 
0431 /* host stream trigger */
0432 static inline int
0433 snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
0434                  struct snd_pcm_substream *substream, int cmd)
0435 {
0436     if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
0437         return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
0438 
0439     return 0;
0440 }
0441 
0442 /* Firmware loading */
0443 static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
0444 {
0445     dev_dbg(sdev->dev, "loading firmware\n");
0446 
0447     return sof_ops(sdev)->load_firmware(sdev);
0448 }
0449 
0450 /* host DSP message data */
0451 static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
0452                        struct snd_pcm_substream *substream,
0453                        void *p, size_t sz)
0454 {
0455     return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
0456 }
0457 /* host side configuration of the stream's data offset in stream mailbox area */
0458 static inline int
0459 snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev,
0460                    struct snd_pcm_substream *substream,
0461                    size_t posn_offset)
0462 {
0463     if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset)
0464         return sof_ops(sdev)->set_stream_data_offset(sdev, substream,
0465                                  posn_offset);
0466 
0467     return 0;
0468 }
0469 
0470 /* host stream pointer */
0471 static inline snd_pcm_uframes_t
0472 snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
0473                  struct snd_pcm_substream *substream)
0474 {
0475     if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
0476         return sof_ops(sdev)->pcm_pointer(sdev, substream);
0477 
0478     return 0;
0479 }
0480 
0481 /* pcm ack */
0482 static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev,
0483                        struct snd_pcm_substream *substream)
0484 {
0485     if (sof_ops(sdev) && sof_ops(sdev)->pcm_ack)
0486         return sof_ops(sdev)->pcm_ack(sdev, substream);
0487 
0488     return 0;
0489 }
0490 
0491 /* machine driver */
0492 static inline int
0493 snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
0494 {
0495     if (sof_ops(sdev) && sof_ops(sdev)->machine_register)
0496         return sof_ops(sdev)->machine_register(sdev, pdata);
0497 
0498     return 0;
0499 }
0500 
0501 static inline void
0502 snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
0503 {
0504     if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister)
0505         sof_ops(sdev)->machine_unregister(sdev, pdata);
0506 }
0507 
0508 static inline struct snd_soc_acpi_mach *
0509 snd_sof_machine_select(struct snd_sof_dev *sdev)
0510 {
0511     if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
0512         return sof_ops(sdev)->machine_select(sdev);
0513 
0514     return NULL;
0515 }
0516 
0517 static inline void
0518 snd_sof_set_mach_params(struct snd_soc_acpi_mach *mach,
0519             struct snd_sof_dev *sdev)
0520 {
0521     if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
0522         sof_ops(sdev)->set_mach_params(mach, sdev);
0523 }
0524 
0525 /**
0526  * snd_sof_dsp_register_poll_timeout - Periodically poll an address
0527  * until a condition is met or a timeout occurs
0528  * @op: accessor function (takes @addr as its only argument)
0529  * @addr: Address to poll
0530  * @val: Variable to read the value into
0531  * @cond: Break condition (usually involving @val)
0532  * @sleep_us: Maximum time to sleep between reads in us (0
0533  *            tight-loops).  Should be less than ~20ms since usleep_range
0534  *            is used (see Documentation/timers/timers-howto.rst).
0535  * @timeout_us: Timeout in us, 0 means never timeout
0536  *
0537  * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
0538  * case, the last read value at @addr is stored in @val. Must not
0539  * be called from atomic context if sleep_us or timeout_us are used.
0540  *
0541  * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
0542  */
0543 #define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
0544 ({ \
0545     u64 __timeout_us = (timeout_us); \
0546     unsigned long __sleep_us = (sleep_us); \
0547     ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
0548     might_sleep_if((__sleep_us) != 0); \
0549     for (;;) {                          \
0550         (val) = snd_sof_dsp_read(sdev, bar, offset);        \
0551         if (cond) { \
0552             dev_dbg(sdev->dev, \
0553                 "FW Poll Status: reg[%#x]=%#x successful\n", \
0554                 (offset), (val)); \
0555             break; \
0556         } \
0557         if (__timeout_us && \
0558             ktime_compare(ktime_get(), __timeout) > 0) { \
0559             (val) = snd_sof_dsp_read(sdev, bar, offset); \
0560             dev_dbg(sdev->dev, \
0561                 "FW Poll Status: reg[%#x]=%#x timedout\n", \
0562                 (offset), (val)); \
0563             break; \
0564         } \
0565         if (__sleep_us) \
0566             usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
0567     } \
0568     (cond) ? 0 : -ETIMEDOUT; \
0569 })
0570 
0571 /* This is for registers bits with attribute RWC */
0572 bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
0573                  u32 mask, u32 value);
0574 
0575 bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
0576                       u32 offset, u32 mask, u32 value);
0577 
0578 bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
0579                     u32 offset, u64 mask, u64 value);
0580 
0581 bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
0582                  u32 mask, u32 value);
0583 
0584 bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
0585                    u32 offset, u64 mask, u64 value);
0586 
0587 void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
0588                     u32 offset, u32 mask, u32 value);
0589 
0590 int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
0591                   u32 mask, u32 target, u32 timeout_ms,
0592                   u32 interval_us);
0593 
0594 void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset, bool non_recoverable);
0595 #endif