summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/sof/amd/acp-ipc.c8
-rw-r--r--sound/soc/sof/amd/acp.h5
-rw-r--r--sound/soc/sof/compress.c9
-rw-r--r--sound/soc/sof/intel/hda-ipc.c8
-rw-r--r--sound/soc/sof/intel/hda.h4
-rw-r--r--sound/soc/sof/ipc3-pcm.c3
-rw-r--r--sound/soc/sof/ipc3.c4
-rw-r--r--sound/soc/sof/mediatek/mt8186/mt8186.c2
-rw-r--r--sound/soc/sof/mediatek/mt8195/mt8195.c2
-rw-r--r--sound/soc/sof/ops.h8
-rw-r--r--sound/soc/sof/sof-priv.h11
-rw-r--r--sound/soc/sof/stream-ipc.c53
12 files changed, 81 insertions, 36 deletions
diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c
index 5a02753c4610..4e0c48a36159 100644
--- a/sound/soc/sof/amd/acp-ipc.c
+++ b/sound/soc/sof/amd/acp-ipc.c
@@ -200,14 +200,15 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
}
EXPORT_SYMBOL_NS(acp_sof_ipc_irq_thread, SND_SOC_SOF_AMD_COMMON);
-int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
+int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps,
void *p, size_t sz)
{
unsigned int offset = sdev->dsp_box.offset;
- if (!substream || !sdev->stream_box.size) {
+ if (!sps || !sdev->stream_box.size) {
acp_mailbox_read(sdev, offset, p, sz);
} else {
+ struct snd_pcm_substream *substream = sps->substream;
struct acp_dsp_stream *stream = substream->runtime->private_data;
if (!stream)
@@ -221,9 +222,10 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_pcm_substream *sub
EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, SND_SOC_SOF_AMD_COMMON);
int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset)
{
+ struct snd_pcm_substream *substream = sps->substream;
struct acp_dsp_stream *stream = substream->runtime->private_data;
/* check for unaligned offset or overflow */
diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h
index 4314094a97fd..39165ebf684b 100644
--- a/sound/soc/sof/amd/acp.h
+++ b/sound/soc/sof/amd/acp.h
@@ -12,6 +12,7 @@
#define __SOF_AMD_ACP_H
#include "../sof-priv.h"
+#include "../sof-audio.h"
#define ACP_MAX_STREAM 8
@@ -211,10 +212,10 @@ int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_ty
/* IPC callbacks */
irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context);
-int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
+int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps,
void *p, size_t sz);
int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset);
int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev,
struct snd_sof_ipc_msg *msg);
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c
index 8e1a9ba111ad..8d205eb16d2f 100644
--- a/sound/soc/sof/compress.c
+++ b/sound/soc/sof/compress.c
@@ -10,6 +10,7 @@
#include "sof-audio.h"
#include "sof-priv.h"
#include "sof-utils.h"
+#include "ops.h"
static void sof_set_transferred_bytes(struct sof_compr_stream *sstream,
u64 host_pos, u64 buffer_size)
@@ -237,6 +238,14 @@ static int sof_compr_set_params(struct snd_soc_component *component,
goto out;
}
+ ret = snd_sof_set_stream_data_offset(sdev, &spcm->stream[cstream->direction],
+ ipc_params_reply.posn_offset);
+ if (ret < 0) {
+ dev_err(component->dev, "Invalid stream data offset for Compr %d\n",
+ spcm->pcm.pcm_id);
+ goto out;
+ }
+
sstream->sampling_rate = params->codec.sample_rate;
sstream->channels = params->codec.ch_out;
sstream->sample_container_bytes = pcm->params.sample_container_bytes;
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c
index a7c454e03952..d7e16e6b6f52 100644
--- a/sound/soc/sof/intel/hda-ipc.c
+++ b/sound/soc/sof/intel/hda-ipc.c
@@ -361,12 +361,13 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
}
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz)
{
- if (!substream || !sdev->stream_box.size) {
+ if (!sps || !sdev->stream_box.size) {
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
} else {
+ struct snd_pcm_substream *substream = sps->substream;
struct hdac_stream *hstream = substream->runtime->private_data;
struct sof_intel_hda_stream *hda_stream;
@@ -385,9 +386,10 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev,
}
int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset)
{
+ struct snd_pcm_substream *substream = sps->substream;
struct hdac_stream *hstream = substream->runtime->private_data;
struct sof_intel_hda_stream *hda_stream;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index caccaf8fba9c..b3080b82ca25 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -656,10 +656,10 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
int enable, u32 size);
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz);
int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset);
/*
diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
index f10bfc9bd5cb..b29d93e0d216 100644
--- a/sound/soc/sof/ipc3-pcm.c
+++ b/sound/soc/sof/ipc3-pcm.c
@@ -129,7 +129,8 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
return ret;
}
- ret = snd_sof_set_stream_data_offset(sdev, substream, ipc_params_reply.posn_offset);
+ ret = snd_sof_set_stream_data_offset(sdev, &spcm->stream[substream->stream],
+ ipc_params_reply.posn_offset);
if (ret < 0) {
dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n",
__func__, spcm->pcm.pcm_id);
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 1fef4dcc0936..8e936353c1c0 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -847,7 +847,7 @@ static void ipc3_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
}
stream = &spcm->stream[direction];
- ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return;
@@ -882,7 +882,7 @@ static void ipc3_xrun(struct snd_sof_dev *sdev, u32 msg_id)
}
stream = &spcm->stream[direction];
- ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
if (ret < 0) {
dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
return;
diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c
index dbea604ebc04..597cb4476acb 100644
--- a/sound/soc/sof/mediatek/mt8186/mt8186.c
+++ b/sound/soc/sof/mediatek/mt8186/mt8186.c
@@ -494,7 +494,7 @@ static snd_pcm_uframes_t mt8186_pcm_pointer(struct snd_sof_dev *sdev,
}
stream = &spcm->stream[substream->stream];
- ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return 0;
diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c
index 5b04fec9c9c9..42bae574c87a 100644
--- a/sound/soc/sof/mediatek/mt8195/mt8195.c
+++ b/sound/soc/sof/mediatek/mt8195/mt8195.c
@@ -520,7 +520,7 @@ static snd_pcm_uframes_t mt8195_pcm_pointer(struct snd_sof_dev *sdev,
}
stream = &spcm->stream[substream->stream];
- ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return 0;
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index c52752250565..febe318b9427 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -472,19 +472,19 @@ static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
/* host DSP message data */
static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz)
{
- return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
+ return sof_ops(sdev)->ipc_msg_data(sdev, sps, p, sz);
}
/* host side configuration of the stream's data offset in stream mailbox area */
static inline int
snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset)
{
if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset)
- return sof_ops(sdev)->set_stream_data_offset(sdev, substream,
+ return sof_ops(sdev)->set_stream_data_offset(sdev, sps,
posn_offset);
return 0;
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 752bf46c7bc9..86fc5c6a9c39 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -20,6 +20,8 @@
#include <uapi/sound/sof/fw.h>
#include <sound/sof/ext_manifest.h>
+struct snd_sof_pcm_stream;
+
/* Flag definitions used in sof_core_debug (sof_debug module parameter) */
#define SOF_DBG_ENABLE_TRACE BIT(0)
#define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */
@@ -113,6 +115,7 @@ struct sof_compr_stream {
u32 sampling_rate;
u16 channels;
u16 sample_container_bytes;
+ size_t posn_offset;
};
struct snd_sof_dev;
@@ -247,12 +250,12 @@ struct snd_sof_dsp_ops {
/* host read DSP stream data */
int (*ipc_msg_data)(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz); /* mandatory */
/* host side configuration of the stream's data offset in stream mailbox area */
int (*set_stream_data_offset)(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset); /* optional */
/* pre/post firmware run */
@@ -761,10 +764,10 @@ int sof_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
u32 offset, void *dest, size_t size);
int sof_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz);
int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset);
int sof_stream_pcm_open(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/stream-ipc.c b/sound/soc/sof/stream-ipc.c
index 5f1ceeea893a..216b454f6b94 100644
--- a/sound/soc/sof/stream-ipc.c
+++ b/sound/soc/sof/stream-ipc.c
@@ -19,6 +19,7 @@
#include "ops.h"
#include "sof-priv.h"
+#include "sof-audio.h"
struct sof_stream {
size_t posn_offset;
@@ -26,19 +27,33 @@ struct sof_stream {
/* Mailbox-based Generic IPC implementation */
int sof_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
void *p, size_t sz)
{
- if (!substream || !sdev->stream_box.size) {
+ if (!sps || !sdev->stream_box.size) {
snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
} else {
- struct sof_stream *stream = substream->runtime->private_data;
+ size_t posn_offset;
- /* The stream might already be closed */
- if (!stream)
- return -ESTRPIPE;
+ if (sps->substream) {
+ struct sof_stream *stream = sps->substream->runtime->private_data;
- snd_sof_dsp_mailbox_read(sdev, stream->posn_offset, p, sz);
+ /* The stream might already be closed */
+ if (!stream)
+ return -ESTRPIPE;
+
+ posn_offset = stream->posn_offset;
+ } else {
+
+ struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
+
+ if (!sstream)
+ return -ESTRPIPE;
+
+ posn_offset = sstream->posn_offset;
+ }
+
+ snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz);
}
return 0;
@@ -46,20 +61,32 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
EXPORT_SYMBOL(sof_ipc_msg_data);
int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
+ struct snd_sof_pcm_stream *sps,
size_t posn_offset)
{
- struct sof_stream *stream = substream->runtime->private_data;
-
/* check if offset is overflow or it is not aligned */
if (posn_offset > sdev->stream_box.size ||
posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
return -EINVAL;
- stream->posn_offset = sdev->stream_box.offset + posn_offset;
+ posn_offset += sdev->stream_box.offset;
+
+ if (sps->substream) {
+ struct sof_stream *stream = sps->substream->runtime->private_data;
+
+ stream->posn_offset = posn_offset;
+ dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
+ sps->substream->stream, posn_offset);
+ } else if (sps->cstream) {
+ struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
- dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
- substream->stream, stream->posn_offset);
+ sstream->posn_offset = posn_offset;
+ dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu",
+ sps->cstream->direction, posn_offset);
+ } else {
+ dev_err(sdev->dev, "No stream opened");
+ return -EINVAL;
+ }
return 0;
}