From 4f7fcea7402d7d788fe959bc9b7ced86af72d806 Mon Sep 17 00:00:00 2001
From:  R, Dharageswari <dharageswari.r@intel.com>
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 <vinod.koul@intel.com>

	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 <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
+ */
+#include <linux/time.h>
+#ifdef CONFIG_MSTWN_POWER_MGMT
+#include <linux/intel_mid.h>
+#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 <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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This driver exposes the audio engine functionalities to the ALSA
+ * 	 and middleware.
+ *
+ *  This file contains all private functions
+ */
+
+#include <linux/cdev.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <sound/intel_lpe.h>
+#include <sound/intel_sst_ioctl.h>
+#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

