Skip to content
Permalink
Browse files
ASoC: SOF: add hw params fixup setting for SSP dais
Currently SSP dais don't have BE fixup function as there wasn't anything
to setup after initial topology loading. After enabling multiple dai
configs the current config can be sent in BE fixup, thus add it.

This patch adds also a config match function to seek for enum control
bound to dai for setting the current config. Functionality for dais with
1 config remains the same as before.

Signed-off-by: Jaska Uimonen <jaska.uimonen@linux.intel.com>
  • Loading branch information
Jaska Uimonen authored and juimonen committed Mar 12, 2021
1 parent aa3c39a commit ae3b570f382618a4b251df52e90871fbb0cfb818
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 4 deletions.
@@ -400,6 +400,101 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = {
.prepare = hda_link_pcm_prepare,
};

static struct sof_ipc_dai_config* ssp_dai_config_control(struct snd_sof_dev *sdev,
struct snd_sof_dai *dai)
{
struct sof_ipc_dai_config *config;
struct snd_sof_control *scontrol;
struct sof_ipc_ctrl_data *cdata;
int number_configs = dai->number_configs;
int current_config = dai->current_config;
int index;

if (current_config > number_configs - 1) {
dev_err(sdev->dev, "error: dai config index out of range\n");
return NULL;
}

config = &dai->dai_config[current_config];

/* return the only possible config if only 1 config present */
if (number_configs < 2)
return config;

/* find out if there's a control associated with the dai */
list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
cdata = scontrol->control_data;
if (scontrol->comp_id == dai->comp_dai.comp.id) {
/* find out if this control is meant for choosing dai config */
if (cdata->cmd == SOF_CTRL_CMD_ENUM) {
index = cdata->chanv[0].value;
/* check that the control value is in range and for ssp only */
if (index < number_configs &&
dai->dai_config[index].type == SOF_DAI_INTEL_SSP) {
dev_dbg(sdev->dev,
"found dai config at index %d\n", index);
config = &dai->dai_config[index];
dai->current_config = index;
}
}
break;
}
}

return config;
}

static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{

struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;

list_for_each_entry(sof_dai, &sdev->dai_list, list) {
if (!sof_dai->cpu_dai_name)
continue;

if (!strcmp(dai->name, sof_dai->cpu_dai_name) &&
substream->stream == sof_dai->comp_dai.direction) {
config = ssp_dai_config_control(sdev, sof_dai);

if (!config) {
dev_err(sdev->dev,
"error: no config for DAI %s\n",
sof_dai->name);
return -EINVAL;
}

/* send IPC */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd,
config,
config->hdr.size,
&reply, sizeof(reply));

if (ret < 0)
dev_err(sdev->dev,
"error: failed to set dai config for %s\n",
sof_dai->name);
return ret;
}
}

return 0;
}

static const struct snd_soc_dai_ops ssp_link_dai_ops = {
.hw_params = ssp_dai_hw_params,
};

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
#include "../compress.h"

@@ -422,6 +517,7 @@ static struct snd_soc_cdai_ops sof_probe_compr_ops = {
struct snd_soc_dai_driver skl_dai[] = {
{
.name = "SSP0 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -433,6 +529,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
{
.name = "SSP1 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -444,6 +541,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
{
.name = "SSP2 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -455,6 +553,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
{
.name = "SSP3 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -466,6 +565,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
{
.name = "SSP4 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -477,6 +577,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
{
.name = "SSP5 Pin",
.ops = &ssp_link_dai_ops,
.playback = {
.channels_min = 1,
.channels_max = 8,
@@ -673,10 +673,10 @@ 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) {
case SOF_DAI_INTEL_SSP:
rate->min = dai->dai_config->ssp.fsync_rate;
rate->max = dai->dai_config->ssp.fsync_rate;
channels->min = dai->dai_config->ssp.tdm_slots;
channels->max = dai->dai_config->ssp.tdm_slots;
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;

dev_dbg(component->dev,
"rate_min: %d rate_max: %d\n", rate->min, rate->max);

0 comments on commit ae3b570

Please sign in to comment.