Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion drivers/soundwire/intel_ace2x.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,16 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
dir = SDW_DATA_DIR_TX;

pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);

if (!pdi) {
ret = -EINVAL;
goto error;
}

/* use same definitions for alh_id as previous generations */
pdi->intel_alh_id = (sdw->instance * 16) + pdi->num + 3;
if (pdi->num >= 2)
pdi->intel_alh_id += 2;

/* the SHIM will be configured in the callback functions */

sdw_cdns_config_stream(cdns, ch, dir, pdi);
Expand Down
63 changes: 5 additions & 58 deletions sound/soc/sof/intel/hda-dai-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,9 @@ static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev,
struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *dai;
struct hdac_ext_stream *hext_stream;

/* only allocate a stream_tag for the first DAI in the dailink */
dai = snd_soc_rtd_to_cpu(rtd, 0);
if (dai == cpu_dai)
hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
else
hext_stream = snd_soc_dai_get_dma_data(dai, substream);

hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
if (!hext_stream)
return NULL;

Expand All @@ -168,14 +160,9 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *dai;

/* only release a stream_tag for the first DAI in the dailink */
dai = snd_soc_rtd_to_cpu(rtd, 0);
if (dai == cpu_dai)
snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
}

static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream,
Expand Down Expand Up @@ -239,34 +226,16 @@ static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai_link_ch_map *ch_maps;
unsigned int format_val;
unsigned int bits;
int num_channels;
u32 ch_mask = 0;
int i;

/*
* if the multiple dais are handled by the same dailink, we may need to update the
* stream channel count - the params are modified in soc-pcm based on the ch_maps info
*/
for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
ch_mask |= ch_maps->ch_mask;

num_channels = ch_mask ? hweight_long(ch_mask) : params_channels(params);

if (num_channels != params_channels(params))
dev_dbg(sdev->dev, "configuring stream format for %d channels, params_channels was %d\n",
num_channels, params_channels(params));

bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD,
params_physical_width(params));

format_val = snd_hdac_stream_format(num_channels, bits, params_rate(params));
format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params));

dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
params_rate(params), num_channels, params_format(params));
params_rate(params), params_channels(params), params_format(params));

return format_val;
}
Expand Down Expand Up @@ -454,28 +423,6 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
return ret;
}

static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev,
struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_sof_dai *dai = swidget->private;
struct sof_ipc4_copier *ipc4_copier = dai->private;
struct sof_ipc4_alh_configuration_blob *blob;

blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;

/*
* Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using
* the multi-gateway firmware configuration. The DMA hardware can take care of
* multiple links without needing any firmware assistance
*/
blob->alh_cfg.device_count = 1;

return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream);
}

static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
.get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
Expand Down Expand Up @@ -517,7 +464,7 @@ static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = {
};

static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = {
.get_hext_stream = sdw_hda_ipc4_get_hext_stream,
.get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
.release_hext_stream = hda_release_hext_stream,
.setup_hext_stream = hda_setup_hext_stream,
Expand Down
87 changes: 66 additions & 21 deletions sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,15 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
}

static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai,
struct snd_sof_dai_config_data *data,
unsigned int flags)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
struct hdac_ext_stream *hext_stream;
struct snd_sof_dai_config_data data = { 0 };
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
struct snd_sof_dev *sdev = widget_to_sdev(w);
int ret;

Expand All @@ -250,9 +250,19 @@ static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
hext_stream = ops->get_hext_stream(sdev, dai, substream);

flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
data.dai_data = hdac_stream(hext_stream)->stream_tag - 1;
data->dai_data = hdac_stream(hext_stream)->stream_tag - 1;

return hda_dai_config(w, flags, data);
}

static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_sof_dai_config_data data = { 0 };
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;

return hda_dai_config(w, flags, &data);
return hda_dai_hw_params_data(substream, params, dai, &data, flags);
}

/*
Expand Down Expand Up @@ -342,20 +352,26 @@ static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w)
return ipc4_copier;
}

static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai,
struct snd_sof_dai_config_data *data,
unsigned int flags)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_dma_config_tlv *dma_config_tlv;
const struct hda_dai_widget_dma_ops *ops;
struct sof_ipc4_dma_config *dma_config;
struct sof_ipc4_copier *ipc4_copier;
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
struct snd_sof_dev *sdev;
struct snd_soc_dai *dai;
int cpu_dai_id;
int stream_id;
int ret;
int i;

ops = hda_dai_get_ops(substream, cpu_dai);
if (!ops) {
Expand Down Expand Up @@ -393,7 +409,12 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
/* configure TLV */
ipc4_copier = widget_to_copier(w);

dma_config_tlv = &ipc4_copier->dma_config_tlv;
for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
if (dai == cpu_dai)
break;
}

dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID;
/* dma_config_priv_size is zero */
dma_config_tlv->length = sizeof(dma_config_tlv->dma_config);
Expand All @@ -404,13 +425,38 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
dma_config->pre_allocated_by_host = 1;
dma_config->dma_channel_id = stream_id - 1;
dma_config->stream_id = stream_id;
dma_config->dma_stream_channel_map.device_count = 0; /* mapping not used */
/*
* Currently we use a DMA for each device in ALH blob.
*/
dma_config->dma_stream_channel_map.device_count = 1;
dma_config->dma_stream_channel_map.mapping[0].device = data->dai_index;
dma_config->dma_priv_config_size = 0;

/*
* copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier
* will be handled in sof_ipc4_prepare_copier_module.
*/
for_each_rtd_cpu_dais(rtd, i, dai) {
w = snd_soc_dai_get_widget(dai, substream->stream);
ipc4_copier = widget_to_copier(w);
memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv,
sizeof(*dma_config_tlv));
}

skip_tlv:
return 0;
}

static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
{
struct snd_sof_dai_config_data data = { 0 };
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;

return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
}

static int non_hda_dai_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
Expand All @@ -437,22 +483,25 @@ static const struct snd_soc_dai_ops dmic_dai_ops = {
int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai,
int link_id)
int link_id,
int intel_alh_id)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_dai_config_data data = { 0 };
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
const struct hda_dai_widget_dma_ops *ops;
struct snd_soc_dai_link_ch_map *ch_maps;
struct hdac_ext_stream *hext_stream;
struct snd_soc_dai *dai;
struct snd_sof_dev *sdev;
bool cpu_dai_found = false;
int cpu_dai_id;
int ch_mask;
int ret;
int j;

ret = non_hda_dai_hw_params(substream, params, cpu_dai);
data.dai_index = (link_id << 8) | cpu_dai->id;
data.dai_node_id = intel_alh_id;
ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
if (ret < 0) {
dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret);
return ret;
Expand Down Expand Up @@ -480,11 +529,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
if (!cpu_dai_found)
return -ENODEV;

ch_mask = 0;
for_each_link_ch_maps(rtd->dai_link, j, ch_maps) {
if (ch_maps->cpu == cpu_dai_id)
ch_mask |= ch_maps->ch_mask;
}
ch_mask = GENMASK(params_channels(params) - 1, 0);

ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
ch_mask,
Expand Down
4 changes: 3 additions & 1 deletion sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static int sdw_params_stream(struct device *dev,

data.dai_index = (params_data->link_id << 8) | d->id;
data.dai_data = params_data->alh_stream_id;
data.dai_node_id = data.dai_data;

return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data);
}
Expand All @@ -77,7 +78,8 @@ static int sdw_ace2x_params_stream(struct device *dev,
return sdw_hda_dai_hw_params(params_data->substream,
params_data->hw_params,
params_data->dai,
params_data->link_id);
params_data->link_id,
params_data->alh_stream_id);
}

static int sdw_ace2x_free_stream(struct device *dev,
Expand Down
3 changes: 2 additions & 1 deletion sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,8 @@ static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai,
int link_id);
int link_id,
int intel_alh_id);

int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai,
Expand Down
Loading