| /* |
| * sst.h - Intel SST Driver for audio engine |
| * |
| * Copyright (C) 2008-10 Intel Corporation |
| * Authors: Vinod Koul <vinod.koul@intel.com> |
| * Harsha Priya <priya.harsha@intel.com> |
| * Dharageswari R <dharageswari.r@intel.com> |
| * KP Jeeja <jeeja.kp@intel.com> |
| * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; version 2 of the License. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
| * |
| * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| * |
| * Common private declarations for SST |
| */ |
| #ifndef __SST_H__ |
| #define __SST_H__ |
| |
| #include <linux/dmaengine.h> |
| #include <linux/pm_runtime.h> |
| #include <linux/firmware.h> |
| #include <linux/intel_mid_dma.h> |
| #include <linux/lnw_gpio.h> |
| #include <asm/platform_sst.h> |
| #include <sound/intel_sst_ioctl.h> |
| |
| #define SST_DRIVER_VERSION "3.0.8" |
| |
| /* driver names */ |
| #define SST_DRV_NAME "intel_sst_driver" |
| #define SST_CLV_PCI_ID 0x08E7 |
| #define SST_MRFLD_PCI_ID 0x119A |
| #define SST_BYT_PCI_ID 0x0F28 |
| #define SST_CHT_PCI_ID 0x22A8 |
| |
| #define SST_SUSPEND_DELAY 2000 |
| #define FW_CONTEXT_MEM (64*1024) |
| #define SST_ICCM_BOUNDARY 4 |
| #define SST_CONFIG_SSP_SIGN 0x7ffe8001 |
| |
| /* FIXME: All this info should come from platform data |
| * move this when the base framework is ready to pass |
| * platform data to SST driver |
| */ |
| #define MRFLD_FW_VIRTUAL_BASE 0xC0000000 |
| #define MRFLD_FW_DDR_BASE_OFFSET 0x0 |
| #define MRFLD_FW_FEATURE_BASE_OFFSET 0x4 |
| #define MRFLD_FW_BSS_RESET_BIT 0 |
| extern struct intel_sst_drv *sst_drv_ctx; |
| enum sst_states { |
| SST_FW_LOADED = 1, |
| SST_FW_RUNNING, |
| SST_START_INIT, |
| SST_UN_INIT, |
| SST_ERROR, |
| SST_SUSPENDED, |
| SST_FW_CTXT_RESTORE, |
| SST_SHUTDOWN, |
| SST_FW_LIB_LOAD, |
| }; |
| |
| enum sst_algo_ops { |
| SST_SET_ALGO = 0, |
| SST_GET_ALGO = 1, |
| }; |
| |
| #define SST_BLOCK_TIMEOUT 1000 |
| |
| /* SST register map */ |
| #define SST_CSR 0x00 |
| #define SST_PISR 0x08 |
| #define SST_PIMR 0x10 |
| #define SST_ISRX 0x18 |
| #define SST_ISRD 0x20 |
| #define SST_IMRX 0x28 |
| #define SST_IMRD 0x30 |
| #define SST_IPCX 0x38 /* IPC IA-SST */ |
| #define SST_IPCD 0x40 /* IPC SST-IA */ |
| #define SST_ISRSC 0x48 |
| #define SST_ISRLPESC 0x50 |
| #define SST_IMRSC 0x58 |
| #define SST_IMRLPESC 0x60 |
| #define SST_IPCSC 0x68 |
| #define SST_IPCLPESC 0x70 |
| #define SST_CLKCTL 0x78 |
| #define SST_CSR2 0x80 |
| |
| #define SST_SHIM_BEGIN SST_CSR |
| #define SST_SHIM_END SST_CSR2 |
| #define SST_SHIM_SIZE 0x88 |
| |
| #define FW_SIGNATURE_SIZE 4 |
| |
| /* stream states */ |
| enum sst_stream_states { |
| STREAM_UN_INIT = 0, /* Freed/Not used stream */ |
| STREAM_RUNNING = 1, /* Running */ |
| STREAM_PAUSED = 2, /* Paused stream */ |
| STREAM_DECODE = 3, /* stream is in decoding only state */ |
| STREAM_INIT = 4, /* stream init, waiting for data */ |
| STREAM_RESET = 5, /* force reset on recovery */ |
| }; |
| |
| enum sst_ram_type { |
| SST_IRAM = 1, |
| SST_DRAM = 2, |
| }; |
| |
| /* SST shim registers to structure mapping */ |
| union config_status_reg { |
| struct { |
| u32 mfld_strb:1; |
| u32 sst_reset:1; |
| u32 clk_sel:3; |
| u32 sst_clk:2; |
| u32 bypass:3; |
| u32 run_stall:1; |
| u32 rsvd1:2; |
| u32 strb_cntr_rst:1; |
| u32 rsvd:18; |
| } part; |
| u32 full; |
| }; |
| |
| union interrupt_reg { |
| struct { |
| u64 done_interrupt:1; |
| u64 busy_interrupt:1; |
| u64 rsvd:62; |
| } part; |
| u64 full; |
| }; |
| |
| union sst_imr_reg { |
| struct { |
| u32 done_interrupt:1; |
| u32 busy_interrupt:1; |
| u32 rsvd:30; |
| } part; |
| u32 full; |
| }; |
| |
| union sst_pisr_reg { |
| struct { |
| u32 pssp0:1; |
| u32 pssp1:1; |
| u32 rsvd0:3; |
| u32 dmac:1; |
| u32 rsvd1:26; |
| } part; |
| u32 full; |
| }; |
| |
| union sst_pimr_reg { |
| struct { |
| u32 ssp0:1; |
| u32 ssp1:1; |
| u32 rsvd0:3; |
| u32 dmac:1; |
| u32 rsvd1:10; |
| u32 ssp0_sc:1; |
| u32 ssp1_sc:1; |
| u32 rsvd2:3; |
| u32 dmac_sc:1; |
| u32 rsvd3:10; |
| } part; |
| u32 full; |
| }; |
| |
| union config_status_reg_mrfld { |
| struct { |
| u64 lpe_reset:1; |
| u64 lpe_reset_vector:1; |
| u64 runstall:1; |
| u64 pwaitmode:1; |
| u64 clk_sel:3; |
| u64 rsvd2:1; |
| u64 sst_clk:3; |
| u64 xt_snoop:1; |
| u64 rsvd3:4; |
| u64 clk_sel1:6; |
| u64 clk_enable:3; |
| u64 rsvd4:6; |
| u64 slim0baseclk:1; |
| u64 rsvd:32; |
| } part; |
| u64 full; |
| }; |
| |
| union interrupt_reg_mrfld { |
| struct { |
| u64 done_interrupt:1; |
| u64 busy_interrupt:1; |
| u64 rsvd:62; |
| } part; |
| u64 full; |
| }; |
| |
| union sst_imr_reg_mrfld { |
| struct { |
| u64 done_interrupt:1; |
| u64 busy_interrupt:1; |
| u64 rsvd:62; |
| } part; |
| u64 full; |
| }; |
| |
| /*This structure is used to block a user/fw data call to another |
| fw/user call |
| */ |
| struct sst_block { |
| bool condition; /* condition for blocking check */ |
| int ret_code; /* ret code when block is released */ |
| void *data; /* data to be appsed for block if any */ |
| u32 size; |
| bool on; |
| u32 msg_id; /*msg_id = msgid in mfld/ctp, mrfld = 0 */ |
| u32 drv_id; /* = str_id in mfld/ctp, = drv_id in mrfld*/ |
| struct list_head node; |
| }; |
| |
| /** |
| * struct stream_info - structure that holds the stream information |
| * |
| * @status : stream current state |
| * @prev : stream prev state |
| * @ops : stream operation pb/cp/drm... |
| * @bufs: stream buffer list |
| * @lock : stream mutex for protecting state |
| * @pcm_substream : PCM substream |
| * @period_elapsed : PCM period elapsed callback |
| * @sfreq : stream sampling freq |
| * @str_type : stream type |
| * @cumm_bytes : cummulative bytes decoded |
| * @str_type : stream type |
| * @src : stream source |
| * @device : output device type (medfield only) |
| */ |
| struct stream_info { |
| unsigned int status; |
| unsigned int prev; |
| unsigned int ops; |
| struct mutex lock; /* mutex */ |
| void *pcm_substream; |
| void (*period_elapsed) (void *pcm_substream); |
| unsigned int sfreq; |
| u32 cumm_bytes; |
| void *compr_cb_param; |
| void (*compr_cb) (void *compr_cb_param); |
| void *drain_cb_param; |
| void (*drain_notify) (void *drain_cb_param); |
| |
| unsigned int num_ch; |
| unsigned int pipe_id; |
| unsigned int str_id; |
| unsigned int task_id; |
| }; |
| |
| #define SST_FW_SIGN "$SST" |
| #define SST_FW_LIB_SIGN "$LIB" |
| |
| /* |
| * struct fw_header - FW file headers |
| * |
| * @signature : FW signature |
| * @modules : # of modules |
| * @file_format : version of header format |
| * @reserved : reserved fields |
| */ |
| struct fw_header { |
| unsigned char signature[FW_SIGNATURE_SIZE]; /* FW signature */ |
| u32 file_size; /* size of fw minus this header */ |
| u32 modules; /* # of modules */ |
| u32 file_format; /* version of header format */ |
| u32 reserved[4]; |
| }; |
| |
| struct fw_module_header { |
| unsigned char signature[FW_SIGNATURE_SIZE]; /* module signature */ |
| u32 mod_size; /* size of module */ |
| u32 blocks; /* # of blocks */ |
| u32 type; /* codec type, pp lib */ |
| u32 entry_point; |
| }; |
| |
| struct fw_block_info { |
| enum sst_ram_type type; /* IRAM/DRAM */ |
| u32 size; /* Bytes */ |
| u32 ram_offset; /* Offset in I/DRAM */ |
| u32 rsvd; /* Reserved field */ |
| }; |
| |
| struct sst_ipc_msg_wq { |
| union ipc_header_mrfld mrfld_header; |
| struct ipc_dsp_hdr dsp_hdr; |
| char mailbox[SST_MAILBOX_SIZE]; |
| struct work_struct wq; |
| union ipc_header header; |
| }; |
| |
| struct sst_dma { |
| struct dma_chan *ch; |
| struct intel_mid_dma_slave slave; |
| struct device *dev; |
| }; |
| |
| struct sst_runtime_param { |
| struct snd_sst_runtime_params param; |
| }; |
| |
| struct sst_sg_list { |
| struct scatterlist *src; |
| struct scatterlist *dst; |
| int list_len; |
| unsigned int sg_idx; |
| }; |
| |
| struct sst_memcpy_list { |
| struct list_head memcpylist; |
| void *dstn; |
| const void *src; |
| u32 size; |
| bool is_io; |
| }; |
| |
| struct sst_debugfs { |
| #ifdef CONFIG_DEBUG_FS |
| struct dentry *root; |
| #endif |
| int runtime_pm_status; |
| void __iomem *ssp[SST_MAX_SSP_PORTS]; |
| void __iomem *dma_reg[SST_MAX_DMA]; |
| unsigned char get_params_data[1024]; |
| ssize_t get_params_len; |
| }; |
| |
| struct lpe_log_buf_hdr { |
| u32 base_addr; |
| u32 end_addr; |
| u32 rd_addr; |
| u32 wr_addr; |
| }; |
| |
| struct snd_ssp_config { |
| int size; |
| char bytes[0]; |
| }; |
| |
| struct snd_sst_probe_bytes { |
| u16 len; |
| char bytes[0]; |
| }; |
| |
| #define PCI_DMAC_CLV_ID 0x08F0 |
| #define PCI_DMAC_MRFLD_ID 0x119B |
| |
| struct sst_ram_buf { |
| u32 size; |
| char *buf; |
| }; |
| |
| /* Firmware Module Information*/ |
| |
| enum sst_lib_dwnld_status { |
| SST_LIB_NOT_FOUND = 0, |
| SST_LIB_FOUND, |
| SST_LIB_DOWNLOADED, |
| }; |
| |
| struct sst_module_info { |
| const char *name; /* Library name */ |
| u32 id; /* Module ID */ |
| u32 entry_pt; /* Module entry point */ |
| u8 status; /* module status*/ |
| u8 rsvd1; |
| u16 rsvd2; |
| }; |
| |
| /* Structure for managing the Library Region(1.5MB) |
| * in DDR in Merrifield |
| */ |
| struct sst_mem_mgr { |
| phys_addr_t current_base; |
| int avail; |
| unsigned int count; |
| }; |
| |
| struct sst_dump_buf { |
| /* buffers for iram-dram dump crash */ |
| struct sst_ram_buf iram_buf; |
| struct sst_ram_buf dram_buf; |
| }; |
| |
| struct sst_ipc_reg { |
| int ipcx; |
| int ipcd; |
| }; |
| |
| struct sst_shim_regs64 { |
| u64 csr; |
| u64 pisr; |
| u64 pimr; |
| u64 isrx; |
| u64 isrd; |
| u64 imrx; |
| u64 imrd; |
| u64 ipcx; |
| u64 ipcd; |
| u64 isrsc; |
| u64 isrlpesc; |
| u64 imrsc; |
| u64 imrlpesc; |
| u64 ipcsc; |
| u64 ipclpesc; |
| u64 clkctl; |
| u64 csr2; |
| }; |
| |
| struct sst_vtsv_cache { |
| void *file1_in_mem; |
| u32 size1; |
| void *file2_in_mem; |
| u32 size2; |
| }; |
| |
| /*** |
| * |
| * struct intel_sst_drv - driver ops |
| * |
| * @sst_state : current sst device state |
| * @pci_id : PCI device id loaded |
| * @shim : SST shim pointer |
| * @mailbox : SST mailbox pointer |
| * @iram : SST IRAM pointer |
| * @dram : SST DRAM pointer |
| * @pdata : SST info passed as a part of pci platform data |
| * @shim_phy_add : SST shim phy addr |
| * @shim_regs64: Struct to save shim registers |
| * @ipc_dispatch_list : ipc messages dispatched |
| * @rx_list : to copy the process_reply/process_msg from DSP |
| * @ipc_post_msg_wq : wq to post IPC messages context |
| * @ipc_post_msg : wq to post reply from FW context |
| * @mad_ops : MAD driver operations registered |
| * @mad_wq : MAD driver wq |
| * @post_msg_wq : wq to post IPC messages |
| * @streams : sst stream contexts |
| * @list_lock : sst driver list lock (deprecated) |
| * @ipc_spin_lock : spin lock to handle audio shim access and ipc queue |
| * @rx_msg_lock : spin lock to handle the rx messages from the DSP |
| * @scard_ops : sst card ops |
| * @pci : sst pci device struture |
| * @dev : pointer to current device struct |
| * @sst_lock : sst device lock |
| * @stream_lock : sst stream lock |
| * @pvt_id : sst private id |
| * @stream_cnt : total sst active stream count |
| * @pb_streams : total active pb streams |
| * @cp_streams : total active cp streams |
| * @audio_start : audio status |
| * @qos : PM Qos struct |
| * firmware_name : Firmware / Library name |
| */ |
| struct intel_sst_drv { |
| int sst_state; |
| int irq_num; |
| unsigned int pci_id; |
| bool use_32bit_ops; |
| void __iomem *ddr; |
| void __iomem *shim; |
| void __iomem *mailbox; |
| void __iomem *iram; |
| void __iomem *dram; |
| unsigned int mailbox_add; |
| unsigned int iram_base; |
| unsigned int dram_base; |
| unsigned int shim_phy_add; |
| unsigned int iram_end; |
| unsigned int dram_end; |
| unsigned int ddr_end; |
| unsigned int ddr_base; |
| unsigned int mailbox_recv_offset; |
| atomic_t pm_usage_count; |
| struct sst_shim_regs64 *shim_regs64; |
| struct list_head block_list; |
| struct list_head ipc_dispatch_list; |
| struct sst_platform_info *pdata; |
| struct sst_ipc_msg_wq ipc_post_msg; |
| struct list_head rx_list; |
| struct work_struct ipc_post_msg_wq; |
| wait_queue_head_t wait_queue; |
| struct workqueue_struct *mad_wq; |
| struct workqueue_struct *post_msg_wq; |
| unsigned int tstamp; |
| struct stream_info streams[MAX_NUM_STREAMS+1]; /*str_id 0 is not used*/ |
| spinlock_t ipc_spin_lock; /* lock for Shim reg access and ipc queue */ |
| spinlock_t block_lock; /* lock for adding block to block_list */ |
| spinlock_t pvt_id_lock; /* lock for allocating private id */ |
| spinlock_t rx_msg_lock; |
| struct pci_dev *pci; |
| struct device *dev; |
| unsigned int pvt_id; |
| struct mutex sst_lock; |
| struct mutex stream_lock; |
| unsigned int stream_cnt; |
| unsigned int *fw_cntx; |
| unsigned int fw_cntx_size; |
| unsigned int csr_value; |
| struct sst_dma dma; |
| void *fw_in_mem; |
| struct sst_runtime_param runtime_param; |
| unsigned int device_input_mixer; |
| struct mutex mixer_ctrl_lock; |
| struct dma_async_tx_descriptor *desc; |
| struct sst_sg_list fw_sg_list, library_list; |
| struct intel_sst_ops *ops; |
| struct sst_debugfs debugfs; |
| struct pm_qos_request *qos; |
| struct sst_info info; |
| unsigned int use_dma; |
| unsigned int use_lli; |
| atomic_t fw_clear_context; |
| atomic_t fw_clear_cache; |
| bool lib_dwnld_reqd; |
| /* list used during FW download in memcpy mode */ |
| struct list_head memcpy_list; |
| /* list used during LIB download in memcpy mode */ |
| struct list_head libmemcpy_list; |
| /* holds the stucts of iram/dram local buffers for dump*/ |
| struct sst_dump_buf dump_buf; |
| /* Lock for CSR register change */ |
| struct mutex csr_lock; |
| /* byte control to set the probe stream */ |
| struct snd_sst_probe_bytes *probe_bytes; |
| /* contains the ipc registers */ |
| struct sst_ipc_reg ipc_reg; |
| /* IMR region Library space memory manager */ |
| struct sst_mem_mgr lib_mem_mgr; |
| /* Contains the cached vtsv files*/ |
| struct sst_vtsv_cache vcache; |
| /* Pointer to device ID, now for same PCI_ID, HID will be |
| * will be different for FDK and EDK2. This will be used |
| * for devices where PCI or ACPI id is same but HID is |
| * different |
| */ |
| const char *hid; |
| /* Holder for firmware name. Due to async call it needs to be |
| * persistent till worker thread gets called |
| */ |
| char firmware_name[20]; |
| }; |
| |
| extern struct intel_sst_drv *sst_drv_ctx; |
| extern struct sst_platform_info byt_rvp_platform_data; |
| extern struct sst_platform_info byt_ffrd8_platform_data; |
| extern struct sst_platform_info cht_platform_data; |
| |
| /* misc definitions */ |
| #define FW_DWNL_ID 0xFF |
| |
| struct sst_fill_config { |
| u32 sign; |
| struct sst_board_config_data sst_bdata; |
| struct sst_platform_config_data sst_pdata; |
| u32 shim_phy_add; |
| u32 mailbox_add; |
| } __packed; |
| |
| struct intel_sst_ops { |
| irqreturn_t (*interrupt) (int, void *); |
| irqreturn_t (*irq_thread) (int, void *); |
| void (*clear_interrupt) (void); |
| int (*start) (void); |
| int (*reset) (void); |
| void (*process_reply) (struct ipc_post *msg); |
| void (*post_message) (struct work_struct *work); |
| int (*sync_post_message) (struct ipc_post *msg); |
| void (*process_message) (struct ipc_post *msg); |
| void (*set_bypass)(bool set); |
| int (*save_dsp_context) (struct intel_sst_drv *sst); |
| void (*restore_dsp_context) (void); |
| int (*alloc_stream) (char *params, struct sst_block *block); |
| void (*post_download)(struct intel_sst_drv *sst); |
| void (*do_recovery)(struct intel_sst_drv *sst); |
| }; |
| |
| int sst_alloc_stream(char *params, struct sst_block *block); |
| int sst_pause_stream(int id); |
| int sst_resume_stream(int id); |
| int sst_drop_stream(int id); |
| int sst_next_track(void); |
| int sst_free_stream(int id); |
| int sst_start_stream(int str_id); |
| int sst_send_byte_stream_mrfld(void *sbytes); |
| int sst_send_probe_bytes(struct intel_sst_drv *sst); |
| int sst_set_stream_param(int str_id, struct snd_sst_params *str_param); |
| int sst_set_metadata(int str_id, char *params); |
| int sst_get_stream(struct snd_sst_params *str_param); |
| int sst_get_stream_allocated(struct snd_sst_params *str_param, |
| struct snd_sst_lib_download **lib_dnld); |
| int sst_drain_stream(int str_id, bool partial_drain); |
| |
| |
| int sst_sync_post_message_mfld(struct ipc_post *msg); |
| void sst_post_message_mfld(struct work_struct *work); |
| void sst_process_message_mfld(struct ipc_post *msg); |
| void sst_process_reply_mfld(struct ipc_post *msg); |
| int sst_start_mfld(void); |
| int intel_sst_reset_dsp_mfld(void); |
| void intel_sst_clear_intr_mfld(void); |
| void intel_sst_set_bypass_mfld(bool set); |
| |
| int sst_sync_post_message_mrfld(struct ipc_post *msg); |
| void sst_post_message_mrfld(struct work_struct *work); |
| void sst_process_message_mrfld(struct ipc_post *msg); |
| void sst_process_reply_mrfld(struct ipc_post *msg); |
| int sst_start_mrfld(void); |
| int intel_sst_reset_dsp_mrfld(void); |
| void intel_sst_clear_intr_mrfld(void); |
| void sst_process_mad_ops(struct work_struct *work); |
| |
| long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, |
| unsigned long arg); |
| int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr); |
| int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr); |
| |
| int sst_load_fw(void); |
| int sst_load_library(struct snd_sst_lib_download *lib, u8 ops); |
| int sst_load_all_modules_elf(struct intel_sst_drv *ctx, |
| struct sst_module_info *mod_table, int mod_table_size); |
| int sst_get_next_lib_mem(struct sst_mem_mgr *mgr, int size, |
| unsigned long *lib_base); |
| void sst_post_download_ctp(struct intel_sst_drv *ctx); |
| void sst_post_download_mrfld(struct intel_sst_drv *ctx); |
| void sst_post_download_byt(struct intel_sst_drv *ctx); |
| int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx); |
| void sst_memcpy_free_resources(void); |
| |
| int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx, |
| struct sst_block *block); |
| int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, |
| struct sst_block *block); |
| int sst_create_ipc_msg(struct ipc_post **arg, bool large); |
| int sst_download_fw(void); |
| int free_stream_context(unsigned int str_id); |
| void sst_clean_stream(struct stream_info *stream); |
| int intel_sst_register_compress(struct intel_sst_drv *sst); |
| int intel_sst_remove_compress(struct intel_sst_drv *sst); |
| void sst_cdev_fragment_elapsed(int str_id); |
| int sst_send_sync_msg(int ipc, int str_id); |
| int sst_get_num_channel(struct snd_sst_params *str_param); |
| int sst_get_sfreq(struct snd_sst_params *str_param); |
| int intel_sst_check_device(void); |
| int sst_alloc_stream_ctp(char *params, struct sst_block *block); |
| int sst_alloc_stream_mrfld(char *params, struct sst_block *block); |
| void sst_restore_fw_context(void); |
| struct sst_block *sst_create_block(struct intel_sst_drv *ctx, |
| u32 msg_id, u32 drv_id); |
| int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large, |
| struct intel_sst_drv *sst_drv_ctx, struct sst_block **block, |
| u32 msg_id, u32 drv_id); |
| int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed); |
| int sst_wake_up_block(struct intel_sst_drv *ctx, int result, |
| u32 drv_id, u32 ipc, void *data, u32 size); |
| int sst_alloc_drv_context(struct device *dev); |
| int sst_request_firmware_async(struct intel_sst_drv *ctx); |
| int sst_driver_ops(struct intel_sst_drv *sst); |
| struct sst_platform_info *sst_get_acpi_driver_data(const char *hid); |
| int sst_acpi_probe(struct platform_device *pdev); |
| int sst_acpi_remove(struct platform_device *pdev); |
| void sst_save_shim64(struct intel_sst_drv *ctx, void __iomem *shim, |
| struct sst_shim_regs64 *shim_regs); |
| void sst_firmware_load_cb(const struct firmware *fw, void *context); |
| int sst_send_vtsv_data_to_fw(struct intel_sst_drv *ctx); |
| |
| void sst_do_recovery_mrfld(struct intel_sst_drv *sst); |
| void sst_do_recovery(struct intel_sst_drv *sst); |
| long intel_sst_ioctl_dsp(unsigned int cmd, |
| struct snd_ppp_params *algo_params, unsigned long arg); |
| |
| void sst_dump_to_buffer(const void *from, size_t from_len, char *buf); |
| |
| extern int intel_scu_ipc_simple_command(int, int); |
| |
| static inline int sst_pm_runtime_put(struct intel_sst_drv *sst_drv) |
| { |
| int ret; |
| |
| ret = pm_runtime_put_sync(sst_drv->dev); |
| if (ret < 0) |
| return ret; |
| atomic_dec(&sst_drv->pm_usage_count); |
| |
| pr_debug("%s: count is %d now..\n", __func__, |
| atomic_read(&sst_drv->pm_usage_count)); |
| return 0; |
| } |
| /* |
| * sst_fill_header - inline to fill sst header |
| * |
| * @header : ipc header |
| * @msg : IPC message to be sent |
| * @large : is ipc large msg |
| * @str_id : stream id |
| * |
| * this function is an inline function that sets the headers before |
| * sending a message |
| */ |
| static inline void sst_fill_header(union ipc_header *header, |
| int msg, int large, int str_id) |
| { |
| header->part.msg_id = msg; |
| header->part.str_id = str_id; |
| header->part.large = large; |
| header->part.done = 0; |
| header->part.busy = 1; |
| header->part.data = 0; |
| } |
| |
| |
| static inline void sst_fill_header_mrfld(union ipc_header_mrfld *header, |
| int msg, int task_id, int large, int drv_id) |
| { |
| header->full = 0; |
| header->p.header_high.part.msg_id = msg; |
| header->p.header_high.part.task_id = task_id; |
| header->p.header_high.part.large = large; |
| header->p.header_high.part.drv_id = drv_id; |
| header->p.header_high.part.done = 0; |
| header->p.header_high.part.busy = 1; |
| header->p.header_high.part.res_rqd = 1; |
| } |
| |
| static inline void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg, |
| int pipe_id, int len) |
| { |
| dsp->cmd_id = msg; |
| dsp->mod_index_id = 0xff; |
| dsp->pipe_id = pipe_id; |
| dsp->length = len; |
| dsp->mod_id = 0; |
| } |
| |
| #define MAX_BLOCKS 15 |
| /* sst_assign_pvt_id - assign a pvt id for stream |
| * |
| * @sst_drv_ctx : driver context |
| * |
| * this inline function assigns a private id for calls that dont have stream |
| * context yet, should be called with lock held |
| */ |
| static inline unsigned int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx) |
| { |
| unsigned int local; |
| |
| spin_lock(&sst_drv_ctx->pvt_id_lock); |
| sst_drv_ctx->pvt_id++; |
| if (sst_drv_ctx->pvt_id > MAX_BLOCKS) |
| sst_drv_ctx->pvt_id = 1; |
| local = sst_drv_ctx->pvt_id; |
| spin_unlock(&sst_drv_ctx->pvt_id_lock); |
| return local; |
| } |
| |
| |
| /* |
| * sst_init_stream - this function initialzes stream context |
| * |
| * @stream : stream struture |
| * @codec : codec for stream |
| * @sst_id : stream id |
| * @ops : stream operation |
| * @slot : stream pcm slot |
| * @device : device type |
| * |
| * this inline function initialzes stream context for allocated stream |
| */ |
| static inline void sst_init_stream(struct stream_info *stream, |
| int codec, int sst_id, int ops, u8 slot) |
| { |
| stream->status = STREAM_INIT; |
| stream->prev = STREAM_UN_INIT; |
| stream->ops = ops; |
| } |
| |
| static inline void sst_set_gpio_conf(const struct sst_gpio_config *gpio_conf) |
| { |
| lnw_gpio_set_alt(gpio_conf->i2s_rx_alt, gpio_conf->alt_function); |
| lnw_gpio_set_alt(gpio_conf->i2s_tx_alt, gpio_conf->alt_function); |
| lnw_gpio_set_alt(gpio_conf->i2s_frame, gpio_conf->alt_function); |
| lnw_gpio_set_alt(gpio_conf->i2s_clock, gpio_conf->alt_function); |
| } |
| |
| |
| /* |
| * sst_validate_strid - this function validates the stream id |
| * |
| * @str_id : stream id to be validated |
| * |
| * returns 0 if valid stream |
| */ |
| static inline int sst_validate_strid(int str_id) |
| { |
| if (str_id <= 0 || str_id > sst_drv_ctx->info.max_streams) { |
| pr_err("SST ERR: invalid stream id : %d, max %d\n", |
| str_id, sst_drv_ctx->info.max_streams); |
| return -EINVAL; |
| } else |
| return 0; |
| } |
| |
| static inline int sst_shim_write(void __iomem *addr, int offset, int value) |
| { |
| writel(value, addr + offset); |
| return 0; |
| } |
| |
| static inline u32 sst_shim_read(void __iomem *addr, int offset) |
| { |
| |
| return readl(addr + offset); |
| } |
| |
| static inline u32 sst_reg_read(void __iomem *addr, int offset) |
| { |
| |
| return readl(addr + offset); |
| } |
| |
| static inline u64 sst_reg_read64(void __iomem *addr, int offset) |
| { |
| u64 val = 0; |
| |
| memcpy_fromio(&val, addr + offset, sizeof(val)); |
| |
| return val; |
| } |
| |
| static inline int sst_shim_write64(void __iomem *addr, int offset, u64 value) |
| { |
| memcpy_toio(addr + offset, &value, sizeof(value)); |
| return 0; |
| } |
| |
| static inline u64 sst_shim_read64(void __iomem *addr, int offset) |
| { |
| u64 val = 0; |
| |
| memcpy_fromio(&val, addr + offset, sizeof(val)); |
| return val; |
| } |
| |
| static inline void |
| sst_set_fw_state_locked(struct intel_sst_drv *sst_drv_ctx, int sst_state) |
| { |
| mutex_lock(&sst_drv_ctx->sst_lock); |
| sst_drv_ctx->sst_state = sst_state; |
| mutex_unlock(&sst_drv_ctx->sst_lock); |
| } |
| |
| static inline struct stream_info *get_stream_info(int str_id) |
| { |
| if (sst_validate_strid(str_id)) |
| return NULL; |
| return &sst_drv_ctx->streams[str_id]; |
| } |
| |
| static inline int get_stream_id_mrfld(u32 pipe_id) |
| { |
| int i; |
| |
| for (i = 1; i <= sst_drv_ctx->info.max_streams; i++) |
| if (pipe_id == sst_drv_ctx->streams[i].pipe_id) |
| return i; |
| |
| pr_debug("%s: no such pipe_id(%u)", __func__, pipe_id); |
| return -1; |
| } |
| |
| int register_sst(struct device *); |
| int unregister_sst(struct device *); |
| |
| #ifdef CONFIG_DEBUG_FS |
| void sst_debugfs_init(struct intel_sst_drv *sst); |
| void sst_debugfs_exit(struct intel_sst_drv *sst); |
| #else |
| static inline void sst_debugfs_init(struct intel_sst_drv *sst) |
| { |
| } |
| |
| static inline void sst_debugfs_exit(struct intel_sst_drv *sst) |
| { |
| } |
| #endif /* CONFIG_DEBUG_FS */ |
| |
| /* |
| * FW should use virtual address 0xC000_0000 to map to the DDR |
| * reserved 2MB region at 512MB boundary. Currently the address of |
| * DDR region allocated by IA FW is not 512MB aligned. So FW is |
| * statically linking the DDR region at 0xDF600000. So we need to |
| * use the translated address to identify the DDR regions in the FW |
| * ELF binary. |
| */ |
| static inline u32 relocate_imr_addr_mrfld(u32 base_addr) |
| { |
| /* Get the difference from 512MB aligned base addr */ |
| /* relocate the base */ |
| base_addr = MRFLD_FW_VIRTUAL_BASE + (base_addr % (512 * 1024 * 1024)); |
| return base_addr; |
| } |
| |
| static inline void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst, |
| struct ipc_post *msg) |
| { |
| unsigned long irq_flags; |
| spin_lock_irqsave(&sst->ipc_spin_lock, irq_flags); |
| list_add_tail(&msg->node, &sst->ipc_dispatch_list); |
| spin_unlock_irqrestore(&sst->ipc_spin_lock, irq_flags); |
| sst->ops->post_message(&sst->ipc_post_msg_wq); |
| } |
| #endif |