Commit 233d2c4a authored by Mark Brown's avatar Mark Brown

Clean ups and preparation for IPC abstraction in the SOF driver

Merge series from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

In preparation for adding support for the new IPC version that has been
introduced in the SOF firmware, this patch set includes some clean ups
and necessary modifications to commonly used functions that will be
re-used across different IPC-specific code.
parents efb1a2d3 f535880b
......@@ -116,4 +116,9 @@ struct sof_ipc_dai_config {
};
} __packed;
struct sof_dai_private_data {
struct sof_ipc_comp_dai *comp_dai;
struct sof_ipc_dai_config *dai_config;
};
#endif
......@@ -87,9 +87,6 @@ struct sof_ipc_comp {
*/
#define SOF_BUF_UNDERRUN_PERMITTED BIT(1)
/* the UUID size in bytes, shared between FW and host */
#define SOF_UUID_SIZE 16
/* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */
struct sof_ipc_buffer {
struct sof_ipc_comp comp;
......@@ -303,9 +300,4 @@ enum sof_event_types {
SOF_KEYWORD_DETECT_DAPM_EVENT,
};
/* extended data struct for UUID components */
struct sof_ipc_comp_ext {
uint8_t uuid[SOF_UUID_SIZE];
} __packed;
#endif
......@@ -167,6 +167,7 @@ static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widg
int channel)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
......@@ -175,12 +176,19 @@ static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widg
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(swidget->scomp->dev, "error: No config for DAI %s\n", w->name);
if (!sof_dai || !sof_dai->private) {
dev_err(swidget->scomp->dev, "%s: No private data for DAI %s\n", __func__,
w->name);
return NULL;
}
config = &sof_dai->dai_config[sof_dai->current_config];
private = sof_dai->private;
if (!private->dai_config) {
dev_err(swidget->scomp->dev, "%s: No config for DAI %s\n", __func__, w->name);
return NULL;
}
config = &private->dai_config[sof_dai->current_config];
/* update config with stream tag */
config->hda.link_dma_ch = channel;
......@@ -294,6 +302,7 @@ static int hda_link_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
......@@ -301,12 +310,18 @@ static int hda_link_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "No config for DAI %s\n", w->name);
if (!sof_dai || !sof_dai->private) {
dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
return -EINVAL;
}
private = sof_dai->private;
if (!private->dai_config) {
dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
config = &sof_dai->dai_config[sof_dai->current_config];
config = &private->dai_config[sof_dai->current_config];
/* set PAUSE command flag */
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_CMD_MASK, SOF_DAI_CONFIG_FLAGS_PAUSE);
......
......@@ -47,14 +47,21 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_dai_config *config;
struct sof_dai_private_data *private;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "No config for DAI %s\n", w->name);
if (!sof_dai || !sof_dai->private) {
dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
return -EINVAL;
}
private = sof_dai->private;
if (!private->dai_config) {
dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
......@@ -65,7 +72,7 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_
return ret;
}
config = &sof_dai->dai_config[sof_dai->current_config];
config = &private->dai_config[sof_dai->current_config];
/*
* For static pipelines, the DAI widget would already be set up and calling
......@@ -101,6 +108,7 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
......@@ -108,8 +116,14 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "error: No config to free DAI %s\n", w->name);
if (!sof_dai || !sof_dai->private) {
dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
return -EINVAL;
}
private = sof_dai->private;
if (!private->dai_config) {
dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
......@@ -117,7 +131,7 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_f
if (!sof_dai->configured)
return 0;
config = &sof_dai->dai_config[sof_dai->current_config];
config = &private->dai_config[sof_dai->current_config];
/* set HW_FREE flag along with any quirks */
config->flags = SOF_DAI_CONFIG_FLAGS_HW_FREE |
......@@ -154,6 +168,7 @@ static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
int link_id, int alh_stream_id, int dai_id, bool setup)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct sof_dai_private_data *private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
......@@ -164,12 +179,18 @@ static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "error: No config for DAI %s\n", w->name);
if (!sof_dai || !sof_dai->private) {
dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name);
return -EINVAL;
}
private = sof_dai->private;
if (!private->dai_config) {
dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name);
return -EINVAL;
}
config = &sof_dai->dai_config[sof_dai->current_config];
config = &private->dai_config[sof_dai->current_config];
/* update config with link and stream ID */
config->dai_index = (link_id << 8) | dai_id;
......
......@@ -27,18 +27,6 @@ static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
* IPC message Tx/Rx message handling.
*/
/* SOF generic IPC data */
struct snd_sof_ipc {
struct snd_sof_dev *sdev;
/* protects messages and the disable flag */
struct mutex tx_mutex;
/* disables further sending of ipc's */
bool disable_ipc_tx;
struct snd_sof_ipc_msg msg;
};
struct sof_ipc_ctrl_data_params {
size_t msg_bytes;
size_t hdr_bytes;
......
......@@ -670,7 +670,9 @@ static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char
if (!dai->name || strcmp(link_name, dai->name))
continue;
for (i = 0; i < dai->number_configs; i++) {
config = &dai->dai_config[i];
struct sof_dai_private_data *private = dai->private;
config = &private->dai_config[i];
if (config->ssp.fsync_rate == params_rate(params)) {
dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i);
dai->current_config = i;
......@@ -693,6 +695,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
struct snd_sof_dai *dai =
snd_sof_find_dai(component, (char *)rtd->dai_link->name);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_dai_private_data *private = dai->private;
struct snd_soc_dpcm *dpcm;
/* no topology exists for this BE, try a common configuration */
......@@ -717,7 +720,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
/* read format from topology */
snd_mask_none(fmt);
switch (dai->comp_dai->config.frame_fmt) {
switch (private->comp_dai->config.frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
break;
......@@ -733,15 +736,15 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
}
/* read rate and channels from topology */
switch (dai->dai_config->type) {
switch (private->dai_config->type) {
case SOF_DAI_INTEL_SSP:
/* search for config to pcm params match, if not found use default */
ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
rate->min = dai->dai_config[dai->current_config].ssp.fsync_rate;
rate->max = dai->dai_config[dai->current_config].ssp.fsync_rate;
channels->min = dai->dai_config[dai->current_config].ssp.tdm_slots;
channels->max = dai->dai_config[dai->current_config].ssp.tdm_slots;
rate->min = private->dai_config[dai->current_config].ssp.fsync_rate;
rate->max = private->dai_config[dai->current_config].ssp.fsync_rate;
channels->min = private->dai_config[dai->current_config].ssp.tdm_slots;
channels->max = private->dai_config[dai->current_config].ssp.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -752,11 +755,11 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
break;
case SOF_DAI_INTEL_DMIC:
/* DMIC only supports 16 or 32 bit formats */
if (dai->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
if (private->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
dev_err(component->dev,
"error: invalid fmt %d for DAI type %d\n",
dai->comp_dai->config.frame_fmt,
dai->dai_config->type);
private->comp_dai->config.frame_fmt,
private->dai_config->type);
}
break;
case SOF_DAI_INTEL_HDA:
......@@ -776,14 +779,14 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
* Dai could run with different channel count compared with
* front end, so get dai channel count from topology
*/
channels->min = dai->dai_config->alh.channels;
channels->max = dai->dai_config->alh.channels;
channels->min = private->dai_config->alh.channels;
channels->max = private->dai_config->alh.channels;
break;
case SOF_DAI_IMX_ESAI:
rate->min = dai->dai_config->esai.fsync_rate;
rate->max = dai->dai_config->esai.fsync_rate;
channels->min = dai->dai_config->esai.tdm_slots;
channels->max = dai->dai_config->esai.tdm_slots;
rate->min = private->dai_config->esai.fsync_rate;
rate->max = private->dai_config->esai.fsync_rate;
channels->min = private->dai_config->esai.tdm_slots;
channels->max = private->dai_config->esai.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -792,10 +795,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_MEDIATEK_AFE:
rate->min = dai->dai_config->afe.rate;
rate->max = dai->dai_config->afe.rate;
channels->min = dai->dai_config->afe.channels;
channels->max = dai->dai_config->afe.channels;
rate->min = private->dai_config->afe.rate;
rate->max = private->dai_config->afe.rate;
channels->min = private->dai_config->afe.channels;
channels->max = private->dai_config->afe.channels;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -804,10 +807,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_IMX_SAI:
rate->min = dai->dai_config->sai.fsync_rate;
rate->max = dai->dai_config->sai.fsync_rate;
channels->min = dai->dai_config->sai.tdm_slots;
channels->max = dai->dai_config->sai.tdm_slots;
rate->min = private->dai_config->sai.fsync_rate;
rate->max = private->dai_config->sai.fsync_rate;
channels->min = private->dai_config->sai.tdm_slots;
channels->max = private->dai_config->sai.tdm_slots;
dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -816,10 +819,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_BT:
rate->min = dai->dai_config->acpbt.fsync_rate;
rate->max = dai->dai_config->acpbt.fsync_rate;
channels->min = dai->dai_config->acpbt.tdm_slots;
channels->max = dai->dai_config->acpbt.tdm_slots;
rate->min = private->dai_config->acpbt.fsync_rate;
rate->max = private->dai_config->acpbt.fsync_rate;
channels->min = private->dai_config->acpbt.tdm_slots;
channels->max = private->dai_config->acpbt.tdm_slots;
dev_dbg(component->dev,
"AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -828,10 +831,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_SP:
rate->min = dai->dai_config->acpsp.fsync_rate;
rate->max = dai->dai_config->acpsp.fsync_rate;
channels->min = dai->dai_config->acpsp.tdm_slots;
channels->max = dai->dai_config->acpsp.tdm_slots;
rate->min = private->dai_config->acpsp.fsync_rate;
rate->max = private->dai_config->acpsp.fsync_rate;
channels->min = private->dai_config->acpsp.tdm_slots;
channels->max = private->dai_config->acpsp.tdm_slots;
dev_dbg(component->dev,
"AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -840,10 +843,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
channels->min, channels->max);
break;
case SOF_DAI_AMD_DMIC:
rate->min = dai->dai_config->acpdmic.fsync_rate;
rate->max = dai->dai_config->acpdmic.fsync_rate;
channels->min = dai->dai_config->acpdmic.tdm_slots;
channels->max = dai->dai_config->acpdmic.tdm_slots;
rate->min = private->dai_config->acpdmic.fsync_rate;
rate->max = private->dai_config->acpdmic.fsync_rate;
channels->min = private->dai_config->acpdmic.tdm_slots;
channels->max = private->dai_config->acpdmic.tdm_slots;
dev_dbg(component->dev,
"AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max);
......@@ -853,7 +856,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
break;
default:
dev_err(component->dev, "error: invalid DAI type %d\n",
dai->dai_config->type);
private->dai_config->type);
break;
}
......
......@@ -29,11 +29,12 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control *
static int sof_dai_config_setup(struct snd_sof_dev *sdev, struct snd_sof_dai *dai)
{
struct sof_dai_private_data *private = dai->private;
struct sof_ipc_dai_config *config;
struct sof_ipc_reply reply;
int ret;
config = &dai->dai_config[dai->current_config];
config = &private->dai_config[dai->current_config];
if (!config) {
dev_err(sdev->dev, "error: no config for DAI %s\n", dai->name);
return -EINVAL;
......@@ -191,12 +192,16 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
switch (swidget->id) {
case snd_soc_dapm_dai_in:
case snd_soc_dapm_dai_out:
{
struct sof_dai_private_data *dai_data;
dai = swidget->private;
comp = &dai->comp_dai->comp;
dai_data = dai->private;
comp = &dai_data->comp_dai->comp;
dai->configured = false;
ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai->comp_dai, comp->hdr.size,
&r, sizeof(r));
ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai,
comp->hdr.size, &r, sizeof(r));
if (ret < 0) {
dev_err(sdev->dev, "error: failed to load widget %s\n",
swidget->widget->name);
......@@ -216,6 +221,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
return ret;
}
break;
}
case snd_soc_dapm_scheduler:
pipeline = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline,
......@@ -259,28 +265,25 @@ EXPORT_SYMBOL(sof_widget_setup);
static int sof_route_setup_ipc(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
{
struct sof_ipc_pipe_comp_connect *connect;
struct sof_ipc_pipe_comp_connect connect;
struct sof_ipc_reply reply;
int ret;
/* skip if there's no private data */
if (!sroute->private)
return 0;
/* nothing to do if route is already set up */
if (sroute->setup)
return 0;
connect = sroute->private;
connect.hdr.size = sizeof(connect);
connect.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT;
connect.source_id = sroute->src_widget->comp_id;
connect.sink_id = sroute->sink_widget->comp_id;
dev_dbg(sdev->dev, "setting up route %s -> %s\n",
sroute->src_widget->widget->name,
sroute->sink_widget->widget->name);
/* send ipc */
ret = sof_ipc_tx_message(sdev->ipc,
connect->hdr.cmd,
connect, sizeof(*connect),
ret = sof_ipc_tx_message(sdev->ipc, connect.hdr.cmd, &connect, sizeof(connect),
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev, "%s: route setup failed %d\n", __func__, ret);
......@@ -623,12 +626,13 @@ int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify)
/* update DAI config. The IPC will be sent in sof_widget_setup() */
if (WIDGET_IS_DAI(swidget->id)) {
struct snd_sof_dai *dai = swidget->private;
struct sof_dai_private_data *private = dai->private;
struct sof_ipc_dai_config *config;
if (!dai || !dai->dai_config)
if (!dai || !private || !private->dai_config)
continue;
config = dai->dai_config;
config = private->dai_config;
/*
* The link DMA channel would be invalidated for running
* streams but not for streams that were in the PAUSED
......@@ -914,18 +918,19 @@ static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dai *dai =
snd_sof_find_dai(component, (char *)rtd->dai_link->name);
struct sof_dai_private_data *private = dai->private;
/* use the tplg configured mclk if existed */
if (!dai || !dai->dai_config)
if (!dai || !private || !private->dai_config)
return 0;
switch (dai->dai_config->type) {
switch (private->dai_config->type) {
case SOF_DAI_INTEL_SSP:
switch (clk_type) {
case SOF_DAI_CLK_INTEL_SSP_MCLK:
return dai->dai_config->ssp.mclk_rate;
return private->dai_config->ssp.mclk_rate;
case SOF_DAI_CLK_INTEL_SSP_BCLK:
return dai->dai_config->ssp.bclk_rate;
return private->dai_config->ssp.bclk_rate;
default:
dev_err(rtd->dev, "fail to get SSP clk %d rate\n",
clk_type);
......@@ -935,7 +940,7 @@ static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
default:
/* not yet implemented for platforms other than the above */
dev_err(rtd->dev, "DAI type %d not supported yet!\n",
dai->dai_config->type);
private->dai_config->type);
return -EINVAL;
}
}
......
......@@ -30,6 +30,18 @@
#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
/** struct snd_sof_tuple - Tuple info
* @token: Token ID
* @value: union of a string or a u32 values
*/
struct snd_sof_tuple {
u32 token;
union {
u32 v;
const char *s;
} value;
};
/* PCM stream, mapped to FW component */
struct snd_sof_pcm_stream {
u32 comp_id;
......@@ -110,8 +122,10 @@ struct snd_sof_widget {
struct list_head list; /* list in sdev widget list */
struct snd_sof_widget *pipe_widget;
/* extended data for UUID components */
struct sof_ipc_comp_ext comp_ext;
const guid_t uuid;
int num_tuples;
struct snd_sof_tuple *tuples;
void *private; /* core does not touch this */
};
......@@ -134,12 +148,11 @@ struct snd_sof_dai {
struct snd_soc_component *scomp;
const char *name;
struct sof_ipc_comp_dai *comp_dai;
int number_configs;
int current_config;
bool configured; /* DAI configured during BE hw_params */
struct sof_ipc_dai_config *dai_config;
struct list_head list; /* list in sdev dai list */
void *private;
};
/*
......
......@@ -345,6 +345,18 @@ struct snd_sof_ipc_msg {
bool ipc_complete;
};
/* SOF generic IPC data */
struct snd_sof_ipc {
struct snd_sof_dev *sdev;
/* protects messages and the disable flag */
struct mutex tx_mutex;
/* disables further sending of ipc's */
bool disable_ipc_tx;
struct snd_sof_ipc_msg msg;
};
/*
* SOF Device Level.
*/
......
This diff is collapsed.
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