2020-05-01 17:58:50 +03:00
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2019-04-12 19:05:06 +03:00
/*
* This file is provided under a dual BSD / GPLv2 license . When using or
* redistributing this file , you may do so under either license .
*
* Copyright ( c ) 2018 Intel Corporation . All rights reserved .
*
* Author : Liam Girdwood < liam . r . girdwood @ linux . intel . com >
*/
# ifndef __SOUND_SOC_SOF_PRIV_H
# define __SOUND_SOC_SOF_PRIV_H
# include <linux/device.h>
# include <sound/hdaudio.h>
# include <sound/sof.h>
# include <sound/sof/info.h>
# include <sound/sof/pm.h>
# include <sound/sof/trace.h>
# include <uapi/sound/sof/fw.h>
2020-11-27 19:40:18 +03:00
# include <sound/sof/ext_manifest.h>
2019-04-12 19:05:06 +03:00
2023-01-17 15:25:30 +03:00
struct snd_sof_pcm_stream ;
2021-12-23 14:36:26 +03:00
/* Flag definitions used in sof_core_debug (sof_debug module parameter) */
2019-09-27 23:05:28 +03:00
# define SOF_DBG_ENABLE_TRACE BIT(0)
2020-12-11 13:07:42 +03:00
# define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */
2021-09-27 15:05:17 +03:00
# define SOF_DBG_VERIFY_TPLG BIT(2) /* verify topology during load */
2021-10-05 00:27:28 +03:00
# define SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE BIT(3) / * 0: use topology token
* 1 : override topology
*/
# define SOF_DBG_DYNAMIC_PIPELINES_ENABLE BIT(4) / * 0: use static pipelines
* 1 : use dynamic pipelines
*/
2021-10-06 14:06:27 +03:00
# define SOF_DBG_DISABLE_MULTICORE BIT(5) / * schedule all pipelines / widgets
* on primary core
*/
2021-10-06 14:06:30 +03:00
# define SOF_DBG_PRINT_ALL_DUMPS BIT(6) /* Print all ipc and dsp dumps */
2022-01-21 02:15:32 +03:00
# define SOF_DBG_IGNORE_D3_PERSISTENT BIT(7) / * ignore the DSP D3 persistent capability
* and always download firmware upon D3 exit
*/
2022-06-11 00:46:01 +03:00
# define SOF_DBG_PRINT_DMA_POSITION_UPDATE_LOGS BIT(8) / * print DMA position updates
* in dmesg logs
*/
# define SOF_DBG_PRINT_IPC_SUCCESS_LOGS BIT(9) / * print IPC success
* in dmesg logs
*/
2022-10-27 22:35:40 +03:00
# define SOF_DBG_FORCE_NOCODEC BIT(10) / * ignore all codec-related
* configurations
*/
2023-06-16 13:00:35 +03:00
# define SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD BIT(11) / * On top of the IPC message header
* dump the message payload also
*/
2023-04-04 12:21:05 +03:00
# define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */
2020-12-11 13:07:42 +03:00
2021-12-23 14:36:26 +03:00
/* Flag definitions used for controlling the DSP dump behavior */
2020-12-11 13:07:42 +03:00
# define SOF_DBG_DUMP_REGS BIT(0)
# define SOF_DBG_DUMP_MBOX BIT(1)
# define SOF_DBG_DUMP_TEXT BIT(2)
# define SOF_DBG_DUMP_PCI BIT(3)
2021-12-23 14:36:26 +03:00
/* Output this dump (at the DEBUG level) only when SOF_DBG_PRINT_ALL_DUMPS is set */
# define SOF_DBG_DUMP_OPTIONAL BIT(4)
2019-09-27 23:05:28 +03:00
/* global debug state set by SOF_DBG_ flags */
2021-12-23 14:36:11 +03:00
bool sof_debug_check_flag ( int mask ) ;
2019-04-12 19:05:06 +03:00
/* max BARs mmaped devices can use */
# define SND_SOF_BARS 8
/* time in ms for runtime suspend delay */
# define SND_SOF_SUSPEND_DELAY_MS 2000
/* DMA buffer size for trace */
# define DMA_BUF_SIZE_FOR_TRACE (PAGE_SIZE * 16)
# define SOF_IPC_DSP_REPLY 0
# define SOF_IPC_HOST_REPLY 1
/* convenience constructor for DAI driver streams */
# define SOF_DAI_STREAM(sname, scmin, scmax, srates, sfmt) \
{ . stream_name = sname , . channels_min = scmin , . channels_max = scmax , \
. rates = srates , . formats = sfmt }
# define SOF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT )
2020-09-02 17:07:54 +03:00
/* So far the primary core on all DSPs has ID 0 */
# define SOF_DSP_PRIMARY_CORE 0
2021-11-19 22:26:13 +03:00
/* max number of DSP cores */
# define SOF_MAX_DSP_NUM_CORES 8
2020-01-30 01:07:22 +03:00
struct sof_dsp_power_state {
u32 state ;
u32 substate ; /* platform-specific */
2019-10-26 01:40:57 +03:00
} ;
2020-01-30 01:07:20 +03:00
/* System suspend target state */
enum sof_system_suspend_state {
SOF_SUSPEND_NONE = 0 ,
SOF_SUSPEND_S0IX ,
SOF_SUSPEND_S3 ,
2022-06-16 23:18:17 +03:00
SOF_SUSPEND_S4 ,
SOF_SUSPEND_S5 ,
2020-01-30 01:07:20 +03:00
} ;
2021-09-15 15:21:12 +03:00
enum sof_dfsentry_type {
SOF_DFSENTRY_TYPE_IOMEM = 0 ,
SOF_DFSENTRY_TYPE_BUF ,
} ;
enum sof_debugfs_access_type {
SOF_DEBUGFS_ACCESS_ALWAYS = 0 ,
SOF_DEBUGFS_ACCESS_D0_ONLY ,
} ;
2022-08-17 11:05:27 +03:00
struct sof_compr_stream {
u64 copied_total ;
u32 sampling_rate ;
2022-08-17 11:05:28 +03:00
u16 channels ;
u16 sample_container_bytes ;
2023-01-17 15:25:32 +03:00
size_t posn_offset ;
2022-08-17 11:05:27 +03:00
} ;
2019-04-12 19:05:06 +03:00
struct snd_sof_dev ;
struct snd_sof_ipc_msg ;
struct snd_sof_ipc ;
struct snd_sof_debugfs_map ;
struct snd_soc_tplg_ops ;
struct snd_soc_component ;
struct snd_sof_pdata ;
2022-03-10 07:27:12 +03:00
/**
* struct snd_sof_platform_stream_params - platform dependent stream parameters
* @ stream_tag : Stream tag to use
* @ use_phy_addr : Use the provided @ phy_addr for configuration
* @ phy_addr : Platform dependent address to be used , if @ use_phy_addr
* is true
* @ no_ipc_position : Disable position update IPC from firmware
*/
struct snd_sof_platform_stream_params {
u16 stream_tag ;
bool use_phy_address ;
u32 phy_addr ;
bool no_ipc_position ;
2022-07-25 22:53:42 +03:00
bool cont_update_posn ;
2022-03-10 07:27:12 +03:00
} ;
2022-10-20 15:12:21 +03:00
/**
* struct sof_firmware - Container struct for SOF firmware
* @ fw : Pointer to the firmware
* @ payload_offset : Offset of the data within the loaded firmware image to be
* loaded to the DSP ( skipping for example ext_manifest section )
*/
struct sof_firmware {
const struct firmware * fw ;
u32 payload_offset ;
} ;
2019-04-12 19:05:06 +03:00
/*
* SOF DSP HW abstraction operations .
* Used to abstract DSP HW architecture and any IO busses between host CPU
* and DSP device ( s ) .
*/
struct snd_sof_dsp_ops {
2021-01-13 18:26:14 +03:00
/* probe/remove/shutdown */
2023-10-09 14:54:26 +03:00
int ( * probe_early ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-04-12 19:05:06 +03:00
int ( * probe ) ( struct snd_sof_dev * sof_dev ) ; /* mandatory */
2023-10-12 22:18:50 +03:00
void ( * remove ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2023-10-23 18:36:05 +03:00
void ( * remove_late ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2021-01-13 18:26:14 +03:00
int ( * shutdown ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* DSP core boot / reset */
int ( * run ) ( struct snd_sof_dev * sof_dev ) ; /* mandatory */
2020-11-27 19:40:21 +03:00
int ( * stall ) ( struct snd_sof_dev * sof_dev , unsigned int core_mask ) ; /* optional */
2019-04-12 19:05:06 +03:00
int ( * reset ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2021-11-19 22:26:14 +03:00
int ( * core_get ) ( struct snd_sof_dev * sof_dev , int core ) ; /* optional */
int ( * core_put ) ( struct snd_sof_dev * sof_dev , int core ) ; /* optional */
2019-04-12 19:05:06 +03:00
/*
* Register IO : only used by respective drivers themselves ,
* TODO : consider removing these operations and calling respective
* implementations directly
*/
2022-10-31 22:53:40 +03:00
void ( * write8 ) ( struct snd_sof_dev * sof_dev , void __iomem * addr ,
2022-10-24 19:52:57 +03:00
u8 value ) ; /* optional */
2022-10-31 22:53:40 +03:00
u8 ( * read8 ) ( struct snd_sof_dev * sof_dev ,
2022-10-24 19:52:57 +03:00
void __iomem * addr ) ; /* optional */
2019-04-12 19:05:06 +03:00
void ( * write ) ( struct snd_sof_dev * sof_dev , void __iomem * addr ,
u32 value ) ; /* optional */
u32 ( * read ) ( struct snd_sof_dev * sof_dev ,
void __iomem * addr ) ; /* optional */
void ( * write64 ) ( struct snd_sof_dev * sof_dev , void __iomem * addr ,
u64 value ) ; /* optional */
u64 ( * read64 ) ( struct snd_sof_dev * sof_dev ,
void __iomem * addr ) ; /* optional */
/* memcpy IO */
2021-09-15 15:21:11 +03:00
int ( * block_read ) ( struct snd_sof_dev * sof_dev ,
enum snd_sof_fw_blk_type type , u32 offset ,
void * dest , size_t size ) ; /* mandatory */
int ( * block_write ) ( struct snd_sof_dev * sof_dev ,
enum snd_sof_fw_blk_type type , u32 offset ,
void * src , size_t size ) ; /* mandatory */
2019-04-12 19:05:06 +03:00
2021-10-04 18:21:44 +03:00
/* Mailbox IO */
void ( * mailbox_read ) ( struct snd_sof_dev * sof_dev ,
u32 offset , void * dest ,
size_t size ) ; /* optional */
void ( * mailbox_write ) ( struct snd_sof_dev * sof_dev ,
u32 offset , void * src ,
size_t size ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* doorbell */
irqreturn_t ( * irq_handler ) ( int irq , void * context ) ; /* optional */
irqreturn_t ( * irq_thread ) ( int irq , void * context ) ; /* optional */
/* ipc */
int ( * send_msg ) ( struct snd_sof_dev * sof_dev ,
struct snd_sof_ipc_msg * msg ) ; /* mandatory */
/* FW loading */
int ( * load_firmware ) ( struct snd_sof_dev * sof_dev ) ; /* mandatory */
int ( * load_module ) ( struct snd_sof_dev * sof_dev ,
struct snd_sof_mod_hdr * hdr ) ; /* optional */
/* connect pcm substream to a host stream */
int ( * pcm_open ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ; /* optional */
/* disconnect pcm substream to a host stream */
int ( * pcm_close ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ; /* optional */
/* host stream hw params */
int ( * pcm_hw_params ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
2022-03-10 07:27:12 +03:00
struct snd_sof_platform_stream_params * platform_params ) ; /* optional */
2019-04-12 19:05:06 +03:00
2019-06-12 20:23:39 +03:00
/* host stream hw_free */
int ( * pcm_hw_free ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* host stream trigger */
int ( * pcm_trigger ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ,
int cmd ) ; /* optional */
/* host stream pointer */
snd_pcm_uframes_t ( * pcm_pointer ) ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ; /* optional */
2021-11-20 02:08:51 +03:00
/* pcm ack */
int ( * pcm_ack ) ( struct snd_sof_dev * sdev , struct snd_pcm_substream * substream ) ; /* optional */
2023-02-02 16:29:52 +03:00
/*
* optional callback to retrieve the link DMA position for the substream
* when the position is not reported in the shared SRAM windows but
* instead from a host - accessible hardware counter .
*/
u64 ( * get_stream_position ) ( struct snd_sof_dev * sdev ,
struct snd_soc_component * component ,
struct snd_pcm_substream * substream ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* host read DSP stream data */
2021-09-28 13:35:16 +03:00
int ( * ipc_msg_data ) ( struct snd_sof_dev * sdev ,
2023-01-17 15:25:30 +03:00
struct snd_sof_pcm_stream * sps ,
2021-09-28 13:35:16 +03:00
void * p , size_t sz ) ; /* mandatory */
2019-04-12 19:05:06 +03:00
2022-03-10 07:27:14 +03:00
/* host side configuration of the stream's data offset in stream mailbox area */
int ( * set_stream_data_offset ) ( struct snd_sof_dev * sdev ,
2023-01-17 15:25:31 +03:00
struct snd_sof_pcm_stream * sps ,
2022-03-10 07:27:14 +03:00
size_t posn_offset ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* pre/post firmware run */
int ( * pre_fw_run ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
int ( * post_fw_run ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2020-11-27 19:40:18 +03:00
/* parse platform specific extended manifest, optional */
int ( * parse_platform_ext_manifest ) ( struct snd_sof_dev * sof_dev ,
const struct sof_ext_man_elem_header * hdr ) ;
2019-04-12 19:05:06 +03:00
/* DSP PM */
2020-01-30 01:07:22 +03:00
int ( * suspend ) ( struct snd_sof_dev * sof_dev ,
u32 target_state ) ; /* optional */
2019-04-12 19:05:06 +03:00
int ( * resume ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-07-22 17:13:50 +03:00
int ( * runtime_suspend ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-04-12 19:05:06 +03:00
int ( * runtime_resume ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-07-02 16:24:27 +03:00
int ( * runtime_idle ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2019-06-12 20:23:38 +03:00
int ( * set_hw_params_upon_resume ) ( struct snd_sof_dev * sdev ) ; /* optional */
2019-10-26 01:40:59 +03:00
int ( * set_power_state ) ( struct snd_sof_dev * sdev ,
2020-01-30 01:07:22 +03:00
const struct sof_dsp_power_state * target_state ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* DSP clocking */
int ( * set_clk ) ( struct snd_sof_dev * sof_dev , u32 freq ) ; /* optional */
/* debug */
const struct snd_sof_debugfs_map * debug_map ; /* optional */
int debug_map_count ; /* optional */
void ( * dbg_dump ) ( struct snd_sof_dev * sof_dev ,
u32 flags ) ; /* optional */
2019-05-01 02:09:32 +03:00
void ( * ipc_dump ) ( struct snd_sof_dev * sof_dev ) ; /* optional */
2021-09-15 15:21:12 +03:00
int ( * debugfs_add_region_item ) ( struct snd_sof_dev * sdev ,
enum snd_sof_fw_blk_type blk_type , u32 offset ,
size_t size , const char * name ,
enum sof_debugfs_access_type access_type ) ; /* optional */
2019-04-12 19:05:06 +03:00
2022-05-16 13:47:09 +03:00
/* host DMA trace (IPC3) */
2019-04-12 19:05:06 +03:00
int ( * trace_init ) ( struct snd_sof_dev * sdev ,
2022-05-16 13:47:09 +03:00
struct snd_dma_buffer * dmatb ,
2022-01-28 15:36:23 +03:00
struct sof_ipc_dma_trace_params_ext * dtrace_params ) ; /* optional */
2019-04-12 19:05:06 +03:00
int ( * trace_release ) ( struct snd_sof_dev * sdev ) ; /* optional */
int ( * trace_trigger ) ( struct snd_sof_dev * sdev ,
int cmd ) ; /* optional */
2019-07-22 17:13:47 +03:00
/* misc */
int ( * get_bar_index ) ( struct snd_sof_dev * sdev ,
u32 type ) ; /* optional */
2019-08-07 18:01:59 +03:00
int ( * get_mailbox_offset ) ( struct snd_sof_dev * sdev ) ; /* mandatory for common loader code */
2019-08-07 18:02:00 +03:00
int ( * get_window_offset ) ( struct snd_sof_dev * sdev ,
u32 id ) ; /* mandatory for common loader code */
2019-08-07 18:01:59 +03:00
2019-12-05 00:15:53 +03:00
/* machine driver ops */
int ( * machine_register ) ( struct snd_sof_dev * sdev ,
void * pdata ) ; /* optional */
void ( * machine_unregister ) ( struct snd_sof_dev * sdev ,
void * pdata ) ; /* optional */
2021-12-17 02:24:20 +03:00
struct snd_soc_acpi_mach * ( * machine_select ) ( struct snd_sof_dev * sdev ) ; /* optional */
void ( * set_mach_params ) ( struct snd_soc_acpi_mach * mach ,
2021-04-10 01:01:18 +03:00
struct snd_sof_dev * sdev ) ; /* optional */
2019-12-05 00:15:53 +03:00
2022-02-10 18:05:21 +03:00
/* IPC client ops */
int ( * register_ipc_clients ) ( struct snd_sof_dev * sdev ) ; /* optional */
void ( * unregister_ipc_clients ) ( struct snd_sof_dev * sdev ) ; /* optional */
2019-04-12 19:05:06 +03:00
/* DAI ops */
struct snd_soc_dai_driver * drv ;
int num_drv ;
2019-10-25 00:03:17 +03:00
/* ALSA HW info flags, will be stored in snd_pcm_runtime.hw.info */
u32 hw_info ;
2019-12-17 23:22:30 +03:00
2021-09-16 16:03:08 +03:00
const struct dsp_arch_ops * dsp_arch_ops ;
2019-04-12 19:05:06 +03:00
} ;
/* DSP architecture specific callbacks for oops and stack dumps */
2021-09-16 16:03:08 +03:00
struct dsp_arch_ops {
2021-12-23 14:36:24 +03:00
void ( * dsp_oops ) ( struct snd_sof_dev * sdev , const char * level , void * oops ) ;
void ( * dsp_stack ) ( struct snd_sof_dev * sdev , const char * level , void * oops ,
2019-04-12 19:05:06 +03:00
u32 * stack , u32 stack_words ) ;
} ;
2021-09-16 16:03:08 +03:00
# define sof_dsp_arch_ops(sdev) ((sdev)->pdata->desc->ops->dsp_arch_ops)
2019-04-12 19:05:06 +03:00
/* FS entry for debug files that can expose DSP memories, registers */
struct snd_sof_dfsentry {
size_t size ;
2020-11-24 21:00:17 +03:00
size_t buf_data_size ; /* length of buffered data for file read operation */
2019-04-12 19:05:06 +03:00
enum sof_dfsentry_type type ;
/*
* access_type specifies if the
* memory - > DSP resource ( memory , register etc ) is always accessible
* or if it is accessible only when the DSP is in D0 .
*/
enum sof_debugfs_access_type access_type ;
2022-02-10 18:05:23 +03:00
# if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
2019-04-12 19:05:06 +03:00
char * cache_buf ; /* buffer to cache the contents of debugfs memory */
# endif
struct snd_sof_dev * sdev ;
struct list_head list ; /* list in sdev dfsentry list */
union {
void __iomem * io_mem ;
void * buf ;
} ;
} ;
/* Debug mapping for any DSP memory or registers that can used for debug */
struct snd_sof_debugfs_map {
const char * name ;
u32 bar ;
u32 offset ;
u32 size ;
/*
* access_type specifies if the memory is always accessible
* or if it is accessible only when the DSP is in D0 .
*/
enum sof_debugfs_access_type access_type ;
} ;
/* mailbox descriptor, used for host <-> DSP IPC */
struct snd_sof_mailbox {
u32 offset ;
size_t size ;
} ;
/* IPC message descriptor for host <-> DSP IO */
struct snd_sof_ipc_msg {
/* message data */
void * msg_data ;
void * reply_data ;
size_t msg_size ;
size_t reply_size ;
int reply_error ;
2022-05-05 12:48:16 +03:00
/* notification, firmware initiated messages */
void * rx_data ;
2019-04-12 19:05:06 +03:00
wait_queue_head_t waitq ;
bool ipc_complete ;
} ;
2022-05-16 13:47:04 +03:00
/**
* struct sof_ipc_fw_tracing_ops - IPC - specific firmware tracing ops
* @ init : Function pointer for initialization of the tracing
* @ free : Optional function pointer for freeing of the tracing
* @ fw_crashed : Optional function pointer to notify the tracing of a firmware crash
* @ suspend : Function pointer for system / runtime suspend
* @ resume : Function pointer for system / runtime resume
*/
struct sof_ipc_fw_tracing_ops {
int ( * init ) ( struct snd_sof_dev * sdev ) ;
void ( * free ) ( struct snd_sof_dev * sdev ) ;
void ( * fw_crashed ) ( struct snd_sof_dev * sdev ) ;
void ( * suspend ) ( struct snd_sof_dev * sdev , pm_message_t pm_state ) ;
int ( * resume ) ( struct snd_sof_dev * sdev ) ;
} ;
2022-03-17 20:50:28 +03:00
/**
* struct sof_ipc_pm_ops - IPC - specific PM ops
2022-06-10 11:35:44 +03:00
* @ ctx_save : Optional function pointer for context save
* @ ctx_restore : Optional function pointer for context restore
2022-06-10 11:35:45 +03:00
* @ set_core_state : Optional function pointer for turning on / off a DSP core
2023-02-14 13:33:41 +03:00
* @ set_pm_gate : Optional function pointer for pm gate settings
2022-03-17 20:50:28 +03:00
*/
struct sof_ipc_pm_ops {
int ( * ctx_save ) ( struct snd_sof_dev * sdev ) ;
int ( * ctx_restore ) ( struct snd_sof_dev * sdev ) ;
2022-06-10 11:35:45 +03:00
int ( * set_core_state ) ( struct snd_sof_dev * sdev , int core_idx , bool on ) ;
2023-02-14 13:33:41 +03:00
int ( * set_pm_gate ) ( struct snd_sof_dev * sdev , u32 flags ) ;
2022-03-17 20:50:28 +03:00
} ;
2022-04-26 01:11:20 +03:00
/**
* struct sof_ipc_fw_loader_ops - IPC / FW - specific loader ops
* @ validate : Function pointer for validating the firmware image
* @ parse_ext_manifest : Function pointer for parsing the manifest of the firmware
* @ load_fw_to_dsp : Optional function pointer for loading the firmware to the
* DSP .
* The function implements generic , hardware independent way
* of loading the initial firmware and its modules ( if any ) .
*/
struct sof_ipc_fw_loader_ops {
int ( * validate ) ( struct snd_sof_dev * sdev ) ;
size_t ( * parse_ext_manifest ) ( struct snd_sof_dev * sdev ) ;
int ( * load_fw_to_dsp ) ( struct snd_sof_dev * sdev ) ;
} ;
2022-03-14 23:05:04 +03:00
struct sof_ipc_tplg_ops ;
2022-03-17 20:50:36 +03:00
struct sof_ipc_pcm_ops ;
2022-03-14 23:05:04 +03:00
/**
* struct sof_ipc_ops - IPC - specific ops
* @ tplg : Pointer to IPC - specific topology ops
2022-03-17 20:50:28 +03:00
* @ pm : Pointer to PM ops
2022-03-17 20:50:36 +03:00
* @ pcm : Pointer to PCM ops
2022-04-26 01:11:20 +03:00
* @ fw_loader : Pointer to Firmware Loader ops
2022-12-21 13:23:26 +03:00
* @ fw_tracing : Optional pointer to Firmware tracing ops
2022-04-05 20:26:55 +03:00
*
2022-10-20 15:12:26 +03:00
* @ init : Optional pointer for IPC related initialization
* @ exit : Optional pointer for IPC related cleanup
2022-10-20 15:12:35 +03:00
* @ post_fw_boot : Optional pointer to execute IPC related tasks after firmware
* boot .
2022-10-20 15:12:26 +03:00
*
2022-04-05 20:26:55 +03:00
* @ tx_msg : Function pointer for sending a ' short ' IPC message
* @ set_get_data : Function pointer for set / get data ( ' large ' IPC message ) . This
* function may split up the ' large ' message and use the @ tx_msg
* path to transfer individual chunks , or use other means to transfer
* the message .
* @ get_reply : Function pointer for fetching the reply to
* sdev - > ipc - > msg . reply_data
* @ rx_msg : Function pointer for handling a received message
*
* Note : both @ tx_msg and @ set_get_data considered as TX functions and they are
* serialized for the duration of the instructed transfer . A large message sent
* via @ set_get_data is a single transfer even if at the hardware level it is
* handled with multiple chunks .
2022-03-14 23:05:04 +03:00
*/
struct sof_ipc_ops {
const struct sof_ipc_tplg_ops * tplg ;
2022-03-17 20:50:28 +03:00
const struct sof_ipc_pm_ops * pm ;
2022-03-17 20:50:36 +03:00
const struct sof_ipc_pcm_ops * pcm ;
2022-04-26 01:11:20 +03:00
const struct sof_ipc_fw_loader_ops * fw_loader ;
2022-05-16 13:47:04 +03:00
const struct sof_ipc_fw_tracing_ops * fw_tracing ;
2022-04-05 20:26:55 +03:00
2022-10-20 15:12:26 +03:00
int ( * init ) ( struct snd_sof_dev * sdev ) ;
void ( * exit ) ( struct snd_sof_dev * sdev ) ;
2022-10-20 15:12:35 +03:00
int ( * post_fw_boot ) ( struct snd_sof_dev * sdev ) ;
2022-10-20 15:12:26 +03:00
2022-04-05 20:26:55 +03:00
int ( * tx_msg ) ( struct snd_sof_dev * sdev , void * msg_data , size_t msg_bytes ,
void * reply_data , size_t reply_bytes , bool no_pm ) ;
int ( * set_get_data ) ( struct snd_sof_dev * sdev , void * data , size_t data_bytes ,
bool set ) ;
int ( * get_reply ) ( struct snd_sof_dev * sdev ) ;
void ( * rx_msg ) ( struct snd_sof_dev * sdev ) ;
2022-03-14 23:05:04 +03:00
} ;
2022-03-08 19:43:44 +03:00
/* SOF generic IPC data */
struct snd_sof_ipc {
struct snd_sof_dev * sdev ;
/* protects messages and the disable flag */
struct mutex tx_mutex ;
/* disables further sending of ipc's */
bool disable_ipc_tx ;
2022-03-30 23:19:18 +03:00
/* Maximum allowed size of a single IPC message/reply */
size_t max_payload_size ;
2022-03-08 19:43:44 +03:00
struct snd_sof_ipc_msg msg ;
2022-03-14 23:05:04 +03:00
/* IPC ops based on version */
const struct sof_ipc_ops * ops ;
2022-03-08 19:43:44 +03:00
} ;
2022-12-21 13:23:20 +03:00
/* Helper to retrieve the IPC ops */
# define sof_ipc_get_ops(sdev, ops_name) \
( ( ( sdev ) - > ipc & & ( sdev ) - > ipc - > ops ) ? ( sdev ) - > ipc - > ops - > ops_name : NULL )
2019-04-12 19:05:06 +03:00
/*
* SOF Device Level .
*/
struct snd_sof_dev {
struct device * dev ;
spinlock_t ipc_lock ; /* lock for IPC users */
spinlock_t hw_lock ; /* lock for HW IO access */
2023-04-04 12:21:05 +03:00
/*
* When true the DSP is not used .
* It is set under the following condition :
* User sets the SOF_DBG_DSPLESS_MODE flag in sof_debug module parameter
* and
* the platform advertises that it can support such mode
* pdata - > desc - > dspless_mode_supported is true .
*/
bool dspless_mode_selected ;
2022-10-20 15:12:21 +03:00
/* Main, Base firmware image */
struct sof_firmware basefw ;
2019-04-12 19:05:06 +03:00
/*
* ASoC components . plat_drv fields are set dynamically so
* can ' t use const
*/
struct snd_soc_component_driver plat_drv ;
2020-01-30 01:07:22 +03:00
/* current DSP power state */
struct sof_dsp_power_state dsp_power_state ;
2021-01-05 18:56:40 +03:00
/* mutex to protect the dsp_power_state access */
struct mutex power_state_access ;
2020-01-30 01:07:20 +03:00
/* Intended power target of system suspend */
enum sof_system_suspend_state system_suspend_target ;
2019-10-26 01:40:57 +03:00
2019-04-12 19:05:06 +03:00
/* DSP firmware boot */
wait_queue_head_t boot_wait ;
2021-12-23 14:36:18 +03:00
enum sof_fw_state fw_state ;
2020-08-24 23:09:06 +03:00
bool first_boot ;
2019-04-12 19:05:06 +03:00
/* work queue in case the probe is implemented in two steps */
struct work_struct probe_work ;
2021-02-10 13:52:37 +03:00
bool probe_completed ;
2019-04-12 19:05:06 +03:00
/* DSP HW differentiation */
struct snd_sof_pdata * pdata ;
/* IPC */
struct snd_sof_ipc * ipc ;
2023-02-02 16:29:47 +03:00
struct snd_sof_mailbox fw_info_box ; /* FW shared memory */
2019-04-12 19:05:06 +03:00
struct snd_sof_mailbox dsp_box ; /* DSP initiated IPC */
struct snd_sof_mailbox host_box ; /* Host initiated IPC */
struct snd_sof_mailbox stream_box ; /* Stream position update */
2020-08-26 02:58:54 +03:00
struct snd_sof_mailbox debug_box ; /* Debug info updates */
2019-04-12 19:05:06 +03:00
struct snd_sof_ipc_msg * msg ;
int ipc_irq ;
u32 next_comp_id ; /* monotonic - reset during S3 */
/* memory bases for mmaped DSPs - set by dsp_init() */
void __iomem * bar [ SND_SOF_BARS ] ; /* DSP base address */
int mmio_bar ;
int mailbox_bar ;
size_t dsp_oops_offset ;
/* debug */
struct dentry * debugfs_root ;
struct list_head dfsentry_list ;
2021-10-06 14:06:30 +03:00
bool dbg_dump_printed ;
bool ipc_dump_printed ;
2019-04-12 19:05:06 +03:00
/* firmware loader */
struct sof_ipc_fw_ready fw_ready ;
struct sof_ipc_fw_version fw_version ;
2019-12-18 03:26:11 +03:00
struct sof_ipc_cc_version * cc_version ;
2019-04-12 19:05:06 +03:00
/* topology */
struct snd_soc_tplg_ops * tplg_ops ;
struct list_head pcm_list ;
struct list_head kcontrol_list ;
struct list_head widget_list ;
2023-01-27 15:00:25 +03:00
struct list_head pipeline_list ;
2019-04-12 19:05:06 +03:00
struct list_head dai_list ;
2022-03-14 23:05:02 +03:00
struct list_head dai_link_list ;
2019-04-12 19:05:06 +03:00
struct list_head route_list ;
struct snd_soc_component * component ;
u32 enabled_cores_mask ; /* keep track of enabled cores */
2022-03-29 15:00:39 +03:00
bool led_present ;
2019-04-12 19:05:06 +03:00
/* FW configuration */
struct sof_ipc_window * info_window ;
/* IPC timeouts in ms */
int ipc_timeout ;
int boot_timeout ;
2022-05-16 13:47:05 +03:00
/* firmwre tracing */
bool fw_trace_is_supported ; /* set with Kconfig or module parameter */
2022-05-16 13:47:10 +03:00
void * fw_trace_data ; /* private data used by firmware tracing implementation */
2022-05-16 13:47:05 +03:00
2019-07-22 17:13:57 +03:00
bool msi_enabled ;
2019-04-12 19:05:06 +03:00
2021-11-19 22:26:13 +03:00
/* DSP core context */
u32 num_cores ;
/*
* ref count per core that will be modified during system suspend / resume and during pcm
* hw_params / hw_free . This doesn ' t need to be protected with a mutex because pcm
* hw_params / hw_free are already protected by the PCM mutex in the ALSA framework in
* sound / core / when streams are active and during system suspend / resume , streams are
* already suspended .
*/
int dsp_core_ref_count [ SOF_MAX_DSP_NUM_CORES ] ;
2022-02-10 18:05:21 +03:00
/*
* Used to keep track of registered IPC client devices so that they can
* be removed when the parent SOF module is removed .
*/
struct list_head ipc_client_list ;
/* mutex to protect client list */
struct mutex ipc_client_mutex ;
/*
* Used for tracking the IPC client ' s RX registration for DSP initiated
* message handling .
*/
struct list_head ipc_rx_handler_list ;
/*
* Used for tracking the IPC client ' s registration for DSP state change
* notification
*/
struct list_head fw_state_handler_list ;
/* to protect the ipc_rx_handler_list and dsp_state_handler_list list */
struct mutex client_event_handler_mutex ;
2022-09-19 14:53:48 +03:00
/* quirks to override topology values */
bool mclk_id_override ;
u16 mclk_id_quirk ; /* same size as in IPC3 definitions */
2019-04-12 19:05:06 +03:00
void * private ; /* core does not touch this */
} ;
/*
* Device Level .
*/
int snd_sof_device_probe ( struct device * dev , struct snd_sof_pdata * plat_data ) ;
int snd_sof_device_remove ( struct device * dev ) ;
2021-01-13 18:26:14 +03:00
int snd_sof_device_shutdown ( struct device * dev ) ;
2021-02-10 13:52:37 +03:00
bool snd_sof_device_probe_completed ( struct device * dev ) ;
2019-04-12 19:05:06 +03:00
int snd_sof_runtime_suspend ( struct device * dev ) ;
int snd_sof_runtime_resume ( struct device * dev ) ;
2019-07-02 16:24:27 +03:00
int snd_sof_runtime_idle ( struct device * dev ) ;
2019-04-12 19:05:06 +03:00
int snd_sof_resume ( struct device * dev ) ;
int snd_sof_suspend ( struct device * dev ) ;
2020-05-15 16:59:52 +03:00
int snd_sof_dsp_power_down_notify ( struct snd_sof_dev * sdev ) ;
2019-10-26 01:41:17 +03:00
int snd_sof_prepare ( struct device * dev ) ;
void snd_sof_complete ( struct device * dev ) ;
2019-04-12 19:05:06 +03:00
void snd_sof_new_platform_drv ( struct snd_sof_dev * sdev ) ;
2022-02-24 20:23:24 +03:00
/*
* Compress support
*/
extern struct snd_compress_ops sof_compressed_ops ;
2019-04-12 19:05:06 +03:00
/*
* Firmware loading .
*/
int snd_sof_load_firmware_raw ( struct snd_sof_dev * sdev ) ;
int snd_sof_load_firmware_memcpy ( struct snd_sof_dev * sdev ) ;
int snd_sof_run_firmware ( struct snd_sof_dev * sdev ) ;
void snd_sof_fw_unload ( struct snd_sof_dev * sdev ) ;
/*
* IPC low level APIs .
*/
struct snd_sof_ipc * snd_sof_ipc_init ( struct snd_sof_dev * sdev ) ;
void snd_sof_ipc_free ( struct snd_sof_dev * sdev ) ;
2021-11-16 18:21:34 +03:00
void snd_sof_ipc_get_reply ( struct snd_sof_dev * sdev ) ;
2020-05-26 23:36:37 +03:00
void snd_sof_ipc_reply ( struct snd_sof_dev * sdev , u32 msg_id ) ;
2022-04-05 20:27:05 +03:00
static inline void snd_sof_ipc_msgs_rx ( struct snd_sof_dev * sdev )
{
sdev - > ipc - > ops - > rx_msg ( sdev ) ;
}
2022-03-30 23:19:24 +03:00
int sof_ipc_tx_message ( struct snd_sof_ipc * ipc , void * msg_data , size_t msg_bytes ,
void * reply_data , size_t reply_bytes ) ;
2023-04-19 22:40:56 +03:00
static inline int sof_ipc_tx_message_no_reply ( struct snd_sof_ipc * ipc , void * msg_data ,
size_t msg_bytes )
{
return sof_ipc_tx_message ( ipc , msg_data , msg_bytes , NULL , 0 ) ;
}
2022-10-31 13:51:39 +03:00
int sof_ipc_set_get_data ( struct snd_sof_ipc * ipc , void * msg_data ,
size_t msg_bytes , bool set ) ;
2022-03-30 23:19:24 +03:00
int sof_ipc_tx_message_no_pm ( struct snd_sof_ipc * ipc , void * msg_data , size_t msg_bytes ,
2020-01-30 01:07:25 +03:00
void * reply_data , size_t reply_bytes ) ;
2023-04-19 22:40:56 +03:00
static inline int sof_ipc_tx_message_no_pm_no_reply ( struct snd_sof_ipc * ipc , void * msg_data ,
size_t msg_bytes )
{
return sof_ipc_tx_message_no_pm ( ipc , msg_data , msg_bytes , NULL , 0 ) ;
}
2022-04-05 20:26:54 +03:00
int sof_ipc_send_msg ( struct snd_sof_dev * sdev , void * msg_data , size_t msg_bytes ,
size_t reply_bytes ) ;
2022-04-21 11:07:35 +03:00
2021-11-16 18:21:34 +03:00
static inline void snd_sof_ipc_process_reply ( struct snd_sof_dev * sdev , u32 msg_id )
{
snd_sof_ipc_get_reply ( sdev ) ;
snd_sof_ipc_reply ( sdev , msg_id ) ;
}
2019-04-12 19:05:06 +03:00
/*
* Trace / debug
*/
int snd_sof_dbg_init ( struct snd_sof_dev * sdev ) ;
void snd_sof_free_debug ( struct snd_sof_dev * sdev ) ;
int snd_sof_debugfs_buf_item ( struct snd_sof_dev * sdev ,
void * base , size_t size ,
2019-06-03 19:18:18 +03:00
const char * name , mode_t mode ) ;
2021-12-23 14:36:25 +03:00
void sof_print_oops_and_stack ( struct snd_sof_dev * sdev , const char * level ,
u32 panic_code , u32 tracep_code , void * oops ,
struct sof_ipc_panic_info * panic_info ,
void * stack , size_t stack_words ) ;
2022-06-10 11:04:21 +03:00
void snd_sof_handle_fw_exception ( struct snd_sof_dev * sdev , const char * msg ) ;
2020-11-24 21:00:17 +03:00
int snd_sof_dbg_memory_info_init ( struct snd_sof_dev * sdev ) ;
2021-09-15 15:21:12 +03:00
int snd_sof_debugfs_add_region_item_iomem ( struct snd_sof_dev * sdev ,
enum snd_sof_fw_blk_type blk_type , u32 offset , size_t size ,
const char * name , enum sof_debugfs_access_type access_type ) ;
2022-05-16 13:47:07 +03:00
/* Firmware tracing */
int sof_fw_trace_init ( struct snd_sof_dev * sdev ) ;
void sof_fw_trace_free ( struct snd_sof_dev * sdev ) ;
void sof_fw_trace_fw_crashed ( struct snd_sof_dev * sdev ) ;
void sof_fw_trace_suspend ( struct snd_sof_dev * sdev , pm_message_t pm_state ) ;
int sof_fw_trace_resume ( struct snd_sof_dev * sdev ) ;
2019-04-12 19:05:06 +03:00
/*
* DSP Architectures .
*/
2021-12-23 14:36:24 +03:00
static inline void sof_stack ( struct snd_sof_dev * sdev , const char * level ,
void * oops , u32 * stack , u32 stack_words )
2019-04-12 19:05:06 +03:00
{
2021-12-23 14:36:24 +03:00
sof_dsp_arch_ops ( sdev ) - > dsp_stack ( sdev , level , oops , stack ,
stack_words ) ;
2019-04-12 19:05:06 +03:00
}
2021-12-23 14:36:24 +03:00
static inline void sof_oops ( struct snd_sof_dev * sdev , const char * level , void * oops )
2019-04-12 19:05:06 +03:00
{
2021-09-16 16:03:08 +03:00
if ( sof_dsp_arch_ops ( sdev ) - > dsp_oops )
2021-12-23 14:36:24 +03:00
sof_dsp_arch_ops ( sdev ) - > dsp_oops ( sdev , level , oops ) ;
2019-04-12 19:05:06 +03:00
}
2021-09-16 16:03:08 +03:00
extern const struct dsp_arch_ops sof_xtensa_arch_ops ;
2019-04-12 19:05:06 +03:00
2021-10-06 14:06:40 +03:00
/*
* Firmware state tracking
*/
2022-02-10 18:05:21 +03:00
void sof_set_fw_state ( struct snd_sof_dev * sdev , enum sof_fw_state new_state ) ;
2021-10-06 14:06:40 +03:00
2019-04-12 19:05:06 +03:00
/*
* Utilities
*/
void sof_io_write ( struct snd_sof_dev * sdev , void __iomem * addr , u32 value ) ;
void sof_io_write64 ( struct snd_sof_dev * sdev , void __iomem * addr , u64 value ) ;
u32 sof_io_read ( struct snd_sof_dev * sdev , void __iomem * addr ) ;
u64 sof_io_read64 ( struct snd_sof_dev * sdev , void __iomem * addr ) ;
void sof_mailbox_write ( struct snd_sof_dev * sdev , u32 offset ,
void * message , size_t bytes ) ;
void sof_mailbox_read ( struct snd_sof_dev * sdev , u32 offset ,
void * message , size_t bytes ) ;
2021-09-15 15:21:11 +03:00
int sof_block_write ( struct snd_sof_dev * sdev , enum snd_sof_fw_blk_type blk_type ,
u32 offset , void * src , size_t size ) ;
int sof_block_read ( struct snd_sof_dev * sdev , enum snd_sof_fw_blk_type blk_type ,
u32 offset , void * dest , size_t size ) ;
2019-04-12 19:05:06 +03:00
2021-10-04 18:21:45 +03:00
int sof_ipc_msg_data ( struct snd_sof_dev * sdev ,
2023-01-17 15:25:30 +03:00
struct snd_sof_pcm_stream * sps ,
2021-10-04 18:21:45 +03:00
void * p , size_t sz ) ;
2022-03-10 07:27:16 +03:00
int sof_set_stream_data_offset ( struct snd_sof_dev * sdev ,
2023-01-17 15:25:31 +03:00
struct snd_sof_pcm_stream * sps ,
2022-03-10 07:27:16 +03:00
size_t posn_offset ) ;
2021-10-04 18:21:45 +03:00
int sof_stream_pcm_open ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ;
int sof_stream_pcm_close ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream ) ;
2019-04-12 19:05:06 +03:00
2019-12-05 00:15:53 +03:00
int sof_machine_check ( struct snd_sof_dev * sdev ) ;
2022-02-10 18:05:21 +03:00
/* SOF client support */
# if IS_ENABLED(CONFIG_SND_SOC_SOF_CLIENT)
int sof_client_dev_register ( struct snd_sof_dev * sdev , const char * name , u32 id ,
const void * data , size_t size ) ;
void sof_client_dev_unregister ( struct snd_sof_dev * sdev , const char * name , u32 id ) ;
int sof_register_clients ( struct snd_sof_dev * sdev ) ;
void sof_unregister_clients ( struct snd_sof_dev * sdev ) ;
void sof_client_ipc_rx_dispatcher ( struct snd_sof_dev * sdev , void * msg_buf ) ;
void sof_client_fw_state_dispatcher ( struct snd_sof_dev * sdev ) ;
2022-02-10 18:05:22 +03:00
int sof_suspend_clients ( struct snd_sof_dev * sdev , pm_message_t state ) ;
int sof_resume_clients ( struct snd_sof_dev * sdev ) ;
2022-02-10 18:05:21 +03:00
# else /* CONFIG_SND_SOC_SOF_CLIENT */
static inline int sof_client_dev_register ( struct snd_sof_dev * sdev , const char * name ,
u32 id , const void * data , size_t size )
{
return 0 ;
}
static inline void sof_client_dev_unregister ( struct snd_sof_dev * sdev ,
const char * name , u32 id )
{
}
static inline int sof_register_clients ( struct snd_sof_dev * sdev )
{
return 0 ;
}
static inline void sof_unregister_clients ( struct snd_sof_dev * sdev )
{
}
static inline void sof_client_ipc_rx_dispatcher ( struct snd_sof_dev * sdev , void * msg_buf )
{
}
static inline void sof_client_fw_state_dispatcher ( struct snd_sof_dev * sdev )
{
}
2022-02-10 18:05:22 +03:00
static inline int sof_suspend_clients ( struct snd_sof_dev * sdev , pm_message_t state )
{
return 0 ;
}
static inline int sof_resume_clients ( struct snd_sof_dev * sdev )
{
return 0 ;
}
2022-02-10 18:05:21 +03:00
# endif /* CONFIG_SND_SOC_SOF_CLIENT */
2022-05-04 13:28:31 +03:00
/* Main ops for IPC implementations */
extern const struct sof_ipc_ops ipc3_ops ;
2022-05-05 12:48:18 +03:00
extern const struct sof_ipc_ops ipc4_ops ;
2022-05-04 13:28:31 +03:00
2019-04-12 19:05:06 +03:00
# endif