Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / staging / intel_sst / intel_sst_stream_encoded.c
1 /*
2  *  intel_sst_stream.c - Intel SST Driver for audio engine
3  *
4  *  Copyright (C) 2008-10 Intel Corp
5  *  Authors:    Vinod Koul <vinod.koul@intel.com>
6  *              Harsha Priya <priya.harsha@intel.com>
7  *              Dharageswari R <dharageswari.r@intel.com>
8  *              KP Jeeja <jeeja.kp@intel.com>
9  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; version 2 of the License.
14  *
15  *  This program is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23  *
24  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25  *
26  *  This file contains the stream operations of SST driver
27  */
28
29 #include <linux/pci.h>
30 #include <linux/syscalls.h>
31 #include <linux/firmware.h>
32 #include <linux/sched.h>
33 #include <linux/rar_register.h>
34 #ifdef CONFIG_MRST_RAR_HANDLER
35 #include "../../../drivers/staging/memrar/memrar.h"
36 #endif
37 #include "intel_sst_ioctl.h"
38 #include "intel_sst.h"
39 #include "intel_sst_fw_ipc.h"
40 #include "intel_sst_common.h"
41 /**
42 * sst_get_stream_params - Send msg to query for stream parameters
43 * @str_id:      stream id for which the parameters are queried for
44 * @get_params:  out parameters to which the parameters are copied to
45 *
46 * This function is called when the stream parameters are queiried for
47 */
48 int sst_get_stream_params(int str_id,
49                         struct snd_sst_get_stream_params *get_params)
50 {
51         int retval = 0;
52         struct ipc_post *msg = NULL;
53         struct stream_info *str_info;
54         struct snd_sst_fw_get_stream_params *fw_params;
55
56         pr_debug("sst: get_stream for %d\n", str_id);
57         retval = sst_validate_strid(str_id);
58         if (retval)
59                 return retval;
60
61         str_info = &sst_drv_ctx->streams[str_id];
62         if (str_info->status != STREAM_UN_INIT) {
63                 if (str_info->ctrl_blk.on == true) {
64                         pr_err("sst: control path in use\n");
65                         return -EINVAL;
66                 }
67                 if (sst_create_short_msg(&msg)) {
68                         pr_err("sst: message creation failed\n");
69                         return -ENOMEM;
70                 }
71                 fw_params = kzalloc(sizeof(*fw_params), GFP_ATOMIC);
72                 if (!fw_params) {
73                         pr_err("sst: mem allcoation failed\n ");
74                         kfree(msg);
75                         return -ENOMEM;
76                 }
77
78                 sst_fill_header(&msg->header, IPC_IA_GET_STREAM_PARAMS,
79                                         0, str_id);
80                 str_info->ctrl_blk.condition = false;
81                 str_info->ctrl_blk.ret_code = 0;
82                 str_info->ctrl_blk.on = true;
83                 str_info->ctrl_blk.data = (void *) fw_params;
84                 spin_lock(&sst_drv_ctx->list_spin_lock);
85                 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
86                 spin_unlock(&sst_drv_ctx->list_spin_lock);
87                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
88                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
89                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
90                 if (retval) {
91                         get_params->codec_params.result = retval;
92                         kfree(fw_params);
93                         return -EIO;
94                 }
95                 memcpy(&get_params->pcm_params, &fw_params->pcm_params,
96                                 sizeof(fw_params->pcm_params));
97                 memcpy(&get_params->codec_params.sparams,
98                                 &fw_params->codec_params,
99                                 sizeof(fw_params->codec_params));
100                 get_params->codec_params.result = 0;
101                 get_params->codec_params.stream_id = str_id;
102                 get_params->codec_params.codec = str_info->codec;
103                 get_params->codec_params.ops = str_info->ops;
104                 get_params->codec_params.stream_type = str_info->str_type;
105                 kfree(fw_params);
106         } else {
107                 pr_debug("sst: Stream is not in the init state\n");
108         }
109         return retval;
110 }
111
112 /**
113  * sst_set_stream_param - Send msg for setting stream parameters
114  *
115  * @str_id: stream id
116  * @str_param: stream params
117  *
118  * This function sets stream params during runtime
119  */
120 int sst_set_stream_param(int str_id, struct snd_sst_params *str_param)
121 {
122         int retval = 0;
123         struct ipc_post *msg = NULL;
124         struct stream_info *str_info;
125
126         BUG_ON(!str_param);
127         if (sst_drv_ctx->streams[str_id].ops != str_param->ops) {
128                 pr_err("sst: Invalid operation\n");
129                 return -EINVAL;
130         }
131         retval = sst_validate_strid(str_id);
132         if (retval)
133                 return retval;
134         pr_debug("sst: set_stream for %d\n", str_id);
135         str_info =  &sst_drv_ctx->streams[str_id];
136         if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) {
137                 if (str_info->ctrl_blk.on == true) {
138                         pr_err("sst: control path in use\n");
139                         return -EAGAIN;
140                 }
141                 if (sst_create_large_msg(&msg))
142                         return -ENOMEM;
143
144                 sst_fill_header(&msg->header,
145                                 IPC_IA_SET_STREAM_PARAMS, 1, str_id);
146                 str_info->ctrl_blk.condition = false;
147                 str_info->ctrl_blk.ret_code = 0;
148                 str_info->ctrl_blk.on = true;
149                 msg->header.part.data = sizeof(u32) +
150                                 sizeof(str_param->sparams);
151                 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
152                 memcpy(msg->mailbox_data + sizeof(u32), &str_param->sparams,
153                                 sizeof(str_param->sparams));
154                 spin_lock(&sst_drv_ctx->list_spin_lock);
155                 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
156                 spin_unlock(&sst_drv_ctx->list_spin_lock);
157                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
158                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
159                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
160                 if (retval < 0) {
161                         retval = -EIO;
162                         sst_clean_stream(str_info);
163                 }
164         } else {
165                 retval = -EBADRQC;
166                 pr_err("sst: BADQRC for stream\n");
167         }
168         return retval;
169 }
170
171 /**
172 * sst_get_vol - This fuction allows to get the premix gain or gain of a stream
173 *
174 * @get_vol: this is an output param through which the volume
175 *       structure is passed back to user
176 *
177 * This function is called when the premix gain or stream gain is queried for
178 */
179 int sst_get_vol(struct snd_sst_vol *get_vol)
180 {
181         int retval = 0;
182         struct ipc_post *msg = NULL;
183         struct snd_sst_vol *fw_get_vol;
184         int str_id = get_vol->stream_id;
185
186         pr_debug("sst: get vol called\n");
187
188         if (sst_create_short_msg(&msg))
189                 return -ENOMEM;
190
191         sst_fill_header(&msg->header,
192                                 IPC_IA_GET_STREAM_VOL, 0, str_id);
193         sst_drv_ctx->vol_info_blk.condition = false;
194         sst_drv_ctx->vol_info_blk.ret_code = 0;
195         sst_drv_ctx->vol_info_blk.on = true;
196         fw_get_vol = kzalloc(sizeof(*fw_get_vol), GFP_ATOMIC);
197         if (!fw_get_vol) {
198                 pr_err("sst: mem allocation failed\n");
199                 kfree(msg);
200                 return -ENOMEM;
201         }
202         sst_drv_ctx->vol_info_blk.data = (void *)fw_get_vol;
203         spin_lock(&sst_drv_ctx->list_spin_lock);
204         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
205         spin_unlock(&sst_drv_ctx->list_spin_lock);
206         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
207         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
208                         &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
209         if (retval)
210                 retval = -EIO;
211         else {
212                 pr_debug("sst: stream id %d\n", fw_get_vol->stream_id);
213                 pr_debug("sst: volume %d\n", fw_get_vol->volume);
214                 pr_debug("sst: ramp duration %d\n", fw_get_vol->ramp_duration);
215                 pr_debug("sst: ramp_type %d\n", fw_get_vol->ramp_type);
216                 memcpy(get_vol, fw_get_vol, sizeof(*fw_get_vol));
217         }
218         return retval;
219 }
220
221 /**
222 * sst_set_vol - This fuction allows to set the premix gain or gain of a stream
223 *
224 * @set_vol:     this holds the volume structure that needs to be set
225 *
226 * This function is called when premix gain or stream gain is requested to be set
227 */
228 int sst_set_vol(struct snd_sst_vol *set_vol)
229 {
230
231         int retval = 0;
232         struct ipc_post *msg = NULL;
233
234         pr_debug("sst: set vol called\n");
235
236         if (sst_create_large_msg(&msg)) {
237                 pr_err("sst: message creation failed\n");
238                 return -ENOMEM;
239         }
240         sst_fill_header(&msg->header, IPC_IA_SET_STREAM_VOL, 1,
241                                 set_vol->stream_id);
242
243         msg->header.part.data = sizeof(u32) + sizeof(*set_vol);
244         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
245         memcpy(msg->mailbox_data + sizeof(u32), set_vol, sizeof(*set_vol));
246         sst_drv_ctx->vol_info_blk.condition = false;
247         sst_drv_ctx->vol_info_blk.ret_code = 0;
248         sst_drv_ctx->vol_info_blk.on = true;
249         sst_drv_ctx->vol_info_blk.data = set_vol;
250         spin_lock(&sst_drv_ctx->list_spin_lock);
251         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
252         spin_unlock(&sst_drv_ctx->list_spin_lock);
253         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
254         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
255                         &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
256         if (retval) {
257                 pr_err("sst: error in set_vol = %d\n", retval);
258                 retval = -EIO;
259         }
260         return retval;
261 }
262
263 /**
264 * sst_set_mute - This fuction sets premix mute or soft mute of a stream
265 *
266 * @set_mute:    this holds the mute structure that needs to be set
267 *
268 * This function is called when premix mute or stream mute requested to be set
269 */
270 int sst_set_mute(struct snd_sst_mute *set_mute)
271 {
272
273         int retval = 0;
274         struct ipc_post *msg = NULL;
275
276         pr_debug("sst: set mute called\n");
277
278         if (sst_create_large_msg(&msg)) {
279                 pr_err("sst: message creation failed\n");
280                 return -ENOMEM;
281         }
282         sst_fill_header(&msg->header, IPC_IA_SET_STREAM_MUTE, 1,
283                                 set_mute->stream_id);
284         sst_drv_ctx->mute_info_blk.condition = false;
285         sst_drv_ctx->mute_info_blk.ret_code = 0;
286         sst_drv_ctx->mute_info_blk.on = true;
287         sst_drv_ctx->mute_info_blk.data = set_mute;
288
289         msg->header.part.data = sizeof(u32) + sizeof(*set_mute);
290         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
291         memcpy(msg->mailbox_data + sizeof(u32), set_mute,
292                         sizeof(*set_mute));
293         spin_lock(&sst_drv_ctx->list_spin_lock);
294         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
295         spin_unlock(&sst_drv_ctx->list_spin_lock);
296         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
297         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
298                         &sst_drv_ctx->mute_info_blk, SST_BLOCK_TIMEOUT);
299         if (retval) {
300                 pr_err("sst: error in set_mute = %d\n", retval);
301                 retval = -EIO;
302         }
303         return retval;
304 }
305
306 int sst_prepare_target(struct snd_sst_slot_info *slot)
307 {
308         if (slot->target_device == SND_SST_TARGET_PMIC
309                 && slot->device_instance == 1) {
310                         /*music mode*/
311                         if (sst_drv_ctx->pmic_port_instance == 0)
312                                 sst_drv_ctx->scard_ops->set_voice_port(
313                                         DEACTIVATE);
314         } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
315                         slot->target_device == SND_SST_TARGET_MODEM) &&
316                         slot->device_instance == 0) {
317                                 /*voip mode where pcm0 is active*/
318                                 if (sst_drv_ctx->pmic_port_instance == 1)
319                                         sst_drv_ctx->scard_ops->set_audio_port(
320                                                 DEACTIVATE);
321         }
322         return 0;
323 }
324
325 int sst_activate_target(struct snd_sst_slot_info *slot)
326 {
327         if (slot->target_device == SND_SST_TARGET_PMIC &&
328                 slot->device_instance == 1) {
329                         /*music mode*/
330                         sst_drv_ctx->pmic_port_instance = 1;
331                         sst_drv_ctx->scard_ops->set_audio_port(ACTIVATE);
332                         sst_drv_ctx->scard_ops->set_pcm_audio_params(
333                                 slot->pcm_params.sfreq,
334                                 slot->pcm_params.pcm_wd_sz,
335                                 slot->pcm_params.num_chan);
336                         if (sst_drv_ctx->pb_streams)
337                                 sst_drv_ctx->scard_ops->power_up_pmic_pb(1);
338                         if (sst_drv_ctx->cp_streams)
339                                 sst_drv_ctx->scard_ops->power_up_pmic_cp(1);
340         } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
341                         slot->target_device == SND_SST_TARGET_MODEM) &&
342                         slot->device_instance == 0) {
343                                 /*voip mode where pcm0 is active*/
344                                 sst_drv_ctx->pmic_port_instance = 0;
345                                 sst_drv_ctx->scard_ops->set_voice_port(
346                                         ACTIVATE);
347                                 sst_drv_ctx->scard_ops->power_up_pmic_pb(0);
348                                 /*sst_drv_ctx->scard_ops->power_up_pmic_cp(0);*/
349         }
350         return 0;
351 }
352
353 int sst_parse_target(struct snd_sst_slot_info *slot)
354 {
355         int retval = 0;
356
357         if (slot->action == SND_SST_PORT_ACTIVATE &&
358                 slot->device_type == SND_SST_DEVICE_PCM) {
359                         retval = sst_activate_target(slot);
360                         if (retval)
361                                 pr_err("sst: SST_Activate_target_fail\n");
362                         else
363                                 pr_err("sst: SST_Activate_target_pass\n");
364                 return retval;
365         } else if (slot->action == SND_SST_PORT_PREPARE &&
366                         slot->device_type == SND_SST_DEVICE_PCM) {
367                                 retval = sst_prepare_target(slot);
368                         if (retval)
369                                 pr_err("sst: SST_prepare_target_fail\n");
370                         else
371                                 pr_err("sst: SST_prepare_target_pass\n");
372                         return retval;
373         } else {
374                 pr_err("sst: slot_action : %d, device_type: %d\n",
375                                 slot->action, slot->device_type);
376                 return retval;
377         }
378 }
379
380 int sst_send_target(struct snd_sst_target_device *target)
381 {
382         int retval;
383         struct ipc_post *msg;
384
385         if (sst_create_large_msg(&msg)) {
386                 pr_err("sst: message creation failed\n");
387                 return -ENOMEM;
388         }
389         sst_fill_header(&msg->header, IPC_IA_TARGET_DEV_SELECT, 1, 0);
390         sst_drv_ctx->tgt_dev_blk.condition = false;
391         sst_drv_ctx->tgt_dev_blk.ret_code = 0;
392         sst_drv_ctx->tgt_dev_blk.on = true;
393
394         msg->header.part.data = sizeof(u32) + sizeof(*target);
395         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
396         memcpy(msg->mailbox_data + sizeof(u32), target,
397                         sizeof(*target));
398         spin_lock(&sst_drv_ctx->list_spin_lock);
399         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
400         spin_unlock(&sst_drv_ctx->list_spin_lock);
401         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
402         pr_debug("sst: message sent- waiting\n");
403         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
404                         &sst_drv_ctx->tgt_dev_blk, TARGET_DEV_BLOCK_TIMEOUT);
405         if (retval)
406                 pr_err("sst: target device ipc failed = 0x%x\n", retval);
407         return retval;
408
409 }
410
411 int sst_target_device_validate(struct snd_sst_target_device *target)
412 {
413         int retval = 0;
414        int i;
415
416         for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
417                 if (target->devices[i].device_type == SND_SST_DEVICE_PCM) {
418                         /*pcm device, check params*/
419                         if (target->devices[i].device_instance == 1) {
420                                 if ((target->devices[i].device_mode !=
421                                 SND_SST_DEV_MODE_PCM_MODE4_I2S) &&
422                                 (target->devices[i].device_mode !=
423                                 SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED)
424                                 && (target->devices[i].device_mode !=
425                                 SND_SST_DEV_MODE_PCM_MODE1))
426                                         goto err;
427                         } else if (target->devices[i].device_instance == 0) {
428                                 if ((target->devices[i].device_mode !=
429                                                 SND_SST_DEV_MODE_PCM_MODE2)
430                                         && (target->devices[i].device_mode !=
431                                                 SND_SST_DEV_MODE_PCM_MODE4_I2S)
432                                         && (target->devices[i].device_mode !=
433                                                 SND_SST_DEV_MODE_PCM_MODE1))
434                                         goto err;
435                                 if (target->devices[i].pcm_params.sfreq != 8000
436                                 || target->devices[i].pcm_params.num_chan != 1
437                                 || target->devices[i].pcm_params.pcm_wd_sz !=
438                                                                         16)
439                                         goto err;
440                         } else {
441 err:
442                                 pr_err("sst: i/p params incorrect\n");
443                                 return -EINVAL;
444                         }
445                 }
446         }
447     return retval;
448 }
449
450 /**
451  * sst_target_device_select - This fuction sets the target device configurations
452  *
453  * @target: this parameter holds the configurations to be set
454  *
455  * This function is called when the user layer wants to change the target
456  * device's configurations
457  */
458
459 int sst_target_device_select(struct snd_sst_target_device *target)
460 {
461         int retval, i, prepare_count = 0;
462
463         pr_debug("sst: Target Device Select\n");
464
465         if (target->device_route < 0 || target->device_route > 2) {
466                 pr_err("sst: device route is invalid\n");
467                 return -EINVAL;
468         }
469
470         if (target->device_route != 0) {
471                 pr_err("sst: Unsupported config\n");
472                 return -EIO;
473         }
474         retval = sst_target_device_validate(target);
475         if (retval)
476                 return retval;
477
478         retval = sst_send_target(target);
479         if (retval)
480                 return retval;
481         for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
482                 if (target->devices[i].action == SND_SST_PORT_ACTIVATE) {
483                         pr_debug("sst: activate called in %d\n", i);
484                         retval = sst_parse_target(&target->devices[i]);
485                         if (retval)
486                                 return retval;
487                 } else if (target->devices[i].action == SND_SST_PORT_PREPARE) {
488                         pr_debug("sst: PREPARE in %d, Forwading\n", i);
489                         retval = sst_parse_target(&target->devices[i]);
490                         if (retval) {
491                                 pr_err("sst: Parse Target fail %d", retval);
492                                 return retval;
493                         }
494                         pr_debug("sst: Parse Target successful %d", retval);
495                         if (target->devices[i].device_type ==
496                                                 SND_SST_DEVICE_PCM)
497                                 prepare_count++;
498                 }
499         }
500         if (target->devices[0].action == SND_SST_PORT_PREPARE &&
501                 prepare_count == 0)
502                         sst_drv_ctx->scard_ops->power_down_pmic();
503
504         return retval;
505 }
506 #ifdef CONFIG_MRST_RAR_HANDLER
507 /*This function gets the physical address of the secure memory from the handle*/
508 static inline int sst_get_RAR(struct RAR_buffer *buffers, int count)
509 {
510         int retval = 0, rar_status = 0;
511
512         rar_status = rar_handle_to_bus(buffers, count);
513
514         if (count != rar_status) {
515                 pr_err("sst: The rar CALL Failed");
516                 retval = -EIO;
517         }
518         if (buffers->info.type != RAR_TYPE_AUDIO) {
519                 pr_err("sst: Invalid RAR type\n");
520                 return -EINVAL;
521         }
522         return retval;
523 }
524
525 #endif
526
527 /* This function creates the scatter gather list to be sent to firmware to
528 capture/playback data*/
529 static int sst_create_sg_list(struct stream_info *stream,
530                 struct sst_frame_info *sg_list)
531 {
532         struct sst_stream_bufs *kbufs = NULL;
533 #ifdef CONFIG_MRST_RAR_HANDLER
534         struct RAR_buffer rar_buffers;
535         int retval = 0;
536 #endif
537         int i = 0;
538         list_for_each_entry(kbufs, &stream->bufs, node) {
539                 if (kbufs->in_use == false) {
540 #ifdef CONFIG_MRST_RAR_HANDLER
541                         if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
542                                 pr_debug("sst: DRM playback handling\n");
543                                 rar_buffers.info.handle = (__u32)kbufs->addr;
544                                 rar_buffers.info.size = kbufs->size;
545                                 pr_debug("sst: rar handle 0x%x size=0x%x",
546                                         rar_buffers.info.handle,
547                                         rar_buffers.info.size);
548                                 retval =  sst_get_RAR(&rar_buffers, 1);
549
550                                 if (retval)
551                                         return retval;
552                                 sg_list->addr[i].addr = rar_buffers.bus_address;
553                                 /* rar_buffers.info.size; */
554                                 sg_list->addr[i].size = (__u32)kbufs->size;
555                                 pr_debug("sst: phyaddr[%d] 0x%x Size:0x%x\n"
556                                         , i, sg_list->addr[i].addr,
557                                         sg_list->addr[i].size);
558                         }
559 #endif
560                         if (stream->ops != STREAM_OPS_PLAYBACK_DRM) {
561                                 sg_list->addr[i].addr =
562                                         virt_to_phys((void *)
563                                                 kbufs->addr + kbufs->offset);
564                                 sg_list->addr[i].size = kbufs->size;
565                                 pr_debug("sst: phyaddr[%d]:0x%x Size:0x%x\n"
566                                 , i , sg_list->addr[i].addr, kbufs->size);
567                         }
568                         stream->curr_bytes += sg_list->addr[i].size;
569                         kbufs->in_use = true;
570                         i++;
571                 }
572                 if (i >= MAX_NUM_SCATTER_BUFFERS)
573                         break;
574         }
575
576         sg_list->num_entries = i;
577         pr_debug("sst:sg list entries = %d\n", sg_list->num_entries);
578         return i;
579 }
580
581
582 /**
583  * sst_play_frame - Send msg for sending stream frames
584  *
585  * @str_id:     ID of stream
586  *
587  * This function is called to send data to be played out
588  * to the firmware
589  */
590 int sst_play_frame(int str_id)
591 {
592         int i = 0, retval = 0;
593         struct ipc_post *msg = NULL;
594         struct sst_frame_info sg_list = {0};
595         struct sst_stream_bufs *kbufs = NULL, *_kbufs;
596         struct stream_info *stream;
597
598         pr_debug("sst: play frame for %d\n", str_id);
599         retval = sst_validate_strid(str_id);
600         if (retval)
601                 return retval;
602
603         stream = &sst_drv_ctx->streams[str_id];
604         /* clear prev sent buffers */
605         list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
606                 if (kbufs->in_use == true) {
607                         spin_lock(&stream->pcm_lock);
608                         list_del(&kbufs->node);
609                         spin_unlock(&stream->pcm_lock);
610                         kfree(kbufs);
611                 }
612         }
613         /* update bytes sent */
614         stream->cumm_bytes += stream->curr_bytes;
615         stream->curr_bytes = 0;
616         if (list_empty(&stream->bufs)) {
617                 /* no user buffer available */
618                 pr_debug("sst: Null buffer stream status %d\n", stream->status);
619                 stream->prev = stream->status;
620                 stream->status = STREAM_INIT;
621                 pr_debug("sst:new stream status = %d\n", stream->status);
622                 if (stream->need_draining == true) {
623                         pr_debug("sst:draining stream\n");
624                         if (sst_create_short_msg(&msg)) {
625                                 pr_err("sst: mem alloc failed\n");
626                                 return -ENOMEM;
627                         }
628                         sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM,
629                                                 0, str_id);
630                         spin_lock(&sst_drv_ctx->list_spin_lock);
631                         list_add_tail(&msg->node,
632                                         &sst_drv_ctx->ipc_dispatch_list);
633                         spin_unlock(&sst_drv_ctx->list_spin_lock);
634                         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
635                 } else if (stream->data_blk.on == true) {
636                         pr_debug("sst:user list empty.. wake\n");
637                         /* unblock */
638                         stream->data_blk.ret_code = 0;
639                         stream->data_blk.condition = true;
640                         stream->data_blk.on = false;
641                         wake_up(&sst_drv_ctx->wait_queue);
642                 }
643                 return 0;
644         }
645
646         /* create list */
647         i = sst_create_sg_list(stream, &sg_list);
648
649         /* post msg */
650         if (sst_create_large_msg(&msg))
651                 return -ENOMEM;
652
653         sst_fill_header(&msg->header, IPC_IA_PLAY_FRAMES, 1, str_id);
654         msg->header.part.data = sizeof(u32) + sizeof(sg_list);
655         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
656         memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
657         spin_lock(&sst_drv_ctx->list_spin_lock);
658         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
659         spin_unlock(&sst_drv_ctx->list_spin_lock);
660         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
661         return 0;
662
663 }
664
665 /**
666  * sst_capture_frame - Send msg for sending stream frames
667  *
668  * @str_id:     ID of stream
669  *
670  * This function is called to capture data from the firmware
671  */
672 int sst_capture_frame(int str_id)
673 {
674         int i = 0, retval = 0;
675         struct ipc_post *msg = NULL;
676         struct sst_frame_info sg_list = {0};
677         struct sst_stream_bufs *kbufs = NULL, *_kbufs;
678         struct stream_info *stream;
679
680
681         pr_debug("sst:capture frame for %d\n", str_id);
682         retval = sst_validate_strid(str_id);
683         if (retval)
684                 return retval;
685         stream = &sst_drv_ctx->streams[str_id];
686         /* clear prev sent buffers */
687         list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
688                 if (kbufs->in_use == true) {
689                         list_del(&kbufs->node);
690                         kfree(kbufs);
691                         pr_debug("sst:del node\n");
692                 }
693         }
694         if (list_empty(&stream->bufs)) {
695                 /* no user buffer available */
696                 pr_debug("sst:Null buffer!!!!stream status %d\n",
697                                stream->status);
698                 stream->prev = stream->status;
699                 stream->status = STREAM_INIT;
700                 pr_debug("sst:new stream status = %d\n",
701                                stream->status);
702                 if (stream->data_blk.on == true) {
703                         pr_debug("sst:user list empty.. wake\n");
704                         /* unblock */
705                         stream->data_blk.ret_code = 0;
706                         stream->data_blk.condition = true;
707                         stream->data_blk.on = false;
708                         wake_up(&sst_drv_ctx->wait_queue);
709
710                 }
711                 return 0;
712         }
713         /* create new sg list */
714         i = sst_create_sg_list(stream, &sg_list);
715
716         /* post msg */
717         if (sst_create_large_msg(&msg))
718                 return -ENOMEM;
719
720         sst_fill_header(&msg->header, IPC_IA_CAPT_FRAMES, 1, str_id);
721         msg->header.part.data = sizeof(u32) + sizeof(sg_list);
722         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
723         memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
724         spin_lock(&sst_drv_ctx->list_spin_lock);
725         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
726         spin_unlock(&sst_drv_ctx->list_spin_lock);
727         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
728
729
730         /*update bytes recevied*/
731         stream->cumm_bytes += stream->curr_bytes;
732         stream->curr_bytes = 0;
733
734     pr_debug("sst:Cum bytes  = %d\n", stream->cumm_bytes);
735         return 0;
736 }
737
738 /*This function is used to calculate the minimum size of input buffers given*/
739 static unsigned int calculate_min_size(struct snd_sst_buffs *bufs)
740 {
741         int i, min_val = bufs->buff_entry[0].size;
742         for (i = 1 ; i < bufs->entries; i++) {
743                 if (bufs->buff_entry[i].size < min_val)
744                         min_val = bufs->buff_entry[i].size;
745         }
746         pr_debug("sst:min_val = %d\n", min_val);
747         return min_val;
748 }
749
750 static unsigned int calculate_max_size(struct snd_sst_buffs *bufs)
751 {
752         int i, max_val = bufs->buff_entry[0].size;
753         for (i = 1 ; i < bufs->entries; i++) {
754                 if (bufs->buff_entry[i].size > max_val)
755                         max_val = bufs->buff_entry[i].size;
756         }
757         pr_debug("sst:max_val = %d\n", max_val);
758         return max_val;
759 }
760
761 /*This function is used to allocate input and output buffers to be sent to
762 the firmware that will take encoded data and return decoded data*/
763 static int sst_allocate_decode_buf(struct stream_info *str_info,
764                                 struct snd_sst_dbufs *dbufs,
765                                 unsigned int cum_input_given,
766                                 unsigned int cum_output_given)
767 {
768 #ifdef CONFIG_MRST_RAR_HANDLER
769         if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
770
771                 if (dbufs->ibufs->type == SST_BUF_RAR  &&
772                         dbufs->obufs->type == SST_BUF_RAR) {
773                         if (dbufs->ibufs->entries == dbufs->obufs->entries)
774                                 return 0;
775                         else {
776                                 pr_err("sst: RAR entries dont match\n");
777                                  return -EINVAL;
778                         }
779                 } else
780                         str_info->decode_osize = cum_output_given;
781                 return 0;
782
783         }
784 #endif
785         if (!str_info->decode_ibuf) {
786                 pr_debug("sst:no i/p buffers, trying full size\n");
787                 str_info->decode_isize = cum_input_given;
788                 str_info->decode_ibuf = kzalloc(str_info->decode_isize,
789                                                 GFP_KERNEL);
790                 str_info->idecode_alloc = str_info->decode_isize;
791         }
792         if (!str_info->decode_ibuf) {
793                 pr_debug("sst:buff alloc failed, try max size\n");
794                 str_info->decode_isize = calculate_max_size(dbufs->ibufs);
795                 str_info->decode_ibuf = kzalloc(
796                                 str_info->decode_isize, GFP_KERNEL);
797                 str_info->idecode_alloc = str_info->decode_isize;
798         }
799         if (!str_info->decode_ibuf) {
800                 pr_debug("sst:buff alloc failed, try min size\n");
801                 str_info->decode_isize = calculate_min_size(dbufs->ibufs);
802                 str_info->decode_ibuf = kzalloc(str_info->decode_isize,
803                                                 GFP_KERNEL);
804                 if (!str_info->decode_ibuf) {
805                         pr_err("sst: mem allocation failed\n");
806                         return -ENOMEM;
807                 }
808                 str_info->idecode_alloc = str_info->decode_isize;
809         }
810         str_info->decode_osize = cum_output_given;
811         if (str_info->decode_osize > sst_drv_ctx->mmap_len)
812                 str_info->decode_osize = sst_drv_ctx->mmap_len;
813         return 0;
814 }
815
816 /*This function is used to send the message to firmware to decode the data*/
817 static int sst_send_decode_mess(int str_id, struct stream_info *str_info,
818                                 struct snd_sst_decode_info *dec_info)
819 {
820         struct ipc_post *msg = NULL;
821         int retval = 0;
822
823         pr_debug("SST DBGsst_set_mute:called\n");
824
825         if (str_info->decode_ibuf_type == SST_BUF_RAR) {
826 #ifdef CONFIG_MRST_RAR_HANDLER
827                         dec_info->frames_in.addr[0].addr =
828                                 (unsigned long)str_info->decode_ibuf;
829                         dec_info->frames_in.addr[0].size =
830                                                         str_info->decode_isize;
831 #endif
832
833         } else {
834                 dec_info->frames_in.addr[0].addr = virt_to_phys((void *)
835                                         str_info->decode_ibuf);
836                 dec_info->frames_in.addr[0].size = str_info->decode_isize;
837         }
838
839
840         if (str_info->decode_obuf_type == SST_BUF_RAR) {
841 #ifdef CONFIG_MRST_RAR_HANDLER
842                 dec_info->frames_out.addr[0].addr =
843                                 (unsigned long)str_info->decode_obuf;
844                 dec_info->frames_out.addr[0].size = str_info->decode_osize;
845 #endif
846
847         } else {
848                 dec_info->frames_out.addr[0].addr = virt_to_phys((void *)
849                                                 str_info->decode_obuf) ;
850                 dec_info->frames_out.addr[0].size = str_info->decode_osize;
851         }
852
853         dec_info->frames_in.num_entries = 1;
854         dec_info->frames_out.num_entries = 1;
855         dec_info->frames_in.rsrvd = 0;
856         dec_info->frames_out.rsrvd = 0;
857         dec_info->input_bytes_consumed = 0;
858         dec_info->output_bytes_produced = 0;
859         if (sst_create_large_msg(&msg)) {
860                 pr_err("sst: message creation failed\n");
861                 return -ENOMEM;
862         }
863
864         sst_fill_header(&msg->header, IPC_IA_DECODE_FRAMES, 1, str_id);
865         msg->header.part.data = sizeof(u32) + sizeof(*dec_info);
866         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
867         memcpy(msg->mailbox_data + sizeof(u32), dec_info,
868                         sizeof(*dec_info));
869         spin_lock(&sst_drv_ctx->list_spin_lock);
870         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
871         spin_unlock(&sst_drv_ctx->list_spin_lock);
872         str_info->data_blk.condition = false;
873         str_info->data_blk.ret_code = 0;
874         str_info->data_blk.on = true;
875         str_info->data_blk.data = dec_info;
876         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
877         retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
878         return retval;
879 }
880
881 static int sst_prepare_input_buffers_rar(struct stream_info *str_info,
882                         struct snd_sst_dbufs *dbufs,
883                         int *input_index, int *in_copied,
884                         int *input_index_valid_size, int *new_entry_flag)
885 {
886         int retval = 0;
887 #ifdef CONFIG_MRST_RAR_HANDLER
888         int i;
889
890         if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
891                 struct RAR_buffer rar_buffers;
892                 __u32 info;
893                 retval = copy_from_user((void *) &info,
894                                 dbufs->ibufs->buff_entry[i].buffer,
895                                 sizeof(__u32));
896                 if (retval) {
897                         pr_err("sst:cpy from user fail\n");
898                         return -EAGAIN;
899                 }
900                 rar_buffers.info.type = dbufs->ibufs->type;
901                 rar_buffers.info.size = dbufs->ibufs->buff_entry[i].size;
902                 rar_buffers.info.handle =  info;
903                 pr_debug("rar in DnR(input buffer function)=0x%x size=0x%x",
904                                 rar_buffers.info.handle,
905                                 rar_buffers.info.size);
906                 retval =  sst_get_RAR(&rar_buffers, 1);
907                 if (retval) {
908                         pr_debug("SST ERR: RAR API failed\n");
909                         return retval;
910                 }
911                 str_info->decode_ibuf =
912                 (void *) ((unsigned long) rar_buffers.bus_address);
913                 pr_debug("RAR buf addr in DnR (input buffer function)0x%lu",
914                                  (unsigned long) str_info->decode_ibuf);
915                 pr_debug("rar in DnR decode funtion/output b_add rar =0x%lu",
916                                 (unsigned long) rar_buffers.bus_address);
917                 *input_index = i + 1;
918                 str_info->decode_isize = dbufs->ibufs->buff_entry[i].size;
919                 str_info->decode_ibuf_type = dbufs->ibufs->type;
920                 *in_copied = str_info->decode_isize;
921         }
922 #endif
923         return retval;
924 }
925 /*This function is used to prepare the kernel input buffers with contents
926 before sending for decode*/
927 static int sst_prepare_input_buffers(struct stream_info *str_info,
928                         struct snd_sst_dbufs *dbufs,
929                         int *input_index, int *in_copied,
930                         int *input_index_valid_size, int *new_entry_flag)
931 {
932         int i, cpy_size, retval = 0;
933
934         pr_debug("sst:input_index = %d, input entries = %d\n",
935                          *input_index, dbufs->ibufs->entries);
936         for (i = *input_index; i < dbufs->ibufs->entries; i++) {
937 #ifdef CONFIG_MRST_RAR_HANDLER
938                 retval = sst_prepare_input_buffers_rar(str_info,
939                         dbufs, input_index, in_copied,
940                                 input_index_valid_size, new_entry_flag);
941                 if (retval) {
942                         pr_err("sst: In prepare input buffers for RAR\n");
943                         return -EIO;
944                 }
945 #endif
946                 *input_index = i;
947                 if (*input_index_valid_size == 0)
948                         *input_index_valid_size =
949                                 dbufs->ibufs->buff_entry[i].size;
950                 pr_debug("sst:inout addr = %p, size = %d\n",
951                         dbufs->ibufs->buff_entry[i].buffer,
952                         *input_index_valid_size);
953                 pr_debug("sst:decode_isize = %d, in_copied %d\n",
954                         str_info->decode_isize, *in_copied);
955                 if (*input_index_valid_size <=
956                                         (str_info->decode_isize - *in_copied))
957                         cpy_size = *input_index_valid_size;
958                 else
959                         cpy_size = str_info->decode_isize - *in_copied;
960
961                 pr_debug("sst:cpy size = %d\n", cpy_size);
962                 if (!dbufs->ibufs->buff_entry[i].buffer) {
963                         pr_err("sst: i/p buffer is null\n");
964                         return -EINVAL;
965                 }
966                 pr_debug("sst:Try copy To %p, From %p, size %d\n",
967                                 str_info->decode_ibuf + *in_copied,
968                                 dbufs->ibufs->buff_entry[i].buffer, cpy_size);
969
970                 retval =
971                 copy_from_user((void *)(str_info->decode_ibuf + *in_copied),
972                                 (void *) dbufs->ibufs->buff_entry[i].buffer,
973                                 cpy_size);
974                 if (retval) {
975                         pr_err("sst: copy from user failed\n");
976                         return -EIO;
977                 }
978                 *in_copied += cpy_size;
979                 *input_index_valid_size -= cpy_size;
980                 pr_debug("sst:in buff size = %d, in_copied = %d\n",
981                         *input_index_valid_size, *in_copied);
982                 if (*input_index_valid_size != 0) {
983                         pr_debug("sst:more input buffers left\n");
984                         dbufs->ibufs->buff_entry[i].buffer += cpy_size;
985                         break;
986                 }
987                 if (*in_copied == str_info->decode_isize &&
988                         *input_index_valid_size == 0 &&
989                         (i+1) <= dbufs->ibufs->entries) {
990                         pr_debug("sst:all input buffers copied\n");
991                         *new_entry_flag = true;
992                         *input_index = i + 1;
993                         break;
994                 }
995         }
996         return retval;
997 }
998
999 /* This function is used to copy the decoded data from kernel buffers to
1000 the user output buffers with contents after decode*/
1001 static int sst_prepare_output_buffers(struct stream_info *str_info,
1002                         struct snd_sst_dbufs *dbufs,
1003                         int *output_index, int output_size,
1004                         int *out_copied)
1005
1006 {
1007         int i, cpy_size, retval = 0;
1008         pr_debug("sst:output_index = %d, output entries = %d\n",
1009                                 *output_index,
1010                                 dbufs->obufs->entries);
1011         for (i = *output_index; i < dbufs->obufs->entries; i++) {
1012                 *output_index = i;
1013                 pr_debug("sst:output addr = %p, size = %d\n",
1014                         dbufs->obufs->buff_entry[i].buffer,
1015                         dbufs->obufs->buff_entry[i].size);
1016                 pr_debug("sst:output_size = %d, out_copied = %d\n",
1017                                 output_size, *out_copied);
1018                 if (dbufs->obufs->buff_entry[i].size <
1019                                 (output_size - *out_copied))
1020                         cpy_size = dbufs->obufs->buff_entry[i].size;
1021                 else
1022                         cpy_size = output_size - *out_copied;
1023                 pr_debug("sst:cpy size = %d\n", cpy_size);
1024                 pr_debug("sst:Try copy To: %p, From %p, size %d\n",
1025                                 dbufs->obufs->buff_entry[i].buffer,
1026                                 sst_drv_ctx->mmap_mem + *out_copied,
1027                                 cpy_size);
1028                 retval = copy_to_user(dbufs->obufs->buff_entry[i].buffer,
1029                                         sst_drv_ctx->mmap_mem + *out_copied,
1030                                         cpy_size);
1031                 if (retval) {
1032                         pr_err("sst: copy to user failed\n");
1033                         return -EIO;
1034                 } else
1035                         pr_debug("sst:copy to user passed\n");
1036                 *out_copied += cpy_size;
1037                 dbufs->obufs->buff_entry[i].size -= cpy_size;
1038                 pr_debug("sst:o/p buff size %d, out_copied %d\n",
1039                         dbufs->obufs->buff_entry[i].size, *out_copied);
1040                 if (dbufs->obufs->buff_entry[i].size != 0) {
1041                         *output_index = i;
1042                         dbufs->obufs->buff_entry[i].buffer += cpy_size;
1043                         break;
1044                 } else if (*out_copied == output_size) {
1045                         *output_index = i + 1;
1046                         break;
1047                 }
1048         }
1049         return retval;
1050 }
1051
1052 /**
1053  * sst_decode - Send msg for decoding frames
1054  *
1055  * @str_id: ID of stream
1056  * @dbufs: param that holds the user input and output buffers and size
1057  *
1058  * This function is called to decode data from the firmware
1059  */
1060 int sst_decode(int str_id, struct snd_sst_dbufs *dbufs)
1061 {
1062         int retval = 0, i;
1063         unsigned long long total_input = 0 , total_output = 0;
1064         unsigned int cum_input_given = 0 , cum_output_given = 0;
1065         int copy_in_done = false, copy_out_done = false;
1066         int input_index = 0, output_index = 0;
1067         int input_index_valid_size = 0;
1068         int in_copied, out_copied;
1069         int new_entry_flag;
1070         u64 output_size;
1071         struct stream_info *str_info;
1072         struct snd_sst_decode_info dec_info;
1073         unsigned long long input_bytes, output_bytes;
1074
1075         sst_drv_ctx->scard_ops->power_down_pmic();
1076         pr_debug("sst: Powering_down_PMIC...\n");
1077
1078         retval = sst_validate_strid(str_id);
1079         if (retval)
1080                 return retval;
1081
1082         str_info = &sst_drv_ctx->streams[str_id];
1083         if (str_info->status != STREAM_INIT) {
1084                 pr_err("sst: invalid stream state = %d\n",
1085                                str_info->status);
1086                 return -EINVAL;
1087         }
1088
1089         str_info->prev = str_info->status;
1090         str_info->status = STREAM_DECODE;
1091
1092         for (i = 0; i < dbufs->ibufs->entries; i++)
1093                 cum_input_given += dbufs->ibufs->buff_entry[i].size;
1094         for (i = 0; i < dbufs->obufs->entries; i++)
1095                 cum_output_given += dbufs->obufs->buff_entry[i].size;
1096
1097         /* input and output buffer allocation */
1098         retval =  sst_allocate_decode_buf(str_info, dbufs,
1099                                 cum_input_given, cum_output_given);
1100         if (retval) {
1101                 pr_err("sst: mem allocation failed, abort!!!\n");
1102                 retval = -ENOMEM;
1103                 goto finish;
1104         }
1105
1106         str_info->decode_isize = str_info->idecode_alloc;
1107         str_info->decode_ibuf_type = dbufs->ibufs->type;
1108         str_info->decode_obuf_type = dbufs->obufs->type;
1109
1110         while ((copy_out_done == false) && (copy_in_done == false)) {
1111                 in_copied = 0;
1112                 new_entry_flag = false;
1113                 retval = sst_prepare_input_buffers(str_info,\
1114                         dbufs, &input_index, &in_copied,
1115                         &input_index_valid_size, &new_entry_flag);
1116                 if (retval) {
1117                         pr_err("sst: prepare in buffers failed\n");
1118                         goto finish;
1119                 }
1120
1121                 if (str_info->ops != STREAM_OPS_PLAYBACK_DRM)
1122                         str_info->decode_obuf = sst_drv_ctx->mmap_mem;
1123
1124 #ifdef CONFIG_MRST_RAR_HANDLER
1125                 else {
1126                         if (dbufs->obufs->type == SST_BUF_RAR) {
1127                                 struct RAR_buffer rar_buffers;
1128                                 __u32 info;
1129
1130                                 pr_debug("DRM");
1131                                 retval = copy_from_user((void *) &info,
1132                                                 dbufs->obufs->
1133                                                 buff_entry[output_index].buffer,
1134                                                 sizeof(__u32));
1135
1136                                 rar_buffers.info.size = dbufs->obufs->
1137                                         buff_entry[output_index].size;
1138                                 rar_buffers.info.handle =  info;
1139                                 retval =  sst_get_RAR(&rar_buffers, 1);
1140                                 if (retval)
1141                                         return retval;
1142
1143                                 str_info->decode_obuf = (void *)((unsigned long)
1144                                                 rar_buffers.bus_address);
1145                                 str_info->decode_osize = dbufs->obufs->
1146                                         buff_entry[output_index].size;
1147                                 str_info->decode_obuf_type = dbufs->obufs->type;
1148                                 pr_debug("sst:DRM handling\n");
1149                                 pr_debug("o/p_add=0x%lu Size=0x%x",
1150                                         (unsigned long) str_info->decode_obuf,
1151                                         str_info->decode_osize);
1152                         } else {
1153                                 str_info->decode_obuf = sst_drv_ctx->mmap_mem;
1154                                 str_info->decode_osize = dbufs->obufs->
1155                                         buff_entry[output_index].size;
1156
1157                         }
1158                 }
1159 #endif
1160                 if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
1161                         if (str_info->decode_isize > in_copied) {
1162                                 str_info->decode_isize = in_copied;
1163                                 pr_debug("sst:i/p size = %d\n",
1164                                                 str_info->decode_isize);
1165                         }
1166                 }
1167
1168
1169                 retval = sst_send_decode_mess(str_id, str_info, &dec_info);
1170                 if (retval || dec_info.input_bytes_consumed == 0) {
1171                         pr_err(
1172                                 "SST ERR: mess failed or no input consumed\n");
1173                         goto finish;
1174                 }
1175                 input_bytes = dec_info.input_bytes_consumed;
1176                 output_bytes = dec_info.output_bytes_produced;
1177
1178                 pr_debug("sst:in_copied=%d, con=%lld, prod=%lld\n",
1179                         in_copied, input_bytes, output_bytes);
1180                 if (dbufs->obufs->type == SST_BUF_RAR) {
1181                         output_index += 1;
1182                         if (output_index == dbufs->obufs->entries) {
1183                                 copy_in_done = true;
1184                                 pr_debug("sst:all i/p cpy done\n");
1185                         }
1186                         total_output += output_bytes;
1187                 } else {
1188                         out_copied = 0;
1189                         output_size = output_bytes;
1190                         retval = sst_prepare_output_buffers(str_info, dbufs,
1191                                 &output_index, output_size, &out_copied);
1192                         if (retval) {
1193                                 pr_err("sst:prep out buff fail\n");
1194                                 goto finish;
1195                         }
1196                         if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
1197                                 if (in_copied != input_bytes) {
1198                                         int bytes_left = in_copied -
1199                                                                 input_bytes;
1200                                         pr_debug("sst:bytes %d\n",
1201                                                         bytes_left);
1202                                         if (new_entry_flag == true)
1203                                                 input_index--;
1204                                         while (bytes_left) {
1205                                                 struct snd_sst_buffs *ibufs;
1206                                                 struct snd_sst_buff_entry
1207                                                                 *buff_entry;
1208                                                 unsigned int size_sent;
1209
1210                                                 ibufs = dbufs->ibufs;
1211                                                 buff_entry =
1212                                                 &ibufs->buff_entry[input_index];
1213                                                 size_sent = buff_entry->size -\
1214                                                         input_index_valid_size;
1215                                                 if (bytes_left == size_sent) {
1216                                                                 bytes_left = 0;
1217                                                 } else if (bytes_left <
1218                                                                 size_sent) {
1219                                                         buff_entry->buffer +=
1220                                                          (size_sent -
1221                                                                 bytes_left);
1222                                                         buff_entry->size -=
1223                                                          (size_sent -
1224                                                                 bytes_left);
1225                                                         bytes_left = 0;
1226                                                 } else {
1227                                                         bytes_left -= size_sent;
1228                                                         input_index--;
1229                                                         input_index_valid_size =
1230                                                                         0;
1231                                                 }
1232                                         }
1233
1234                                 }
1235                         }
1236
1237                         total_output += out_copied;
1238                         if (str_info->decode_osize != out_copied) {
1239                                 str_info->decode_osize -= out_copied;
1240                                 pr_debug("sst:output size modified = %d\n",
1241                                                 str_info->decode_osize);
1242                         }
1243                 }
1244                 total_input += input_bytes;
1245
1246                 if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
1247                         if (total_input == cum_input_given)
1248                                 copy_in_done = true;
1249                         copy_out_done = true;
1250
1251                 } else {
1252                         if (total_output == cum_output_given) {
1253                                 copy_out_done = true;
1254                                 pr_debug("sst:all o/p cpy done\n");
1255                         }
1256
1257                         if (total_input == cum_input_given) {
1258                                 copy_in_done = true;
1259                                 pr_debug("sst:all i/p cpy done\n");
1260                         }
1261                 }
1262
1263                 pr_debug("sst:copy_out = %d, copy_in = %d\n",
1264                                 copy_out_done, copy_in_done);
1265         }
1266
1267 finish:
1268         dbufs->input_bytes_consumed = total_input;
1269         dbufs->output_bytes_produced = total_output;
1270         str_info->status = str_info->prev;
1271         str_info->prev = STREAM_DECODE;
1272         str_info->decode_ibuf = NULL;
1273         kfree(str_info->decode_ibuf);
1274         return retval;
1275 }