From 4f7fcea7402d7d788fe959bc9b7ced86af72d806 Mon Sep 17 00:00:00 2001 From: R, Dharageswari Date: Thu, 29 Apr 2010 20:20:22 +0530 Subject: [PATCH] ADR-Post-Beta-0.05.002.03-2/8-Adding Moorestown Audio Drivers: SST header files This patch adds the common header files. intel_sst_common.h - This header files is private to SST driver and contain the common structures like SST ops, SST register offsets, debugging macro, sst stream definitions, and Shim register definitions. intel_sst_pvt.c - Utility functions used by SST driver and function prototypes of common functions are implemented in this file Signed-off-by: Vinod Koul new file: sound/pci/sst/intel_sst_common.h new file: sound/pci/sst/intel_sst_pvt.c Patch-mainline: 2.6.35? --- sound/pci/sst/intel_sst_common.h | 538 ++++++++++++++++++++++++++++++++++++++ sound/pci/sst/intel_sst_pvt.c | 323 +++++++++++++++++++++++ 2 files changed, 861 insertions(+), 0 deletions(-) create mode 100644 sound/pci/sst/intel_sst_common.h create mode 100644 sound/pci/sst/intel_sst_pvt.c diff --git a/sound/pci/sst/intel_sst_common.h b/sound/pci/sst/intel_sst_common.h new file mode 100644 index 0000000..d9a720d --- /dev/null +++ b/sound/pci/sst/intel_sst_common.h @@ -0,0 +1,538 @@ +#ifndef __INTEL_SST_COMMON_H__ +#define __INTEL_SST_COMMON_H__ +/* + * intel_sst_common.h - Intel SST Driver for audio engine + * + * Copyright (C) 2008-10 Intel Corporation + * Authors: Vinod Koul + * Harsha Priya + * Dharageswari R + * KP Jeeja + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 + */ +#include +#ifdef CONFIG_MSTWN_POWER_MGMT +#include +#endif +/* #define SND_LOOP_TEST */ + +#define SST_DRIVER_VERSION "0.05.002.03" +#define SST_VERSION_NUM 0x050203 + +/* driver names */ +#define SST_DRV_NAME "intel_sst_driver" +#define SST_FW_STD_FILENAME "fw_sst.bin" + + +enum sst_states { + SST_FW_LOADED = 1, + SST_FW_RUNNING, + SST_UN_INIT, + SST_ERROR, +}; + +#define MAX_ACTIVE_STREAM 3 +#define MAX_ENC_STREAM 1 +#define MAX_AM_HANDLES 1 +#define ALLOC_TIMEOUT 5000 +/* SST numbers */ +#define SST_BLOCK_TIMEOUT 5000 +#define TARGET_DEV_BLOCK_TIMEOUT 5000 + +/* FIXME */ +#define INTEL_SST_MAJOR 255 +#define BLOCK_UNINIT -1 +#define RX_TIMESLOT_UNINIT -1 +/* Chip revision ID */ + +/* +#define CHIP_A1_50 0x01 +#define CHIP_A2_50 0x02 +#define CHIP_A2_100 0x03 +*/ + +/* +#define DSP_CLOCK_SPEED 100 */ /* 50: 50MHz, 100: 100MHz */ + +/* SST register map */ +#define SST_CSR 0x00 +#define SST_PISR 0x08 +#define SST_PIMR 0x10 +#define SST_ISRX 0x18 +#define SST_IMRX 0x28 +#define SST_IPCX 0x38 /* IPC IA-SST */ +#define SST_IPCD 0x40 /* IPC SST-IA */ +#define SST_ISRD 0x20 /* dummy register for shim workaround */ +#define SST_SHIM_SIZE 0X44 + +#define SPI_MODE_ENABLE_BASE_ADDR 0xffae4000 +#define FW_SIGNATURE_SIZE 4 + +/* PMIC and SST hardware states */ +enum sst_mad_states { + SND_MAD_UN_INIT = 0, + SND_MAD_INIT_DONE, +}; + +/* 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 = 4, /* stream is in decoding only state */ + STREAM_INIT = 5, /* stream init, waiting for data */ +}; + + +enum sst_ram_type{ + SST_IRAM = 1, + SST_DRAM = 2, +}; +/* SST shim registers to structure mapping */ +union config_status_reg { + struct { + u32 rsvd0:1; + u32 sst_reset:1; + u32 hw_rsvd: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 { + 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; +}; + + +struct sst_stream_bufs { + struct list_head node; + u32 size; + const char *addr; + u32 data_copied; + bool in_use; + u32 offset; +}; + +struct snd_sst_user_cap_list { + unsigned int iov_index; /* index of iov */ + unsigned long iov_offset; /* offset in iov */ + unsigned long offset; /* offset in kmem */ + unsigned long size; /* size copied */ + struct list_head node; +}; +/* +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 */ + bool on; +}; + +enum snd_sst_buf_type { + SST_BUF_USER_STATIC = 1, + SST_BUF_USER_DYNAMIC, + SST_BUF_MMAP_STATIC, + SST_BUF_MMAP_DYNAMIC, +}; +enum snd_src { + SST_DRV = 1, + MAD_DRV = 2 +}; +/* +structure that holds the stream information +*/ +struct stream_info { + unsigned int status; + unsigned int prev; + u8 codec; + unsigned int sst_id; + unsigned int ops; + struct list_head bufs; + struct mutex lock; /* mutex */ + spinlock_t pcm_lock; + bool mmapped; + unsigned int sg_index; /* current buf Index */ + unsigned char *cur_ptr; /* Current static bufs */ + struct snd_sst_buf_entry *buf_entry; + struct sst_block data_blk; /* stream ops block */ + struct sst_block ctrl_blk; /* stream control cmd block */ + enum snd_sst_buf_type buf_type; + void *pcm_substream; + void (*period_elapsed) (void *pcm_substream); + unsigned int sfreq; + void *decode_ibuf, *decode_obuf; + unsigned int decode_isize, decode_osize; + u8 decode_ibuf_type, decode_obuf_type; + unsigned int idecode_alloc; + unsigned int need_draining; + unsigned int str_type; + u32 curr_bytes; + u32 cumm_bytes; + u32 src; /* hack to remove */ +}; + + + +/* +this structure is used for blocking the user's alloc calls to +fw's response to alloc calls +*/ +struct stream_alloc_block { + int sst_id; /* session id of blocked stream */ + struct sst_block ops_block; /* ops block struture */ +}; + +#define SST_FW_SIGN "$SST" +#define SST_FW_LIB_SIGN "$LIB" + +/* FW file headers */ +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 dma_block_info { + enum sst_ram_type type; /* IRAM/DRAM */ + u32 size; /* Bytes */ + u32 ram_offset; /* Offset in I/DRAM */ + u32 rsvd; /* Reserved field */ +}; + +struct ioctl_pvt_data { + int str_id; + int pvt_id; +}; + +struct sst_ipc_msg_wq { + union ipc_header header; + char mailbox[SST_MAILBOX_SIZE]; + struct work_struct wq; +}; + +struct mad_ops_wq { + int stream_id; + enum sst_controls control_op; + struct work_struct wq; + +}; + +#define SST_MMAP_PAGES (640*1024 / PAGE_SIZE) +#define SST_MMAP_STEP (40*1024 / PAGE_SIZE) + +/* driver ops */ +struct intel_sst_drv { + bool pmic_state; + int pmic_vendor; + int sst_state; +/* int chip_rev_id; */ + void __iomem *shim; + void __iomem *mailbox; + void __iomem *iram; + void __iomem *dram; + unsigned int shim_phy_add; + struct list_head ipc_dispatch_list; + struct work_struct ipc_post_msg_wq; + struct sst_ipc_msg_wq ipc_process_msg; + struct sst_ipc_msg_wq ipc_process_reply; + struct sst_ipc_msg_wq ipc_post_msg; + struct mad_ops_wq mad_ops; + wait_queue_head_t wait_queue; + struct workqueue_struct *mad_wq; + struct workqueue_struct *post_msg_wq; + struct workqueue_struct *process_msg_wq; + struct workqueue_struct *process_reply_wq; + + struct stream_info streams[MAX_NUM_STREAMS]; + struct stream_alloc_block alloc_block[MAX_ACTIVE_STREAM]; + struct sst_block tgt_dev_blk, fw_info_blk, + vol_info_blk, mute_info_blk, hs_info_blk; + struct mutex list_lock;/* mutex for IPC list locking */ + struct snd_pmic_ops *scard_ops; + struct pci_dev *pci; + int active_streams[MAX_NUM_STREAMS]; + void *mmap_mem; + struct mutex stream_cnt_lock; + unsigned int mmap_len; + unsigned int unique_id; + unsigned int stream_cnt; /* total streams */ + unsigned int encoded_cnt; /* enocded streams only */ + unsigned int am_cnt; + unsigned int pb_streams; /* pb streams active */ + unsigned int cp_streams; /* cp streams active */ + unsigned int lpe_stalled; /* LPE is stalled or not */ + unsigned int pmic_port_instance; /*pmic port instance enabled*/ + int rx_time_slot_status; + unsigned int lpaudio_start; /* 1 - LPA stream(MP3 pb) in progress*/ + unsigned int audio_start; /* 1 - LPA stream(Non-MP3 pb) in progress*/ +}; + +extern struct intel_sst_drv *sst_drv_ctx; + +/* register definitions */ +/*SCU FW Changes*/ +/*#define AUD_CLK_ADDR 0xff11d83c +#define AUD_CLK_DISABLE 0x80008008 +#define AUD_CLK_50MHZ 0x80008301 +#define AUD_CLK_RATIO_1_2 0x80000301 +#define AUD_CLK_RATIO_8008 0x80008008 +#define AUD_CLK_RATIO_8101 0x80008101 +#define AUD_CLK_RATIO_0101 0x80000101 +#define AUD_SYS_ADDR 0xff11d118 +#define AUD_SYS_RESET 0x7ffffcff +#define AUD_SYS_SET 0x7fffffff +#define AUD_SHIM_BASE_ADDR 0xffae8000 */ +/* +#define AUD_SHIM_RATIO_1_1 0x382 +#define AUD_SHIM_RATIO 0x3a2 +*/ +/*SCU FW Changes*/ +/*#define AUD_CLK_200 0xff11d200 +#define AUD_CLK_204 0xff11d204 +#define AUD_INIT_VAL 0x0*/ +#define CHIP_REV_REG 0xff108000 +#define CHIP_REV_ADDR 0x78 +/* +#define CHIP_REV_A1 0x0 +#define CHIP_REV_A2 0x3 +#define CLK_50MHZ 50 +#define CLK_100MHZ 100 +*/ +/* misc definitions */ +#define FW_DWNL_ID 0xFF +#define LOOP1 0x11111111 +#define LOOP2 0x22222222 +#define LOOP3 0x33333333 +#define LOOP4 0x44444444 + +#define SST_DEFAULT_PMIC_PORT 1 /*audio port*/ +/* NOTE: status will +ve for good cases and -ve for error ones */ +#define MAX_STREAM_FIELD 255 + +int sst_alloc_stream(char *params, unsigned int stream_ops, u8 codec, + unsigned int session_id); +int sst_alloc_stream_response(unsigned int str_id, + struct snd_sst_str_type *type); +int sst_stalled(void); +int sst_pause_stream(int id); +int sst_resume_stream(int id); +int sst_enable_rx_timeslot(int status); +int sst_drop_stream(int id); +int sst_free_stream(int id); +int sst_play_frame(int streamID); +int sst_capture_frame(int streamID); +int sst_set_stream_param(int streamID, struct snd_sst_params *str_param); +int sst_target_device_select(struct snd_sst_target_device *target_device); +int sst_decode(int str_id, struct snd_sst_dbufs *dbufs); +int sst_get_decoded_bytes(int str_id, unsigned long long *bytes); +int sst_get_fw_info(struct snd_sst_fw_info *info); +int sst_get_stream_params(int str_id, + struct snd_sst_get_stream_params *get_params); +int sst_drain_stream(int str_id); +int sst_get_vol(struct snd_sst_vol *set_vol); +int sst_set_vol(struct snd_sst_vol *set_vol); +int sst_set_mute(struct snd_sst_mute *set_mute); + + +void sst_post_message(struct work_struct *work); +void sst_process_message(struct work_struct *work); +void sst_process_reply(struct work_struct *work); +void sst_process_mad_ops(struct work_struct *work); +void sst_process_mad_jack_detection(struct work_struct *work); + +int intel_sst_ioctl(struct inode *i_node, struct file *file_ptr, + unsigned int cmd, unsigned long arg); +int intel_sst_open(struct inode *i_node, struct file *file_ptr); +int intel_sst_release(struct inode *i_node, struct file *file_ptr); +int intel_sst_read(struct file *file_ptr, char __user *buf, + size_t count, loff_t *ppos); +int intel_sst_write(struct file *file_ptr, const char __user *buf, + size_t count, loff_t *ppos); +int intel_sst_mmap(struct file *fp, struct vm_area_struct *vma); +ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov, + unsigned long nr_segs, loff_t offset); +ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov, + unsigned long nr_segs, loff_t offset); + +int sst_load_fw(const struct firmware *fw, void *context); +int sst_load_library(struct snd_sst_lib_download *lib, u8 ops, u32 pvt_id); +int sst_spi_mode_enable(void); +int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx); + +void sst_print_hex(unsigned char *buf, unsigned int size); +int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx, + struct sst_block *block); +int sst_wait_interruptible_timeout(struct intel_sst_drv *sst_drv_ctx, + struct sst_block *block, int timeout); +int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, + struct stream_alloc_block *block); +int sst_create_large_msg(struct ipc_post **arg); +int sst_create_short_msg(struct ipc_post **arg); +void sst_print_params(struct snd_sst_params *str_params); +void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx, + u8 sst_id, int status, void *data); +void sst_clear_interrupt(void); + +/** +* 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 strID) +{ + header->part.msg_id = msg; + header->part.str_id = strID; + header->part.large = large; + header->part.done = 0; + header->part.busy = 1; + header->part.data = 0; +} + +/** +* this inline function assigns a private id for calls that dont have stream +* context yet +*/ +static inline unsigned int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx) +{ + sst_drv_ctx->unique_id++; + if (sst_drv_ctx->unique_id >= MAX_NUM_STREAMS) + sst_drv_ctx->unique_id = 1; + return sst_drv_ctx->unique_id; +} + +/** +* this function initialzes stream context +*/ +static inline void sst_init_stream(struct stream_info *stream, + int codec, int str_type, int sst_id, int ops) +{ + stream->status = STREAM_INIT; + stream->prev = STREAM_UN_INIT; + stream->codec = codec; + stream->sst_id = sst_id; + stream->str_type = str_type; + stream->ops = ops; + stream->data_blk.on = false; + stream->data_blk.condition = false; + stream->data_blk.ret_code = 0; + stream->data_blk.data = NULL; + stream->ctrl_blk.on = false; + stream->ctrl_blk.condition = false; + stream->ctrl_blk.ret_code = 0; + stream->ctrl_blk.data = NULL; + stream->need_draining = false; + stream->decode_ibuf = NULL; + stream->decode_isize = 0; + stream->mmapped = false; +} + +/** +* this function resets the stream contexts +*/ +static inline void sst_clean_stream(struct stream_info *stream) +{ + struct sst_stream_bufs *bufs = NULL, *_bufs; + stream->status = STREAM_UN_INIT; + stream->prev = STREAM_UN_INIT; + mutex_lock(&stream->lock); + list_for_each_entry_safe(bufs, _bufs, &stream->bufs, node) { + list_del(&bufs->node); + kfree(bufs); + } + mutex_unlock(&stream->lock); + + if (stream->ops != STREAM_OPS_PLAYBACK_DRM) + kfree(stream->decode_ibuf); +} + +/** +* this function generates events for OSPM +*/ +static inline int sst_ospm_send_event(int event) +{ +#ifdef CONFIG_MSTWN_POWER_MGMT + return ospm_generate_netlink_event(AUDIO_SUBSYTEM_ID, event); +#else + return 0; +#endif +} + +/** +* this function validates the stream id +*/ +static inline int sst_validate_strid(int str_id) +{ + if (str_id <= 0 || str_id >= MAX_NUM_STREAMS) + return -EINVAL; + else + return 0; +} + +#endif /* __INTEL_SST_COMMON_H__ */ diff --git a/sound/pci/sst/intel_sst_pvt.c b/sound/pci/sst/intel_sst_pvt.c new file mode 100644 index 0000000..95d79be --- /dev/null +++ b/sound/pci/sst/intel_sst_pvt.c @@ -0,0 +1,323 @@ +/* + * intel_sst_pvt.c - Intel SST Driver for audio engine + * + * Copyright (C) 2008-10 Intel Corp + * Authors: Vinod Koul + * Harsha Priya + * Dharageswari R + * KP Jeeja + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This driver exposes the audio engine functionalities to the ALSA + * and middleware. + * + * This file contains all private functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "intel_sst_fw_ipc.h" +#include "intel_sst_common.h" + +/** +* this function assigns a block for the calls that dont have stream context yet +* the blocks are used for waiting on Firmware's response for any operation +*/ +int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx) +{ + int i; + + for (i = 0; i < MAX_ACTIVE_STREAM; i++) { + if (sst_drv_ctx->alloc_block[i].sst_id == BLOCK_UNINIT) { + sst_drv_ctx->alloc_block[i].ops_block.condition = false; + sst_drv_ctx->alloc_block[i].ops_block.ret_code = 0; + sst_drv_ctx->alloc_block[i].sst_id = 0; + break; + } + } + if (i == MAX_ACTIVE_STREAM) { + printk(KERN_ERR + "SST ERR: max alloc_stream reached"); + i = -EBUSY; /* active stream limit reached */ + } + return i; +} + +/** +* this function is a debug function that is used to print contents of a buffer +*/ +void sst_print_hex(unsigned char *buf, unsigned int size) +{ + unsigned int i; + + for (i = 0; i < size; i++) { + printk(KERN_DEBUG "SST DBG:%02x ", buf[i]); + if ((i != 0) && ((i % 8) == 0)) + printk(KERN_DEBUG "SST DBG:\n"); + } +} +/** +* this function waits without a timeout (and is interruptable) for a +* given block event +*/ +int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx, + struct sst_block *block) +{ + int retval = 0; + + if (!wait_event_interruptible(sst_drv_ctx->wait_queue, + block->condition)) { + /* event wake */ + if (block->ret_code < 0) { + printk(KERN_ERR + "SST ERR: stream failed %d\n"\ + , block->ret_code); + retval = -EBUSY; + } else { + printk(KERN_DEBUG "SST DBG:event up\n"); + retval = 0; + } + } else { + printk(KERN_ERR + "SST ERR: signal interrupted\n"); + retval = -EINTR; + } + return retval; + +} + +/** +* this function waits with a timeout value (and is interruptle) on a +* given block event +*/ +int sst_wait_interruptible_timeout( + struct intel_sst_drv *sst_drv_ctx, + struct sst_block *block, int timeout) +{ + int retval = 0; + + printk(KERN_DEBUG "SST DBG:waiting....\n"); + if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue, + block->condition, + msecs_to_jiffies(timeout))) { + if (block->ret_code < 0) { + printk(KERN_ERR + "SST ERR: stream failed %d\n"\ + , block->ret_code); + } else + printk(KERN_DEBUG "SST DBG:event up\n"); + retval = block->ret_code; + } else { + block->on = false; + printk(KERN_ERR + "SST ERR: timeout occured...\n"); + /* settign firmware state as uninit so that the + firmware will get redownloaded on next request + this is because firmare not responding for 5 sec + is equalant to some unrecoverable error of FW + sst_drv_ctx->sst_state = SST_UN_INIT;*/ + retval = -EBUSY; + } + return retval; + +} + +/** +* this function waits with on a given block event +*/ +int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, + struct stream_alloc_block *block) +{ + int retval = 0; + + /* NOTE: + Observed that FW processes the alloc msg and replies even + before the alloc thread has finished execution */ + printk(KERN_DEBUG "SST DBG:waiting for %x, +\ + condition %x \n", block->sst_id, + block->ops_block.condition); + if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue, + block->ops_block.condition, + msecs_to_jiffies(SST_BLOCK_TIMEOUT))) { + /* event wake */ + printk(KERN_DEBUG "SST DBG:Event wake +\ + ... %x \n", block->ops_block.condition); + printk(KERN_DEBUG "SST DBG:message +\ + ret: %d\n", block->ops_block.ret_code); + retval = block->ops_block.ret_code; + } else { + block->ops_block.on = false; + printk(KERN_ERR + "SST ERR: Wait timed-out %x \n",\ + block->ops_block.condition); + /* settign firmware state as uninit so that the + firmware will get redownloaded on next request + this is because firmare not responding for 5 sec + is equalant to some unrecoverable error of FW + sst_drv_ctx->sst_state = SST_UN_INIT;*/ + retval = -EBUSY; + } + return retval; + +} + +/** +* this function allocats structures to send a large message to the firmware +*/ +int sst_create_large_msg(struct ipc_post **arg) +{ + struct ipc_post *msg; + + msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC); + if (!msg) { + printk(KERN_ERR + "SST ERR: kzalloc msg failed \n"); + return -ENOMEM; + } + + msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC); + if (!msg->mailbox_data) { + kfree(msg); + printk(KERN_ERR + "SST ERR: kzalloc mailbox_data failed"); + return -ENOMEM; + }; + *arg = msg; + return 0; +} + +/** +* this function allocats structures to send a short message to the firmware +*/ +int sst_create_short_msg(struct ipc_post **arg) +{ + struct ipc_post *msg; + + msg = kzalloc(sizeof(*msg), GFP_ATOMIC); + if (!msg) { + printk(KERN_ERR + "SST ERR: kzalloc msg failed \n"); + return -ENOMEM; + } + msg->mailbox_data = NULL; + *arg = msg; + return 0; +} + +/** +* this function is a debug funtion to print the stream parameters +*/ +void sst_print_params(struct snd_sst_params *str_params) +{ + switch (str_params->codec) { + case SST_CODEC_TYPE_PCM: + printk(KERN_DEBUG "SST DBG:pcm \n"); + printk(KERN_DEBUG "SST DBG:chan=%d, sfreq = %d, wd_sz = %d \ + brate = %d buffer_size= 0x%d\ + period_cnt = %d\n", + str_params->sparams.uc.pcm_params.num_chan, + str_params->sparams.uc.pcm_params.sfreq, + str_params->sparams.uc.pcm_params.pcm_wd_sz, + str_params->sparams.uc.pcm_params.brate, + // str_params->sparams.uc.pcm_params.frame_size, + // str_params->sparams.uc.pcm_params.samples_per_frame, + str_params->sparams.uc.pcm_params.buffer_size, + str_params->sparams.uc.pcm_params.period_count); + break; + + case SST_CODEC_TYPE_MP3: + printk(KERN_DEBUG "SST DBG:mp3 \n"); + printk(KERN_DEBUG "SST DBG:chan=%d, brate=%d, sfreq = %d, wd_sz = %d\n", + str_params->sparams.uc.mp3_params.num_chan, + str_params->sparams.uc.mp3_params.brate, + str_params->sparams.uc.mp3_params.sfreq, + str_params->sparams.uc.mp3_params.pcm_wd_sz); + break; + + case SST_CODEC_TYPE_AAC: + printk(KERN_DEBUG "SST DBG:aac \n"); + printk(KERN_DEBUG "SST DBG:chan=%d, brate=%d, sfreq = %d, wd_sz = %d,asrate=%d\n", + str_params->sparams. uc.aac_params.num_chan, + str_params->sparams.uc.aac_params.brate, + str_params->sparams.uc.aac_params.sfreq, + str_params->sparams.uc.aac_params.pcm_wd_sz, + str_params->sparams.uc.aac_params.aac_srate); + printk(KERN_DEBUG "SST DBG:mpgid=%d profile=%d, aot = %d\n", + str_params->sparams.uc.aac_params.mpg_id, + str_params->sparams.uc.aac_params.aac_profile, + str_params->sparams.uc.aac_params.aot); + break; + case SST_CODEC_TYPE_WMA9: + printk(KERN_DEBUG "SST DBG:wma type \n"); + printk(KERN_DEBUG "SST DBG:chan=%d, brate=%d, sfreq = %d, wd_sz = %d, tag=%d\n", + str_params->sparams. uc.wma_params.num_chan, + str_params->sparams.uc.wma_params.brate, + str_params->sparams.uc.wma_params.sfreq, + str_params->sparams.uc.wma_params.pcm_wd_sz, + str_params->sparams.uc.wma_params.format_tag); + printk(KERN_DEBUG "SST DBG:mask=%d, +\ + b align=%d, enc opt =%d, op align =%d\n", + str_params->sparams.uc.wma_params.channel_mask, + str_params->sparams.uc.wma_params.block_align, + str_params->sparams.uc.wma_params.wma_encode_opt, + str_params->sparams.uc.wma_params.op_align); + break; + default: + printk(KERN_DEBUG "SST DBG:other +\ + codec 0x%x\n", str_params->codec); + } +} + +/** +* this function wakes up a sleeping block event based on the response +*/ +void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx, + u8 sst_id, int status, void *data) +{ + int i; + + /* Unblock with retval code */ + for (i = 0; i < MAX_ACTIVE_STREAM; i++) { + if (sst_id == sst_drv_ctx->alloc_block[i].sst_id) { + sst_drv_ctx->alloc_block[i].ops_block.condition = true; + sst_drv_ctx->alloc_block[i].ops_block.ret_code = status; + sst_drv_ctx->alloc_block[i].ops_block.data = data; + printk(KERN_DEBUG "SST DBG:wake id %d, +\ + sst_id %d condition %x\n", i, + sst_drv_ctx->alloc_block[i].sst_id, + sst_drv_ctx->alloc_block[i].ops_block.condition); + wake_up(&sst_drv_ctx->wait_queue); + break; + } + } +} -- 1.6.2.2