Commit | Line | Data |
---|---|---|
e149ca29 | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
351d1174 GL |
2 | // |
3 | // This file is provided under a dual BSD/GPLv2 license. When using or | |
4 | // redistributing this file, you may do so under either license. | |
5 | // | |
6 | // Copyright(c) 2019 Intel Corporation. All rights reserved. | |
7 | // | |
8 | // Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> | |
9 | ||
97e22cbd | 10 | /* Generic SOF IPC code */ |
351d1174 GL |
11 | |
12 | #include <linux/device.h> | |
13 | #include <linux/export.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/types.h> | |
16 | ||
17 | #include <sound/pcm.h> | |
18 | #include <sound/sof/stream.h> | |
19 | ||
97e22cbd BLA |
20 | #include "ops.h" |
21 | #include "sof-priv.h" | |
1b905942 | 22 | #include "sof-audio.h" |
351d1174 | 23 | |
97e22cbd | 24 | struct sof_stream { |
351d1174 GL |
25 | size_t posn_offset; |
26 | }; | |
27 | ||
97e22cbd BLA |
28 | /* Mailbox-based Generic IPC implementation */ |
29 | int sof_ipc_msg_data(struct snd_sof_dev *sdev, | |
1b905942 | 30 | struct snd_sof_pcm_stream *sps, |
97e22cbd | 31 | void *p, size_t sz) |
351d1174 | 32 | { |
1b905942 | 33 | if (!sps || !sdev->stream_box.size) { |
97e22cbd | 34 | snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); |
351d1174 | 35 | } else { |
090349a9 | 36 | size_t posn_offset; |
351d1174 | 37 | |
090349a9 DB |
38 | if (sps->substream) { |
39 | struct sof_stream *stream = sps->substream->runtime->private_data; | |
6a0ba071 | 40 | |
090349a9 DB |
41 | /* The stream might already be closed */ |
42 | if (!stream) | |
43 | return -ESTRPIPE; | |
44 | ||
45 | posn_offset = stream->posn_offset; | |
46 | } else { | |
47 | ||
48 | struct sof_compr_stream *sstream = sps->cstream->runtime->private_data; | |
49 | ||
50 | if (!sstream) | |
51 | return -ESTRPIPE; | |
52 | ||
53 | posn_offset = sstream->posn_offset; | |
54 | } | |
55 | ||
56 | snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz); | |
351d1174 | 57 | } |
6a0ba071 GL |
58 | |
59 | return 0; | |
351d1174 | 60 | } |
97e22cbd | 61 | EXPORT_SYMBOL(sof_ipc_msg_data); |
351d1174 | 62 | |
9a0a809a | 63 | int sof_set_stream_data_offset(struct snd_sof_dev *sdev, |
249f186d | 64 | struct snd_sof_pcm_stream *sps, |
9a0a809a | 65 | size_t posn_offset) |
351d1174 | 66 | { |
351d1174 GL |
67 | /* check if offset is overflow or it is not aligned */ |
68 | if (posn_offset > sdev->stream_box.size || | |
69 | posn_offset % sizeof(struct sof_ipc_stream_posn) != 0) | |
70 | return -EINVAL; | |
71 | ||
090349a9 DB |
72 | posn_offset += sdev->stream_box.offset; |
73 | ||
74 | if (sps->substream) { | |
75 | struct sof_stream *stream = sps->substream->runtime->private_data; | |
76 | ||
77 | stream->posn_offset = posn_offset; | |
78 | dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu", | |
79 | sps->substream->stream, posn_offset); | |
80 | } else if (sps->cstream) { | |
81 | struct sof_compr_stream *sstream = sps->cstream->runtime->private_data; | |
351d1174 | 82 | |
090349a9 DB |
83 | sstream->posn_offset = posn_offset; |
84 | dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu", | |
85 | sps->cstream->direction, posn_offset); | |
86 | } else { | |
87 | dev_err(sdev->dev, "No stream opened"); | |
88 | return -EINVAL; | |
89 | } | |
351d1174 GL |
90 | |
91 | return 0; | |
92 | } | |
9a0a809a PU |
93 | EXPORT_SYMBOL(sof_set_stream_data_offset); |
94 | ||
97e22cbd BLA |
95 | int sof_stream_pcm_open(struct snd_sof_dev *sdev, |
96 | struct snd_pcm_substream *substream) | |
351d1174 | 97 | { |
97e22cbd | 98 | struct sof_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL); |
351d1174 GL |
99 | |
100 | if (!stream) | |
101 | return -ENOMEM; | |
102 | ||
103 | /* binding pcm substream to hda stream */ | |
104 | substream->runtime->private_data = stream; | |
105 | ||
caebea04 KV |
106 | /* align to DMA minimum transfer size */ |
107 | snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); | |
108 | ||
109 | /* avoid circular buffer wrap in middle of period */ | |
110 | snd_pcm_hw_constraint_integer(substream->runtime, | |
111 | SNDRV_PCM_HW_PARAM_PERIODS); | |
112 | ||
351d1174 GL |
113 | return 0; |
114 | } | |
97e22cbd | 115 | EXPORT_SYMBOL(sof_stream_pcm_open); |
351d1174 | 116 | |
97e22cbd BLA |
117 | int sof_stream_pcm_close(struct snd_sof_dev *sdev, |
118 | struct snd_pcm_substream *substream) | |
351d1174 | 119 | { |
97e22cbd | 120 | struct sof_stream *stream = substream->runtime->private_data; |
351d1174 GL |
121 | |
122 | substream->runtime->private_data = NULL; | |
123 | kfree(stream); | |
124 | ||
125 | return 0; | |
126 | } | |
97e22cbd | 127 | EXPORT_SYMBOL(sof_stream_pcm_close); |
351d1174 GL |
128 | |
129 | MODULE_LICENSE("Dual BSD/GPL"); |