Commit ae7c40bc authored by Mark Brown's avatar Mark Brown

Add support to compress API to ipc_msg_data /

Merge series from Daniel Baluta <daniel.baluta@oss.nxp.com>:

This patch series adds compress API support to ipc_msg_data /
set_stream_data_offset callbacks.

Changes since v1:
	- fixed reviewed-by list (+Peter, -Pierre). Since github had
	  some glitches I added the reviews received manually in the
          commits.
	- Github PR link: https://github.com/thesofproject/linux/pull/4133

Daniel Baluta (4):
  ASoC: SOF: Prepare ipc_msg_data to be used with compress API
  ASoC: SOF: Prepare set_stream_data_offset for compress API
  ASoC: SOF: Add support for compress API for stream data/offset
  ASoC: SOF: compress: Set compress data offset

 sound/soc/sof/amd/acp-ipc.c            |  8 ++--
 sound/soc/sof/amd/acp.h                |  5 ++-
 sound/soc/sof/compress.c               |  9 +++++
 sound/soc/sof/intel/hda-ipc.c          |  8 ++--
 sound/soc/sof/intel/hda.h              |  4 +-
 sound/soc/sof/ipc3-pcm.c               |  3 +-
 sound/soc/sof/ipc3.c                   |  4 +-
 sound/soc/sof/mediatek/mt8186/mt8186.c |  2 +-
 sound/soc/sof/mediatek/mt8195/mt8195.c |  2 +-
 sound/soc/sof/ops.h                    |  8 ++--
 sound/soc/sof/sof-priv.h               | 11 ++++--
 sound/soc/sof/stream-ipc.c             | 53 +++++++++++++++++++-------
 12 files changed, 81 insertions(+), 36 deletions(-)

--
2.25.1
parents 309d4014 a9737808
...@@ -200,14 +200,15 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) ...@@ -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); 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) void *p, size_t sz)
{ {
unsigned int offset = sdev->dsp_box.offset; 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); acp_mailbox_read(sdev, offset, p, sz);
} else { } else {
struct snd_pcm_substream *substream = sps->substream;
struct acp_dsp_stream *stream = substream->runtime->private_data; struct acp_dsp_stream *stream = substream->runtime->private_data;
if (!stream) if (!stream)
...@@ -221,9 +222,10 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_pcm_substream *sub ...@@ -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); EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, SND_SOC_SOF_AMD_COMMON);
int acp_set_stream_data_offset(struct snd_sof_dev *sdev, 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) size_t posn_offset)
{ {
struct snd_pcm_substream *substream = sps->substream;
struct acp_dsp_stream *stream = substream->runtime->private_data; struct acp_dsp_stream *stream = substream->runtime->private_data;
/* check for unaligned offset or overflow */ /* check for unaligned offset or overflow */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define __SOF_AMD_ACP_H #define __SOF_AMD_ACP_H
#include "../sof-priv.h" #include "../sof-priv.h"
#include "../sof-audio.h"
#define ACP_MAX_STREAM 8 #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 ...@@ -211,10 +212,10 @@ int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_ty
/* IPC callbacks */ /* IPC callbacks */
irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context); 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); void *p, size_t sz);
int acp_set_stream_data_offset(struct snd_sof_dev *sdev, 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); size_t posn_offset);
int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev,
struct snd_sof_ipc_msg *msg); struct snd_sof_ipc_msg *msg);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "sof-audio.h" #include "sof-audio.h"
#include "sof-priv.h" #include "sof-priv.h"
#include "sof-utils.h" #include "sof-utils.h"
#include "ops.h"
static void sof_set_transferred_bytes(struct sof_compr_stream *sstream, static void sof_set_transferred_bytes(struct sof_compr_stream *sstream,
u64 host_pos, u64 buffer_size) u64 host_pos, u64 buffer_size)
...@@ -237,6 +238,14 @@ static int sof_compr_set_params(struct snd_soc_component *component, ...@@ -237,6 +238,14 @@ static int sof_compr_set_params(struct snd_soc_component *component,
goto out; 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->sampling_rate = params->codec.sample_rate;
sstream->channels = params->codec.ch_out; sstream->channels = params->codec.ch_out;
sstream->sample_container_bytes = pcm->params.sample_container_bytes; sstream->sample_container_bytes = pcm->params.sample_container_bytes;
......
...@@ -361,12 +361,13 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) ...@@ -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, 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) 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); sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
} else { } else {
struct snd_pcm_substream *substream = sps->substream;
struct hdac_stream *hstream = substream->runtime->private_data; struct hdac_stream *hstream = substream->runtime->private_data;
struct sof_intel_hda_stream *hda_stream; struct sof_intel_hda_stream *hda_stream;
...@@ -385,9 +386,10 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev, ...@@ -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, 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) size_t posn_offset)
{ {
struct snd_pcm_substream *substream = sps->substream;
struct hdac_stream *hstream = substream->runtime->private_data; struct hdac_stream *hstream = substream->runtime->private_data;
struct sof_intel_hda_stream *hda_stream; struct sof_intel_hda_stream *hda_stream;
......
...@@ -656,10 +656,10 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, ...@@ -656,10 +656,10 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
int enable, u32 size); int enable, u32 size);
int hda_ipc_msg_data(struct snd_sof_dev *sdev, 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); void *p, size_t sz);
int hda_set_stream_data_offset(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); size_t posn_offset);
/* /*
......
...@@ -129,7 +129,8 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, ...@@ -129,7 +129,8 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
return ret; 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) { if (ret < 0) {
dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n", dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n",
__func__, spcm->pcm.pcm_id); __func__, spcm->pcm.pcm_id);
......
...@@ -847,7 +847,7 @@ static void ipc3_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id) ...@@ -847,7 +847,7 @@ static void ipc3_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
} }
stream = &spcm->stream[direction]; 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) { if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return; return;
...@@ -882,7 +882,7 @@ static void ipc3_xrun(struct snd_sof_dev *sdev, u32 msg_id) ...@@ -882,7 +882,7 @@ static void ipc3_xrun(struct snd_sof_dev *sdev, u32 msg_id)
} }
stream = &spcm->stream[direction]; 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) { if (ret < 0) {
dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret); dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
return; return;
......
...@@ -494,7 +494,7 @@ static snd_pcm_uframes_t mt8186_pcm_pointer(struct snd_sof_dev *sdev, ...@@ -494,7 +494,7 @@ static snd_pcm_uframes_t mt8186_pcm_pointer(struct snd_sof_dev *sdev,
} }
stream = &spcm->stream[substream->stream]; 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) { if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return 0; return 0;
......
...@@ -520,7 +520,7 @@ static snd_pcm_uframes_t mt8195_pcm_pointer(struct snd_sof_dev *sdev, ...@@ -520,7 +520,7 @@ static snd_pcm_uframes_t mt8195_pcm_pointer(struct snd_sof_dev *sdev,
} }
stream = &spcm->stream[substream->stream]; 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) { if (ret < 0) {
dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
return 0; return 0;
......
...@@ -472,19 +472,19 @@ static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev) ...@@ -472,19 +472,19 @@ static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
/* host DSP message data */ /* host DSP message data */
static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev, 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) 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 */ /* host side configuration of the stream's data offset in stream mailbox area */
static inline int static inline int
snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev, 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) size_t posn_offset)
{ {
if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_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); posn_offset);
return 0; return 0;
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <uapi/sound/sof/fw.h> #include <uapi/sound/sof/fw.h>
#include <sound/sof/ext_manifest.h> #include <sound/sof/ext_manifest.h>
struct snd_sof_pcm_stream;
/* Flag definitions used in sof_core_debug (sof_debug module parameter) */ /* Flag definitions used in sof_core_debug (sof_debug module parameter) */
#define SOF_DBG_ENABLE_TRACE BIT(0) #define SOF_DBG_ENABLE_TRACE BIT(0)
#define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */ #define SOF_DBG_RETAIN_CTX BIT(1) /* prevent DSP D3 on FW exception */
...@@ -113,6 +115,7 @@ struct sof_compr_stream { ...@@ -113,6 +115,7 @@ struct sof_compr_stream {
u32 sampling_rate; u32 sampling_rate;
u16 channels; u16 channels;
u16 sample_container_bytes; u16 sample_container_bytes;
size_t posn_offset;
}; };
struct snd_sof_dev; struct snd_sof_dev;
...@@ -247,12 +250,12 @@ struct snd_sof_dsp_ops { ...@@ -247,12 +250,12 @@ struct snd_sof_dsp_ops {
/* host read DSP stream data */ /* host read DSP stream data */
int (*ipc_msg_data)(struct snd_sof_dev *sdev, 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 */ void *p, size_t sz); /* mandatory */
/* host side configuration of the stream's data offset in stream mailbox area */ /* host side configuration of the stream's data offset in stream mailbox area */
int (*set_stream_data_offset)(struct snd_sof_dev *sdev, 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 */ size_t posn_offset); /* optional */
/* pre/post firmware run */ /* 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, ...@@ -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); u32 offset, void *dest, size_t size);
int sof_ipc_msg_data(struct snd_sof_dev *sdev, 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); void *p, size_t sz);
int sof_set_stream_data_offset(struct snd_sof_dev *sdev, 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); size_t posn_offset);
int sof_stream_pcm_open(struct snd_sof_dev *sdev, int sof_stream_pcm_open(struct snd_sof_dev *sdev,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ops.h" #include "ops.h"
#include "sof-priv.h" #include "sof-priv.h"
#include "sof-audio.h"
struct sof_stream { struct sof_stream {
size_t posn_offset; size_t posn_offset;
...@@ -26,19 +27,33 @@ struct sof_stream { ...@@ -26,19 +27,33 @@ struct sof_stream {
/* Mailbox-based Generic IPC implementation */ /* Mailbox-based Generic IPC implementation */
int sof_ipc_msg_data(struct snd_sof_dev *sdev, 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) 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); snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
} else { } else {
struct sof_stream *stream = substream->runtime->private_data; size_t posn_offset;
if (sps->substream) {
struct sof_stream *stream = sps->substream->runtime->private_data;
/* The stream might already be closed */ /* The stream might already be closed */
if (!stream) if (!stream)
return -ESTRPIPE; return -ESTRPIPE;
snd_sof_dsp_mailbox_read(sdev, stream->posn_offset, p, sz); 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; return 0;
...@@ -46,20 +61,32 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev, ...@@ -46,20 +61,32 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
EXPORT_SYMBOL(sof_ipc_msg_data); EXPORT_SYMBOL(sof_ipc_msg_data);
int sof_set_stream_data_offset(struct snd_sof_dev *sdev, 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) size_t posn_offset)
{ {
struct sof_stream *stream = substream->runtime->private_data;
/* check if offset is overflow or it is not aligned */ /* check if offset is overflow or it is not aligned */
if (posn_offset > sdev->stream_box.size || if (posn_offset > sdev->stream_box.size ||
posn_offset % sizeof(struct sof_ipc_stream_posn) != 0) posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
return -EINVAL; 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", dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
substream->stream, stream->posn_offset); sps->substream->stream, posn_offset);
} else if (sps->cstream) {
struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment