Make the SOF pcm_hw_params DSP op IPC agnostic
Merge series from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>: In preparation for supporting the newly introduced IPC version in the SOF firmware, this patchset adds the changes required to make the pcm_hw_params DSP op IPC agnostic.
This commit is contained in:
commit
8fc2622659
@ -17,7 +17,8 @@
|
||||
#include "acp-dsp-offset.h"
|
||||
|
||||
int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, struct sof_ipc_stream_params *ipc_params)
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_sof_platform_stream_params *platform_params)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct acp_dsp_stream *stream = runtime->private_data;
|
||||
@ -35,8 +36,9 @@ int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substr
|
||||
return ret;
|
||||
}
|
||||
|
||||
ipc_params->buffer.phy_addr = stream->reg_offset;
|
||||
ipc_params->stream_tag = stream->stream_tag;
|
||||
platform_params->use_phy_address = true;
|
||||
platform_params->phy_addr = stream->reg_offset;
|
||||
platform_params->stream_tag = stream->stream_tag;
|
||||
|
||||
/* write buffer size of stream in scratch memory */
|
||||
|
||||
|
@ -201,7 +201,8 @@ int acp_dsp_stream_put(struct snd_sof_dev *sdev, struct acp_dsp_stream *acp_stre
|
||||
int acp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream);
|
||||
int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream);
|
||||
int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, struct sof_ipc_stream_params *ipc_params);
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_sof_platform_stream_params *platform_params);
|
||||
|
||||
extern const struct snd_sof_dsp_ops sof_renoir_ops;
|
||||
|
||||
|
@ -361,8 +361,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
|
||||
if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run ||
|
||||
!sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write ||
|
||||
!sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware ||
|
||||
!sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params ||
|
||||
!sof_ops(sdev)->fw_ready) {
|
||||
!sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->fw_ready) {
|
||||
dev_err(dev, "error: missing mandatory ops\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ static const struct snd_sof_dsp_ops sof_imx8_ops = {
|
||||
.get_window_offset = imx8_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* module loading */
|
||||
.load_module = snd_sof_parse_module_memcpy,
|
||||
@ -572,7 +572,7 @@ static const struct snd_sof_dsp_ops sof_imx8x_ops = {
|
||||
.get_window_offset = imx8_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* module loading */
|
||||
.load_module = snd_sof_parse_module_memcpy,
|
||||
|
@ -435,7 +435,7 @@ static const struct snd_sof_dsp_ops sof_imx8m_ops = {
|
||||
.get_window_offset = imx8m_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* module loading */
|
||||
.load_module = snd_sof_parse_module_memcpy,
|
||||
|
@ -56,7 +56,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
|
||||
.get_window_offset = hda_dsp_ipc_get_window_offset,
|
||||
|
||||
.ipc_msg_data = hda_ipc_msg_data,
|
||||
.ipc_pcm_params = hda_ipc_pcm_params,
|
||||
.set_stream_data_offset = hda_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = hda_machine_select,
|
||||
|
@ -596,7 +596,7 @@ static const struct snd_sof_dsp_ops sof_bdw_ops = {
|
||||
.get_window_offset = bdw_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = bdw_machine_select,
|
||||
|
@ -250,7 +250,7 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
|
||||
.get_window_offset = atom_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = atom_machine_select,
|
||||
@ -332,7 +332,7 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
|
||||
.get_window_offset = atom_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = atom_machine_select,
|
||||
|
@ -274,7 +274,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
|
||||
.get_window_offset = hda_dsp_ipc_get_window_offset,
|
||||
|
||||
.ipc_msg_data = hda_ipc_msg_data,
|
||||
.ipc_pcm_params = hda_ipc_pcm_params,
|
||||
.set_stream_data_offset = hda_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = hda_machine_select,
|
||||
|
@ -267,14 +267,12 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply)
|
||||
int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
size_t posn_offset)
|
||||
{
|
||||
struct hdac_stream *hstream = substream->runtime->private_data;
|
||||
struct sof_intel_hda_stream *hda_stream;
|
||||
/* validate offset */
|
||||
size_t posn_offset = reply->posn_offset;
|
||||
|
||||
hda_stream = container_of(hstream, struct sof_intel_hda_stream,
|
||||
hext_stream.hstream);
|
||||
|
@ -93,13 +93,12 @@ u32 hda_dsp_get_bits(struct snd_sof_dev *sdev, int sample_bits)
|
||||
int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params)
|
||||
struct snd_sof_platform_stream_params *platform_params)
|
||||
{
|
||||
struct hdac_stream *hstream = substream->runtime->private_data;
|
||||
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
|
||||
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
|
||||
struct snd_dma_buffer *dmab;
|
||||
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
|
||||
int ret;
|
||||
u32 size, rate, bits;
|
||||
|
||||
@ -130,19 +129,10 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
|
||||
else
|
||||
hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0);
|
||||
|
||||
/* update no_stream_position flag for ipc params */
|
||||
if (hda && hda->no_ipc_position) {
|
||||
/* For older ABIs set host_period_bytes to zero to inform
|
||||
* FW we don't want position updates. Newer versions use
|
||||
* no_stream_position for this purpose.
|
||||
*/
|
||||
if (v->abi_version < SOF_ABI_VER(3, 10, 0))
|
||||
ipc_params->host_period_bytes = 0;
|
||||
else
|
||||
ipc_params->no_stream_position = 1;
|
||||
}
|
||||
if (hda)
|
||||
platform_params->no_ipc_position = hda->no_ipc_position;
|
||||
|
||||
ipc_params->stream_tag = hstream->stream_tag;
|
||||
platform_params->stream_tag = hstream->stream_tag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -524,7 +524,7 @@ int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
|
||||
int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params);
|
||||
struct snd_sof_platform_stream_params *platform_params);
|
||||
int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream);
|
||||
int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
|
||||
@ -566,9 +566,9 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
|
||||
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
void *p, size_t sz);
|
||||
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply);
|
||||
int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
size_t posn_offset);
|
||||
|
||||
/*
|
||||
* DSP IPC Operations.
|
||||
|
@ -118,7 +118,7 @@ const struct snd_sof_dsp_ops sof_icl_ops = {
|
||||
.get_window_offset = hda_dsp_ipc_get_window_offset,
|
||||
|
||||
.ipc_msg_data = hda_ipc_msg_data,
|
||||
.ipc_pcm_params = hda_ipc_pcm_params,
|
||||
.set_stream_data_offset = hda_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = hda_machine_select,
|
||||
|
@ -165,7 +165,7 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
|
||||
.get_window_offset = atom_get_window_offset,
|
||||
|
||||
.ipc_msg_data = sof_ipc_msg_data,
|
||||
.ipc_pcm_params = sof_ipc_pcm_params,
|
||||
.set_stream_data_offset = sof_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = atom_machine_select,
|
||||
|
@ -91,7 +91,7 @@ const struct snd_sof_dsp_ops sof_tgl_ops = {
|
||||
.get_window_offset = hda_dsp_ipc_get_window_offset,
|
||||
|
||||
.ipc_msg_data = hda_ipc_msg_data,
|
||||
.ipc_pcm_params = hda_ipc_pcm_params,
|
||||
.set_stream_data_offset = hda_set_stream_data_offset,
|
||||
|
||||
/* machine driver */
|
||||
.machine_select = hda_machine_select,
|
||||
|
@ -420,11 +420,11 @@ static inline int
|
||||
snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params)
|
||||
struct snd_sof_platform_stream_params *platform_params)
|
||||
{
|
||||
if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
|
||||
return sof_ops(sdev)->pcm_hw_params(sdev, substream,
|
||||
params, ipc_params);
|
||||
return sof_ops(sdev)->pcm_hw_params(sdev, substream, params,
|
||||
platform_params);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -466,14 +466,17 @@ static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||
{
|
||||
return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
|
||||
}
|
||||
|
||||
/* host configure DSP HW parameters */
|
||||
/* host side configuration of the stream's data offset in stream mailbox area */
|
||||
static inline int
|
||||
snd_sof_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply)
|
||||
snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
size_t posn_offset)
|
||||
{
|
||||
return sof_ops(sdev)->ipc_pcm_params(sdev, substream, reply);
|
||||
if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset)
|
||||
return sof_ops(sdev)->set_stream_data_offset(sdev, substream,
|
||||
posn_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* host stream pointer */
|
||||
|
@ -36,22 +36,6 @@ static int create_page_table(struct snd_soc_component *component,
|
||||
spcm->stream[stream].page_table.area, size);
|
||||
}
|
||||
|
||||
static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply)
|
||||
{
|
||||
struct snd_soc_component *scomp = spcm->scomp;
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||
|
||||
/* validate offset */
|
||||
int ret = snd_sof_ipc_pcm_params(sdev, substream, reply);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(scomp->dev, "error: got wrong reply for PCM %d\n",
|
||||
spcm->pcm.pcm_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* sof pcm period elapse work
|
||||
*/
|
||||
@ -162,6 +146,8 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
|
||||
struct snd_sof_platform_stream_params platform_params = { 0 };
|
||||
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
|
||||
struct snd_sof_pcm *spcm;
|
||||
struct sof_ipc_pcm_params pcm;
|
||||
struct sof_ipc_pcm_params_reply ipc_params_reply;
|
||||
@ -242,12 +228,29 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
|
||||
ret = snd_sof_pcm_platform_hw_params(sdev,
|
||||
substream,
|
||||
params,
|
||||
&pcm.params);
|
||||
&platform_params);
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "error: platform hw params failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update the IPC message with information from the platform */
|
||||
pcm.params.stream_tag = platform_params.stream_tag;
|
||||
|
||||
if (platform_params.use_phy_address)
|
||||
pcm.params.buffer.phy_addr = platform_params.phy_addr;
|
||||
|
||||
if (platform_params.no_ipc_position) {
|
||||
/* For older ABIs set host_period_bytes to zero to inform
|
||||
* FW we don't want position updates. Newer versions use
|
||||
* no_stream_position for this purpose.
|
||||
*/
|
||||
if (v->abi_version < SOF_ABI_VER(3, 10, 0))
|
||||
pcm.params.host_period_bytes = 0;
|
||||
else
|
||||
pcm.params.no_stream_position = 1;
|
||||
}
|
||||
|
||||
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
|
||||
|
||||
/* if this is a repeated hw_params without hw_free, skip setting up widgets */
|
||||
@ -266,9 +269,13 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply);
|
||||
if (ret < 0)
|
||||
ret = snd_sof_set_stream_data_offset(sdev, substream,
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spcm->prepared[substream->stream] = true;
|
||||
|
||||
|
@ -105,6 +105,21 @@ struct snd_soc_tplg_ops;
|
||||
struct snd_soc_component;
|
||||
struct snd_sof_pdata;
|
||||
|
||||
/**
|
||||
* struct snd_sof_platform_stream_params - platform dependent stream parameters
|
||||
* @stream_tag: Stream tag to use
|
||||
* @use_phy_addr: Use the provided @phy_addr for configuration
|
||||
* @phy_addr: Platform dependent address to be used, if @use_phy_addr
|
||||
* is true
|
||||
* @no_ipc_position: Disable position update IPC from firmware
|
||||
*/
|
||||
struct snd_sof_platform_stream_params {
|
||||
u16 stream_tag;
|
||||
bool use_phy_address;
|
||||
u32 phy_addr;
|
||||
bool no_ipc_position;
|
||||
};
|
||||
|
||||
/*
|
||||
* SOF DSP HW abstraction operations.
|
||||
* Used to abstract DSP HW architecture and any IO busses between host CPU
|
||||
@ -183,7 +198,7 @@ struct snd_sof_dsp_ops {
|
||||
int (*pcm_hw_params)(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params); /* optional */
|
||||
struct snd_sof_platform_stream_params *platform_params); /* optional */
|
||||
|
||||
/* host stream hw_free */
|
||||
int (*pcm_hw_free)(struct snd_sof_dev *sdev,
|
||||
@ -206,10 +221,10 @@ struct snd_sof_dsp_ops {
|
||||
struct snd_pcm_substream *substream,
|
||||
void *p, size_t sz); /* mandatory */
|
||||
|
||||
/* host configure DSP HW parameters */
|
||||
int (*ipc_pcm_params)(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply); /* 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,
|
||||
size_t posn_offset); /* optional */
|
||||
|
||||
/* pre/post firmware run */
|
||||
int (*pre_fw_run)(struct snd_sof_dev *sof_dev); /* optional */
|
||||
@ -532,8 +547,6 @@ void snd_sof_ipc_free(struct snd_sof_dev *sdev);
|
||||
void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev);
|
||||
void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id);
|
||||
void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev);
|
||||
int snd_sof_ipc_stream_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct sof_ipc_pcm_params *params);
|
||||
int snd_sof_ipc_valid(struct snd_sof_dev *sdev);
|
||||
int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
|
||||
void *msg_data, size_t msg_bytes, void *reply_data,
|
||||
@ -617,9 +630,9 @@ int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
|
||||
int sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
void *p, size_t sz);
|
||||
int sof_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply);
|
||||
int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
size_t posn_offset);
|
||||
|
||||
int sof_stream_pcm_open(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream);
|
||||
|
@ -45,12 +45,11 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||
}
|
||||
EXPORT_SYMBOL(sof_ipc_msg_data);
|
||||
|
||||
int sof_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
const struct sof_ipc_pcm_params_reply *reply)
|
||||
int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
size_t posn_offset)
|
||||
{
|
||||
struct sof_stream *stream = substream->runtime->private_data;
|
||||
size_t posn_offset = reply->posn_offset;
|
||||
|
||||
/* check if offset is overflow or it is not aligned */
|
||||
if (posn_offset > sdev->stream_box.size ||
|
||||
@ -64,7 +63,7 @@ int sof_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(sof_ipc_pcm_params);
|
||||
EXPORT_SYMBOL(sof_set_stream_data_offset);
|
||||
|
||||
int sof_stream_pcm_open(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream)
|
||||
|
Loading…
Reference in New Issue
Block a user