]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/intel_sst/intel_sst_app_interface.c
Staging: sst: user pointers in intel_sst_mmap_play_capture()
[mv-sheeva.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
1 /*
2  *  intel_sst_interface.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  *  Jeeja KP <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  *  This driver exposes the audio engine functionalities to the ALSA
26  *      and middleware.
27  *  Upper layer interfaces (MAD driver, MMF) to SST driver
28  */
29
30 #include <linux/pci.h>
31 #include <linux/fs.h>
32 #include <linux/uio.h>
33 #include <linux/aio.h>
34 #include <linux/uaccess.h>
35 #include <linux/firmware.h>
36 #include <linux/ioctl.h>
37 #include <linux/smp_lock.h>
38 #ifdef CONFIG_MRST_RAR_HANDLER
39 #include <linux/rar_register.h>
40 #include "../../../drivers/staging/memrar/memrar.h"
41 #endif
42 #include "intel_sst.h"
43 #include "intel_sst_ioctl.h"
44 #include "intel_sst_fw_ipc.h"
45 #include "intel_sst_common.h"
46
47 #define AM_MODULE 1
48 #define STREAM_MODULE 0
49
50
51 /**
52 * intel_sst_check_device - checks SST device
53 *
54 * This utility function checks the state of SST device and downlaods FW if
55 * not done, or resumes the device if suspended
56 */
57
58 static int intel_sst_check_device(void)
59 {
60         int retval = 0;
61         if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
62                 pr_warn("sst: Sound card not availble\n ");
63                 return -EIO;
64         }
65         if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
66                 pr_debug("sst: Resuming from Suspended state\n");
67                 retval = intel_sst_resume(sst_drv_ctx->pci);
68                 if (retval) {
69                         pr_debug("sst: Resume Failed= %#x,abort\n", retval);
70                         return retval;
71                 }
72         }
73
74         if (sst_drv_ctx->sst_state == SST_UN_INIT) {
75                 /* FW is not downloaded */
76                 retval = sst_download_fw();
77                 if (retval)
78                         return -ENODEV;
79                 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
80                         retval = sst_drv_ctx->rx_time_slot_status;
81                         if (retval != RX_TIMESLOT_UNINIT
82                                         && sst_drv_ctx->pmic_vendor != SND_NC)
83                                 sst_enable_rx_timeslot(retval);
84                 }
85         }
86         return 0;
87 }
88
89 /**
90  * intel_sst_open - opens a handle to driver
91  *
92  * @i_node:     inode structure
93  * @file_ptr:pointer to file
94  *
95  * This function is called by OS when a user space component
96  * tries to get a driver handle. Only one handle at a time
97  * will be allowed
98  */
99 int intel_sst_open(struct inode *i_node, struct file *file_ptr)
100 {
101         int retval = intel_sst_check_device();
102         if (retval)
103                 return retval;
104
105         mutex_lock(&sst_drv_ctx->stream_lock);
106         if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
107                 struct ioctl_pvt_data *data =
108                         kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
109                 if (!data) {
110                         mutex_unlock(&sst_drv_ctx->stream_lock);
111                         return -ENOMEM;
112                 }
113
114                 sst_drv_ctx->encoded_cnt++;
115                 mutex_unlock(&sst_drv_ctx->stream_lock);
116                 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
117                 data->str_id = 0;
118                 file_ptr->private_data = (void *)data;
119                 pr_debug("sst: pvt_id handle = %d!\n", data->pvt_id);
120         } else {
121                 retval = -EUSERS;
122                 mutex_unlock(&sst_drv_ctx->stream_lock);
123         }
124         return retval;
125 }
126
127 /**
128  * intel_sst_open_cntrl - opens a handle to driver
129  *
130  * @i_node:     inode structure
131  * @file_ptr:pointer to file
132  *
133  * This function is called by OS when a user space component
134  * tries to get a driver handle to /dev/intel_sst_control.
135  * Only one handle at a time will be allowed
136  * This is for control operations only
137  */
138 int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
139 {
140         int retval = intel_sst_check_device();
141         if (retval)
142                 return retval;
143
144         /* audio manager open */
145         mutex_lock(&sst_drv_ctx->stream_lock);
146         if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
147                 sst_drv_ctx->am_cnt++;
148                 pr_debug("sst: AM handle opened...\n");
149                 file_ptr->private_data = NULL;
150         } else
151                 retval = -EACCES;
152
153         mutex_unlock(&sst_drv_ctx->stream_lock);
154         return retval;
155 }
156
157 /**
158  * intel_sst_release - releases a handle to driver
159  *
160  * @i_node:     inode structure
161  * @file_ptr:   pointer to file
162  *
163  * This function is called by OS when a user space component
164  * tries to release a driver handle.
165  */
166 int intel_sst_release(struct inode *i_node, struct file *file_ptr)
167 {
168         struct ioctl_pvt_data *data = file_ptr->private_data;
169
170         pr_debug("sst: Release called, closing app handle\n");
171         mutex_lock(&sst_drv_ctx->stream_lock);
172         sst_drv_ctx->encoded_cnt--;
173         sst_drv_ctx->stream_cnt--;
174         mutex_unlock(&sst_drv_ctx->stream_lock);
175         free_stream_context(data->str_id);
176         kfree(data);
177         return 0;
178 }
179
180 int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
181 {
182         /* audio manager close */
183         mutex_lock(&sst_drv_ctx->stream_lock);
184         sst_drv_ctx->am_cnt--;
185         mutex_unlock(&sst_drv_ctx->stream_lock);
186         pr_debug("sst: AM handle closed\n");
187         return 0;
188 }
189
190 /**
191 * intel_sst_mmap - mmaps a kernel buffer to user space for copying data
192 *
193 * @vma:         vm area structure instance
194 * @file_ptr:    pointer to file
195 *
196 * This function is called by OS when a user space component
197 * tries to get mmap memory from driver
198 */
199 int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
200 {
201         int retval, length;
202         struct ioctl_pvt_data *data =
203                 (struct ioctl_pvt_data *)file_ptr->private_data;
204         int str_id = data->str_id;
205         void *mem_area;
206
207         retval = sst_validate_strid(str_id);
208         if (retval)
209                 return -EINVAL;
210
211         length = vma->vm_end - vma->vm_start;
212         pr_debug("sst: called for stream %d length 0x%x\n", str_id, length);
213
214         if (length > sst_drv_ctx->mmap_len)
215                 return -ENOMEM;
216         if (!sst_drv_ctx->mmap_mem)
217                 return -EIO;
218
219         /* round it up to the page bondary  */
220         /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
221                                 + PAGE_SIZE - 1) & PAGE_MASK);*/
222         mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
223
224         /* map the whole physically contiguous area in one piece  */
225         retval = remap_pfn_range(vma,
226                         vma->vm_start,
227                         virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
228                         length,
229                         vma->vm_page_prot);
230         if (retval)
231                 sst_drv_ctx->streams[str_id].mmapped = false;
232         else
233                 sst_drv_ctx->streams[str_id].mmapped = true;
234
235         pr_debug("sst: mmap ret 0x%x\n", retval);
236         return retval;
237 }
238
239 /* sets mmap data buffers to play/capture*/
240 static int intel_sst_mmap_play_capture(u32 str_id,
241                 struct snd_sst_mmap_buffs *mmap_buf)
242 {
243         struct sst_stream_bufs *bufs;
244         int retval, i;
245         struct stream_info *stream;
246         struct snd_sst_mmap_buff_entry *buf_entry;
247         struct snd_sst_mmap_buff_entry *tmp_buf;
248
249         pr_debug("sst:called for str_id %d\n", str_id);
250         retval = sst_validate_strid(str_id);
251         if (retval)
252                 return -EINVAL;
253
254         stream = &sst_drv_ctx->streams[str_id];
255         if (stream->mmapped != true)
256                 return -EIO;
257
258         if (stream->status == STREAM_UN_INIT ||
259                 stream->status == STREAM_DECODE) {
260                 return -EBADRQC;
261         }
262         stream->curr_bytes = 0;
263         stream->cumm_bytes = 0;
264
265         tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
266         if (!tmp_buf)
267                 return -ENOMEM;
268         if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
269                         mmap_buf->entries * sizeof(*tmp_buf))) {
270                 retval = -EFAULT;
271                 goto out_free;
272         }
273
274         pr_debug("sst:new buffers count %d status %d\n",
275                         mmap_buf->entries, stream->status);
276         buf_entry = tmp_buf;
277         for (i = 0; i < mmap_buf->entries; i++) {
278                 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
279                 if (!bufs) {
280                         retval = -ENOMEM;
281                         goto out_free;
282                 }
283                 bufs->size = buf_entry->size;
284                 bufs->offset = buf_entry->offset;
285                 bufs->addr = sst_drv_ctx->mmap_mem;
286                 bufs->in_use = false;
287                 buf_entry++;
288                 /* locking here */
289                 mutex_lock(&stream->lock);
290                 list_add_tail(&bufs->node, &stream->bufs);
291                 mutex_unlock(&stream->lock);
292         }
293
294         mutex_lock(&stream->lock);
295         stream->data_blk.condition = false;
296         stream->data_blk.ret_code = 0;
297         if (stream->status == STREAM_INIT &&
298                         stream->prev != STREAM_UN_INIT &&
299                         stream->need_draining != true) {
300                 stream->prev = stream->status;
301                 stream->status = STREAM_RUNNING;
302                 if (stream->ops == STREAM_OPS_PLAYBACK) {
303                         if (sst_play_frame(str_id) < 0) {
304                                 pr_warn("sst: play frames fail\n");
305                                 mutex_unlock(&stream->lock);
306                                 retval = -EIO;
307                                 goto out_free;
308                         }
309                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
310                         if (sst_capture_frame(str_id) < 0) {
311                                 pr_warn("sst: capture frame fail\n");
312                                 mutex_unlock(&stream->lock);
313                                 retval = -EIO;
314                                 goto out_free;
315                         }
316                 }
317         }
318         mutex_unlock(&stream->lock);
319         /* Block the call for reply */
320         if (!list_empty(&stream->bufs)) {
321                 stream->data_blk.on = true;
322                 retval = sst_wait_interruptible(sst_drv_ctx,
323                                         &stream->data_blk);
324         }
325
326         if (retval >= 0)
327                 retval = stream->cumm_bytes;
328         pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval);
329
330 out_free:
331         kfree(tmp_buf);
332         return retval;
333 }
334
335 /*sets user data buffers to play/capture*/
336 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
337 {
338         int retval;
339
340         stream->data_blk.ret_code = 0;
341         stream->data_blk.on = true;
342         stream->data_blk.condition = false;
343
344         mutex_lock(&stream->lock);
345         if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
346                 /* stream is started */
347                 stream->prev = stream->status;
348                 stream->status = STREAM_RUNNING;
349         }
350
351         if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
352                 /* stream is not started yet */
353                 pr_debug("sst: Stream isn't in started state %d, prev %d\n",
354                         stream->status, stream->prev);
355         } else if ((stream->status == STREAM_RUNNING ||
356                         stream->status == STREAM_PAUSED) &&
357                         stream->need_draining != true) {
358                 /* stream is started */
359                 if (stream->ops == STREAM_OPS_PLAYBACK ||
360                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
361                         if (sst_play_frame(str_id) < 0) {
362                                 pr_warn("sst: play frames failed\n");
363                                 mutex_unlock(&stream->lock);
364                                 return -EIO;
365                         }
366                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
367                         if (sst_capture_frame(str_id) < 0) {
368                                 pr_warn("sst: capture frames failed\n ");
369                                 mutex_unlock(&stream->lock);
370                                 return -EIO;
371                         }
372                 }
373         } else {
374                 mutex_unlock(&stream->lock);
375                 return -EIO;
376         }
377         mutex_unlock(&stream->lock);
378         /* Block the call for reply */
379
380         retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
381         if (retval) {
382                 stream->status = STREAM_INIT;
383                 pr_debug("sst: wait returned error...\n");
384         }
385         return retval;
386 }
387
388 /* fills kernel list with buffer addresses for SST DSP driver to process*/
389 static int snd_sst_fill_kernel_list(struct stream_info *stream,
390                         const struct iovec *iovec, unsigned long nr_segs,
391                         struct list_head *copy_to_list)
392 {
393         struct sst_stream_bufs *stream_bufs;
394         unsigned long index, mmap_len;
395         unsigned char *bufp;
396         unsigned long size, copied_size;
397         int retval = 0, add_to_list = 0;
398         static int sent_offset;
399         static unsigned long sent_index;
400
401         stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
402         if (!stream_bufs)
403                 return -ENOMEM;
404         stream_bufs->addr = sst_drv_ctx->mmap_mem;
405 #ifdef CONFIG_MRST_RAR_HANDLER
406         if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
407                 for (index = stream->sg_index; index < nr_segs; index++) {
408                         __u32 rar_handle;
409                         struct sst_stream_bufs *stream_bufs =
410                                 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
411
412                         stream->sg_index = index;
413                         if (!stream_bufs)
414                                 return -ENOMEM;
415                         if (copy_from_user((void *) &rar_handle,
416                                         iovec[index].iov_base,
417                                         sizeof(__u32)))
418                                 return -EFAULT;
419                         stream_bufs->addr = (char *)rar_handle;
420                         stream_bufs->in_use = false;
421                         stream_bufs->size = iovec[0].iov_len;
422                         /* locking here */
423                         mutex_lock(&stream->lock);
424                         list_add_tail(&stream_bufs->node, &stream->bufs);
425                         mutex_unlock(&stream->lock);
426                 }
427                 stream->sg_index = index;
428                 return retval;
429         }
430 #endif
431         mmap_len = sst_drv_ctx->mmap_len;
432         stream_bufs->addr = sst_drv_ctx->mmap_mem;
433         bufp = stream->cur_ptr;
434
435         copied_size = 0;
436
437         if (!stream->sg_index)
438                 sent_index = sent_offset = 0;
439
440         for (index = stream->sg_index; index < nr_segs; index++) {
441                 stream->sg_index = index;
442                 if (!stream->cur_ptr)
443                         bufp = iovec[index].iov_base;
444
445                 size = ((unsigned long)iovec[index].iov_base
446                         + iovec[index].iov_len) - (unsigned long) bufp;
447
448                 if ((copied_size + size) > mmap_len)
449                         size = mmap_len - copied_size;
450
451
452                 if (stream->ops == STREAM_OPS_PLAYBACK) {
453                         if (copy_from_user((void *)
454                                         (stream_bufs->addr + copied_size),
455                                         bufp, size)) {
456                                 /* Clean up the list and return error code */
457                                 retval = -EFAULT;
458                                 break;
459                         }
460                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
461                         struct snd_sst_user_cap_list *entry =
462                                 kzalloc(sizeof(*entry), GFP_KERNEL);
463
464                         if (!entry) {
465                                 kfree(stream_bufs);
466                                 return -ENOMEM;
467                         }
468                         entry->iov_index = index;
469                         entry->iov_offset = (unsigned long) bufp -
470                                         (unsigned long)iovec[index].iov_base;
471                         entry->offset = copied_size;
472                         entry->size = size;
473                         list_add_tail(&entry->node, copy_to_list);
474                 }
475
476                 stream->cur_ptr = bufp + size;
477
478                 if (((unsigned long)iovec[index].iov_base
479                                 + iovec[index].iov_len) <
480                                 ((unsigned long)iovec[index].iov_base)) {
481                         pr_debug("sst: Buffer overflows");
482                         kfree(stream_bufs);
483                         return -EINVAL;
484                 }
485
486                 if (((unsigned long)iovec[index].iov_base
487                                         + iovec[index].iov_len) ==
488                                         (unsigned long)stream->cur_ptr) {
489                         stream->cur_ptr = NULL;
490                         stream->sg_index++;
491                 }
492
493                 copied_size += size;
494                 pr_debug("sst: copied_size - %lx\n", copied_size);
495                 if ((copied_size >= mmap_len) ||
496                                 (stream->sg_index == nr_segs)) {
497                         add_to_list = 1;
498                 }
499
500                 if (add_to_list) {
501                         stream_bufs->in_use = false;
502                         stream_bufs->size = copied_size;
503                         /* locking here */
504                         mutex_lock(&stream->lock);
505                         list_add_tail(&stream_bufs->node, &stream->bufs);
506                         mutex_unlock(&stream->lock);
507                         break;
508                 }
509         }
510         return retval;
511 }
512
513 /* This function copies the captured data returned from SST DSP engine
514  * to the user buffers*/
515 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
516                         const struct iovec *iovec,
517                         struct list_head *copy_to_list)
518 {
519         struct snd_sst_user_cap_list *entry, *_entry;
520         struct sst_stream_bufs *kbufs = NULL, *_kbufs;
521         int retval = 0;
522
523         /* copy sent buffers */
524         pr_debug("sst: capture stream copying to user now...\n");
525         list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
526                 if (kbufs->in_use == true) {
527                         /* copy to user */
528                         list_for_each_entry_safe(entry, _entry,
529                                                 copy_to_list, node) {
530                                 if (copy_to_user((void *)
531                                              iovec[entry->iov_index].iov_base +
532                                              entry->iov_offset,
533                                              kbufs->addr + entry->offset,
534                                              entry->size)) {
535                                         /* Clean up the list and return error */
536                                         retval = -EFAULT;
537                                         break;
538                                 }
539                                 list_del(&entry->node);
540                                 kfree(entry);
541                         }
542                 }
543         }
544         pr_debug("sst: end of cap copy\n");
545         return retval;
546 }
547
548 /*
549  * snd_sst_userbufs_play_cap - constructs the list from user buffers
550  *
551  * @iovec:pointer to iovec structure
552  * @nr_segs:number entries in the iovec structure
553  * @str_id:stream id
554  * @stream:pointer to stream_info structure
555  *
556  * This function will traverse the user list and copy the data to the kernel
557  * space buffers.
558  */
559 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
560                         unsigned long nr_segs, unsigned int str_id,
561                         struct stream_info *stream)
562 {
563         int retval;
564         LIST_HEAD(copy_to_list);
565
566
567         retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
568                        &copy_to_list);
569
570         retval = intel_sst_play_capture(stream, str_id);
571         if (retval < 0)
572                 return retval;
573
574         if (stream->ops == STREAM_OPS_CAPTURE) {
575                 retval = snd_sst_copy_userbuf_capture(stream, iovec,
576                                 &copy_to_list);
577         }
578         return retval;
579 }
580
581 /* This function is common function across read/write
582   for user buffers called from system calls*/
583 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
584                                         size_t count)
585 {
586         int retval;
587         struct stream_info *stream;
588         struct iovec iovec;
589         unsigned long nr_segs;
590
591         retval = sst_validate_strid(str_id);
592         if (retval)
593                 return -EINVAL;
594         stream = &sst_drv_ctx->streams[str_id];
595         if (stream->mmapped == true) {
596                 pr_warn("sst: user write and stream is mapped");
597                 return -EIO;
598         }
599         if (!count)
600                 return -EINVAL;
601         stream->curr_bytes = 0;
602         stream->cumm_bytes = 0;
603         /* copy user buf details */
604         pr_debug("sst: new buffers %p, copy size %d, status %d\n" ,
605                         buf, (int) count, (int) stream->status);
606
607         stream->buf_type = SST_BUF_USER_STATIC;
608         iovec.iov_base = (void *)buf;
609         iovec.iov_len  = count;
610         nr_segs = 1;
611
612         do {
613                 retval = snd_sst_userbufs_play_cap(
614                                 &iovec, nr_segs, str_id, stream);
615                 if (retval < 0)
616                         break;
617
618         } while (stream->sg_index < nr_segs);
619
620         stream->sg_index = 0;
621         stream->cur_ptr = NULL;
622         if (retval >= 0)
623                 retval = stream->cumm_bytes;
624         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
625         return retval;
626 }
627
628 /***
629  * intel_sst_write - This function is called when user tries to play out data
630  *
631  * @file_ptr:pointer to file
632  * @buf:user buffer to be played out
633  * @count:size of tthe buffer
634  * @offset:offset to start from
635  *
636  * writes the encoded data into DSP
637  */
638 int intel_sst_write(struct file *file_ptr, const char __user *buf,
639                         size_t count, loff_t *offset)
640 {
641         struct ioctl_pvt_data *data = file_ptr->private_data;
642         int str_id = data->str_id;
643         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
644
645         pr_debug("sst: called for %d\n", str_id);
646         if (stream->status == STREAM_UN_INIT ||
647                 stream->status == STREAM_DECODE) {
648                 return -EBADRQC;
649         }
650         return intel_sst_read_write(str_id, (char __user *)buf, count);
651 }
652
653 /*
654  * intel_sst_aio_write - write buffers
655  *
656  * @kiocb:pointer to a structure containing file pointer
657  * @iov:list of user buffer to be played out
658  * @nr_segs:number of entries
659  * @offset:offset to start from
660  *
661  * This function is called when user tries to play out multiple data buffers
662  */
663 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
664                         unsigned long nr_segs, loff_t  offset)
665 {
666         int retval;
667         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
668         int str_id = data->str_id;
669         struct stream_info *stream;
670
671         pr_debug("sst: entry - %ld\n", nr_segs);
672
673         if (is_sync_kiocb(kiocb) == false)
674                 return -EINVAL;
675
676         pr_debug("sst: called for str_id %d\n", str_id);
677         retval = sst_validate_strid(str_id);
678         if (retval)
679                 return -EINVAL;
680         stream = &sst_drv_ctx->streams[str_id];
681         if (stream->mmapped == true)
682                 return -EIO;
683         if (stream->status == STREAM_UN_INIT ||
684                 stream->status == STREAM_DECODE) {
685                 return -EBADRQC;
686         }
687         stream->curr_bytes = 0;
688         stream->cumm_bytes = 0;
689         pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
690                         nr_segs, (int) offset, (int) stream->status);
691         stream->buf_type = SST_BUF_USER_STATIC;
692         do {
693                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
694                                                 str_id, stream);
695                 if (retval < 0)
696                         break;
697
698         } while (stream->sg_index < nr_segs);
699
700         stream->sg_index = 0;
701         stream->cur_ptr = NULL;
702         if (retval >= 0)
703                 retval = stream->cumm_bytes;
704         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
705         return retval;
706 }
707
708 /*
709  * intel_sst_read - read the encoded data
710  *
711  * @file_ptr: pointer to file
712  * @buf: user buffer to be filled with captured data
713  * @count: size of tthe buffer
714  * @offset: offset to start from
715  *
716  * This function is called when user tries to capture data
717  */
718 int intel_sst_read(struct file *file_ptr, char __user *buf,
719                         size_t count, loff_t *offset)
720 {
721         struct ioctl_pvt_data *data = file_ptr->private_data;
722         int str_id = data->str_id;
723         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
724
725         pr_debug("sst: called for %d\n", str_id);
726         if (stream->status == STREAM_UN_INIT ||
727                         stream->status == STREAM_DECODE)
728                 return -EBADRQC;
729         return intel_sst_read_write(str_id, buf, count);
730 }
731
732 /*
733  * intel_sst_aio_read - aio read
734  *
735  * @kiocb: pointer to a structure containing file pointer
736  * @iov: list of user buffer to be filled with captured
737  * @nr_segs: number of entries
738  * @offset: offset to start from
739  *
740  * This function is called when user tries to capture out multiple data buffers
741  */
742 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
743                          unsigned long nr_segs, loff_t offset)
744 {
745         int retval;
746         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
747         int str_id = data->str_id;
748         struct stream_info *stream;
749
750         pr_debug("sst: entry - %ld\n", nr_segs);
751
752         if (is_sync_kiocb(kiocb) == false) {
753                 pr_debug("sst: aio_read from user space is not allowed\n");
754                 return -EINVAL;
755         }
756
757         pr_debug("sst: called for str_id %d\n", str_id);
758         retval = sst_validate_strid(str_id);
759         if (retval)
760                 return -EINVAL;
761         stream = &sst_drv_ctx->streams[str_id];
762         if (stream->mmapped == true)
763                 return -EIO;
764         if (stream->status == STREAM_UN_INIT ||
765                         stream->status == STREAM_DECODE)
766                 return -EBADRQC;
767         stream->curr_bytes = 0;
768         stream->cumm_bytes = 0;
769
770         pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
771                         nr_segs, (int) offset, (int) stream->status);
772         stream->buf_type = SST_BUF_USER_STATIC;
773         do {
774                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
775                                                 str_id, stream);
776                 if (retval < 0)
777                         break;
778
779         } while (stream->sg_index < nr_segs);
780
781         stream->sg_index = 0;
782         stream->cur_ptr = NULL;
783         if (retval >= 0)
784                 retval = stream->cumm_bytes;
785         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
786         return retval;
787 }
788
789 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
790 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
791 {
792         pr_debug("sst: codec params:result =%d\n",
793                                 get_prm->codec_params.result);
794         pr_debug("sst: codec params:stream = %d\n",
795                                 get_prm->codec_params.stream_id);
796         pr_debug("sst: codec params:codec = %d\n",
797                                 get_prm->codec_params.codec);
798         pr_debug("sst: codec params:ops = %d\n",
799                                 get_prm->codec_params.ops);
800         pr_debug("sst: codec params:stream_type= %d\n",
801                                 get_prm->codec_params.stream_type);
802         pr_debug("sst: pcmparams:sfreq= %d\n",
803                                 get_prm->pcm_params.sfreq);
804         pr_debug("sst: pcmparams:num_chan= %d\n",
805                                 get_prm->pcm_params.num_chan);
806         pr_debug("sst: pcmparams:pcm_wd_sz= %d\n",
807                                 get_prm->pcm_params.pcm_wd_sz);
808         return;
809 }
810
811 /**
812  * intel_sst_ioctl - recieves the device ioctl's
813  * @file_ptr:pointer to file
814  * @cmd:Ioctl cmd
815  * @arg:data
816  *
817  * This function is called by OS when a user space component
818  * sends an Ioctl to SST driver
819  */
820 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
821 {
822         int retval = 0;
823         struct ioctl_pvt_data *data = NULL;
824         int str_id = 0, minor = 0;
825
826         data = file_ptr->private_data;
827         if (data) {
828                 minor = 0;
829                 str_id = data->str_id;
830         } else
831                 minor = 1;
832
833         if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
834                 return -EBUSY;
835
836         switch (_IOC_NR(cmd)) {
837         case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
838                 pr_debug("sst: IOCTL_PAUSE recieved for %d!\n", str_id);
839                 if (minor != STREAM_MODULE) {
840                         retval = -EBADRQC;
841                         break;
842                 }
843                 retval = sst_pause_stream(str_id);
844                 break;
845
846         case _IOC_NR(SNDRV_SST_STREAM_RESUME):
847                 pr_debug("sst: SNDRV_SST_IOCTL_RESUME recieved!\n");
848                 if (minor != STREAM_MODULE) {
849                         retval = -EBADRQC;
850                         break;
851                 }
852                 retval = sst_resume_stream(str_id);
853                 break;
854
855         case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
856                 struct snd_sst_params str_param;
857
858                 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n");
859                 if (minor != STREAM_MODULE) {
860                         retval = -EBADRQC;
861                         break;
862                 }
863
864                 if (copy_from_user(&str_param, (void __user *)arg,
865                                 sizeof(str_param))) {
866                         retval = -EFAULT;
867                         break;
868                 }
869
870                 if (!str_id) {
871
872                         retval = sst_get_stream(&str_param);
873                         if (retval > 0) {
874                                 struct stream_info *str_info;
875                                 char __user *dest;
876
877                                 sst_drv_ctx->stream_cnt++;
878                                 data->str_id = retval;
879                                 str_info = &sst_drv_ctx->streams[retval];
880                                 str_info->src = SST_DRV;
881                                 dest = (char *)arg + offsetof(struct snd_sst_params, stream_id);
882                                 retval = copy_to_user(dest, &retval, sizeof(__u32));
883                                 if (retval)
884                                         retval = -EFAULT;
885                         } else {
886                                 if (retval == -SST_ERR_INVALID_PARAMS)
887                                         retval = -EINVAL;
888                         }
889                 } else {
890                         pr_debug("sst: SET_STREAM_PARAMS recieved!\n");
891                         /* allocated set params only */
892                         retval = sst_set_stream_param(str_id, &str_param);
893                         /* Block the call for reply */
894                         if (!retval) {
895                                 int sfreq = 0, word_size = 0, num_channel = 0;
896                                 sfreq = str_param.sparams.uc.pcm_params.sfreq;
897                                 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
898                                 num_channel = str_param.sparams.uc.pcm_params.num_chan;
899                                 if (str_param.ops == STREAM_OPS_CAPTURE) {
900                                         sst_drv_ctx->scard_ops->\
901                                         set_pcm_audio_params(sfreq,
902                                                 word_size, num_channel);
903                                 }
904                         }
905                 }
906                 break;
907         }
908         case _IOC_NR(SNDRV_SST_SET_VOL): {
909                 struct snd_sst_vol set_vol;
910
911                 if (copy_from_user(&set_vol, (void __user *)arg,
912                                 sizeof(set_vol))) {
913                         pr_debug("sst: copy failed\n");
914                         retval = -EFAULT;
915                         break;
916                 }
917                 pr_debug("sst: SET_VOLUME recieved for %d!\n",
918                                 set_vol.stream_id);
919                 if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
920                         pr_debug("sst: invalid operation!\n");
921                         retval = -EPERM;
922                         break;
923                 }
924                 retval = sst_set_vol(&set_vol);
925                 break;
926         }
927         case _IOC_NR(SNDRV_SST_GET_VOL): {
928                 struct snd_sst_vol get_vol;
929
930                 if (copy_from_user(&get_vol, (void __user *)arg,
931                                 sizeof(get_vol))) {
932                         retval = -EFAULT;
933                         break;
934                 }
935                 pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n",
936                                 get_vol.stream_id);
937                 if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
938                         pr_debug("sst: invalid operation!\n");
939                         retval = -EPERM;
940                         break;
941                 }
942                 retval = sst_get_vol(&get_vol);
943                 if (retval) {
944                         retval = -EIO;
945                         break;
946                 }
947                 pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
948                                 get_vol.stream_id, get_vol.volume,
949                                 get_vol.ramp_duration, get_vol.ramp_type);
950                 if (copy_to_user((struct snd_sst_vol *)arg,
951                                 &get_vol, sizeof(get_vol))) {
952                         retval = -EFAULT;
953                         break;
954                 }
955                 /*sst_print_get_vol_info(str_id, &get_vol);*/
956                 break;
957         }
958
959         case _IOC_NR(SNDRV_SST_MUTE): {
960                 struct snd_sst_mute set_mute;
961
962                 if (copy_from_user(&set_mute, (void __user *)arg,
963                                 sizeof(set_mute))) {
964                         retval = -EFAULT;
965                         break;
966                 }
967                 pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n",
968                         set_mute.stream_id);
969                 if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
970                         retval = -EPERM;
971                         break;
972                 }
973                 retval = sst_set_mute(&set_mute);
974                 break;
975         }
976         case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
977                 struct snd_sst_get_stream_params get_params;
978
979                 pr_debug("sst: IOCTL_GET_PARAMS recieved!\n");
980                 if (minor != 0) {
981                         retval = -EBADRQC;
982                         break;
983                 }
984
985                 retval = sst_get_stream_params(str_id, &get_params);
986                 if (retval) {
987                         retval = -EIO;
988                         break;
989                 }
990                 if (copy_to_user((struct snd_sst_get_stream_params *)arg,
991                                         &get_params, sizeof(get_params))) {
992                         retval = -EFAULT;
993                         break;
994                 }
995                 sst_print_stream_params(&get_params);
996                 break;
997         }
998
999         case _IOC_NR(SNDRV_SST_MMAP_PLAY):
1000         case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
1001                 struct snd_sst_mmap_buffs mmap_buf;
1002
1003                 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n");
1004                 if (minor != STREAM_MODULE) {
1005                         retval = -EBADRQC;
1006                         break;
1007                 }
1008                 if (copy_from_user(&mmap_buf, (void __user *)arg,
1009                                 sizeof(mmap_buf))) {
1010                         retval = -EFAULT;
1011                         break;
1012                 }
1013                 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
1014                 break;
1015         }
1016         case _IOC_NR(SNDRV_SST_STREAM_DROP):
1017                 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n");
1018                 if (minor != STREAM_MODULE) {
1019                         retval = -EINVAL;
1020                         break;
1021                 }
1022                 retval = sst_drop_stream(str_id);
1023                 break;
1024
1025         case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1026                 struct snd_sst_tstamp tstamp = {0};
1027                 unsigned long long time, freq, mod;
1028
1029                 pr_debug("sst: SNDRV_SST_STREAM_GET_TSTAMP recieved!\n");
1030                 if (minor != STREAM_MODULE) {
1031                         retval = -EBADRQC;
1032                         break;
1033                 }
1034                 memcpy_fromio(&tstamp,
1035                         ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1036                         +(str_id * sizeof(tstamp))),
1037                         sizeof(tstamp));
1038                 time = tstamp.samples_rendered;
1039                 freq = (unsigned long long) tstamp.sampling_frequency;
1040                 time = time * 1000; /* converting it to ms */
1041                 mod = do_div(time, freq);
1042                 if (copy_to_user((void __user *)arg, &time,
1043                                 sizeof(unsigned long long)))
1044                         retval = -EFAULT;
1045                 break;
1046         }
1047
1048         case _IOC_NR(SNDRV_SST_STREAM_START):{
1049                 struct stream_info *stream;
1050
1051                 pr_debug("sst: SNDRV_SST_STREAM_START recieved!\n");
1052                 if (minor != STREAM_MODULE) {
1053                         retval = -EINVAL;
1054                         break;
1055                 }
1056                 retval = sst_validate_strid(str_id);
1057                 if (retval)
1058                         break;
1059                 stream = &sst_drv_ctx->streams[str_id];
1060                 mutex_lock(&stream->lock);
1061                 if (stream->status == STREAM_INIT &&
1062                         stream->need_draining != true) {
1063                         stream->prev = stream->status;
1064                         stream->status = STREAM_RUNNING;
1065                         if (stream->ops == STREAM_OPS_PLAYBACK ||
1066                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1067                                 retval = sst_play_frame(str_id);
1068                         } else if (stream->ops == STREAM_OPS_CAPTURE)
1069                                 retval = sst_capture_frame(str_id);
1070                         else {
1071                                 retval = -EINVAL;
1072                                 mutex_unlock(&stream->lock);
1073                                 break;
1074                         }
1075                         if (retval < 0) {
1076                                 stream->status = STREAM_INIT;
1077                                 mutex_unlock(&stream->lock);
1078                                 break;
1079                         }
1080                 } else {
1081                         retval = -EINVAL;
1082                 }
1083                 mutex_unlock(&stream->lock);
1084                 break;
1085         }
1086
1087         case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1088                 struct snd_sst_target_device target_device;
1089
1090                 pr_debug("sst: SET_TARGET_DEVICE recieved!\n");
1091                 if (copy_from_user(&target_device, (void __user *)arg,
1092                                 sizeof(target_device))) {
1093                         retval = -EFAULT;
1094                         break;
1095                 }
1096                 if (minor != AM_MODULE) {
1097                         retval = -EBADRQC;
1098                         break;
1099                 }
1100                 retval = sst_target_device_select(&target_device);
1101                 break;
1102         }
1103
1104         case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1105                 struct snd_sst_driver_info info;
1106
1107                 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n");
1108                 info.version = SST_VERSION_NUM;
1109                 /* hard coding, shud get sumhow later */
1110                 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1111                                                 sst_drv_ctx->encoded_cnt;
1112                 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1113                 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1114                 info.max_enc_streams = MAX_ENC_STREAM;
1115                 info.buf_per_stream = sst_drv_ctx->mmap_len;
1116                 if (copy_to_user((void __user *)arg, &info,
1117                                 sizeof(info)))
1118                         retval = -EFAULT;
1119                 break;
1120         }
1121
1122         case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1123                 struct snd_sst_dbufs param;
1124                 struct snd_sst_dbufs dbufs_local;
1125                 struct snd_sst_buffs ibufs, obufs;
1126                 struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
1127                 char __user *dest;
1128
1129                 pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n");
1130                 if (minor != STREAM_MODULE) {
1131                         retval = -EBADRQC;
1132                         break;
1133                 }
1134                 if (copy_from_user(&param, (void __user *)arg,
1135                                 sizeof(param))) {
1136                         retval = -EFAULT;
1137                         break;
1138                 }
1139
1140                 dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
1141                 dbufs_local.output_bytes_produced =
1142                                         param.output_bytes_produced;
1143
1144                 if (copy_from_user(&ibufs, param.ibufs, sizeof(ibufs))) {
1145                         retval = -EFAULT;
1146                         break;
1147                 }
1148                 if (copy_from_user(&obufs, param.obufs, sizeof(obufs))) {
1149                         retval = -EFAULT;
1150                         break;
1151                 }
1152
1153                 ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
1154                 obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
1155                 if (!ibuf_tmp || !obuf_tmp) {
1156                         retval = -ENOMEM;
1157                         goto free_iobufs;
1158                 }
1159
1160                 if (copy_from_user(ibuf_tmp, ibufs.buff_entry,
1161                                 ibufs.entries * sizeof(*ibuf_tmp))) {
1162                         retval = -EFAULT;
1163                         goto free_iobufs;
1164                 }
1165                 ibufs.buff_entry = ibuf_tmp;
1166                 dbufs_local.ibufs = &ibufs;
1167
1168                 if (copy_from_user(obuf_tmp, obufs.buff_entry,
1169                                 obufs.entries * sizeof(*obuf_tmp))) {
1170                         retval = -EFAULT;
1171                         goto free_iobufs;
1172                 }
1173                 obufs.buff_entry = obuf_tmp;
1174                 dbufs_local.obufs = &obufs;
1175
1176                 retval = sst_decode(str_id, &dbufs_local);
1177                 if (retval) {
1178                         retval = -EAGAIN;
1179                         goto free_iobufs;
1180                 }
1181
1182                 dest = (char *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1183                 if (copy_to_user(dest,
1184                                 &dbufs_local.input_bytes_consumed,
1185                                 sizeof(unsigned long long))) {
1186                         retval = -EFAULT;
1187                         goto free_iobufs;
1188                 }
1189
1190                 dest = (char *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1191                 if (copy_to_user(dest,
1192                                 &dbufs_local.output_bytes_produced,
1193                                 sizeof(unsigned long long))) {
1194                         retval = -EFAULT;
1195                         goto free_iobufs;
1196                 }
1197 free_iobufs:
1198                 kfree(ibuf_tmp);
1199                 kfree(obuf_tmp);
1200                 break;
1201         }
1202
1203         case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1204                 pr_debug("sst: SNDRV_SST_STREAM_DRAIN recived\n");
1205                 if (minor != STREAM_MODULE) {
1206                         retval = -EINVAL;
1207                         break;
1208                 }
1209                 retval = sst_drain_stream(str_id);
1210                 break;
1211
1212         case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1213                 unsigned long long *bytes = (unsigned long long *)arg;
1214                 struct snd_sst_tstamp tstamp = {0};
1215
1216                 pr_debug("sst: STREAM_BYTES_DECODED recieved!\n");
1217                 if (minor != STREAM_MODULE) {
1218                         retval = -EINVAL;
1219                         break;
1220                 }
1221                 memcpy_fromio(&tstamp,
1222                         ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1223                         +(str_id * sizeof(tstamp))),
1224                         sizeof(tstamp));
1225                 if (copy_to_user(bytes, &tstamp.bytes_processed,
1226                                 sizeof(*bytes)))
1227                         retval = -EFAULT;
1228                 break;
1229         }
1230         case _IOC_NR(SNDRV_SST_FW_INFO): {
1231                 struct snd_sst_fw_info *fw_info;
1232
1233                 pr_debug("sst: SNDRV_SST_FW_INFO recived\n");
1234
1235                 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1236                 if (!fw_info) {
1237                         retval = -ENOMEM;
1238                         break;
1239                 }
1240                 retval = sst_get_fw_info(fw_info);
1241                 if (retval) {
1242                         retval = -EIO;
1243                         kfree(fw_info);
1244                         break;
1245                 }
1246                 if (copy_to_user((struct snd_sst_dbufs *)arg,
1247                                 fw_info, sizeof(*fw_info))) {
1248                         kfree(fw_info);
1249                         retval = -EFAULT;
1250                         break;
1251                 }
1252                 /*sst_print_fw_info(fw_info);*/
1253                 kfree(fw_info);
1254                 break;
1255         }
1256         default:
1257                 retval = -EINVAL;
1258         }
1259         pr_debug("sst: intel_sst_ioctl:complete ret code = %d\n", retval);
1260         return retval;
1261 }
1262