vmwgfx: Fix assignment in vmw_framebuffer_create_handle
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
blob93b41a284d83be8941a1c18d280d00885dc0be11
1 /*
2 * intel_sst_interface.c - Intel SST Driver for audio engine
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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
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
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/pci.h>
33 #include <linux/fs.h>
34 #include <linux/uio.h>
35 #include <linux/aio.h>
36 #include <linux/uaccess.h>
37 #include <linux/firmware.h>
38 #include <linux/pm_runtime.h>
39 #include <linux/ioctl.h>
40 #ifdef CONFIG_MRST_RAR_HANDLER
41 #include <linux/rar_register.h>
42 #include "../../../drivers/staging/memrar/memrar.h"
43 #endif
44 #include "intel_sst.h"
45 #include "intel_sst_ioctl.h"
46 #include "intel_sst_fw_ipc.h"
47 #include "intel_sst_common.h"
49 #define AM_MODULE 1
50 #define STREAM_MODULE 0
53 /**
54 * intel_sst_check_device - checks SST device
56 * This utility function checks the state of SST device and downlaods FW if
57 * not done, or resumes the device if suspended
60 static int intel_sst_check_device(void)
62 int retval = 0;
63 if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
64 pr_warn("Sound card not available\n");
65 return -EIO;
67 if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
68 pr_debug("Resuming from Suspended state\n");
69 retval = intel_sst_resume(sst_drv_ctx->pci);
70 if (retval) {
71 pr_debug("Resume Failed= %#x,abort\n", retval);
72 return retval;
76 if (sst_drv_ctx->sst_state == SST_UN_INIT) {
77 /* FW is not downloaded */
78 retval = sst_download_fw();
79 if (retval)
80 return -ENODEV;
81 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
82 retval = sst_drv_ctx->rx_time_slot_status;
83 if (retval != RX_TIMESLOT_UNINIT
84 && sst_drv_ctx->pmic_vendor != SND_NC)
85 sst_enable_rx_timeslot(retval);
88 return 0;
91 /**
92 * intel_sst_open - opens a handle to driver
94 * @i_node: inode structure
95 * @file_ptr:pointer to file
97 * This function is called by OS when a user space component
98 * tries to get a driver handle. Only one handle at a time
99 * will be allowed
101 int intel_sst_open(struct inode *i_node, struct file *file_ptr)
103 unsigned int retval;
105 mutex_lock(&sst_drv_ctx->stream_lock);
106 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
107 retval = intel_sst_check_device();
108 if (retval) {
109 pm_runtime_put(&sst_drv_ctx->pci->dev);
110 mutex_unlock(&sst_drv_ctx->stream_lock);
111 return retval;
114 if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
115 struct ioctl_pvt_data *data =
116 kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
117 if (!data) {
118 pm_runtime_put(&sst_drv_ctx->pci->dev);
119 mutex_unlock(&sst_drv_ctx->stream_lock);
120 return -ENOMEM;
123 sst_drv_ctx->encoded_cnt++;
124 mutex_unlock(&sst_drv_ctx->stream_lock);
125 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
126 data->str_id = 0;
127 file_ptr->private_data = (void *)data;
128 pr_debug("pvt_id handle = %d!\n", data->pvt_id);
129 } else {
130 retval = -EUSERS;
131 pm_runtime_put(&sst_drv_ctx->pci->dev);
132 mutex_unlock(&sst_drv_ctx->stream_lock);
134 return retval;
138 * intel_sst_open_cntrl - opens a handle to driver
140 * @i_node: inode structure
141 * @file_ptr:pointer to file
143 * This function is called by OS when a user space component
144 * tries to get a driver handle to /dev/intel_sst_control.
145 * Only one handle at a time will be allowed
146 * This is for control operations only
148 int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
150 unsigned int retval;
152 /* audio manager open */
153 mutex_lock(&sst_drv_ctx->stream_lock);
154 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
155 retval = intel_sst_check_device();
156 if (retval) {
157 pm_runtime_put(&sst_drv_ctx->pci->dev);
158 mutex_unlock(&sst_drv_ctx->stream_lock);
159 return retval;
162 if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
163 sst_drv_ctx->am_cnt++;
164 pr_debug("AM handle opened...\n");
165 file_ptr->private_data = NULL;
166 } else {
167 retval = -EACCES;
168 pm_runtime_put(&sst_drv_ctx->pci->dev);
171 mutex_unlock(&sst_drv_ctx->stream_lock);
172 return retval;
176 * intel_sst_release - releases a handle to driver
178 * @i_node: inode structure
179 * @file_ptr: pointer to file
181 * This function is called by OS when a user space component
182 * tries to release a driver handle.
184 int intel_sst_release(struct inode *i_node, struct file *file_ptr)
186 struct ioctl_pvt_data *data = file_ptr->private_data;
188 pr_debug("Release called, closing app handle\n");
189 mutex_lock(&sst_drv_ctx->stream_lock);
190 sst_drv_ctx->encoded_cnt--;
191 sst_drv_ctx->stream_cnt--;
192 pm_runtime_put(&sst_drv_ctx->pci->dev);
193 mutex_unlock(&sst_drv_ctx->stream_lock);
194 free_stream_context(data->str_id);
195 kfree(data);
196 return 0;
199 int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
201 /* audio manager close */
202 mutex_lock(&sst_drv_ctx->stream_lock);
203 sst_drv_ctx->am_cnt--;
204 pm_runtime_put(&sst_drv_ctx->pci->dev);
205 mutex_unlock(&sst_drv_ctx->stream_lock);
206 pr_debug("AM handle closed\n");
207 return 0;
211 * intel_sst_mmap - mmaps a kernel buffer to user space for copying data
213 * @vma: vm area structure instance
214 * @file_ptr: pointer to file
216 * This function is called by OS when a user space component
217 * tries to get mmap memory from driver
219 int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
221 int retval, length;
222 struct ioctl_pvt_data *data =
223 (struct ioctl_pvt_data *)file_ptr->private_data;
224 int str_id = data->str_id;
225 void *mem_area;
227 retval = sst_validate_strid(str_id);
228 if (retval)
229 return -EINVAL;
231 length = vma->vm_end - vma->vm_start;
232 pr_debug("called for stream %d length 0x%x\n", str_id, length);
234 if (length > sst_drv_ctx->mmap_len)
235 return -ENOMEM;
236 if (!sst_drv_ctx->mmap_mem)
237 return -EIO;
239 /* round it up to the page boundary */
240 /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
241 + PAGE_SIZE - 1) & PAGE_MASK);*/
242 mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
244 /* map the whole physically contiguous area in one piece */
245 retval = remap_pfn_range(vma,
246 vma->vm_start,
247 virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
248 length,
249 vma->vm_page_prot);
250 if (retval)
251 sst_drv_ctx->streams[str_id].mmapped = false;
252 else
253 sst_drv_ctx->streams[str_id].mmapped = true;
255 pr_debug("mmap ret 0x%x\n", retval);
256 return retval;
259 /* sets mmap data buffers to play/capture*/
260 static int intel_sst_mmap_play_capture(u32 str_id,
261 struct snd_sst_mmap_buffs *mmap_buf)
263 struct sst_stream_bufs *bufs;
264 int retval, i;
265 struct stream_info *stream;
266 struct snd_sst_mmap_buff_entry *buf_entry;
267 struct snd_sst_mmap_buff_entry *tmp_buf;
269 pr_debug("called for str_id %d\n", str_id);
270 retval = sst_validate_strid(str_id);
271 if (retval)
272 return -EINVAL;
274 stream = &sst_drv_ctx->streams[str_id];
275 if (stream->mmapped != true)
276 return -EIO;
278 if (stream->status == STREAM_UN_INIT ||
279 stream->status == STREAM_DECODE) {
280 return -EBADRQC;
282 stream->curr_bytes = 0;
283 stream->cumm_bytes = 0;
285 tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
286 if (!tmp_buf)
287 return -ENOMEM;
288 if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
289 mmap_buf->entries * sizeof(*tmp_buf))) {
290 retval = -EFAULT;
291 goto out_free;
294 pr_debug("new buffers count %d status %d\n",
295 mmap_buf->entries, stream->status);
296 buf_entry = tmp_buf;
297 for (i = 0; i < mmap_buf->entries; i++) {
298 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
299 if (!bufs) {
300 retval = -ENOMEM;
301 goto out_free;
303 bufs->size = buf_entry->size;
304 bufs->offset = buf_entry->offset;
305 bufs->addr = sst_drv_ctx->mmap_mem;
306 bufs->in_use = false;
307 buf_entry++;
308 /* locking here */
309 mutex_lock(&stream->lock);
310 list_add_tail(&bufs->node, &stream->bufs);
311 mutex_unlock(&stream->lock);
314 mutex_lock(&stream->lock);
315 stream->data_blk.condition = false;
316 stream->data_blk.ret_code = 0;
317 if (stream->status == STREAM_INIT &&
318 stream->prev != STREAM_UN_INIT &&
319 stream->need_draining != true) {
320 stream->prev = stream->status;
321 stream->status = STREAM_RUNNING;
322 if (stream->ops == STREAM_OPS_PLAYBACK) {
323 if (sst_play_frame(str_id) < 0) {
324 pr_warn("play frames fail\n");
325 mutex_unlock(&stream->lock);
326 retval = -EIO;
327 goto out_free;
329 } else if (stream->ops == STREAM_OPS_CAPTURE) {
330 if (sst_capture_frame(str_id) < 0) {
331 pr_warn("capture frame fail\n");
332 mutex_unlock(&stream->lock);
333 retval = -EIO;
334 goto out_free;
338 mutex_unlock(&stream->lock);
339 /* Block the call for reply */
340 if (!list_empty(&stream->bufs)) {
341 stream->data_blk.on = true;
342 retval = sst_wait_interruptible(sst_drv_ctx,
343 &stream->data_blk);
346 if (retval >= 0)
347 retval = stream->cumm_bytes;
348 pr_debug("end of play/rec ioctl bytes = %d!!\n", retval);
350 out_free:
351 kfree(tmp_buf);
352 return retval;
355 /*sets user data buffers to play/capture*/
356 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
358 int retval;
360 stream->data_blk.ret_code = 0;
361 stream->data_blk.on = true;
362 stream->data_blk.condition = false;
364 mutex_lock(&stream->lock);
365 if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
366 /* stream is started */
367 stream->prev = stream->status;
368 stream->status = STREAM_RUNNING;
371 if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
372 /* stream is not started yet */
373 pr_debug("Stream isn't in started state %d, prev %d\n",
374 stream->status, stream->prev);
375 } else if ((stream->status == STREAM_RUNNING ||
376 stream->status == STREAM_PAUSED) &&
377 stream->need_draining != true) {
378 /* stream is started */
379 if (stream->ops == STREAM_OPS_PLAYBACK ||
380 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
381 if (sst_play_frame(str_id) < 0) {
382 pr_warn("play frames failed\n");
383 mutex_unlock(&stream->lock);
384 return -EIO;
386 } else if (stream->ops == STREAM_OPS_CAPTURE) {
387 if (sst_capture_frame(str_id) < 0) {
388 pr_warn("capture frames failed\n");
389 mutex_unlock(&stream->lock);
390 return -EIO;
393 } else {
394 mutex_unlock(&stream->lock);
395 return -EIO;
397 mutex_unlock(&stream->lock);
398 /* Block the call for reply */
400 retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
401 if (retval) {
402 stream->status = STREAM_INIT;
403 pr_debug("wait returned error...\n");
405 return retval;
408 /* fills kernel list with buffer addresses for SST DSP driver to process*/
409 static int snd_sst_fill_kernel_list(struct stream_info *stream,
410 const struct iovec *iovec, unsigned long nr_segs,
411 struct list_head *copy_to_list)
413 struct sst_stream_bufs *stream_bufs;
414 unsigned long index, mmap_len;
415 unsigned char __user *bufp;
416 unsigned long size, copied_size;
417 int retval = 0, add_to_list = 0;
418 static int sent_offset;
419 static unsigned long sent_index;
421 #ifdef CONFIG_MRST_RAR_HANDLER
422 if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
423 for (index = stream->sg_index; index < nr_segs; index++) {
424 __u32 rar_handle;
425 struct sst_stream_bufs *stream_bufs =
426 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
428 stream->sg_index = index;
429 if (!stream_bufs)
430 return -ENOMEM;
431 if (copy_from_user((void *) &rar_handle,
432 iovec[index].iov_base,
433 sizeof(__u32))) {
434 kfree(stream_bufs);
435 return -EFAULT;
437 stream_bufs->addr = (char *)rar_handle;
438 stream_bufs->in_use = false;
439 stream_bufs->size = iovec[0].iov_len;
440 /* locking here */
441 mutex_lock(&stream->lock);
442 list_add_tail(&stream_bufs->node, &stream->bufs);
443 mutex_unlock(&stream->lock);
445 stream->sg_index = index;
446 return retval;
448 #endif
449 stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
450 if (!stream_bufs)
451 return -ENOMEM;
452 stream_bufs->addr = sst_drv_ctx->mmap_mem;
453 mmap_len = sst_drv_ctx->mmap_len;
454 stream_bufs->addr = sst_drv_ctx->mmap_mem;
455 bufp = stream->cur_ptr;
457 copied_size = 0;
459 if (!stream->sg_index)
460 sent_index = sent_offset = 0;
462 for (index = stream->sg_index; index < nr_segs; index++) {
463 stream->sg_index = index;
464 if (!stream->cur_ptr)
465 bufp = iovec[index].iov_base;
467 size = ((unsigned long)iovec[index].iov_base
468 + iovec[index].iov_len) - (unsigned long) bufp;
470 if ((copied_size + size) > mmap_len)
471 size = mmap_len - copied_size;
474 if (stream->ops == STREAM_OPS_PLAYBACK) {
475 if (copy_from_user((void *)
476 (stream_bufs->addr + copied_size),
477 bufp, size)) {
478 /* Clean up the list and return error code */
479 retval = -EFAULT;
480 break;
482 } else if (stream->ops == STREAM_OPS_CAPTURE) {
483 struct snd_sst_user_cap_list *entry =
484 kzalloc(sizeof(*entry), GFP_KERNEL);
486 if (!entry) {
487 kfree(stream_bufs);
488 return -ENOMEM;
490 entry->iov_index = index;
491 entry->iov_offset = (unsigned long) bufp -
492 (unsigned long)iovec[index].iov_base;
493 entry->offset = copied_size;
494 entry->size = size;
495 list_add_tail(&entry->node, copy_to_list);
498 stream->cur_ptr = bufp + size;
500 if (((unsigned long)iovec[index].iov_base
501 + iovec[index].iov_len) <
502 ((unsigned long)iovec[index].iov_base)) {
503 pr_debug("Buffer overflows\n");
504 kfree(stream_bufs);
505 return -EINVAL;
508 if (((unsigned long)iovec[index].iov_base
509 + iovec[index].iov_len) ==
510 (unsigned long)stream->cur_ptr) {
511 stream->cur_ptr = NULL;
512 stream->sg_index++;
515 copied_size += size;
516 pr_debug("copied_size - %lx\n", copied_size);
517 if ((copied_size >= mmap_len) ||
518 (stream->sg_index == nr_segs)) {
519 add_to_list = 1;
522 if (add_to_list) {
523 stream_bufs->in_use = false;
524 stream_bufs->size = copied_size;
525 /* locking here */
526 mutex_lock(&stream->lock);
527 list_add_tail(&stream_bufs->node, &stream->bufs);
528 mutex_unlock(&stream->lock);
529 break;
532 return retval;
535 /* This function copies the captured data returned from SST DSP engine
536 * to the user buffers*/
537 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
538 const struct iovec *iovec,
539 struct list_head *copy_to_list)
541 struct snd_sst_user_cap_list *entry, *_entry;
542 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
543 int retval = 0;
545 /* copy sent buffers */
546 pr_debug("capture stream copying to user now...\n");
547 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
548 if (kbufs->in_use == true) {
549 /* copy to user */
550 list_for_each_entry_safe(entry, _entry,
551 copy_to_list, node) {
552 if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
553 kbufs->addr + entry->offset,
554 entry->size)) {
555 /* Clean up the list and return error */
556 retval = -EFAULT;
557 break;
559 list_del(&entry->node);
560 kfree(entry);
564 pr_debug("end of cap copy\n");
565 return retval;
569 * snd_sst_userbufs_play_cap - constructs the list from user buffers
571 * @iovec:pointer to iovec structure
572 * @nr_segs:number entries in the iovec structure
573 * @str_id:stream id
574 * @stream:pointer to stream_info structure
576 * This function will traverse the user list and copy the data to the kernel
577 * space buffers.
579 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
580 unsigned long nr_segs, unsigned int str_id,
581 struct stream_info *stream)
583 int retval;
584 LIST_HEAD(copy_to_list);
587 retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
588 &copy_to_list);
590 retval = intel_sst_play_capture(stream, str_id);
591 if (retval < 0)
592 return retval;
594 if (stream->ops == STREAM_OPS_CAPTURE) {
595 retval = snd_sst_copy_userbuf_capture(stream, iovec,
596 &copy_to_list);
598 return retval;
601 /* This function is common function across read/write
602 for user buffers called from system calls*/
603 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
604 size_t count)
606 int retval;
607 struct stream_info *stream;
608 struct iovec iovec;
609 unsigned long nr_segs;
611 retval = sst_validate_strid(str_id);
612 if (retval)
613 return -EINVAL;
614 stream = &sst_drv_ctx->streams[str_id];
615 if (stream->mmapped == true) {
616 pr_warn("user write and stream is mapped\n");
617 return -EIO;
619 if (!count)
620 return -EINVAL;
621 stream->curr_bytes = 0;
622 stream->cumm_bytes = 0;
623 /* copy user buf details */
624 pr_debug("new buffers %p, copy size %d, status %d\n" ,
625 buf, (int) count, (int) stream->status);
627 stream->buf_type = SST_BUF_USER_STATIC;
628 iovec.iov_base = buf;
629 iovec.iov_len = count;
630 nr_segs = 1;
632 do {
633 retval = snd_sst_userbufs_play_cap(
634 &iovec, nr_segs, str_id, stream);
635 if (retval < 0)
636 break;
638 } while (stream->sg_index < nr_segs);
640 stream->sg_index = 0;
641 stream->cur_ptr = NULL;
642 if (retval >= 0)
643 retval = stream->cumm_bytes;
644 pr_debug("end of play/rec bytes = %d!!\n", retval);
645 return retval;
648 /***
649 * intel_sst_write - This function is called when user tries to play out data
651 * @file_ptr:pointer to file
652 * @buf:user buffer to be played out
653 * @count:size of tthe buffer
654 * @offset:offset to start from
656 * writes the encoded data into DSP
658 int intel_sst_write(struct file *file_ptr, const char __user *buf,
659 size_t count, loff_t *offset)
661 struct ioctl_pvt_data *data = file_ptr->private_data;
662 int str_id = data->str_id;
663 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
665 pr_debug("called for %d\n", str_id);
666 if (stream->status == STREAM_UN_INIT ||
667 stream->status == STREAM_DECODE) {
668 return -EBADRQC;
670 return intel_sst_read_write(str_id, (char __user *)buf, count);
674 * intel_sst_aio_write - write buffers
676 * @kiocb:pointer to a structure containing file pointer
677 * @iov:list of user buffer to be played out
678 * @nr_segs:number of entries
679 * @offset:offset to start from
681 * This function is called when user tries to play out multiple data buffers
683 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
684 unsigned long nr_segs, loff_t offset)
686 int retval;
687 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
688 int str_id = data->str_id;
689 struct stream_info *stream;
691 pr_debug("entry - %ld\n", nr_segs);
693 if (is_sync_kiocb(kiocb) == false)
694 return -EINVAL;
696 pr_debug("called for str_id %d\n", str_id);
697 retval = sst_validate_strid(str_id);
698 if (retval)
699 return -EINVAL;
700 stream = &sst_drv_ctx->streams[str_id];
701 if (stream->mmapped == true)
702 return -EIO;
703 if (stream->status == STREAM_UN_INIT ||
704 stream->status == STREAM_DECODE) {
705 return -EBADRQC;
707 stream->curr_bytes = 0;
708 stream->cumm_bytes = 0;
709 pr_debug("new segs %ld, offset %d, status %d\n" ,
710 nr_segs, (int) offset, (int) stream->status);
711 stream->buf_type = SST_BUF_USER_STATIC;
712 do {
713 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
714 str_id, stream);
715 if (retval < 0)
716 break;
718 } while (stream->sg_index < nr_segs);
720 stream->sg_index = 0;
721 stream->cur_ptr = NULL;
722 if (retval >= 0)
723 retval = stream->cumm_bytes;
724 pr_debug("end of play/rec bytes = %d!!\n", retval);
725 return retval;
729 * intel_sst_read - read the encoded data
731 * @file_ptr: pointer to file
732 * @buf: user buffer to be filled with captured data
733 * @count: size of tthe buffer
734 * @offset: offset to start from
736 * This function is called when user tries to capture data
738 int intel_sst_read(struct file *file_ptr, char __user *buf,
739 size_t count, loff_t *offset)
741 struct ioctl_pvt_data *data = file_ptr->private_data;
742 int str_id = data->str_id;
743 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
745 pr_debug("called for %d\n", str_id);
746 if (stream->status == STREAM_UN_INIT ||
747 stream->status == STREAM_DECODE)
748 return -EBADRQC;
749 return intel_sst_read_write(str_id, buf, count);
753 * intel_sst_aio_read - aio read
755 * @kiocb: pointer to a structure containing file pointer
756 * @iov: list of user buffer to be filled with captured
757 * @nr_segs: number of entries
758 * @offset: offset to start from
760 * This function is called when user tries to capture out multiple data buffers
762 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
763 unsigned long nr_segs, loff_t offset)
765 int retval;
766 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
767 int str_id = data->str_id;
768 struct stream_info *stream;
770 pr_debug("entry - %ld\n", nr_segs);
772 if (is_sync_kiocb(kiocb) == false) {
773 pr_debug("aio_read from user space is not allowed\n");
774 return -EINVAL;
777 pr_debug("called for str_id %d\n", str_id);
778 retval = sst_validate_strid(str_id);
779 if (retval)
780 return -EINVAL;
781 stream = &sst_drv_ctx->streams[str_id];
782 if (stream->mmapped == true)
783 return -EIO;
784 if (stream->status == STREAM_UN_INIT ||
785 stream->status == STREAM_DECODE)
786 return -EBADRQC;
787 stream->curr_bytes = 0;
788 stream->cumm_bytes = 0;
790 pr_debug("new segs %ld, offset %d, status %d\n" ,
791 nr_segs, (int) offset, (int) stream->status);
792 stream->buf_type = SST_BUF_USER_STATIC;
793 do {
794 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
795 str_id, stream);
796 if (retval < 0)
797 break;
799 } while (stream->sg_index < nr_segs);
801 stream->sg_index = 0;
802 stream->cur_ptr = NULL;
803 if (retval >= 0)
804 retval = stream->cumm_bytes;
805 pr_debug("end of play/rec bytes = %d!!\n", retval);
806 return retval;
809 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
810 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
812 pr_debug("codec params:result = %d\n",
813 get_prm->codec_params.result);
814 pr_debug("codec params:stream = %d\n",
815 get_prm->codec_params.stream_id);
816 pr_debug("codec params:codec = %d\n",
817 get_prm->codec_params.codec);
818 pr_debug("codec params:ops = %d\n",
819 get_prm->codec_params.ops);
820 pr_debug("codec params:stream_type = %d\n",
821 get_prm->codec_params.stream_type);
822 pr_debug("pcmparams:sfreq = %d\n",
823 get_prm->pcm_params.sfreq);
824 pr_debug("pcmparams:num_chan = %d\n",
825 get_prm->pcm_params.num_chan);
826 pr_debug("pcmparams:pcm_wd_sz = %d\n",
827 get_prm->pcm_params.pcm_wd_sz);
828 return;
832 * sst_create_algo_ipc - create ipc msg for algorithm parameters
834 * @algo_params: Algorithm parameters
835 * @msg: post msg pointer
837 * This function is called to create ipc msg
839 int sst_create_algo_ipc(struct snd_ppp_params *algo_params,
840 struct ipc_post **msg)
842 if (sst_create_large_msg(msg))
843 return -ENOMEM;
844 sst_fill_header(&(*msg)->header,
845 IPC_IA_ALG_PARAMS, 1, algo_params->str_id);
846 (*msg)->header.part.data = sizeof(u32) +
847 sizeof(*algo_params) + algo_params->size;
848 memcpy((*msg)->mailbox_data, &(*msg)->header, sizeof(u32));
849 memcpy((*msg)->mailbox_data + sizeof(u32),
850 algo_params, sizeof(*algo_params));
851 return 0;
855 * sst_send_algo_ipc - send ipc msg for algorithm parameters
857 * @msg: post msg pointer
859 * This function is called to send ipc msg
861 int sst_send_algo_ipc(struct ipc_post **msg)
863 sst_drv_ctx->ppp_params_blk.condition = false;
864 sst_drv_ctx->ppp_params_blk.ret_code = 0;
865 sst_drv_ctx->ppp_params_blk.on = true;
866 sst_drv_ctx->ppp_params_blk.data = NULL;
867 spin_lock(&sst_drv_ctx->list_spin_lock);
868 list_add_tail(&(*msg)->node, &sst_drv_ctx->ipc_dispatch_list);
869 spin_unlock(&sst_drv_ctx->list_spin_lock);
870 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
871 return sst_wait_interruptible_timeout(sst_drv_ctx,
872 &sst_drv_ctx->ppp_params_blk, SST_BLOCK_TIMEOUT);
876 * intel_sst_ioctl_dsp - receives the device ioctl's
878 * @cmd:Ioctl cmd
879 * @arg:data
881 * This function is called when a user space component
882 * sends a DSP Ioctl to SST driver
884 long intel_sst_ioctl_dsp(unsigned int cmd, unsigned long arg)
886 int retval = 0;
887 struct snd_ppp_params algo_params;
888 struct snd_ppp_params *algo_params_copied;
889 struct ipc_post *msg;
891 switch (_IOC_NR(cmd)) {
892 case _IOC_NR(SNDRV_SST_SET_ALGO):
893 if (copy_from_user(&algo_params, (void __user *)arg,
894 sizeof(algo_params)))
895 return -EFAULT;
896 if (algo_params.size > SST_MAILBOX_SIZE)
897 return -EMSGSIZE;
899 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
900 algo_params.algo_id, algo_params.str_id,
901 algo_params.enable, algo_params.size);
902 retval = sst_create_algo_ipc(&algo_params, &msg);
903 if (retval)
904 break;
905 algo_params.reserved = 0;
906 if (copy_from_user(msg->mailbox_data + sizeof(algo_params),
907 algo_params.params, algo_params.size))
908 return -EFAULT;
910 retval = sst_send_algo_ipc(&msg);
911 if (retval) {
912 pr_debug("Error in sst_set_algo = %d\n", retval);
913 retval = -EIO;
915 break;
917 case _IOC_NR(SNDRV_SST_GET_ALGO):
918 if (copy_from_user(&algo_params, (void __user *)arg,
919 sizeof(algo_params)))
920 return -EFAULT;
921 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
922 algo_params.algo_id, algo_params.str_id,
923 algo_params.enable, algo_params.size);
924 retval = sst_create_algo_ipc(&algo_params, &msg);
925 if (retval)
926 break;
927 algo_params.reserved = 1;
928 retval = sst_send_algo_ipc(&msg);
929 if (retval) {
930 pr_debug("Error in sst_get_algo = %d\n", retval);
931 retval = -EIO;
932 break;
934 algo_params_copied = (struct snd_ppp_params *)
935 sst_drv_ctx->ppp_params_blk.data;
936 if (algo_params_copied->size > algo_params.size) {
937 pr_debug("mem insufficient to copy\n");
938 retval = -EMSGSIZE;
939 goto free_mem;
940 } else {
941 char __user *tmp;
943 if (copy_to_user(algo_params.params,
944 algo_params_copied->params,
945 algo_params_copied->size)) {
946 retval = -EFAULT;
947 goto free_mem;
949 tmp = (char __user *)arg + offsetof(
950 struct snd_ppp_params, size);
951 if (copy_to_user(tmp, &algo_params_copied->size,
952 sizeof(__u32))) {
953 retval = -EFAULT;
954 goto free_mem;
958 free_mem:
959 kfree(algo_params_copied->params);
960 kfree(algo_params_copied);
961 break;
963 return retval;
967 int sst_ioctl_tuning_params(unsigned long arg)
969 struct snd_sst_tuning_params params;
970 struct ipc_post *msg;
972 if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
973 return -EFAULT;
974 if (params.size > SST_MAILBOX_SIZE)
975 return -ENOMEM;
976 pr_debug("Parameter %d, Stream %d, Size %d\n", params.type,
977 params.str_id, params.size);
978 if (sst_create_large_msg(&msg))
979 return -ENOMEM;
981 sst_fill_header(&msg->header, IPC_IA_TUNING_PARAMS, 1, params.str_id);
982 msg->header.part.data = sizeof(u32) + sizeof(params) + params.size;
983 memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
984 memcpy(msg->mailbox_data + sizeof(u32), &params, sizeof(params));
985 if (copy_from_user(msg->mailbox_data + sizeof(params),
986 (void __user *)(unsigned long)params.addr,
987 params.size)) {
988 kfree(msg->mailbox_data);
989 kfree(msg);
990 return -EFAULT;
992 return sst_send_algo_ipc(&msg);
995 * intel_sst_ioctl - receives the device ioctl's
996 * @file_ptr:pointer to file
997 * @cmd:Ioctl cmd
998 * @arg:data
1000 * This function is called by OS when a user space component
1001 * sends an Ioctl to SST driver
1003 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
1005 int retval = 0;
1006 struct ioctl_pvt_data *data = NULL;
1007 int str_id = 0, minor = 0;
1009 data = file_ptr->private_data;
1010 if (data) {
1011 minor = 0;
1012 str_id = data->str_id;
1013 } else
1014 minor = 1;
1016 if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
1017 return -EBUSY;
1019 switch (_IOC_NR(cmd)) {
1020 case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
1021 pr_debug("IOCTL_PAUSE received for %d!\n", str_id);
1022 if (minor != STREAM_MODULE) {
1023 retval = -EBADRQC;
1024 break;
1026 retval = sst_pause_stream(str_id);
1027 break;
1029 case _IOC_NR(SNDRV_SST_STREAM_RESUME):
1030 pr_debug("SNDRV_SST_IOCTL_RESUME received!\n");
1031 if (minor != STREAM_MODULE) {
1032 retval = -EBADRQC;
1033 break;
1035 retval = sst_resume_stream(str_id);
1036 break;
1038 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
1039 struct snd_sst_params str_param;
1041 pr_debug("IOCTL_SET_PARAMS received!\n");
1042 if (minor != STREAM_MODULE) {
1043 retval = -EBADRQC;
1044 break;
1047 if (copy_from_user(&str_param, (void __user *)arg,
1048 sizeof(str_param))) {
1049 retval = -EFAULT;
1050 break;
1053 if (!str_id) {
1055 retval = sst_get_stream(&str_param);
1056 if (retval > 0) {
1057 struct stream_info *str_info;
1058 char __user *dest;
1060 sst_drv_ctx->stream_cnt++;
1061 data->str_id = retval;
1062 str_info = &sst_drv_ctx->streams[retval];
1063 str_info->src = SST_DRV;
1064 dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
1065 retval = copy_to_user(dest, &retval, sizeof(__u32));
1066 if (retval)
1067 retval = -EFAULT;
1068 } else {
1069 if (retval == -SST_ERR_INVALID_PARAMS)
1070 retval = -EINVAL;
1072 } else {
1073 pr_debug("SET_STREAM_PARAMS received!\n");
1074 /* allocated set params only */
1075 retval = sst_set_stream_param(str_id, &str_param);
1076 /* Block the call for reply */
1077 if (!retval) {
1078 int sfreq = 0, word_size = 0, num_channel = 0;
1079 sfreq = str_param.sparams.uc.pcm_params.sfreq;
1080 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
1081 num_channel = str_param.sparams.uc.pcm_params.num_chan;
1082 if (str_param.ops == STREAM_OPS_CAPTURE) {
1083 sst_drv_ctx->scard_ops->\
1084 set_pcm_audio_params(sfreq,
1085 word_size, num_channel);
1089 break;
1091 case _IOC_NR(SNDRV_SST_SET_VOL): {
1092 struct snd_sst_vol set_vol;
1094 if (copy_from_user(&set_vol, (void __user *)arg,
1095 sizeof(set_vol))) {
1096 pr_debug("copy failed\n");
1097 retval = -EFAULT;
1098 break;
1100 pr_debug("SET_VOLUME received for %d!\n",
1101 set_vol.stream_id);
1102 if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
1103 pr_debug("invalid operation!\n");
1104 retval = -EPERM;
1105 break;
1107 retval = sst_set_vol(&set_vol);
1108 break;
1110 case _IOC_NR(SNDRV_SST_GET_VOL): {
1111 struct snd_sst_vol get_vol;
1113 if (copy_from_user(&get_vol, (void __user *)arg,
1114 sizeof(get_vol))) {
1115 retval = -EFAULT;
1116 break;
1118 pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n",
1119 get_vol.stream_id);
1120 if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
1121 pr_debug("invalid operation!\n");
1122 retval = -EPERM;
1123 break;
1125 retval = sst_get_vol(&get_vol);
1126 if (retval) {
1127 retval = -EIO;
1128 break;
1130 pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
1131 get_vol.stream_id, get_vol.volume,
1132 get_vol.ramp_duration, get_vol.ramp_type);
1133 if (copy_to_user((struct snd_sst_vol __user *)arg,
1134 &get_vol, sizeof(get_vol))) {
1135 retval = -EFAULT;
1136 break;
1138 /*sst_print_get_vol_info(str_id, &get_vol);*/
1139 break;
1142 case _IOC_NR(SNDRV_SST_MUTE): {
1143 struct snd_sst_mute set_mute;
1145 if (copy_from_user(&set_mute, (void __user *)arg,
1146 sizeof(set_mute))) {
1147 retval = -EFAULT;
1148 break;
1150 pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n",
1151 set_mute.stream_id);
1152 if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
1153 retval = -EPERM;
1154 break;
1156 retval = sst_set_mute(&set_mute);
1157 break;
1159 case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
1160 struct snd_sst_get_stream_params get_params;
1162 pr_debug("IOCTL_GET_PARAMS received!\n");
1163 if (minor != 0) {
1164 retval = -EBADRQC;
1165 break;
1168 retval = sst_get_stream_params(str_id, &get_params);
1169 if (retval) {
1170 retval = -EIO;
1171 break;
1173 if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
1174 &get_params, sizeof(get_params))) {
1175 retval = -EFAULT;
1176 break;
1178 sst_print_stream_params(&get_params);
1179 break;
1182 case _IOC_NR(SNDRV_SST_MMAP_PLAY):
1183 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
1184 struct snd_sst_mmap_buffs mmap_buf;
1186 pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n");
1187 if (minor != STREAM_MODULE) {
1188 retval = -EBADRQC;
1189 break;
1191 if (copy_from_user(&mmap_buf, (void __user *)arg,
1192 sizeof(mmap_buf))) {
1193 retval = -EFAULT;
1194 break;
1196 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
1197 break;
1199 case _IOC_NR(SNDRV_SST_STREAM_DROP):
1200 pr_debug("SNDRV_SST_IOCTL_DROP received!\n");
1201 if (minor != STREAM_MODULE) {
1202 retval = -EINVAL;
1203 break;
1205 retval = sst_drop_stream(str_id);
1206 break;
1208 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1209 struct snd_sst_tstamp tstamp = {0};
1210 unsigned long long time, freq, mod;
1212 pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n");
1213 if (minor != STREAM_MODULE) {
1214 retval = -EBADRQC;
1215 break;
1217 memcpy_fromio(&tstamp,
1218 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1219 sizeof(tstamp));
1220 time = tstamp.samples_rendered;
1221 freq = (unsigned long long) tstamp.sampling_frequency;
1222 time = time * 1000; /* converting it to ms */
1223 mod = do_div(time, freq);
1224 if (copy_to_user((void __user *)arg, &time,
1225 sizeof(unsigned long long)))
1226 retval = -EFAULT;
1227 break;
1230 case _IOC_NR(SNDRV_SST_STREAM_START):{
1231 struct stream_info *stream;
1233 pr_debug("SNDRV_SST_STREAM_START received!\n");
1234 if (minor != STREAM_MODULE) {
1235 retval = -EINVAL;
1236 break;
1238 retval = sst_validate_strid(str_id);
1239 if (retval)
1240 break;
1241 stream = &sst_drv_ctx->streams[str_id];
1242 mutex_lock(&stream->lock);
1243 if (stream->status == STREAM_INIT &&
1244 stream->need_draining != true) {
1245 stream->prev = stream->status;
1246 stream->status = STREAM_RUNNING;
1247 if (stream->ops == STREAM_OPS_PLAYBACK ||
1248 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1249 retval = sst_play_frame(str_id);
1250 } else if (stream->ops == STREAM_OPS_CAPTURE)
1251 retval = sst_capture_frame(str_id);
1252 else {
1253 retval = -EINVAL;
1254 mutex_unlock(&stream->lock);
1255 break;
1257 if (retval < 0) {
1258 stream->status = STREAM_INIT;
1259 mutex_unlock(&stream->lock);
1260 break;
1262 } else {
1263 retval = -EINVAL;
1265 mutex_unlock(&stream->lock);
1266 break;
1269 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1270 struct snd_sst_target_device target_device;
1272 pr_debug("SET_TARGET_DEVICE received!\n");
1273 if (copy_from_user(&target_device, (void __user *)arg,
1274 sizeof(target_device))) {
1275 retval = -EFAULT;
1276 break;
1278 if (minor != AM_MODULE) {
1279 retval = -EBADRQC;
1280 break;
1282 retval = sst_target_device_select(&target_device);
1283 break;
1286 case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1287 struct snd_sst_driver_info info;
1289 pr_debug("SNDRV_SST_DRIVER_INFO received\n");
1290 info.version = SST_VERSION_NUM;
1291 /* hard coding, shud get sumhow later */
1292 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1293 sst_drv_ctx->encoded_cnt;
1294 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1295 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1296 info.max_enc_streams = MAX_ENC_STREAM;
1297 info.buf_per_stream = sst_drv_ctx->mmap_len;
1298 if (copy_to_user((void __user *)arg, &info,
1299 sizeof(info)))
1300 retval = -EFAULT;
1301 break;
1304 case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1305 struct snd_sst_dbufs param;
1306 struct snd_sst_dbufs dbufs_local;
1307 struct snd_sst_buffs ibufs, obufs;
1308 struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
1309 char __user *dest;
1311 pr_debug("SNDRV_SST_STREAM_DECODE received\n");
1312 if (minor != STREAM_MODULE) {
1313 retval = -EBADRQC;
1314 break;
1316 if (copy_from_user(&param, (void __user *)arg,
1317 sizeof(param))) {
1318 retval = -EFAULT;
1319 break;
1322 dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
1323 dbufs_local.output_bytes_produced =
1324 param.output_bytes_produced;
1326 if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
1327 retval = -EFAULT;
1328 break;
1330 if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
1331 retval = -EFAULT;
1332 break;
1335 ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
1336 obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
1337 if (!ibuf_tmp || !obuf_tmp) {
1338 retval = -ENOMEM;
1339 goto free_iobufs;
1342 if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
1343 ibufs.entries * sizeof(*ibuf_tmp))) {
1344 retval = -EFAULT;
1345 goto free_iobufs;
1347 ibufs.buff_entry = ibuf_tmp;
1348 dbufs_local.ibufs = &ibufs;
1350 if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
1351 obufs.entries * sizeof(*obuf_tmp))) {
1352 retval = -EFAULT;
1353 goto free_iobufs;
1355 obufs.buff_entry = obuf_tmp;
1356 dbufs_local.obufs = &obufs;
1358 retval = sst_decode(str_id, &dbufs_local);
1359 if (retval) {
1360 retval = -EAGAIN;
1361 goto free_iobufs;
1364 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1365 if (copy_to_user(dest,
1366 &dbufs_local.input_bytes_consumed,
1367 sizeof(unsigned long long))) {
1368 retval = -EFAULT;
1369 goto free_iobufs;
1372 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1373 if (copy_to_user(dest,
1374 &dbufs_local.output_bytes_produced,
1375 sizeof(unsigned long long))) {
1376 retval = -EFAULT;
1377 goto free_iobufs;
1379 free_iobufs:
1380 kfree(ibuf_tmp);
1381 kfree(obuf_tmp);
1382 break;
1385 case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1386 pr_debug("SNDRV_SST_STREAM_DRAIN received\n");
1387 if (minor != STREAM_MODULE) {
1388 retval = -EINVAL;
1389 break;
1391 retval = sst_drain_stream(str_id);
1392 break;
1394 case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1395 unsigned long long __user *bytes = (unsigned long long __user *)arg;
1396 struct snd_sst_tstamp tstamp = {0};
1398 pr_debug("STREAM_BYTES_DECODED received!\n");
1399 if (minor != STREAM_MODULE) {
1400 retval = -EINVAL;
1401 break;
1403 memcpy_fromio(&tstamp,
1404 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1405 sizeof(tstamp));
1406 if (copy_to_user(bytes, &tstamp.bytes_processed,
1407 sizeof(*bytes)))
1408 retval = -EFAULT;
1409 break;
1411 case _IOC_NR(SNDRV_SST_FW_INFO): {
1412 struct snd_sst_fw_info *fw_info;
1414 pr_debug("SNDRV_SST_FW_INFO received\n");
1416 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1417 if (!fw_info) {
1418 retval = -ENOMEM;
1419 break;
1421 retval = sst_get_fw_info(fw_info);
1422 if (retval) {
1423 retval = -EIO;
1424 kfree(fw_info);
1425 break;
1427 if (copy_to_user((struct snd_sst_dbufs __user *)arg,
1428 fw_info, sizeof(*fw_info))) {
1429 kfree(fw_info);
1430 retval = -EFAULT;
1431 break;
1433 /*sst_print_fw_info(fw_info);*/
1434 kfree(fw_info);
1435 break;
1437 case _IOC_NR(SNDRV_SST_GET_ALGO):
1438 case _IOC_NR(SNDRV_SST_SET_ALGO):
1439 if (minor != AM_MODULE) {
1440 retval = -EBADRQC;
1441 break;
1443 retval = intel_sst_ioctl_dsp(cmd, arg);
1444 break;
1446 case _IOC_NR(SNDRV_SST_TUNING_PARAMS):
1447 if (minor != AM_MODULE) {
1448 retval = -EBADRQC;
1449 break;
1451 retval = sst_ioctl_tuning_params(arg);
1452 break;
1454 default:
1455 retval = -EINVAL;
1457 pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval);
1458 return retval;