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