Skip to content

Commit b66bfc3

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: sof-audio: Fix broken early bclk feature for SSP
With the removal of widget setup during BE hw_params, the DAI config IPC is never sent with the SOF_DAI_CONFIG_FLAGS_HW_PARAMS. This means that the early bit clock feature required for certain codecs will be broken. Fix this by saving the config flags sent during BE DAI hw_params and reusing it when the DAI_CONFIG IPC is sent after the DAI widget is set up. Also, free the DAI config before the widget is freed. The DAI_CONFIG IPC sent during the sof_widget_free() does not have the DAI index information. So, save the dai_index in the config during hw_params and reuse it during hw_free. For IPC4, do not clear the node ID during hw_free. It will be needed for freeing the group_ida during unprepare. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://lore.kernel.org/r/20230307114639.4553-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent ca09e2a commit b66bfc3

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

sound/soc/sof/ipc3-topology.c

+30-2
Original file line numberDiff line numberDiff line change
@@ -2081,22 +2081,50 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
20812081
break;
20822082
case SOF_DAI_INTEL_ALH:
20832083
if (data) {
2084-
config->dai_index = data->dai_index;
2084+
/* save the dai_index during hw_params and reuse it for hw_free */
2085+
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
2086+
config->dai_index = data->dai_index;
20852087
config->alh.stream_id = data->dai_data;
20862088
}
20872089
break;
20882090
default:
20892091
break;
20902092
}
20912093

2092-
config->flags = flags;
2094+
/*
2095+
* The dai_config op is invoked several times and the flags argument varies as below:
2096+
* BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains
2097+
* SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks
2098+
* FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has
2099+
* just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no
2100+
* quirks
2101+
* BE DAI trigger: When invoked during the BE DAI trigger, flags is set to
2102+
* SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks
2103+
* BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to
2104+
* SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
2105+
* FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to
2106+
* SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
2107+
*
2108+
* The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE
2109+
* DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks
2110+
* need to be preserved when assigning the flags before sending the IPC.
2111+
* For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.
2112+
*/
2113+
2114+
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
2115+
config->flags |= flags;
2116+
else
2117+
config->flags = flags;
20932118

20942119
/* only send the IPC if the widget is set up in the DSP */
20952120
if (swidget->use_count > 0) {
20962121
ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size,
20972122
&reply, sizeof(reply));
20982123
if (ret < 0)
20992124
dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
2125+
2126+
/* clear the flags once the IPC has been sent even if it fails */
2127+
config->flags = SOF_DAI_CONFIG_FLAGS_NONE;
21002128
}
21012129

21022130
return ret;

sound/soc/sof/ipc4-topology.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
980980

981981
ipc4_copier = dai->private;
982982
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
983+
struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data;
983984
struct sof_ipc4_alh_configuration_blob *blob;
984985
unsigned int group_id;
985986

@@ -989,6 +990,9 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
989990
ALH_MULTI_GTW_BASE;
990991
ida_free(&alh_group_ida, group_id);
991992
}
993+
994+
/* clear the node ID */
995+
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
992996
}
993997
}
994998

@@ -1940,8 +1944,15 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
19401944
pipeline->skip_during_fe_trigger = true;
19411945
fallthrough;
19421946
case SOF_DAI_INTEL_ALH:
1943-
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
1944-
copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
1947+
/*
1948+
* Do not clear the node ID when this op is invoked with
1949+
* SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during
1950+
* unprepare.
1951+
*/
1952+
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
1953+
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
1954+
copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
1955+
}
19451956
break;
19461957
case SOF_DAI_INTEL_DMIC:
19471958
case SOF_DAI_INTEL_SSP:

sound/soc/sof/sof-audio.c

+25-3
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,27 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
5050
/* reset route setup status for all routes that contain this widget */
5151
sof_reset_route_setup_status(sdev, swidget);
5252

53+
/* free DAI config and continue to free widget even if it fails */
54+
if (WIDGET_IS_DAI(swidget->id)) {
55+
struct snd_sof_dai_config_data data;
56+
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE;
57+
58+
data.dai_data = DMA_CHAN_INVALID;
59+
60+
if (tplg_ops && tplg_ops->dai_config) {
61+
err = tplg_ops->dai_config(sdev, swidget, flags, &data);
62+
if (err < 0)
63+
dev_err(sdev->dev, "failed to free config for widget %s\n",
64+
swidget->widget->name);
65+
}
66+
}
67+
5368
/* continue to disable core even if IPC fails */
54-
if (tplg_ops && tplg_ops->widget_free)
55-
err = tplg_ops->widget_free(sdev, swidget);
69+
if (tplg_ops && tplg_ops->widget_free) {
70+
ret = tplg_ops->widget_free(sdev, swidget);
71+
if (ret < 0 && !err)
72+
err = ret;
73+
}
5674

5775
/*
5876
* disable widget core. continue to route setup status and complete flag
@@ -151,8 +169,12 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
151169

152170
/* send config for DAI components */
153171
if (WIDGET_IS_DAI(swidget->id)) {
154-
unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE;
172+
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
155173

174+
/*
175+
* The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does
176+
* not use the flags argument.
177+
*/
156178
if (tplg_ops && tplg_ops->dai_config) {
157179
ret = tplg_ops->dai_config(sdev, swidget, flags, NULL);
158180
if (ret < 0)

0 commit comments

Comments
 (0)