summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch1690
1 files changed, 0 insertions, 1690 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch
deleted file mode 100644
index 888b6a084..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-5-8.patch
+++ /dev/null
@@ -1,1690 +0,0 @@
-From 174aae2c1dcb1b7c49188e13167c21687ef96edc Mon Sep 17 00:00:00 2001
-From: R, Dharageswari <dharageswari.r@intel.com>
-Date: Thu, 29 Apr 2010 20:26:02 +0530
-Subject: [PATCH] ADR-Post-Beta-0.05.002.03-5/8-Moorestown Audio Drivers: SST stream ops module
-
-This adds the stream module which contains the function for stream
-operations & control. For a stream the control and data are two major parts.
-This module implements the control (play/pause/resume/stop/free/alloc)
-for a stream. It also implements data play/capture frames where buffers are
-sent/received to FW. The objective of SST driver is to achieve Low power
-playback by utilizing DSP as much aspossible. So SST gets large music
-buffers from player/middleware and sends them to FW in a scatter gather list.
-The FW decodes and renders them, while IA can goto low power states
-
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-
- new file: sound/pci/sst/intel_sst_stream.c
-Patch-mainline: 2.6.35?
----
- sound/pci/sst/intel_sst_stream.c | 1658 ++++++++++++++++++++++++++++++++++++++
- 1 files changed, 1658 insertions(+), 0 deletions(-)
- create mode 100644 sound/pci/sst/intel_sst_stream.c
-
-diff --git a/sound/pci/sst/intel_sst_stream.c b/sound/pci/sst/intel_sst_stream.c
-new file mode 100644
-index 0000000..07a4e55
---- /dev/null
-+++ b/sound/pci/sst/intel_sst_stream.c
-@@ -0,0 +1,1658 @@
-+/*
-+ * intel_sst_stream.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 file contains the stream operations of SST driver
-+ */
-+
-+#include <linux/cdev.h>
-+#include <linux/pci.h>
-+#include <linux/kernel.h>
-+#include <linux/syscalls.h>
-+#include <linux/file.h>
-+#include <linux/interrupt.h>
-+#include <linux/list.h>
-+#include <linux/uaccess.h>
-+#include <linux/firmware.h>
-+#ifdef CONFIG_MSTWN_POWER_MGMT
-+#include <linux/intel_mid.h>
-+#endif
-+#include <linux/rar/rar_register.h>
-+#include <linux/rar/memrar.h>
-+#include <sound/intel_sst_ioctl.h>
-+#include <sound/intel_lpe.h>
-+#include "intel_sst_fw_ipc.h"
-+#include "intel_sst_common.h"
-+/**
-+* sst_alloc_stream - Send msg for a new stream ID
-+* @params: stream params
-+* @stream_ops: operation of stream PB/capture
-+* @codec: codec for stream
-+* @session_id: pvt_id passed by MMF to distinguish stream
-+*
-+* This function is called by any function which wants to start
-+* a new stream. This also check if a stream exists which is idle
-+* it initializes idle stream id to this request
-+*/
-+int sst_alloc_stream(char *params, unsigned int stream_ops,
-+ u8 codec, unsigned int session_id)
-+{
-+ struct ipc_post *msg = NULL;
-+ struct snd_sst_alloc_params alloc_param = {{0,},};
-+
-+ printk(KERN_DEBUG "SST DBG:entering sst_alloc_stream \n");
-+ printk(KERN_DEBUG "SST DBG:%d %d %d\n", stream_ops, codec, session_id);
-+
-+ BUG_ON(!params);
-+
-+ /* send msg to FW to allocate a stream */
-+ if (sst_create_large_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, 0);
-+ msg->header.part.data = sizeof(alloc_param) + sizeof(u32);
-+ alloc_param.str_type.codec_type = codec;
-+ alloc_param.str_type.str_type = STREAM_TYPE_MUSIC; /* music */
-+ alloc_param.str_type.operation = stream_ops;
-+ alloc_param.str_type.protected_str = 0; /* non drm */
-+ alloc_param.str_type.pvt_id = session_id;
-+ memcpy(&alloc_param.stream_params, params,
-+ sizeof(struct snd_sst_stream_params));
-+
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), &alloc_param,
-+ sizeof(alloc_param));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ printk(KERN_DEBUG "SST DBG:alloc stream done\n");
-+ return 0;
-+}
-+
-+/**
-+* sst_get_stream_params - Send msg to query for stream parameters
-+* @str_id: stream id for which the parameters are queried for
-+* @get_params: out parameters to which the parameters are copied to
-+*
-+* This function is called when the stream parameters are queiried for
-+*/
-+int sst_get_stream_params(int str_id,
-+ struct snd_sst_get_stream_params *get_params)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+ struct snd_sst_fw_get_stream_params *fw_params;
-+
-+ printk(KERN_DEBUG "SST DBG:get_stream for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+
-+ str_info = &sst_drv_ctx->streams[str_id];
-+ if (str_info->status != STREAM_UN_INIT) {
-+ if (str_info->ctrl_blk.on == true) {
-+ printk(KERN_ERR\
-+ "SST ERR: control path is already in use \n");
-+ return -EINVAL;
-+ }
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR
-+ "SST ERR: message creation failed\n");
-+ return -ENOMEM;
-+ }
-+ fw_params = kzalloc(sizeof(*fw_params), GFP_ATOMIC);
-+ if (!fw_params) {
-+ printk(KERN_ERR
-+ "SST ERR: mem allcoation failed\n ");
-+ return -ENOMEM;
-+ }
-+
-+ sst_fill_header(&msg->header, IPC_IA_GET_STREAM_PARAMS,
-+ 0, str_id);
-+ str_info->ctrl_blk.condition = false;
-+ str_info->ctrl_blk.ret_code = 0;
-+ str_info->ctrl_blk.on = true;
-+ str_info->ctrl_blk.data = (void *) fw_params;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
-+ if (retval) {
-+ get_params->codec_params.result = retval;
-+ kfree(fw_params);
-+ return -EIO;
-+ }
-+ memcpy(&get_params->pcm_params, &fw_params->pcm_params,
-+ sizeof(fw_params->pcm_params));
-+ memcpy(&get_params->codec_params.sparams,
-+ &fw_params->codec_params,
-+ sizeof(fw_params->codec_params));
-+ get_params->codec_params.result = 0;
-+ get_params->codec_params.stream_id = str_id;
-+ get_params->codec_params.codec = str_info->codec;
-+ get_params->codec_params.ops = str_info->ops;
-+ get_params->codec_params.stream_type = str_info->str_type;
-+ kfree(fw_params);
-+ } else {
-+ printk(KERN_DEBUG "SST DBG:Stream is not in the init state\n");
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_get_fw_info - Send msg to query for firmware configurations
-+* @info: out param that holds the firmare configurations
-+*
-+* This function is called when the firmware configurations are queiried for
-+*/
-+int sst_get_fw_info(struct snd_sst_fw_info *info)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+
-+ printk(KERN_DEBUG "SST DBG:...called \n");
-+
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR
-+ "SST ERR: message creation failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ sst_fill_header(&msg->header, IPC_IA_GET_FW_INFO, 0, 0);
-+ sst_drv_ctx->fw_info_blk.condition = false;
-+ sst_drv_ctx->fw_info_blk.ret_code = 0;
-+ sst_drv_ctx->fw_info_blk.on = true;
-+ sst_drv_ctx->fw_info_blk.data = info;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->fw_info_blk, SST_BLOCK_TIMEOUT);
-+ if (retval) {
-+ printk(KERN_ERR \
-+ "SST ERR: error in fw_info = %d\n", retval);
-+ retval = -EIO;
-+ }
-+ return retval;
-+}
-+
-+
-+/**
-+* sst_alloc_stream_response - process alloc reply
-+* @str_id: stream id for which the stream has been allocated
-+* @type the stream parameters that are allocated
-+
-+* This function is called by firmware as a response to stream allcoation
-+* request
-+*/
-+int sst_alloc_stream_response(unsigned int str_id,
-+ struct snd_sst_str_type *type)
-+{
-+ int retval = 0, i, valid_str = 0;
-+ struct ipc_post *msg = NULL;
-+
-+ /* allocation succesfull */
-+ printk(KERN_DEBUG "SST DBG:stream number given = %d \n", str_id);
-+
-+ for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
-+ if (type->pvt_id == sst_drv_ctx->alloc_block[i].sst_id) {
-+ valid_str = 1;
-+ break;
-+ }
-+ }
-+ if (!valid_str) {
-+ /* this is not valid stream */
-+ printk(KERN_ERR \
-+ "SST ERR: Invalid stream allocation detetcted... freeing\n");
-+ if (sst_create_short_msg(&msg))
-+ return -ENOMEM;
-+ sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id);
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ return 0;
-+ }
-+
-+ sst_init_stream(&sst_drv_ctx->streams[str_id], type->codec_type,
-+ type->str_type, type->pvt_id, type->operation);
-+
-+ printk(KERN_DEBUG "SST DBG:stream pvt id = %d \n", type->pvt_id);
-+
-+ /* Unblock with retval code */
-+ sst_wake_up_alloc_block(sst_drv_ctx, type->pvt_id, str_id, NULL);
-+ return retval;
-+}
-+
-+/**
-+* sst_pause_stream - Send msg for a pausing stream
-+* @str_id: stream ID
-+*
-+* This function is called by any function which wants to pause
-+* an already running stream.
-+*/
-+int sst_pause_stream(int str_id)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+
-+ printk(KERN_DEBUG "SST DBG:sst_pause_stream for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ str_info = &sst_drv_ctx->streams[str_id];
-+ if (str_info->status == STREAM_PAUSED)
-+ return 0;
-+ if (str_info->status == STREAM_RUNNING ||
-+ str_info->status == STREAM_INIT) {
-+ if (str_info->prev == STREAM_UN_INIT)
-+ return -EBADRQC;
-+ if (str_info->ctrl_blk.on == true) {
-+ printk(KERN_ERR \
-+ "SST ERR: control path is already in use\n ");
-+ return -EINVAL;
-+ }
-+ if (sst_create_short_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header, IPC_IA_PAUSE_STREAM, 0, str_id);
-+ str_info->ctrl_blk.condition = false;
-+ str_info->ctrl_blk.ret_code = 0;
-+ str_info->ctrl_blk.on = true;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node,
-+ &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
-+ if (retval == 0) {
-+ str_info->prev = str_info->status;
-+ str_info->status = STREAM_PAUSED;
-+ /*sst_ospm_send_event(OSPM_EVENT_SUBSYS_STOP_PLAY);*/
-+ } else if (retval == SST_ERR_INVALID_STREAM_ID) {
-+ retval = -EINVAL;
-+ sst_clean_stream(str_info);
-+ }
-+ } else {
-+ retval = -EBADRQC;
-+ printk(KERN_ERR "SST ERR: +\
-+ BADQRC for stream\n ");
-+ }
-+
-+ return retval;
-+}
-+int sst_enable_rx_timeslot(int status)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR \
-+ "SST ERR: short message mem +\
-+ allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ printk(KERN_DEBUG "SST DBG:ipc message sending:: **********SST_ENABLE_RX_TIME_SLOT*********** \n");
-+ sst_fill_header(&msg->header, IPC_IA_ENABLE_RX_TIME_SLOT, 0, 0);
-+ msg->header.part.data = status;
-+ sst_drv_ctx->hs_info_blk.condition = false;
-+ sst_drv_ctx->hs_info_blk.ret_code = 0;
-+ sst_drv_ctx->hs_info_blk.on = true;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node,
-+ &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->hs_info_blk, SST_BLOCK_TIMEOUT);
-+ return retval;
-+}
-+
-+/**
-+* sst_resume_stream - Send msg for resuming stream
-+* @str_id: stream ID
-+*
-+* This function is called by any function which wants to resume
-+* an already paused stream.
-+*/
-+int sst_resume_stream(int str_id)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+
-+ printk(KERN_DEBUG "SST DBG:sst_resume_stream for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ str_info = &sst_drv_ctx->streams[str_id];
-+ if (str_info->status == STREAM_RUNNING)
-+ return 0;
-+ if (str_info->status == STREAM_PAUSED) {
-+ if (str_info->ctrl_blk.on == true) {
-+ printk(KERN_ERR \
-+ "SST ERR: control path is already in use\n");
-+ return -EINVAL;
-+ }
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR \
-+ "SST ERR: short message mem +\
-+ allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_RESUME_STREAM, 0, str_id);
-+ str_info->ctrl_blk.condition = false;
-+ str_info->ctrl_blk.ret_code = 0;
-+ str_info->ctrl_blk.on = true;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node,
-+ &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
-+ if (!retval) {
-+ if (str_info->prev == STREAM_RUNNING)
-+ str_info->status = STREAM_RUNNING;
-+ else
-+ str_info->status = STREAM_INIT;
-+ str_info->prev = STREAM_PAUSED;
-+ /*sst_ospm_send_event(OSPM_EVENT_SUBSYS_START_PLAY);*/
-+ } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
-+ retval = -EINVAL;
-+ sst_clean_stream(str_info);
-+ }
-+ } else {
-+ retval = -EBADRQC;
-+ printk(KERN_ERR "SST ERR: BADQRC for stream\n");
-+ }
-+
-+ return retval;
-+}
-+
-+
-+/**
-+* sst_drop_stream - Send msg for stopping stream
-+* @str_id: stream ID
-+*
-+* This function is called by any function which wants to stop
-+* a stream.
-+*/
-+int sst_drop_stream(int str_id)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct sst_stream_bufs *bufs = NULL, *_bufs;
-+ struct stream_info *str_info;
-+
-+ printk(KERN_DEBUG "SST DBG:sst_drop_stream for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ str_info = &sst_drv_ctx->streams[str_id];
-+
-+ if (str_info->status != STREAM_UN_INIT &&
-+ str_info->status != STREAM_DECODE) {
-+ if (str_info->ctrl_blk.on == true) {
-+ printk(KERN_ERR \
-+ "SST ERR: control path is already in use\n");
-+ return -EINVAL;
-+ }
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR \
-+ "SST ERR: short message mem +\
-+ allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_DROP_STREAM, 0, str_id);
-+ str_info->ctrl_blk.condition = false;
-+ str_info->ctrl_blk.ret_code = 0;
-+ str_info->ctrl_blk.on = true;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node,
-+ &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
-+ if (!retval) {
-+ printk(KERN_DEBUG "SST DBG:drop success\n");
-+ str_info->prev = STREAM_UN_INIT;
-+ str_info->status = STREAM_INIT;
-+ if (str_info->src != MAD_DRV) {
-+ mutex_lock(&str_info->lock);
-+ list_for_each_entry_safe(bufs, _bufs,
-+ &str_info->bufs, node) {
-+ list_del(&bufs->node);
-+ kfree(bufs);
-+ }
-+ mutex_unlock(&str_info->lock);
-+ }
-+ str_info->cumm_bytes += str_info->curr_bytes;
-+ /*sst_ospm_send_event(OSPM_EVENT_SUBSYS_STOP_PLAY);*/
-+ } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
-+ retval = -EINVAL;
-+ sst_clean_stream(str_info);
-+ }
-+ if (str_info->data_blk.on == true) {
-+ str_info->data_blk.condition = true;
-+ str_info->data_blk.ret_code = retval;
-+ wake_up(&sst_drv_ctx->wait_queue);
-+ }
-+ } else {
-+ retval = -EBADRQC;
-+ printk(KERN_ERR "SST ERR:BADQRC for stream\n");
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_drain_stream - Send msg for draining stream
-+* @str_id: stream ID
-+*
-+* This function is called by any function which wants to drain
-+* a stream.
-+*/
-+int sst_drain_stream(int str_id)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+
-+ printk(KERN_DEBUG "SST DBG:sst_drain_stream for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ str_info = &sst_drv_ctx->streams[str_id];
-+
-+ if (str_info->status != STREAM_RUNNING &&
-+ str_info->status != STREAM_INIT &&
-+ str_info->status != STREAM_PAUSED) {
-+ printk(KERN_ERR \
-+ "SST ERR: BADQRC for stream = %d\n", str_info->status);
-+ return -EBADRQC;
-+ }
-+
-+ if (str_info->status == STREAM_INIT) {
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR\
-+ "SST ERR: short message mem +\
-+ allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ } else
-+ str_info->need_draining = true;
-+ str_info->data_blk.condition = false;
-+ str_info->data_blk.ret_code = 0;
-+ str_info->data_blk.on = true;
-+ retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
-+ str_info->need_draining = false;
-+ if (retval == -SST_ERR_INVALID_STREAM_ID) {
-+ retval = -EINVAL;
-+ sst_clean_stream(str_info);
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_free_stream - Frees a stream
-+* @str_id: stream ID
-+*
-+* This function is called by any function which wants to free
-+* a stream.
-+*/
-+int sst_free_stream(int str_id)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+
-+ printk(KERN_DEBUG "SST DBG:sst_free_stream for %d\n", str_id);
-+
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ str_info = &sst_drv_ctx->streams[str_id];
-+
-+ if (str_info->status != STREAM_UN_INIT) {
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR \
-+ "SST ERR: short message mem +\
-+ allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id);
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ str_info->prev = str_info->status;
-+ str_info->status = STREAM_UN_INIT;
-+ if (str_info->data_blk.on == true) {
-+ str_info->data_blk.condition = true;
-+ str_info->data_blk.ret_code = 0;
-+ wake_up(&sst_drv_ctx->wait_queue);
-+ }
-+ sst_clean_stream(str_info);
-+ printk(KERN_DEBUG "SST DBG:Stream freed\n");
-+ /*sst_ospm_send_event(OSPM_EVENT_SUBSYS_STOP_PLAY);*/
-+
-+ } else {
-+ retval = -EBADRQC;
-+ printk(KERN_DEBUG "SST DBG:BADQRC for stream\n");
-+ }
-+
-+ return retval;
-+}
-+
-+
-+/**
-+* sst_set_stream_param - Send msg for setting stream parameters
-+* @id: stream id
-+* @params: stream params
-+*
-+* This function sets stream params during runtime
-+*/
-+int sst_set_stream_param(int str_id, struct snd_sst_params *str_param)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct stream_info *str_info;
-+
-+ BUG_ON(!str_param);
-+ if(sst_drv_ctx->streams[str_id].ops != str_param->ops) {
-+ printk(KERN_ERR "SST ERR: Invalid operation\n");
-+ return -EINVAL;
-+ }
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ printk(KERN_DEBUG "SST DBG:set_stream for %d\n", str_id);
-+ str_info = &sst_drv_ctx->streams[str_id];
-+ if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) {
-+ if (str_info->ctrl_blk.on == true) {
-+ printk(KERN_ERR \
-+ "SST ERR: control path is already in use\n");
-+ return -EINVAL;
-+ }
-+ if (sst_create_large_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header,
-+ IPC_IA_SET_STREAM_PARAMS, 1, str_id);
-+ str_info->ctrl_blk.condition = false;
-+ str_info->ctrl_blk.ret_code = 0;
-+ str_info->ctrl_blk.on = true;
-+ msg->header.part.data = sizeof(u32) +
-+ sizeof(str_param->sparams);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), &str_param->sparams,
-+ sizeof(str_param->sparams));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
-+ if (retval < 0) {
-+ retval = -EIO;
-+ sst_clean_stream(str_info);
-+ }
-+ } else {
-+ retval = -EBADRQC;
-+ printk(KERN_ERR "SST ERR: BADQRC for stream\n");
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_get_vol - This fuction allows to get the premix gain or gain of a stream
-+* @get_vol: this is an output param through which the volume
-+* structure is passed back to user
-+*
-+* This function is called when the premix gain or stream gain is queried for
-+*/
-+int sst_get_vol(struct snd_sst_vol *get_vol)
-+{
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct snd_sst_vol *fw_get_vol;
-+ int str_id = get_vol->stream_id;
-+
-+ printk(KERN_DEBUG "SST DBG:get vol called \n");
-+
-+ if (sst_create_short_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header,
-+ IPC_IA_GET_STREAM_VOL, 0, str_id);
-+ sst_drv_ctx->vol_info_blk.condition = false;
-+ sst_drv_ctx->vol_info_blk.ret_code = 0;
-+ sst_drv_ctx->vol_info_blk.on = true;
-+ fw_get_vol = kzalloc(sizeof(*fw_get_vol), GFP_ATOMIC);
-+ if (!fw_get_vol) {
-+ printk(KERN_ERR "SST ERR: mem +\
-+ allcoation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_drv_ctx->vol_info_blk.data = (void *)fw_get_vol;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
-+ if (retval)
-+ retval = -EIO;
-+ else {
-+ printk(KERN_DEBUG "SST DBG:stream +\
-+ id = %d\n", fw_get_vol->stream_id);
-+ printk(KERN_DEBUG "SST DBG:+\
-+ volume = %d\n", fw_get_vol->volume);
-+ printk(KERN_DEBUG "SST DBG:ramp +\
-+ dur = %d\n", fw_get_vol->ramp_duration);
-+ printk(KERN_DEBUG "SST DBG:ramp_type +\
-+ = %d\n", fw_get_vol->ramp_type);
-+ memcpy(get_vol, fw_get_vol, sizeof(*fw_get_vol));
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_set_vol - This fuction allows to set the premix gain or gain of a stream
-+* @set_vol: this holds the volume structure that needs to be set
-+*
-+* This function is called when premix gain or stream gain is requested to be set
-+*/
-+int sst_set_vol(struct snd_sst_vol *set_vol)
-+{
-+
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+
-+ printk(KERN_DEBUG "SST DBG:set vol called \n");
-+
-+ if (sst_create_large_msg(&msg)) {
-+ printk(KERN_ERR "SST ERR:+\
-+ message creation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_SET_STREAM_VOL, 1,
-+ set_vol->stream_id);
-+
-+ msg->header.part.data = sizeof(u32) + sizeof(*set_vol);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), set_vol, sizeof(*set_vol));
-+ sst_drv_ctx->vol_info_blk.condition = false;
-+ sst_drv_ctx->vol_info_blk.ret_code = 0;
-+ sst_drv_ctx->vol_info_blk.on = true;
-+ sst_drv_ctx->vol_info_blk.data = set_vol;
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
-+ if (retval) {
-+ printk(KERN_ERR \
-+ "SST ERR: error in set_vol = %d\n", retval);
-+ retval = -EIO;
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_get_vol - This fuction allows to set premix mute or soft mute of a stream
-+* @set_mute: this holds the mute structure that needs to be set
-+*
-+* This function is called when premix mute or stream mute is requested to be set
-+*/
-+int sst_set_mute(struct snd_sst_mute *set_mute)
-+{
-+
-+ int retval = 0;
-+ struct ipc_post *msg = NULL;
-+
-+ printk(KERN_DEBUG "SST DBG:set mute called \n");
-+
-+ if (sst_create_large_msg(&msg)) {
-+ printk(KERN_ERR "SST ERR: +\
-+ message creation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_SET_STREAM_MUTE, 1,
-+ set_mute->stream_id);
-+ sst_drv_ctx->mute_info_blk.condition = false;
-+ sst_drv_ctx->mute_info_blk.ret_code = 0;
-+ sst_drv_ctx->mute_info_blk.on = true;
-+ sst_drv_ctx->mute_info_blk.data = set_mute;
-+
-+ msg->header.part.data = sizeof(u32) + sizeof(*set_mute);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), set_mute,
-+ sizeof(*set_mute));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->mute_info_blk, SST_BLOCK_TIMEOUT);
-+ if (retval) {
-+ printk(KERN_ERR\
-+ "SST ERR: error in set_mute +\
-+ = %d\n", retval);
-+ retval = -EIO;
-+ }
-+ return retval;
-+}
-+
-+int sst_parse_target(struct snd_sst_slot_info *slot)
-+{
-+
-+ if (slot->device_type == SND_SST_DEVICE_PCM) {
-+ /*pcm device, check params*/
-+ if(slot->device_instance == 1) {
-+ if ((slot->device_mode != SND_SST_DEV_MODE_PCM_MODE4_I2S)
-+ && (slot->device_mode != SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED))
-+ goto err;
-+ } else if(slot->device_instance == 0) {
-+ if (slot->device_mode != SND_SST_DEV_MODE_PCM_MODE2)
-+ goto err;
-+ if (slot->pcm_params.sfreq != 8000 ||
-+ slot->pcm_params.num_chan != 1 ||
-+ slot->pcm_params.pcm_wd_sz != 16)
-+ goto err;
-+
-+ } else {
-+ err:
-+ dev_err(&sst_drv_ctx->pci->dev, "SST ERR: i/p params incorrect\n");
-+ return -EINVAL;
-+ }
-+ }
-+ /*params ok, now process*/
-+ if (slot->target_type == SND_SST_TARGET_PMIC &&
-+ slot->device_instance == 1) {
-+ sst_drv_ctx->pmic_port_instance = 1;
-+ sst_drv_ctx->scard_ops->set_audio_port(ACTIVATE);
-+ sst_drv_ctx->scard_ops->set_voice_port(DEACTIVATE);
-+ sst_drv_ctx->scard_ops->set_pcm_audio_params(
-+ slot->pcm_params.sfreq,
-+ slot->pcm_params.pcm_wd_sz,
-+ slot->pcm_params.num_chan);
-+ if (sst_drv_ctx->pb_streams )
-+ sst_drv_ctx->scard_ops->power_up_pmic_pb(1);
-+ if (sst_drv_ctx->cp_streams)
-+ sst_drv_ctx->scard_ops->power_up_pmic_cp(1);
-+ } else if ((slot->target_type == SND_SST_TARGET_PMIC ||
-+ slot->target_type == SND_SST_TARGET_OTHER) &&
-+ slot->device_instance == 0) {
-+ sst_drv_ctx->pmic_port_instance = 0;
-+ sst_drv_ctx->scard_ops->set_audio_port(DEACTIVATE);
-+ sst_drv_ctx->scard_ops->set_voice_port(ACTIVATE);
-+ if (sst_drv_ctx->pb_streams )
-+ sst_drv_ctx->scard_ops->power_up_pmic_pb(0);
-+ if (sst_drv_ctx->cp_streams)
-+ sst_drv_ctx->scard_ops->power_up_pmic_cp(0);
-+ }
-+ return 0;
-+}
-+
-+int sst_send_target(struct snd_sst_target_device *target)
-+{
-+ int retval;
-+ struct ipc_post *msg;
-+
-+ if (sst_create_large_msg(&msg)) {
-+ dev_err(&sst_drv_ctx->pci->dev, "SST ERR: message creation failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_TARGET_DEV_SELECT, 1, 0);
-+ sst_drv_ctx->tgt_dev_blk.condition = false;
-+ sst_drv_ctx->tgt_dev_blk.ret_code = 0;
-+ sst_drv_ctx->tgt_dev_blk.on = true;
-+
-+ msg->header.part.data = sizeof(u32) + sizeof(*target);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), target,
-+ sizeof(*target));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ printk(KERN_DEBUG "SST DBG:message sent- waiting\n");
-+ retval = sst_wait_interruptible_timeout(sst_drv_ctx,
-+ &sst_drv_ctx->tgt_dev_blk, TARGET_DEV_BLOCK_TIMEOUT);
-+ if (retval)
-+ dev_err(&sst_drv_ctx->pci->dev, "SST ERR: +\
-+ target device ipc failed = 0x%x\n", retval);
-+ return retval;
-+
-+}
-+/**
-+* sst_target_device_select - This fuction sets the target device configurations
-+* @target_device: this parameter holds the configurations to be set
-+*
-+* This function is called when the user layer wants to change the target
-+* device's configurations
-+*/
-+
-+int sst_target_device_select(struct snd_sst_target_device *target)
-+{
-+ int retval, i;
-+
-+ printk(KERN_DEBUG "SST DBG:Target Device Select\n");
-+
-+ if (target->device_route < 0 || target->device_route > 2) {
-+ dev_err(&sst_drv_ctx->pci->dev, "SST ERR: device route is invalid\n");
-+ return -EINVAL;
-+ }
-+
-+ if (target->device_route != 0) {
-+ dev_err(&sst_drv_ctx->pci->dev, "SST ERR: Unsupported config\n");
-+ return -EIO;
-+ }
-+ for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
-+ if (target->devices[i].action == SND_SST_PORT_ACTIVATE) {
-+ printk(KERN_DEBUG "SST DBG:activate called in %d\n", i);
-+ retval = sst_parse_target(&target->devices[i]);
-+ if (retval)
-+ return retval;
-+ } else if (target->devices[i].action == SND_SST_PORT_PREPARE)
-+ printk(KERN_DEBUG "SST DBG:PREPARE in %d, FWding\n", i);
-+ }
-+ return sst_send_target(target);
-+}
-+
-+/**
-+* This function gets the physical address of the secure memory from the handle
-+*/
-+static inline int sst_get_RAR(struct RAR_buffer *buffers, int count)
-+{
-+ int retval = 0, rar_status = 0;
-+
-+ rar_status = rar_handle_to_bus(buffers, count);
-+
-+ if (count != rar_status) {
-+ printk(KERN_ERR "SST ERR: The rar CALL Failed");
-+ retval = -EIO;
-+ }
-+ if (buffers->info.type != RAR_TYPE_AUDIO) {
-+ printk(KERN_ERR "SST ERR:Invalid RAR type\n");
-+ return -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+/**
-+* This function creates the scatter gather list to be sent to firmware to
-+* capture/playback data
-+*/
-+static int sst_create_sg_list(struct stream_info *stream,
-+ struct sst_frame_info *sg_list)
-+{
-+ struct sst_stream_bufs *kbufs = NULL;
-+ struct RAR_buffer rar_buffers;
-+ int retval = 0;
-+ int i = 0;
-+
-+ list_for_each_entry(kbufs, &stream->bufs, node) {
-+ if (kbufs->in_use == false) {
-+ if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
-+ printk(KERN_DEBUG "DRM playback handling \n");
-+ rar_buffers.info.handle = (__u32)kbufs->addr;
-+ rar_buffers.info.size = kbufs->size;
-+ printk(KERN_DEBUG "rar handle = 0x%x size=0x%x", rar_buffers.info.handle, rar_buffers.info.size);
-+ retval = sst_get_RAR(&rar_buffers, 1);
-+
-+ if (retval)
-+ return retval;
-+ sg_list->addr[i].addr = rar_buffers.bus_address;
-+ sg_list->addr[i].size = (__u32)kbufs->size; /* rar_buffers.info.size; */
-+ printk(KERN_DEBUG "SST DBG:phy addr[%d] 0x%x +\
-+ Size 0x%x\n", i, sg_list->addr[i].addr,\
-+ sg_list->addr[i].size);
-+ } else {
-+ sg_list->addr[i].addr =
-+ virt_to_phys((void *)
-+ kbufs->addr + kbufs->offset);
-+ sg_list->addr[i].size = kbufs->size;
-+ printk(KERN_DEBUG "SST DBG:phy addr[%d] 0x%x +\
-+ Size 0x%x\n", i,\
-+ sg_list->addr[i].addr,\
-+ kbufs->size);
-+ }
-+ stream->curr_bytes += sg_list->addr[i].size;
-+ kbufs->in_use = true;
-+ i++;
-+ }
-+ if (i >= MAX_NUM_SCATTER_BUFFERS)
-+ break;
-+ }
-+
-+ sg_list->num_entries = i;
-+ printk(KERN_DEBUG "SST DBG:sg list entries +\
-+ = %d \n", sg_list->num_entries);
-+ return i;
-+}
-+
-+/**
-+* sst_play_frame - Send msg for sending stream frames
-+* @str_id: ID of stream
-+*
-+* This function is called to send data to be played out
-+* to the firmware
-+*/
-+int sst_play_frame(int str_id)
-+{
-+ int i = 0, retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct sst_frame_info sg_list = {0};
-+ struct sst_stream_bufs *kbufs = NULL, *_kbufs;
-+ struct stream_info *stream;
-+
-+ printk(KERN_DEBUG "SST DBG:play frame for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+
-+ stream = &sst_drv_ctx->streams[str_id];
-+ /* clear prev sent buffers */
-+ list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
-+ if (kbufs->in_use == true) {
-+ if ((!stream->period_elapsed) && !(in_interrupt()) ){
-+ spin_lock(&stream->pcm_lock);
-+ list_del(&kbufs->node);
-+ kfree(kbufs);
-+ printk(KERN_DEBUG "SST DBG:del node \n");
-+ spin_unlock(&stream->pcm_lock);
-+ }
-+ else {
-+ list_del(&kbufs->node);
-+ kfree(kbufs);
-+ printk(KERN_DEBUG "SST DBG:del node \n");
-+ }
-+ }
-+ }
-+ /* update bytes sent */
-+ stream->cumm_bytes += stream->curr_bytes;
-+ stream->curr_bytes = 0;
-+ if (list_empty(&stream->bufs)) {
-+ /* no user buffer available */
-+ printk(KERN_DEBUG "SST DBG:Null buffer!!!!stream +\
-+ status = %d \n", stream->status);
-+ stream->prev = stream->status;
-+ stream->status = STREAM_INIT;
-+ printk(KERN_DEBUG "SST DBG:new stream status +\
-+ = %d \n", stream->status);
-+ if (stream->need_draining == true) {
-+ printk(KERN_DEBUG "SST DBG:draining stream \n");
-+ if (sst_create_short_msg(&msg)) {
-+ printk(KERN_ERR \
-+ "SST ERR: short message mem +\
-+ alloc failed\n");
-+ return -ENOMEM;
-+ }
-+ sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM,
-+ 0, str_id);
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node,
-+ &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ } else if (stream->data_blk.on == true) {
-+ printk(KERN_DEBUG "SST DBG:user list is empty.. wake \n");
-+ /* unblock */
-+ stream->data_blk.ret_code = 0;
-+ stream->data_blk.condition = true;
-+ stream->data_blk.on = false;
-+ wake_up(&sst_drv_ctx->wait_queue);
-+ }
-+#ifdef CONFIG_MSTWN_POWER_MGMT
-+ sst_ospm_send_event(OSPM_EVENT_AUDIO_BUF_EMPTY);
-+#endif
-+ return 0;
-+ }
-+
-+ /* create list */
-+ i = sst_create_sg_list(stream, &sg_list);
-+
-+ /* post msg */
-+ if (sst_create_large_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header, IPC_IA_PLAY_FRAMES, 1, str_id);
-+ msg->header.part.data = sizeof(u32) + sizeof(sg_list);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ return 0;
-+
-+}
-+
-+/**
-+* sst_capture_frame - Send msg for sending stream frames
-+* @str_id: ID of stream
-+*
-+* This function is called to capture data from the firmware
-+*/
-+int sst_capture_frame(int str_id)
-+{
-+ int i = 0, retval = 0;
-+ struct ipc_post *msg = NULL;
-+ struct sst_frame_info sg_list = {0};
-+ struct sst_stream_bufs *kbufs = NULL, *_kbufs;
-+ struct stream_info *stream;
-+
-+
-+ printk(KERN_DEBUG "SST DBG:capture frame for %d\n", str_id);
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+ stream = &sst_drv_ctx->streams[str_id];
-+ /*update bytes sent*/
-+ /*stream->cumm_bytes += stream->curr_bytes;
-+ stream->curr_bytes = 0;*/
-+ /* clear prev sent buffers */
-+ list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
-+ if (kbufs->in_use == true) {
-+ list_del(&kbufs->node);
-+ kfree(kbufs);
-+ printk(KERN_DEBUG "SST DBG:del node \n");
-+ }
-+ }
-+ if (list_empty(&stream->bufs)) {
-+ /* no user buffer available */
-+ printk(KERN_DEBUG "SST DBG:Null buffer!!!!stream +\
-+ status = %d \n", stream->status);
-+ stream->prev = stream->status;
-+ stream->status = STREAM_INIT;
-+ printk(KERN_DEBUG "SST DBG:new stream +\
-+ status = %d \n", stream->status);
-+ if (stream->data_blk.on == true) {
-+ printk(KERN_DEBUG "SST DBG:user list is empty.. wake \n");
-+ /* unblock */
-+ stream->data_blk.ret_code = 0;
-+ stream->data_blk.condition = true;
-+ stream->data_blk.on = false;
-+ wake_up(&sst_drv_ctx->wait_queue);
-+
-+ }
-+#ifdef CONFIG_MSTWN_POWER_MGMT
-+ sst_ospm_send_event(OSPM_EVENT_AUDIO_BUF_FULL);
-+#endif
-+ return 0;
-+ }
-+
-+ /* create new sg list */
-+ i = sst_create_sg_list(stream, &sg_list);
-+
-+ /* post msg */
-+ if (sst_create_large_msg(&msg))
-+ return -ENOMEM;
-+
-+ sst_fill_header(&msg->header, IPC_IA_CAPT_FRAMES, 1, str_id);
-+ msg->header.part.data = sizeof(u32) + sizeof(sg_list);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+
-+
-+ /*update bytes recevied*/
-+ stream->cumm_bytes += stream->curr_bytes;
-+ stream->curr_bytes = 0;
-+
-+ printk(KERN_DEBUG "SST DBG:Cum bytes = %d \n", stream->cumm_bytes);
-+ return 0;
-+}
-+
-+/**
-+* This function is used to calculate the minimum size of input buffers given
-+*/
-+static unsigned int calculate_min_size(struct snd_sst_buffs *bufs)
-+{
-+ int i, min_val = bufs->buff_entry[0].size;
-+ for (i = 1 ; i < bufs->entries; i++) {
-+ if (bufs->buff_entry[i].size < min_val)
-+ min_val = bufs->buff_entry[i].size;
-+ }
-+ printk(KERN_DEBUG "SST DBG:min_val = %d\n", min_val);
-+ return min_val;
-+}
-+
-+/**
-+* This function is used to calculate the maximum size of input buffers given
-+*/
-+static unsigned int calculate_max_size(struct snd_sst_buffs *bufs)
-+{
-+ int i, max_val = bufs->buff_entry[0].size;
-+ for (i = 1 ; i < bufs->entries; i++) {
-+ if (bufs->buff_entry[i].size > max_val)
-+ max_val = bufs->buff_entry[i].size;
-+ }
-+ printk(KERN_DEBUG "SST DBG:max_val = %d\n", max_val);
-+ return max_val;
-+}
-+
-+/**
-+* This function is used to allocate input and output buffers to be sent to
-+* the firmware that will take encoded data and return decoded data
-+*/
-+static int sst_allocate_decode_buf(struct stream_info *str_info,
-+ struct snd_sst_dbufs *dbufs,
-+ unsigned int cum_input_given,
-+ unsigned int cum_output_given)
-+{
-+ if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
-+
-+ if (dbufs->ibufs->type == SST_BUF_RAR && dbufs->obufs->type == SST_BUF_RAR ) {
-+ if (dbufs->ibufs->entries == dbufs->obufs->entries)
-+ return 0;
-+ else {
-+ printk(KERN_ERR "SST ERR: +\
-+ RAR buffer entries do not match \n");
-+ return -EINVAL;
-+ }
-+ }
-+ else
-+ str_info->decode_osize = cum_output_given;
-+ return 0;
-+
-+ }
-+ if (!str_info->decode_ibuf) {
-+ printk(KERN_DEBUG "SST DBG:no input buffers, trying full size\n");
-+ str_info->decode_isize = cum_input_given;
-+ str_info->decode_ibuf = kzalloc(str_info->decode_isize,
-+ GFP_KERNEL);
-+ str_info->idecode_alloc = str_info->decode_isize;
-+ }
-+ if (!str_info->decode_ibuf) {
-+ printk(KERN_DEBUG "SST DBG:buff alloaction failed, trying max size\n");
-+ str_info->decode_isize = calculate_max_size(dbufs->ibufs);
-+ str_info->decode_ibuf = kzalloc(str_info->decode_isize,
-+ GFP_KERNEL);
-+ str_info->idecode_alloc = str_info->decode_isize;
-+ }
-+ if (!str_info->decode_ibuf) {
-+ printk(KERN_DEBUG "SST DBG:buff alloaction failed, trying min size\n");
-+ str_info->decode_isize = calculate_min_size(dbufs->ibufs);
-+ str_info->decode_ibuf = kzalloc(str_info->decode_isize,
-+ GFP_KERNEL);
-+ if (!str_info->decode_ibuf) {
-+ printk(KERN_ERR \
-+ "SST ERR: mem allocation failed\n");
-+ return -ENOMEM;
-+ }
-+ str_info->idecode_alloc = str_info->decode_isize;
-+ }
-+ str_info->decode_osize = cum_output_given;
-+ if (str_info->decode_osize > sst_drv_ctx->mmap_len)
-+ str_info->decode_osize = sst_drv_ctx->mmap_len;
-+ return 0;
-+}
-+
-+/**
-+* This function is used to send the message to firmware to decode the data
-+*/
-+static int sst_send_decode_mess(int str_id, struct stream_info *str_info,
-+ struct snd_sst_decode_info *dec_info)
-+{
-+ struct ipc_post *msg = NULL;
-+ int retval = 0;
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+
-+ if ( str_info->decode_ibuf_type == SST_BUF_RAR ) {
-+ dec_info->frames_in.addr[0].addr = (unsigned long) str_info->decode_ibuf;
-+ dec_info->frames_in.addr[0].size = str_info->decode_isize;
-+
-+ } else {
-+ dec_info->frames_in.addr[0].addr = virt_to_phys((void *)
-+ str_info->decode_ibuf);
-+ dec_info->frames_in.addr[0].size = str_info->decode_isize;
-+ }
-+
-+
-+ if ( str_info->decode_obuf_type == SST_BUF_RAR ) {
-+ dec_info->frames_out.addr[0].addr = (unsigned long) str_info->decode_obuf;
-+ dec_info->frames_out.addr[0].size = str_info->decode_osize;
-+
-+ } else {
-+ dec_info->frames_out.addr[0].addr = virt_to_phys((void *)
-+ str_info->decode_obuf ) ;
-+ dec_info->frames_out.addr[0].size = str_info->decode_osize;
-+ }
-+
-+ dec_info->frames_in.num_entries = 1;
-+ dec_info->frames_out.num_entries = 1;
-+ dec_info->frames_in.rsrvd = 0;
-+ dec_info->frames_out.rsrvd = 0;
-+ dec_info->input_bytes_consumed = 0;
-+ dec_info->output_bytes_produced = 0;
-+ if (sst_create_large_msg(&msg)) {
-+ printk(KERN_ERR "SST ERR: message +\
-+ creation failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ sst_fill_header(&msg->header, IPC_IA_DECODE_FRAMES, 1, str_id);
-+ msg->header.part.data = sizeof(u32) + sizeof(*dec_info);
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), dec_info,
-+ sizeof(*dec_info));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ str_info->data_blk.condition = false;
-+ str_info->data_blk.ret_code = 0;
-+ str_info->data_blk.on = true;
-+ str_info->data_blk.data = dec_info;
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
-+ return retval;
-+}
-+
-+/**
-+* This function is used to prepare the kernel input buffers with contents before
-+* sendind for decode
-+*/
-+static int sst_prepare_input_buffers(struct stream_info *str_info,
-+ struct snd_sst_dbufs *dbufs,
-+ int *input_index, int *in_copied, int *input_index_valid_size, int *new_entry_flag)
-+{
-+ int i, cpy_size, retval = 0;
-+
-+ printk(KERN_DEBUG "SST DBG:input_index = %d, +\
-+ input entries = %d\n", *input_index,
-+ dbufs->ibufs->entries);
-+ for (i = *input_index; i < dbufs->ibufs->entries; i++) {
-+ if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
-+ struct RAR_buffer rar_buffers;
-+ __u32 info;
-+ retval = copy_from_user((void *) &info,
-+ dbufs->ibufs->buff_entry[i].buffer,
-+ sizeof(__u32));
-+ if (retval) {
-+ printk(KERN_ERR "SST ERR:copy from user failed\n");
-+ return -EAGAIN;
-+ }
-+ rar_buffers.info.type = dbufs->ibufs->type;
-+ rar_buffers.info.size = dbufs->ibufs->buff_entry[i].size;
-+ rar_buffers.info.handle = info;
-+ printk(KERN_DEBUG "rar handle in DnR(input buffer function)=0x%x size=0x%x" \
-+ , rar_buffers.info.handle, rar_buffers.info.size);
-+ retval = sst_get_RAR(&rar_buffers, 1);
-+ if (retval) {
-+ printk(KERN_ERR "SST ERR: RAR API failed\n");
-+ return retval;
-+ }
-+ str_info->decode_ibuf = (void *) ((unsigned long) rar_buffers.bus_address);
-+ printk(KERN_DEBUG "RAR buffer address in DnR (input buffer function):: +\
-+ 0x%lu", (unsigned long) str_info->decode_ibuf);
-+ printk(KERN_DEBUG "rar handle in DnR decode funtion/output b_add rar +\
-+ = 0x%lu", (unsigned long) rar_buffers.bus_address);
-+
-+ *input_index = i + 1;
-+
-+ str_info->decode_isize = dbufs->ibufs->buff_entry[i].size;
-+ str_info->decode_ibuf_type = dbufs->ibufs->type;
-+ *in_copied = str_info->decode_isize;
-+ printk(KERN_DEBUG "rar address in input prepare= 0x%lu size=0x%x +\
-+ incopied Size =%d ", (unsigned long) str_info->decode_ibuf, +\
-+ str_info->decode_isize ,*in_copied);
-+ break;
-+ }
-+ *input_index = i;
-+ if (*input_index_valid_size == 0)
-+ *input_index_valid_size = dbufs->ibufs->buff_entry[i].size;
-+ printk(KERN_DEBUG "SST DBG:inout addr = %p, size = %d\n",
-+ dbufs->ibufs->buff_entry[i].buffer,
-+ *input_index_valid_size);
-+ printk(KERN_DEBUG "SST DBG:decode_isize = %d, in_copied = %d\n",
-+ str_info->decode_isize, *in_copied);
-+ if (*input_index_valid_size <=
-+ (str_info->decode_isize - *in_copied))
-+ cpy_size = *input_index_valid_size;
-+ else
-+ cpy_size = str_info->decode_isize - *in_copied;
-+
-+ printk(KERN_DEBUG "SST DBG:cpy size = %d\n", cpy_size);
-+ if (!dbufs->ibufs->buff_entry[i].buffer) {
-+ printk(KERN_ERR "SST ERR: +\
-+ input buffer is null\n");
-+ return -EINVAL;
-+ }
-+ printk(KERN_DEBUG "SST DBG:Trying copy To: %p, From %p, size %d\n",
-+ str_info->decode_ibuf + *in_copied,
-+ dbufs->ibufs->buff_entry[i].buffer, cpy_size);
-+
-+ retval =
-+ copy_from_user((void *)(str_info->decode_ibuf + *in_copied),
-+ (void *) dbufs->ibufs->buff_entry[i].buffer,
-+ cpy_size);
-+ if (retval) {
-+ printk(KERN_ERR\
-+ "SST ERR: copy from user failed \n");
-+ return -EIO;
-+ }
-+ *in_copied += cpy_size;
-+ *input_index_valid_size -= cpy_size;
-+ printk(KERN_DEBUG "SST DBG:in buff size = %d, in_copied = %d\n",
-+ *input_index_valid_size, *in_copied);
-+ if (*input_index_valid_size != 0) {
-+ printk(KERN_DEBUG "SST DBG:more input buffers left \n");
-+ dbufs->ibufs->buff_entry[i].buffer +=
-+ cpy_size;
-+ break;
-+ }
-+ if (*in_copied == str_info->decode_isize &&
-+ *input_index_valid_size == 0 && (i+1) <= dbufs->ibufs->entries) {
-+ printk(KERN_DEBUG "SST DBG:all input buffers copied\n");
-+ *new_entry_flag = true;
-+ *input_index = i + 1;
-+ break;
-+ }
-+ }
-+ return retval;
-+}
-+
-+/**
-+* This function is used to copy the decoded data from kernel buffers to
-+* the user output buffers with contents after decode
-+*/
-+static int sst_prepare_output_buffers(struct stream_info *str_info,
-+ struct snd_sst_dbufs *dbufs,
-+ int *output_index, int output_size,
-+ int *out_copied)
-+
-+{
-+ int i, cpy_size, retval = 0;
-+ printk(KERN_DEBUG "SST DBG:output_index = %d, output entries = %d\n",
-+ *output_index,
-+ dbufs->obufs->entries);
-+ for (i = *output_index; i < dbufs->obufs->entries; i++) {
-+ *output_index = i;
-+ printk(KERN_DEBUG "SST DBG:output addr = %p, size = %d\n",
-+ dbufs->obufs->buff_entry[i].buffer,
-+ dbufs->obufs->buff_entry[i].size);
-+ printk(KERN_DEBUG "SST DBG:output_size = %d, out_copied = %d\n",
-+ output_size, *out_copied);
-+ if (dbufs->obufs->buff_entry[i].size <
-+ (output_size - *out_copied))
-+ cpy_size = dbufs->obufs->buff_entry[i].size;
-+ else
-+ cpy_size = output_size - *out_copied;
-+ printk(KERN_DEBUG "SST DBG:cpy size = %d\n", cpy_size);
-+ printk(KERN_DEBUG "SST DBG:Trying copy To: %p, From %p, size %d\n",
-+ dbufs->obufs->buff_entry[i].buffer,
-+ sst_drv_ctx->mmap_mem + *out_copied,
-+ cpy_size);
-+ retval = copy_to_user(dbufs->obufs->buff_entry[i].buffer,
-+ sst_drv_ctx->mmap_mem + *out_copied,
-+ cpy_size);
-+ if (retval) {
-+ printk(KERN_ERR "SST ERR: +\
-+ copy to user failed \n");
-+ return -EIO;
-+ } else
-+ printk(KERN_DEBUG "SST DBG:copy to user passed \n");
-+ *out_copied += cpy_size;
-+ dbufs->obufs->buff_entry[i].size -= cpy_size;
-+ printk(KERN_DEBUG "SST DBG:output buff size = %d, out_copied = %d\n",
-+ dbufs->obufs->buff_entry[i].size, *out_copied);
-+ if (dbufs->obufs->buff_entry[i].size != 0) {
-+ *output_index = i;
-+ dbufs->obufs->buff_entry[i].buffer += cpy_size;
-+ break;
-+ } else if (*out_copied == output_size) {
-+ *output_index = i + 1;
-+ break;
-+ }
-+ }
-+ return retval;
-+}
-+
-+/**
-+* sst_decode - Send msg for decoding frames
-+* @str_id: ID of stream
-+* @dbufs - param that holds the user input and output buffers and sizes
-+* This function is called to decode data from the firmware
-+*/
-+int sst_decode(int str_id, struct snd_sst_dbufs *dbufs)
-+{
-+ int retval = 0, i;
-+ unsigned long long total_input = 0 , total_output = 0;
-+ unsigned int cum_input_given = 0 , cum_output_given = 0;
-+ int copy_in_done = false, copy_out_done = false;
-+ int input_index = 0, output_index = 0;
-+ int input_index_valid_size = 0;
-+ int in_copied, out_copied;
-+ int new_entry_flag;
-+ u64 output_size;
-+ struct stream_info *str_info;
-+ struct snd_sst_decode_info dec_info;
-+
-+ printk(KERN_DEBUG "SST DBG:...called \n");
-+ sst_drv_ctx->scard_ops->power_down_pmic();
-+ printk(KERN_DEBUG "SST DBG: Powering_down_PMIC.... \n");
-+ retval = sst_validate_strid(str_id);
-+ if (retval)
-+ return retval;
-+
-+ str_info = &sst_drv_ctx->streams[str_id];
-+ if (str_info->status != STREAM_INIT) {
-+ printk(KERN_ERR "SST ERR: invalid +\
-+ stream state = %d\n", str_info->status);
-+ return -EINVAL;
-+ }
-+
-+ str_info->prev = str_info->status;
-+ str_info->status = STREAM_DECODE;
-+ for (i = 0; i < dbufs->ibufs->entries; i++)
-+ cum_input_given += dbufs->ibufs->buff_entry[i].size;
-+ for (i = 0; i < dbufs->obufs->entries; i++)
-+ cum_output_given += dbufs->obufs->buff_entry[i].size;
-+ /* input and output buffer allocation */
-+ retval = sst_allocate_decode_buf(str_info, dbufs,
-+ cum_input_given, cum_output_given);
-+ str_info->decode_isize = str_info->idecode_alloc;
-+ if (retval) {
-+ printk(KERN_ERR "SST ERR: +\
-+ mem allocation failed, abort!!!\n");
-+ retval = -ENOMEM;
-+ goto finish;
-+ }
-+
-+ str_info->decode_ibuf_type = dbufs->ibufs->type;
-+ str_info->decode_obuf_type = dbufs->obufs->type;
-+
-+ while ((copy_out_done == false) && (copy_in_done == false)) {
-+ in_copied = 0;
-+ new_entry_flag = false;
-+ retval = sst_prepare_input_buffers(str_info,\
-+ dbufs, &input_index, &in_copied, &input_index_valid_size, &new_entry_flag);
-+ printk(KERN_DEBUG "SST DBG:prep inbuf ret %d\n", retval);
-+ if (retval) {
-+ printk(KERN_ERR \
-+ "SST ERR: prepare in buffers failed\n");
-+ goto finish;
-+ }
-+
-+ printk(KERN_DEBUG "rar handle output buffer type = 0x%x ", dbufs->obufs->type);
-+ if (str_info->ops != STREAM_OPS_PLAYBACK_DRM)
-+ str_info->decode_obuf = sst_drv_ctx->mmap_mem;
-+ else {
-+
-+ if( dbufs->obufs->type == SST_BUF_RAR ) {
-+ struct RAR_buffer rar_buffers;
-+ __u32 info;
-+ retval = copy_from_user((void *) &info,
-+ dbufs->obufs->buff_entry[output_index].buffer,
-+ sizeof(__u32));
-+
-+ rar_buffers.info.size = dbufs->obufs->buff_entry[output_index].size;
-+ rar_buffers.info.handle = info;
-+ printk(KERN_DEBUG "rar handle in DnR(decode funtion)= 0x%x size=0x%x",\
-+ rar_buffers.info.handle, rar_buffers.info.size);
-+ retval = sst_get_RAR(&rar_buffers, 1);
-+ if (retval)
-+ return retval;
-+
-+
-+ str_info->decode_obuf = (void *) ((unsigned long)rar_buffers.bus_address);
-+ str_info->decode_osize = dbufs->obufs->buff_entry[output_index].size;
-+ str_info->decode_obuf_type = dbufs->obufs->type;
-+ printk(KERN_DEBUG "SST DBG:DRM handling\n");
-+ printk(KERN_DEBUG "rar handle in DnR decode funtion/output b_add = 0x%lu +\
-+ output Size=0x%x", (unsigned long) str_info->decode_obuf ,\
-+ str_info->decode_osize);
-+ }
-+ else
-+ {
-+ str_info->decode_obuf = sst_drv_ctx->mmap_mem;
-+ str_info->decode_osize = dbufs->obufs->buff_entry[output_index].size;
-+
-+ }
-+ }
-+
-+ if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
-+ if (str_info->decode_isize > in_copied) {
-+ str_info->decode_isize = in_copied;
-+ printk(KERN_DEBUG "SST DBG:input size modified = %d\n",
-+ str_info->decode_isize);
-+ }
-+ }
-+
-+
-+ retval = sst_send_decode_mess(str_id, str_info, &dec_info);
-+ if (retval) {
-+ printk(KERN_ERR \
-+ "SST ERR: sending message failed\n");
-+ goto finish;
-+ }
-+ printk(KERN_DEBUG "SST DBG:in_copied = %d, consumed = %lld, produced = %lld\n",
-+ in_copied,
-+ dec_info.input_bytes_consumed,
-+ dec_info.output_bytes_produced);
-+ if (dbufs->obufs->type == SST_BUF_RAR) {
-+ output_index += 1;
-+ if (output_index == dbufs->obufs->entries) {
-+ copy_in_done = true;
-+ printk(KERN_DEBUG "SST DBG:all input copy done\n");
-+ }
-+ total_output += dec_info.output_bytes_produced;
-+ } else {
-+ out_copied = 0;
-+ output_size = dec_info.output_bytes_produced;
-+ retval = sst_prepare_output_buffers(str_info, dbufs,
-+ &output_index, output_size, &out_copied);
-+ if (retval) {
-+ printk(KERN_ERR \
-+ "SST ERR: prepare out +\
-+ buffers failed\n");
-+ goto finish;
-+ }
-+ if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
-+ if (in_copied != dec_info.input_bytes_consumed) {
-+ int bytes_left = in_copied - dec_info.input_bytes_consumed;
-+ printk(KERN_DEBUG "SST DBG:input left to be copied = %d \n",
-+ bytes_left);
-+ if(new_entry_flag == true) {
-+ input_index--;
-+ }
-+ while (bytes_left) {
-+ unsigned int size_sent = dbufs->ibufs->buff_entry[input_index].size - input_index_valid_size;
-+ if (bytes_left == size_sent) {
-+ bytes_left = 0;
-+ } else if (bytes_left < size_sent) {
-+ dbufs->ibufs->buff_entry[input_index].buffer += (size_sent - bytes_left);
-+ dbufs->ibufs->buff_entry[input_index].size -= (size_sent - bytes_left);
-+ bytes_left = 0;
-+ } else {
-+ bytes_left -= size_sent;
-+ input_index--;
-+ input_index_valid_size = 0;
-+ }
-+ }
-+
-+ }
-+ }
-+
-+ total_output += out_copied;
-+ if (str_info->decode_osize != out_copied) {
-+ str_info->decode_osize -= out_copied;
-+ printk(KERN_DEBUG "SST DBG:output size modified = %d\n",
-+ str_info->decode_osize);
-+ }
-+ }
-+ total_input += dec_info.input_bytes_consumed;
-+
-+ if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
-+ if (total_input == cum_input_given)
-+ copy_in_done = true;
-+ copy_out_done = true;
-+
-+ } else {
-+ if (total_output == cum_output_given) {
-+ copy_out_done = true;
-+ printk(KERN_DEBUG "SST DBG:all output copy done\n");
-+ }
-+
-+ if (total_input == cum_input_given) {
-+ copy_in_done = true;
-+ printk(KERN_DEBUG "SST DBG:all input copy done\n");
-+ }
-+ }
-+
-+ printk(KERN_DEBUG "SST DBG:copy_out_done = %d, copy_in_done = %d \n",
-+ copy_out_done, copy_in_done);
-+ }
-+
-+finish:
-+ dbufs->input_bytes_consumed = total_input;
-+ dbufs->output_bytes_produced = total_output;
-+ str_info->status = str_info->prev;
-+ str_info->prev = STREAM_DECODE;
-+ str_info->decode_ibuf = NULL;
-+ kfree(str_info->decode_ibuf);
-+
-+ return retval;
-+}
---
-1.6.2.2
-