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