]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/intel_sst/intel_sst_app_interface.c
staging: intel_sst: use signed int for error codes
[net-next-2.6.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
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         BUG_ON(!mmap_buf);
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         pr_debug("sst:new buffers count %d status %d\n",
266                         mmap_buf->entries, stream->status);
267         buf_entry = mmap_buf->buff;
268         for (i = 0; i < mmap_buf->entries; i++) {
269                 BUG_ON(!buf_entry);
270                 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
271                 if (!bufs)
272                         return -ENOMEM;
273                 bufs->size = buf_entry->size;
274                 bufs->offset = buf_entry->offset;
275                 bufs->addr = sst_drv_ctx->mmap_mem;
276                 bufs->in_use = false;
277                 buf_entry++;
278                 /* locking here */
279                 mutex_lock(&stream->lock);
280                 list_add_tail(&bufs->node, &stream->bufs);
281                 mutex_unlock(&stream->lock);
282         }
283
284         mutex_lock(&stream->lock);
285         stream->data_blk.condition = false;
286         stream->data_blk.ret_code = 0;
287         if (stream->status == STREAM_INIT &&
288                         stream->prev != STREAM_UN_INIT &&
289                         stream->need_draining != true) {
290                 stream->prev = stream->status;
291                 stream->status = STREAM_RUNNING;
292                 if (stream->ops == STREAM_OPS_PLAYBACK) {
293                         if (sst_play_frame(str_id) < 0) {
294                                 pr_warn("sst: play frames fail\n");
295                                 mutex_unlock(&stream->lock);
296                                 return -EIO;
297                         }
298                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
299                         if (sst_capture_frame(str_id) < 0) {
300                                 pr_warn("sst: capture frame fail\n");
301                                 mutex_unlock(&stream->lock);
302                                 return -EIO;
303                         }
304                 }
305         }
306         mutex_unlock(&stream->lock);
307         /* Block the call for reply */
308         if (!list_empty(&stream->bufs)) {
309                 stream->data_blk.on = true;
310                 retval = sst_wait_interruptible(sst_drv_ctx,
311                                         &stream->data_blk);
312         }
313
314         if (retval >= 0)
315                 retval = stream->cumm_bytes;
316         pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval);
317         return retval;
318 }
319
320 /*sets user data buffers to play/capture*/
321 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
322 {
323         int retval;
324
325         stream->data_blk.ret_code = 0;
326         stream->data_blk.on = true;
327         stream->data_blk.condition = false;
328
329         mutex_lock(&stream->lock);
330         if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
331                 /* stream is started */
332                 stream->prev = stream->status;
333                 stream->status = STREAM_RUNNING;
334         }
335
336         if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
337                 /* stream is not started yet */
338                 pr_debug("sst: Stream isn't in started state %d, prev %d\n",
339                         stream->status, stream->prev);
340         } else if ((stream->status == STREAM_RUNNING ||
341                         stream->status == STREAM_PAUSED) &&
342                         stream->need_draining != true) {
343                 /* stream is started */
344                 if (stream->ops == STREAM_OPS_PLAYBACK ||
345                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
346                         if (sst_play_frame(str_id) < 0) {
347                                 pr_warn("sst: play frames failed\n");
348                                 mutex_unlock(&stream->lock);
349                                 return -EIO;
350                         }
351                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
352                         if (sst_capture_frame(str_id) < 0) {
353                                 pr_warn("sst: capture frames failed\n ");
354                                 mutex_unlock(&stream->lock);
355                                 return -EIO;
356                         }
357                 }
358         } else {
359                 mutex_unlock(&stream->lock);
360                 return -EIO;
361         }
362         mutex_unlock(&stream->lock);
363         /* Block the call for reply */
364
365         retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
366         if (retval) {
367                 stream->status = STREAM_INIT;
368                 pr_debug("sst: wait returned error...\n");
369         }
370         return retval;
371 }
372
373 /* fills kernel list with buffer addresses for SST DSP driver to process*/
374 static int snd_sst_fill_kernel_list(struct stream_info *stream,
375                         const struct iovec *iovec, unsigned long nr_segs,
376                         struct list_head *copy_to_list)
377 {
378         struct sst_stream_bufs *stream_bufs;
379         unsigned long index, data_not_copied, mmap_len;
380         unsigned char *bufp;
381         unsigned long size, copied_size;
382         int retval = 0, add_to_list = 0;
383         static int sent_offset;
384         static unsigned long sent_index;
385
386         stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
387         if (!stream_bufs)
388                 return -ENOMEM;
389         stream_bufs->addr = sst_drv_ctx->mmap_mem;
390 #ifdef CONFIG_MRST_RAR_HANDLER
391         if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
392                 for (index = stream->sg_index; index < nr_segs; index++) {
393                         __u32 rar_handle;
394                         struct sst_stream_bufs *stream_bufs =
395                                 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
396
397                         stream->sg_index = index;
398                         if (!stream_bufs)
399                                 return -ENOMEM;
400                         retval = copy_from_user((void *) &rar_handle,
401                                                 iovec[index].iov_base,
402                                                 sizeof(__u32));
403                         if (retval != 0)
404                                 return -EFAULT;
405                         stream_bufs->addr = (char *)rar_handle;
406                         stream_bufs->in_use = false;
407                         stream_bufs->size = iovec[0].iov_len;
408                         /* locking here */
409                         mutex_lock(&stream->lock);
410                         list_add_tail(&stream_bufs->node, &stream->bufs);
411                         mutex_unlock(&stream->lock);
412                 }
413                 stream->sg_index = index;
414                 return retval;
415         }
416 #endif
417         mmap_len = sst_drv_ctx->mmap_len;
418         stream_bufs->addr = sst_drv_ctx->mmap_mem;
419         bufp = stream->cur_ptr;
420
421         copied_size = 0;
422
423         if (!stream->sg_index)
424                 sent_index = sent_offset = 0;
425
426         for (index = stream->sg_index; index < nr_segs; index++) {
427                 stream->sg_index = index;
428                 if (!stream->cur_ptr)
429                         bufp = iovec[index].iov_base;
430
431                 size = ((unsigned long)iovec[index].iov_base
432                         + iovec[index].iov_len) - (unsigned long) bufp;
433
434                 if ((copied_size + size) > mmap_len)
435                         size = mmap_len - copied_size;
436
437
438                 if (stream->ops == STREAM_OPS_PLAYBACK) {
439                         data_not_copied = copy_from_user(
440                                 (void *)(stream_bufs->addr + copied_size),
441                                 bufp, size);
442                         if (data_not_copied > 0) {
443                                 /* Clean up the list and return error code */
444                                 retval = -EFAULT;
445                                 break;
446                         }
447                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
448                         struct snd_sst_user_cap_list *entry =
449                                 kzalloc(sizeof(*entry), GFP_KERNEL);
450
451                         if (!entry) {
452                                 kfree(stream_bufs);
453                                 return -ENOMEM;
454                         }
455                         entry->iov_index = index;
456                         entry->iov_offset = (unsigned long) bufp -
457                                         (unsigned long)iovec[index].iov_base;
458                         entry->offset = copied_size;
459                         entry->size = size;
460                         list_add_tail(&entry->node, copy_to_list);
461                 }
462
463                 stream->cur_ptr = bufp + size;
464
465                 if (((unsigned long)iovec[index].iov_base
466                                 + iovec[index].iov_len) <
467                                 ((unsigned long)iovec[index].iov_base)) {
468                         pr_debug("sst: Buffer overflows");
469                         kfree(stream_bufs);
470                         return -EINVAL;
471                 }
472
473                 if (((unsigned long)iovec[index].iov_base
474                                         + iovec[index].iov_len) ==
475                                         (unsigned long)stream->cur_ptr) {
476                         stream->cur_ptr = NULL;
477                         stream->sg_index++;
478                 }
479
480                 copied_size += size;
481                 pr_debug("sst: copied_size - %lx\n", copied_size);
482                 if ((copied_size >= mmap_len) ||
483                                 (stream->sg_index == nr_segs)) {
484                         add_to_list = 1;
485                 }
486
487                 if (add_to_list) {
488                         stream_bufs->in_use = false;
489                         stream_bufs->size = copied_size;
490                         /* locking here */
491                         mutex_lock(&stream->lock);
492                         list_add_tail(&stream_bufs->node, &stream->bufs);
493                         mutex_unlock(&stream->lock);
494                         break;
495                 }
496         }
497         return retval;
498 }
499
500 /* This function copies the captured data returned from SST DSP engine
501  * to the user buffers*/
502 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
503                         const struct iovec *iovec,
504                         struct list_head *copy_to_list)
505 {
506         struct snd_sst_user_cap_list *entry, *_entry;
507         struct sst_stream_bufs *kbufs = NULL, *_kbufs;
508         int retval = 0;
509         unsigned long data_not_copied;
510
511         /* copy sent buffers */
512         pr_debug("sst: capture stream copying to user now...\n");
513         list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
514                 if (kbufs->in_use == true) {
515                         /* copy to user */
516                         list_for_each_entry_safe(entry, _entry,
517                                                 copy_to_list, node) {
518                                 data_not_copied = copy_to_user((void *)
519                                         iovec[entry->iov_index].iov_base +
520                                                 entry->iov_offset,
521                                         kbufs->addr + entry->offset,
522                                         entry->size);
523                                 if (data_not_copied > 0) {
524                                         /* Clean up the list and return error */
525                                         retval = -EFAULT;
526                                         break;
527                                 }
528                                 list_del(&entry->node);
529                                 kfree(entry);
530                         }
531                 }
532         }
533         pr_debug("sst: end of cap copy\n");
534         return retval;
535 }
536
537 /*
538  * snd_sst_userbufs_play_cap - constructs the list from user buffers
539  *
540  * @iovec:pointer to iovec structure
541  * @nr_segs:number entries in the iovec structure
542  * @str_id:stream id
543  * @stream:pointer to stream_info structure
544  *
545  * This function will traverse the user list and copy the data to the kernel
546  * space buffers.
547  */
548 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
549                         unsigned long nr_segs, unsigned int str_id,
550                         struct stream_info *stream)
551 {
552         int retval;
553         LIST_HEAD(copy_to_list);
554
555
556         retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
557                        &copy_to_list);
558
559         retval = intel_sst_play_capture(stream, str_id);
560         if (retval < 0)
561                 return retval;
562
563         if (stream->ops == STREAM_OPS_CAPTURE) {
564                 retval = snd_sst_copy_userbuf_capture(stream, iovec,
565                                 &copy_to_list);
566         }
567         return retval;
568 }
569
570 /* This function is common function across read/write
571   for user buffers called from system calls*/
572 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
573                                         size_t count)
574 {
575         int retval;
576         struct stream_info *stream;
577         struct iovec iovec;
578         unsigned long nr_segs;
579
580         retval = sst_validate_strid(str_id);
581         if (retval)
582                 return -EINVAL;
583         stream = &sst_drv_ctx->streams[str_id];
584         if (stream->mmapped == true) {
585                 pr_warn("sst: user write and stream is mapped");
586                 return -EIO;
587         }
588         if (!count)
589                 return -EINVAL;
590         stream->curr_bytes = 0;
591         stream->cumm_bytes = 0;
592         /* copy user buf details */
593         pr_debug("sst: new buffers %p, copy size %d, status %d\n" ,
594                         buf, (int) count, (int) stream->status);
595
596         stream->buf_type = SST_BUF_USER_STATIC;
597         iovec.iov_base = (void *)buf;
598         iovec.iov_len  = count;
599         nr_segs = 1;
600
601         do {
602                 retval = snd_sst_userbufs_play_cap(
603                                 &iovec, nr_segs, str_id, stream);
604                 if (retval < 0)
605                         break;
606
607         } while (stream->sg_index < nr_segs);
608
609         stream->sg_index = 0;
610         stream->cur_ptr = NULL;
611         if (retval >= 0)
612                 retval = stream->cumm_bytes;
613         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
614         return retval;
615 }
616
617 /***
618  * intel_sst_write - This function is called when user tries to play out data
619  *
620  * @file_ptr:pointer to file
621  * @buf:user buffer to be played out
622  * @count:size of tthe buffer
623  * @offset:offset to start from
624  *
625  * writes the encoded data into DSP
626  */
627 int intel_sst_write(struct file *file_ptr, const char __user *buf,
628                         size_t count, loff_t *offset)
629 {
630         struct ioctl_pvt_data *data = file_ptr->private_data;
631         int str_id = data->str_id;
632         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
633
634         pr_debug("sst: called for %d\n", str_id);
635         if (stream->status == STREAM_UN_INIT ||
636                 stream->status == STREAM_DECODE) {
637                 return -EBADRQC;
638         }
639         return intel_sst_read_write(str_id, (char __user *)buf, count);
640 }
641
642 /*
643  * intel_sst_aio_write - write buffers
644  *
645  * @kiocb:pointer to a structure containing file pointer
646  * @iov:list of user buffer to be played out
647  * @nr_segs:number of entries
648  * @offset:offset to start from
649  *
650  * This function is called when user tries to play out multiple data buffers
651  */
652 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
653                         unsigned long nr_segs, loff_t  offset)
654 {
655         int retval;
656         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
657         int str_id = data->str_id;
658         struct stream_info *stream;
659
660         pr_debug("sst: entry - %ld\n", nr_segs);
661
662         if (is_sync_kiocb(kiocb) == false)
663                 return -EINVAL;
664
665         pr_debug("sst: called for str_id %d\n", str_id);
666         retval = sst_validate_strid(str_id);
667         if (retval)
668                 return -EINVAL;
669         stream = &sst_drv_ctx->streams[str_id];
670         if (stream->mmapped == true)
671                 return -EIO;
672         if (stream->status == STREAM_UN_INIT ||
673                 stream->status == STREAM_DECODE) {
674                 return -EBADRQC;
675         }
676         stream->curr_bytes = 0;
677         stream->cumm_bytes = 0;
678         pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
679                         nr_segs, (int) offset, (int) stream->status);
680         stream->buf_type = SST_BUF_USER_STATIC;
681         do {
682                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
683                                                 str_id, stream);
684                 if (retval < 0)
685                         break;
686
687         } while (stream->sg_index < nr_segs);
688
689         stream->sg_index = 0;
690         stream->cur_ptr = NULL;
691         if (retval >= 0)
692                 retval = stream->cumm_bytes;
693         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
694         return retval;
695 }
696
697 /*
698  * intel_sst_read - read the encoded data
699  *
700  * @file_ptr: pointer to file
701  * @buf: user buffer to be filled with captured data
702  * @count: size of tthe buffer
703  * @offset: offset to start from
704  *
705  * This function is called when user tries to capture data
706  */
707 int intel_sst_read(struct file *file_ptr, char __user *buf,
708                         size_t count, loff_t *offset)
709 {
710         struct ioctl_pvt_data *data = file_ptr->private_data;
711         int str_id = data->str_id;
712         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
713
714         pr_debug("sst: called for %d\n", str_id);
715         if (stream->status == STREAM_UN_INIT ||
716                         stream->status == STREAM_DECODE)
717                 return -EBADRQC;
718         return intel_sst_read_write(str_id, buf, count);
719 }
720
721 /*
722  * intel_sst_aio_read - aio read
723  *
724  * @kiocb: pointer to a structure containing file pointer
725  * @iov: list of user buffer to be filled with captured
726  * @nr_segs: number of entries
727  * @offset: offset to start from
728  *
729  * This function is called when user tries to capture out multiple data buffers
730  */
731 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
732                          unsigned long nr_segs, loff_t offset)
733 {
734         int retval;
735         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
736         int str_id = data->str_id;
737         struct stream_info *stream;
738
739         pr_debug("sst: entry - %ld\n", nr_segs);
740
741         if (is_sync_kiocb(kiocb) == false) {
742                 pr_debug("sst: aio_read from user space is not allowed\n");
743                 return -EINVAL;
744         }
745
746         pr_debug("sst: called for str_id %d\n", str_id);
747         retval = sst_validate_strid(str_id);
748         if (retval)
749                 return -EINVAL;
750         stream = &sst_drv_ctx->streams[str_id];
751         if (stream->mmapped == true)
752                 return -EIO;
753         if (stream->status == STREAM_UN_INIT ||
754                         stream->status == STREAM_DECODE)
755                 return -EBADRQC;
756         stream->curr_bytes = 0;
757         stream->cumm_bytes = 0;
758
759         pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
760                         nr_segs, (int) offset, (int) stream->status);
761         stream->buf_type = SST_BUF_USER_STATIC;
762         do {
763                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
764                                                 str_id, stream);
765                 if (retval < 0)
766                         break;
767
768         } while (stream->sg_index < nr_segs);
769
770         stream->sg_index = 0;
771         stream->cur_ptr = NULL;
772         if (retval >= 0)
773                 retval = stream->cumm_bytes;
774         pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
775         return retval;
776 }
777
778 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
779 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
780 {
781         pr_debug("sst: codec params:result =%d\n",
782                                 get_prm->codec_params.result);
783         pr_debug("sst: codec params:stream = %d\n",
784                                 get_prm->codec_params.stream_id);
785         pr_debug("sst: codec params:codec = %d\n",
786                                 get_prm->codec_params.codec);
787         pr_debug("sst: codec params:ops = %d\n",
788                                 get_prm->codec_params.ops);
789         pr_debug("sst: codec params:stream_type= %d\n",
790                                 get_prm->codec_params.stream_type);
791         pr_debug("sst: pcmparams:sfreq= %d\n",
792                                 get_prm->pcm_params.sfreq);
793         pr_debug("sst: pcmparams:num_chan= %d\n",
794                                 get_prm->pcm_params.num_chan);
795         pr_debug("sst: pcmparams:pcm_wd_sz= %d\n",
796                                 get_prm->pcm_params.pcm_wd_sz);
797         return;
798 }
799
800 /**
801  * intel_sst_ioctl - recieves the device ioctl's
802  * @file_ptr:pointer to file
803  * @cmd:Ioctl cmd
804  * @arg:data
805  *
806  * This function is called by OS when a user space component
807  * sends an Ioctl to SST driver
808  */
809 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
810 {
811         int retval = 0;
812         struct ioctl_pvt_data *data = NULL;
813         int str_id = 0, minor = 0;
814
815         lock_kernel();
816
817         data = file_ptr->private_data;
818         if (data) {
819                 minor = 0;
820                 str_id = data->str_id;
821         } else
822                 minor = 1;
823
824         if (sst_drv_ctx->sst_state != SST_FW_RUNNING) {
825                 unlock_kernel();
826                 return -EBUSY;
827         }
828
829         switch (_IOC_NR(cmd)) {
830         case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
831                 pr_debug("sst: IOCTL_PAUSE recieved for %d!\n", str_id);
832                 if (minor != STREAM_MODULE) {
833                         retval = -EBADRQC;
834                         break;
835                 }
836                 retval = sst_pause_stream(str_id);
837                 break;
838
839         case _IOC_NR(SNDRV_SST_STREAM_RESUME):
840                 pr_debug("sst: SNDRV_SST_IOCTL_RESUME recieved!\n");
841                 if (minor != STREAM_MODULE) {
842                         retval = -EBADRQC;
843                         break;
844                 }
845                 retval = sst_resume_stream(str_id);
846                 break;
847
848         case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
849                 struct snd_sst_params *str_param = (struct snd_sst_params *)arg;
850
851                 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n");
852                 if (minor != STREAM_MODULE) {
853                         retval = -EBADRQC;
854                         break;
855                 }
856
857                 if (!str_id) {
858
859                         retval = sst_get_stream(str_param);
860                         if (retval > 0) {
861                                 struct stream_info *str_info;
862                                 sst_drv_ctx->stream_cnt++;
863                                 data->str_id = retval;
864                                 str_info = &sst_drv_ctx->streams[retval];
865                                 str_info->src = SST_DRV;
866                                 retval = copy_to_user(&str_param->stream_id,
867                                                 &retval, sizeof(__u32));
868                         } else {
869                                 if (retval == -SST_ERR_INVALID_PARAMS)
870                                         retval = -EINVAL;
871                         }
872                 } else {
873                         pr_debug("sst: SET_STREAM_PARAMS recieved!\n");
874                         /* allocated set params only */
875                         retval = sst_set_stream_param(str_id, str_param);
876                         /* Block the call for reply */
877                         if (!retval) {
878                                 int sfreq = 0, word_size = 0, num_channel = 0;
879                                 sfreq = str_param->sparams.uc.pcm_params.sfreq;
880                                 word_size = str_param->sparams.
881                                                 uc.pcm_params.pcm_wd_sz;
882                                 num_channel = str_param->
883                                         sparams.uc.pcm_params.num_chan;
884                                 if (str_param->ops == STREAM_OPS_CAPTURE) {
885                                         sst_drv_ctx->scard_ops->\
886                                         set_pcm_audio_params(sfreq,
887                                                 word_size, num_channel);
888                                 }
889                         }
890                 }
891                 break;
892         }
893         case _IOC_NR(SNDRV_SST_SET_VOL): {
894                 struct snd_sst_vol *set_vol;
895                 struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg;
896                 pr_debug("sst: SET_VOLUME recieved for %d!\n",
897                                 rec_vol->stream_id);
898                 if (minor == STREAM_MODULE && rec_vol->stream_id == 0) {
899                         pr_debug("sst: invalid operation!\n");
900                         retval = -EPERM;
901                         break;
902                 }
903                 set_vol = kzalloc(sizeof(*set_vol), GFP_ATOMIC);
904                 if (!set_vol) {
905                         pr_debug("sst: mem allocation failed\n");
906                         retval = -ENOMEM;
907                         break;
908                 }
909                 retval = copy_from_user(set_vol, rec_vol, sizeof(*set_vol));
910                 if (retval) {
911                         pr_debug("sst: copy failed\n");
912                         retval = -EAGAIN;
913                         break;
914                 }
915                 retval = sst_set_vol(set_vol);
916                 kfree(set_vol);
917                 break;
918         }
919         case _IOC_NR(SNDRV_SST_GET_VOL): {
920                 struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg;
921                 struct snd_sst_vol get_vol;
922                 pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n",
923                                 rec_vol->stream_id);
924                 if (minor == STREAM_MODULE && rec_vol->stream_id == 0) {
925                         pr_debug("sst: invalid operation!\n");
926                         retval = -EPERM;
927                         break;
928                 }
929                 get_vol.stream_id = rec_vol->stream_id;
930                 retval = sst_get_vol(&get_vol);
931                 if (retval) {
932                         retval = -EIO;
933                         break;
934                 }
935                 pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
936                                 get_vol.stream_id, get_vol.volume,
937                                 get_vol.ramp_duration, get_vol.ramp_type);
938                 retval = copy_to_user((struct snd_sst_vol *)arg,
939                                                 &get_vol, sizeof(get_vol));
940                 if (retval) {
941                         retval = -EIO;
942                         break;
943                 }
944                 /*sst_print_get_vol_info(str_id, &get_vol);*/
945                 break;
946         }
947
948         case _IOC_NR(SNDRV_SST_MUTE): {
949                 struct snd_sst_mute *set_mute;
950                 struct snd_sst_vol *rec_mute = (struct snd_sst_vol *)arg;
951                 pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n",
952                         rec_mute->stream_id);
953                 if (minor == STREAM_MODULE && rec_mute->stream_id == 0) {
954                         retval = -EPERM;
955                         break;
956                 }
957                 set_mute = kzalloc(sizeof(*set_mute), GFP_ATOMIC);
958                 if (!set_mute) {
959                         retval = -ENOMEM;
960                         break;
961                 }
962                 retval = copy_from_user(set_mute, rec_mute, sizeof(*set_mute));
963                 if (retval) {
964                         retval = -EFAULT;
965                         break;
966                 }
967                 retval = sst_set_mute(set_mute);
968                 kfree(set_mute);
969                 break;
970         }
971         case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
972                 struct snd_sst_get_stream_params get_params;
973
974                 pr_debug("sst: IOCTL_GET_PARAMS recieved!\n");
975                 if (minor != 0) {
976                         retval = -EBADRQC;
977                         break;
978                 }
979
980                 retval = sst_get_stream_params(str_id, &get_params);
981                 if (retval) {
982                         retval = -EIO;
983                         break;
984                 }
985                 retval = copy_to_user((struct snd_sst_get_stream_params *)arg,
986                                         &get_params, sizeof(get_params));
987                 if (retval) {
988                         retval = -EBUSY;
989                         break;
990                 }
991                 sst_print_stream_params(&get_params);
992                 break;
993         }
994
995         case _IOC_NR(SNDRV_SST_MMAP_PLAY):
996         case _IOC_NR(SNDRV_SST_MMAP_CAPTURE):
997                 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n");
998                 if (minor != STREAM_MODULE) {
999                         retval = -EBADRQC;
1000                         break;
1001                 }
1002                 retval = intel_sst_mmap_play_capture(str_id,
1003                                 (struct snd_sst_mmap_buffs *)arg);
1004                 break;
1005
1006         case _IOC_NR(SNDRV_SST_STREAM_DROP):
1007                 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n");
1008                 if (minor != STREAM_MODULE) {
1009                         retval = -EINVAL;
1010                         break;
1011                 }
1012                 retval = sst_drop_stream(str_id);
1013                 break;
1014
1015         case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1016                 unsigned long long *ms = (unsigned long long *)arg;
1017                 struct snd_sst_tstamp tstamp = {0};
1018                 unsigned long long time, freq, mod;
1019
1020                 pr_debug("sst: SNDRV_SST_STREAM_GET_TSTAMP recieved!\n");
1021                 if (minor != STREAM_MODULE) {
1022                         retval = -EBADRQC;
1023                         break;
1024                 }
1025                 memcpy_fromio(&tstamp,
1026                         ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1027                         +(str_id * sizeof(tstamp))),
1028                         sizeof(tstamp));
1029                 time = tstamp.samples_rendered;
1030                 freq = (unsigned long long) tstamp.sampling_frequency;
1031                 time = time * 1000; /* converting it to ms */
1032                 mod = do_div(time, freq);
1033                 retval = copy_to_user(ms, &time, sizeof(*ms));
1034                 if (retval)
1035                         retval = -EFAULT;
1036                 break;
1037         }
1038
1039         case _IOC_NR(SNDRV_SST_STREAM_START):{
1040                 struct stream_info *stream;
1041
1042                 pr_debug("sst: SNDRV_SST_STREAM_START recieved!\n");
1043                 if (minor != STREAM_MODULE) {
1044                         retval = -EINVAL;
1045                         break;
1046                 }
1047                 retval = sst_validate_strid(str_id);
1048                 if (retval)
1049                         break;
1050                 stream = &sst_drv_ctx->streams[str_id];
1051                 mutex_lock(&stream->lock);
1052                 if (stream->status == STREAM_INIT &&
1053                         stream->need_draining != true) {
1054                         stream->prev = stream->status;
1055                         stream->status = STREAM_RUNNING;
1056                         if (stream->ops == STREAM_OPS_PLAYBACK ||
1057                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1058                                 retval = sst_play_frame(str_id);
1059                         } else if (stream->ops == STREAM_OPS_CAPTURE)
1060                                 retval = sst_capture_frame(str_id);
1061                         else {
1062                                 retval = -EINVAL;
1063                                 mutex_unlock(
1064                                         &sst_drv_ctx->streams[str_id].lock);
1065                                 break;
1066                         }
1067                         if (retval < 0) {
1068                                 stream->status = STREAM_INIT;
1069                                 mutex_unlock(
1070                                         &sst_drv_ctx->streams[str_id].lock);
1071                                 break;
1072                         }
1073                 } else {
1074                         retval = -EINVAL;
1075                 }
1076                 mutex_unlock(&sst_drv_ctx->streams[str_id].lock);
1077                 break;
1078         }
1079
1080         case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1081                 struct snd_sst_target_device *target_device;
1082
1083                 pr_debug("sst: SET_TARGET_DEVICE recieved!\n");
1084                 target_device = (struct snd_sst_target_device *)arg;
1085                 BUG_ON(!target_device);
1086                 if (minor != AM_MODULE) {
1087                         retval = -EBADRQC;
1088                         break;
1089                 }
1090                 retval = sst_target_device_select(target_device);
1091                 break;
1092         }
1093
1094         case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1095                 struct snd_sst_driver_info *info =
1096                         (struct snd_sst_driver_info *)arg;
1097
1098                 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n");
1099                 info->version = SST_VERSION_NUM;
1100                 /* hard coding, shud get sumhow later */
1101                 info->active_pcm_streams = sst_drv_ctx->stream_cnt -
1102                                                 sst_drv_ctx->encoded_cnt;
1103                 info->active_enc_streams = sst_drv_ctx->encoded_cnt;
1104                 info->max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1105                 info->max_enc_streams = MAX_ENC_STREAM;
1106                 info->buf_per_stream = sst_drv_ctx->mmap_len;
1107                 break;
1108         }
1109
1110         case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1111                 struct snd_sst_dbufs *param =
1112                                 (struct snd_sst_dbufs *)arg, dbufs_local;
1113                 int i;
1114                 struct snd_sst_buffs ibufs, obufs;
1115                 struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries],
1116                                 obuf_temp[param->obufs->entries];
1117
1118                 pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n");
1119                 if (minor != STREAM_MODULE) {
1120                         retval = -EBADRQC;
1121                         break;
1122                 }
1123                 if (!param) {
1124                         retval = -EINVAL;
1125                         break;
1126                 }
1127
1128                 dbufs_local.input_bytes_consumed = param->input_bytes_consumed;
1129                 dbufs_local.output_bytes_produced =
1130                                         param->output_bytes_produced;
1131                 dbufs_local.ibufs = &ibufs;
1132                 dbufs_local.obufs = &obufs;
1133                 dbufs_local.ibufs->entries = param->ibufs->entries;
1134                 dbufs_local.ibufs->type = param->ibufs->type;
1135                 dbufs_local.obufs->entries = param->obufs->entries;
1136                 dbufs_local.obufs->type = param->obufs->type;
1137
1138                 dbufs_local.ibufs->buff_entry = ibuf_temp;
1139                 for (i = 0; i < dbufs_local.ibufs->entries; i++) {
1140                         ibuf_temp[i].buffer =
1141                                 param->ibufs->buff_entry[i].buffer;
1142                         ibuf_temp[i].size =
1143                                 param->ibufs->buff_entry[i].size;
1144                 }
1145                 dbufs_local.obufs->buff_entry = obuf_temp;
1146                 for (i = 0; i < dbufs_local.obufs->entries; i++) {
1147                         obuf_temp[i].buffer =
1148                                 param->obufs->buff_entry[i].buffer;
1149                         obuf_temp[i].size =
1150                                 param->obufs->buff_entry[i].size;
1151                 }
1152                 retval = sst_decode(str_id, &dbufs_local);
1153                 if (retval)
1154                         retval =  -EAGAIN;
1155                 retval = copy_to_user(&param->input_bytes_consumed,
1156                         &dbufs_local.input_bytes_consumed,
1157                         sizeof(unsigned long long));
1158                 if (retval) {
1159                         retval =  -EFAULT;
1160                         break;
1161                 }
1162                 retval = copy_to_user(&param->output_bytes_produced,
1163                                 &dbufs_local.output_bytes_produced,
1164                                 sizeof(unsigned long long));
1165                 if (retval) {
1166                         retval =  -EFAULT;
1167                         break;
1168                 }
1169                 break;
1170         }
1171
1172         case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1173                 pr_debug("sst: SNDRV_SST_STREAM_DRAIN recived\n");
1174                 if (minor != STREAM_MODULE) {
1175                         retval = -EINVAL;
1176                         break;
1177                 }
1178                 retval = sst_drain_stream(str_id);
1179                 break;
1180
1181         case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1182                 unsigned long long *bytes = (unsigned long long *)arg;
1183                 struct snd_sst_tstamp tstamp = {0};
1184
1185                 pr_debug("sst: STREAM_BYTES_DECODED recieved!\n");
1186                 if (minor != STREAM_MODULE) {
1187                         retval = -EINVAL;
1188                         break;
1189                 }
1190                 memcpy_fromio(&tstamp,
1191                         ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1192                         +(str_id * sizeof(tstamp))),
1193                         sizeof(tstamp));
1194                 retval = copy_to_user(bytes, &tstamp.bytes_processed,
1195                                         sizeof(*bytes));
1196                 if (retval)
1197                         retval = -EFAULT;
1198                 break;
1199         }
1200         case _IOC_NR(SNDRV_SST_FW_INFO): {
1201                 struct snd_sst_fw_info *fw_info;
1202
1203                 pr_debug("sst: SNDRV_SST_FW_INFO recived\n");
1204
1205                 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1206                 if (!fw_info) {
1207                         retval = -ENOMEM;
1208                         break;
1209                 }
1210                 retval = sst_get_fw_info(fw_info);
1211                 if (retval) {
1212                         retval = -EIO;
1213                         kfree(fw_info);
1214                         break;
1215                 }
1216                 retval = copy_to_user((struct snd_sst_dbufs *)arg,
1217                                         fw_info, sizeof(*fw_info));
1218                 if (retval) {
1219                         kfree(fw_info);
1220                         retval = -EFAULT;
1221                         break;
1222                 }
1223                 /*sst_print_fw_info(fw_info);*/
1224                 kfree(fw_info);
1225                 break;
1226         }
1227         default:
1228                 retval = -EINVAL;
1229         }
1230         unlock_kernel();
1231         pr_debug("sst: intel_sst_ioctl:complete ret code = %d\n", retval);
1232         return retval;
1233 }
1234