| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 |
|
| 10 |
|
| 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 |
|
| 20 | #include "ops.h"
|
| 21 | #include "sof-priv.h"
|
| 22 | #include "sof-audio.h"
|
| 23 |
|
| 24 | struct sof_stream {
|
| 25 | size_t posn_offset;
|
| 26 | };
|
| 27 |
|
| 28 |
|
| 29 | int sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
| 30 | struct snd_sof_pcm_stream *sps,
|
| 31 | void *p, size_t sz)
|
| 32 | {
|
| 33 | if (!sps || !sdev->stream_box.size) {
|
| 34 | snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
| 35 | } else {
|
| 36 | size_t posn_offset;
|
| 37 |
|
| 38 | if (sps->substream) {
|
| 39 | struct sof_stream *stream = sps->substream->runtime->private_data;
|
| 40 |
|
| 41 |
|
| 42 | if (!stream)
|
| 43 | return -ESTRPIPE;
|
| 44 |
|
| 45 | posn_offset = stream->posn_offset;
|
| 46 | } else if (sps->cstream) {
|
| 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 | } else {
|
| 56 | dev_err(sdev->dev, "%s: No stream opened\n", __func__);
|
| 57 | return -EINVAL;
|
| 58 | }
|
| 59 |
|
| 60 | snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz);
|
| 61 | }
|
| 62 |
|
| 63 | return 0;
|
| 64 | }
|
| 65 | EXPORT_SYMBOL(sof_ipc_msg_data);
|
| 66 |
|
| 67 | int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
|
| 68 | struct snd_sof_pcm_stream *sps,
|
| 69 | size_t posn_offset)
|
| 70 | {
|
| 71 |
|
| 72 | if (posn_offset > sdev->stream_box.size ||
|
| 73 | posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
|
| 74 | return -EINVAL;
|
| 75 |
|
| 76 | posn_offset += sdev->stream_box.offset;
|
| 77 |
|
| 78 | if (sps->substream) {
|
| 79 | struct sof_stream *stream = sps->substream->runtime->private_data;
|
| 80 |
|
| 81 | stream->posn_offset = posn_offset;
|
| 82 | dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
|
| 83 | sps->substream->stream, posn_offset);
|
| 84 | } else if (sps->cstream) {
|
| 85 | struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
|
| 86 |
|
| 87 | sstream->posn_offset = posn_offset;
|
| 88 | dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu",
|
| 89 | sps->cstream->direction, posn_offset);
|
| 90 | } else {
|
| 91 | dev_err(sdev->dev, "No stream opened");
|
| 92 | return -EINVAL;
|
| 93 | }
|
| 94 |
|
| 95 | return 0;
|
| 96 | }
|
| 97 | EXPORT_SYMBOL(sof_set_stream_data_offset);
|
| 98 |
|
| 99 | int sof_stream_pcm_open(struct snd_sof_dev *sdev,
|
| 100 | struct snd_pcm_substream *substream)
|
| 101 | {
|
| 102 | struct sof_stream *stream = kmalloc_obj(*stream);
|
| 103 |
|
| 104 | if (!stream)
|
| 105 | return -ENOMEM;
|
| 106 |
|
| 107 |
|
| 108 | substream->runtime->private_data = stream;
|
| 109 |
|
| 110 |
|
| 111 | snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
|
| 112 |
|
| 113 |
|
| 114 | snd_pcm_hw_constraint_integer(substream->runtime,
|
| 115 | SNDRV_PCM_HW_PARAM_PERIODS);
|
| 116 |
|
| 117 | return 0;
|
| 118 | }
|
| 119 | EXPORT_SYMBOL(sof_stream_pcm_open);
|
| 120 |
|
| 121 | int sof_stream_pcm_close(struct snd_sof_dev *sdev,
|
| 122 | struct snd_pcm_substream *substream)
|
| 123 | {
|
| 124 | struct sof_stream *stream = substream->runtime->private_data;
|
| 125 |
|
| 126 | substream->runtime->private_data = NULL;
|
| 127 | kfree(stream);
|
| 128 |
|
| 129 | return 0;
|
| 130 | }
|
| 131 | EXPORT_SYMBOL(sof_stream_pcm_close);
|