mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 20:12:00 -04:00
ASoC: SOF: Introduce struct snd_sof_pipeline
Introduce struct snd_sof_pipeline to save the information about pipelines including the pipeline widget, their status wrt how many PCM's are using them and whether they are complete or not. In struct snd_sof_widget, replace pipe_widget with spipe and remove complete. In struct snd_sof_pcm_stream_pipeline_list, replace pipe_widgets with pipelines. Update all users accordingly. 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/20230127120031.10709-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
2d271af1af
commit
9c04363d22
@@ -390,6 +390,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
|
|||||||
INIT_LIST_HEAD(&sdev->pcm_list);
|
INIT_LIST_HEAD(&sdev->pcm_list);
|
||||||
INIT_LIST_HEAD(&sdev->kcontrol_list);
|
INIT_LIST_HEAD(&sdev->kcontrol_list);
|
||||||
INIT_LIST_HEAD(&sdev->widget_list);
|
INIT_LIST_HEAD(&sdev->widget_list);
|
||||||
|
INIT_LIST_HEAD(&sdev->pipeline_list);
|
||||||
INIT_LIST_HEAD(&sdev->dai_list);
|
INIT_LIST_HEAD(&sdev->dai_list);
|
||||||
INIT_LIST_HEAD(&sdev->dai_link_list);
|
INIT_LIST_HEAD(&sdev->dai_link_list);
|
||||||
INIT_LIST_HEAD(&sdev->route_list);
|
INIT_LIST_HEAD(&sdev->route_list);
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
w = snd_soc_dai_get_widget(dai, substream->stream);
|
w = snd_soc_dai_get_widget(dai, substream->stream);
|
||||||
swidget = w->dobj.private;
|
swidget = w->dobj.private;
|
||||||
pipe_widget = swidget->pipe_widget;
|
pipe_widget = swidget->spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|||||||
@@ -2233,9 +2233,9 @@ static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
swidget->complete = sof_ipc3_complete_pipeline(sdev, swidget);
|
swidget->spipe->complete = sof_ipc3_complete_pipeline(sdev, swidget);
|
||||||
if (swidget->complete < 0)
|
if (swidget->spipe->complete < 0)
|
||||||
return swidget->complete;
|
return swidget->spipe->complete;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -2317,7 +2317,8 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
|
|||||||
if (!verify && !swidget->dynamic_pipeline_widget &&
|
if (!verify && !swidget->dynamic_pipeline_widget &&
|
||||||
SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) {
|
SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) {
|
||||||
swidget->use_count = 0;
|
swidget->use_count = 0;
|
||||||
swidget->complete = 0;
|
if (swidget->spipe)
|
||||||
|
swidget->spipe->complete = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
|
|||||||
struct ipc4_pipeline_set_state_data *data;
|
struct ipc4_pipeline_set_state_data *data;
|
||||||
struct snd_sof_widget *pipe_widget;
|
struct snd_sof_widget *pipe_widget;
|
||||||
struct sof_ipc4_pipeline *pipeline;
|
struct sof_ipc4_pipeline *pipeline;
|
||||||
|
struct snd_sof_pipeline *spipe;
|
||||||
struct snd_sof_pcm *spcm;
|
struct snd_sof_pcm *spcm;
|
||||||
int ret;
|
int ret;
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -79,7 +80,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
|
|||||||
pipeline_list = &spcm->stream[substream->stream].pipeline_list;
|
pipeline_list = &spcm->stream[substream->stream].pipeline_list;
|
||||||
|
|
||||||
/* nothing to trigger if the list is empty */
|
/* nothing to trigger if the list is empty */
|
||||||
if (!pipeline_list->pipe_widgets)
|
if (!pipeline_list->pipelines)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* allocate memory for the pipeline data */
|
/* allocate memory for the pipeline data */
|
||||||
@@ -96,7 +97,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
|
|||||||
* sink->source would still be guaranteed for each fork independently.
|
* sink->source would still be guaranteed for each fork independently.
|
||||||
*/
|
*/
|
||||||
for (i = pipeline_list->count - 1; i >= 0; i--) {
|
for (i = pipeline_list->count - 1; i >= 0; i--) {
|
||||||
pipe_widget = pipeline_list->pipe_widgets[i];
|
spipe = pipeline_list->pipelines[i];
|
||||||
|
pipe_widget = spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
if (pipeline->state != state && !pipeline->skip_during_fe_trigger)
|
if (pipeline->state != state && !pipeline->skip_during_fe_trigger)
|
||||||
data->pipeline_ids[data->count++] = pipe_widget->instance_id;
|
data->pipeline_ids[data->count++] = pipe_widget->instance_id;
|
||||||
@@ -122,7 +124,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
|
|||||||
/* update PAUSED state for all pipelines that were just triggered */
|
/* update PAUSED state for all pipelines that were just triggered */
|
||||||
for (i = 0; i < data->count; i++) {
|
for (i = 0; i < data->count; i++) {
|
||||||
for (j = 0; j < pipeline_list->count; j++) {
|
for (j = 0; j < pipeline_list->count; j++) {
|
||||||
pipe_widget = pipeline_list->pipe_widgets[j];
|
spipe = pipeline_list->pipelines[j];
|
||||||
|
pipe_widget = spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
|
|
||||||
if (data->pipeline_ids[i] == pipe_widget->instance_id) {
|
if (data->pipeline_ids[i] == pipe_widget->instance_id) {
|
||||||
@@ -146,7 +149,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
|
|||||||
/* update final state for all pipelines that were just triggered */
|
/* update final state for all pipelines that were just triggered */
|
||||||
for (i = 0; i < data->count; i++) {
|
for (i = 0; i < data->count; i++) {
|
||||||
for (j = 0; j < pipeline_list->count; j++) {
|
for (j = 0; j < pipeline_list->count; j++) {
|
||||||
pipe_widget = pipeline_list->pipe_widgets[j];
|
spipe = pipeline_list->pipelines[j];
|
||||||
|
pipe_widget = spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
|
|
||||||
if (data->pipeline_ids[i] == pipe_widget->instance_id) {
|
if (data->pipeline_ids[i] == pipe_widget->instance_id) {
|
||||||
@@ -274,8 +278,8 @@ static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
|
|||||||
|
|
||||||
for_each_pcm_streams(stream) {
|
for_each_pcm_streams(stream) {
|
||||||
pipeline_list = &spcm->stream[stream].pipeline_list;
|
pipeline_list = &spcm->stream[stream].pipeline_list;
|
||||||
kfree(pipeline_list->pipe_widgets);
|
kfree(pipeline_list->pipelines);
|
||||||
pipeline_list->pipe_widgets = NULL;
|
pipeline_list->pipelines = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,10 +293,9 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
|
|||||||
pipeline_list = &spcm->stream[stream].pipeline_list;
|
pipeline_list = &spcm->stream[stream].pipeline_list;
|
||||||
|
|
||||||
/* allocate memory for max number of pipeline IDs */
|
/* allocate memory for max number of pipeline IDs */
|
||||||
pipeline_list->pipe_widgets = kcalloc(ipc4_data->max_num_pipelines,
|
pipeline_list->pipelines = kcalloc(ipc4_data->max_num_pipelines,
|
||||||
sizeof(struct snd_sof_widget *),
|
sizeof(struct snd_sof_widget *), GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
if (!pipeline_list->pipelines) {
|
||||||
if (!pipeline_list->pipe_widgets) {
|
|
||||||
sof_ipc4_pcm_free(sdev, spcm);
|
sof_ipc4_pcm_free(sdev, spcm);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -855,7 +855,7 @@ sof_ipc4_update_pipeline_mem_usage(struct snd_sof_dev *sdev, struct snd_sof_widg
|
|||||||
|
|
||||||
total = SOF_IPC4_FW_PAGE(task_mem + queue_mem);
|
total = SOF_IPC4_FW_PAGE(task_mem + queue_mem);
|
||||||
|
|
||||||
pipe_widget = swidget->pipe_widget;
|
pipe_widget = swidget->spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
pipeline->mem_usage += total;
|
pipeline->mem_usage += total;
|
||||||
}
|
}
|
||||||
@@ -969,7 +969,7 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
|
|||||||
struct sof_ipc4_pipeline *pipeline;
|
struct sof_ipc4_pipeline *pipeline;
|
||||||
|
|
||||||
/* reset pipeline memory usage */
|
/* reset pipeline memory usage */
|
||||||
pipe_widget = swidget->pipe_widget;
|
pipe_widget = swidget->spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
pipeline->mem_usage = 0;
|
pipeline->mem_usage = 0;
|
||||||
|
|
||||||
@@ -1136,7 +1136,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
|
|||||||
struct snd_sof_widget *pipe_widget;
|
struct snd_sof_widget *pipe_widget;
|
||||||
struct sof_ipc4_pipeline *pipeline;
|
struct sof_ipc4_pipeline *pipeline;
|
||||||
|
|
||||||
pipe_widget = swidget->pipe_widget;
|
pipe_widget = swidget->spipe->pipe_widget;
|
||||||
pipeline = pipe_widget->private;
|
pipeline = pipe_widget->private;
|
||||||
ipc4_copier = (struct sof_ipc4_copier *)swidget->private;
|
ipc4_copier = (struct sof_ipc4_copier *)swidget->private;
|
||||||
gtw_attr = ipc4_copier->gtw_attr;
|
gtw_attr = ipc4_copier->gtw_attr;
|
||||||
@@ -1495,7 +1495,7 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
|
|||||||
|
|
||||||
static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
||||||
{
|
{
|
||||||
struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
|
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
|
||||||
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
|
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
|
||||||
struct sof_ipc4_pipeline *pipeline;
|
struct sof_ipc4_pipeline *pipeline;
|
||||||
struct sof_ipc4_msg *msg;
|
struct sof_ipc4_msg *msg;
|
||||||
@@ -1815,7 +1815,7 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s
|
|||||||
* routes belonging to the same pipeline will be disconnected by the FW when the pipeline
|
* routes belonging to the same pipeline will be disconnected by the FW when the pipeline
|
||||||
* is freed. So avoid sending this IPC which will be ignored by the FW anyway.
|
* is freed. So avoid sending this IPC which will be ignored by the FW anyway.
|
||||||
*/
|
*/
|
||||||
if (src_widget->pipe_widget == sink_widget->pipe_widget)
|
if (src_widget->spipe->pipe_widget == sink_widget->spipe->pipe_widget)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
header = src_fw_module->man4_module_entry.id;
|
header = src_fw_module->man4_module_entry.id;
|
||||||
@@ -1846,7 +1846,7 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s
|
|||||||
static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
|
static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
|
||||||
unsigned int flags, struct snd_sof_dai_config_data *data)
|
unsigned int flags, struct snd_sof_dai_config_data *data)
|
||||||
{
|
{
|
||||||
struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
|
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
|
||||||
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
|
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
|
||||||
struct snd_sof_dai *dai = swidget->private;
|
struct snd_sof_dai *dai = swidget->private;
|
||||||
struct sof_ipc4_gtw_attributes *gtw_attr;
|
struct sof_ipc4_gtw_attributes *gtw_attr;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_so
|
|||||||
int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
||||||
{
|
{
|
||||||
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
|
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
|
||||||
|
struct snd_sof_widget *pipe_widget;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
|||||||
if (--swidget->use_count)
|
if (--swidget->use_count)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
pipe_widget = swidget->spipe->pipe_widget;
|
||||||
|
|
||||||
/* reset route setup status for all routes that contain this widget */
|
/* reset route setup status for all routes that contain this widget */
|
||||||
sof_reset_route_setup_status(sdev, swidget);
|
sof_reset_route_setup_status(sdev, swidget);
|
||||||
|
|
||||||
@@ -67,12 +70,15 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
|||||||
* skip for static pipelines
|
* skip for static pipelines
|
||||||
*/
|
*/
|
||||||
if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
|
if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
|
||||||
ret = sof_widget_free(sdev, swidget->pipe_widget);
|
ret = sof_widget_free(sdev, pipe_widget);
|
||||||
if (ret < 0 && !err)
|
if (ret < 0 && !err)
|
||||||
err = ret;
|
err = ret;
|
||||||
swidget->pipe_widget->complete = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clear pipeline complete */
|
||||||
|
if (swidget->id == snd_soc_dapm_scheduler)
|
||||||
|
swidget->spipe->complete = 0;
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);
|
dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);
|
||||||
|
|
||||||
@@ -103,14 +109,13 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
|||||||
* widget in the pipeline is freed. Skip setting up scheduler widget for static pipelines.
|
* widget in the pipeline is freed. Skip setting up scheduler widget for static pipelines.
|
||||||
*/
|
*/
|
||||||
if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
|
if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
|
||||||
if (!swidget->pipe_widget) {
|
if (!swidget->spipe || !swidget->spipe->pipe_widget) {
|
||||||
dev_err(sdev->dev, "No scheduler widget set for %s\n",
|
dev_err(sdev->dev, "No pipeline set for %s\n", swidget->widget->name);
|
||||||
swidget->widget->name);
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto use_count_dec;
|
goto use_count_dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sof_widget_setup(sdev, swidget->pipe_widget);
|
ret = sof_widget_setup(sdev, swidget->spipe->pipe_widget);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto use_count_dec;
|
goto use_count_dec;
|
||||||
}
|
}
|
||||||
@@ -159,7 +164,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
|||||||
snd_sof_dsp_core_put(sdev, swidget->core);
|
snd_sof_dsp_core_put(sdev, swidget->core);
|
||||||
pipe_widget_free:
|
pipe_widget_free:
|
||||||
if (swidget->id != snd_soc_dapm_scheduler)
|
if (swidget->id != snd_soc_dapm_scheduler)
|
||||||
sof_widget_free(sdev, swidget->pipe_widget);
|
sof_widget_free(sdev, swidget->spipe->pipe_widget);
|
||||||
use_count_dec:
|
use_count_dec:
|
||||||
swidget->use_count--;
|
swidget->use_count--;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -408,7 +413,7 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
|
|||||||
struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list;
|
struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list;
|
||||||
struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
|
struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
|
||||||
struct snd_sof_widget *swidget = widget->dobj.private;
|
struct snd_sof_widget *swidget = widget->dobj.private;
|
||||||
struct snd_sof_widget *pipe_widget;
|
struct snd_sof_pipeline *spipe;
|
||||||
struct snd_soc_dapm_path *p;
|
struct snd_soc_dapm_path *p;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -420,7 +425,7 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* skip populating the pipe_widgets array if it is NULL */
|
/* skip populating the pipe_widgets array if it is NULL */
|
||||||
if (!pipeline_list->pipe_widgets)
|
if (!pipeline_list->pipelines)
|
||||||
goto sink_setup;
|
goto sink_setup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -429,14 +434,14 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
|
|||||||
* order source to sink.
|
* order source to sink.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < pipeline_list->count; i++) {
|
for (i = 0; i < pipeline_list->count; i++) {
|
||||||
pipe_widget = pipeline_list->pipe_widgets[i];
|
spipe = pipeline_list->pipelines[i];
|
||||||
if (pipe_widget == swidget->pipe_widget)
|
if (spipe == swidget->spipe)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == pipeline_list->count) {
|
if (i == pipeline_list->count) {
|
||||||
pipeline_list->count++;
|
pipeline_list->count++;
|
||||||
pipeline_list->pipe_widgets[i] = swidget->pipe_widget;
|
pipeline_list->pipelines[i] = swidget->spipe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,11 +576,20 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
|
|||||||
for_each_dapm_widgets(list, i, widget) {
|
for_each_dapm_widgets(list, i, widget) {
|
||||||
struct snd_sof_widget *swidget = widget->dobj.private;
|
struct snd_sof_widget *swidget = widget->dobj.private;
|
||||||
struct snd_sof_widget *pipe_widget;
|
struct snd_sof_widget *pipe_widget;
|
||||||
|
struct snd_sof_pipeline *spipe;
|
||||||
|
|
||||||
if (!swidget)
|
if (!swidget)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pipe_widget = swidget->pipe_widget;
|
spipe = swidget->spipe;
|
||||||
|
if (!spipe) {
|
||||||
|
dev_err(sdev->dev, "no pipeline found for %s\n",
|
||||||
|
swidget->widget->name);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto widget_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_widget = spipe->pipe_widget;
|
||||||
if (!pipe_widget) {
|
if (!pipe_widget) {
|
||||||
dev_err(sdev->dev, "error: no pipeline widget found for %s\n",
|
dev_err(sdev->dev, "error: no pipeline widget found for %s\n",
|
||||||
swidget->widget->name);
|
swidget->widget->name);
|
||||||
@@ -583,13 +597,13 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
|
|||||||
goto widget_free;
|
goto widget_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe_widget->complete)
|
if (spipe->complete)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tplg_ops && tplg_ops->pipeline_complete) {
|
if (tplg_ops && tplg_ops->pipeline_complete) {
|
||||||
pipe_widget->complete = tplg_ops->pipeline_complete(sdev, pipe_widget);
|
spipe->complete = tplg_ops->pipeline_complete(sdev, pipe_widget);
|
||||||
if (pipe_widget->complete < 0) {
|
if (spipe->complete < 0) {
|
||||||
ret = pipe_widget->complete;
|
ret = spipe->complete;
|
||||||
goto widget_free;
|
goto widget_free;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,11 +288,11 @@ struct sof_token_info {
|
|||||||
/**
|
/**
|
||||||
* struct snd_sof_pcm_stream_pipeline_list - List of pipelines associated with a PCM stream
|
* struct snd_sof_pcm_stream_pipeline_list - List of pipelines associated with a PCM stream
|
||||||
* @count: number of pipeline widgets in the @pipe_widgets array
|
* @count: number of pipeline widgets in the @pipe_widgets array
|
||||||
* @pipe_widgets: array of pipeline widgets
|
* @pipelines: array of pipelines
|
||||||
*/
|
*/
|
||||||
struct snd_sof_pcm_stream_pipeline_list {
|
struct snd_sof_pcm_stream_pipeline_list {
|
||||||
u32 count;
|
u32 count;
|
||||||
struct snd_sof_widget **pipe_widgets;
|
struct snd_sof_pipeline **pipelines;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PCM stream, mapped to FW component */
|
/* PCM stream, mapped to FW component */
|
||||||
@@ -382,11 +382,6 @@ struct snd_sof_widget {
|
|||||||
struct snd_soc_component *scomp;
|
struct snd_soc_component *scomp;
|
||||||
int comp_id;
|
int comp_id;
|
||||||
int pipeline_id;
|
int pipeline_id;
|
||||||
/*
|
|
||||||
* complete flag is used to indicate that pipeline set up is complete for scheduler type
|
|
||||||
* widgets. It is unused for all other widget types.
|
|
||||||
*/
|
|
||||||
int complete;
|
|
||||||
/*
|
/*
|
||||||
* the prepared flag is used to indicate that a widget has been prepared for getting set
|
* the prepared flag is used to indicate that a widget has been prepared for getting set
|
||||||
* up in the DSP.
|
* up in the DSP.
|
||||||
@@ -413,7 +408,7 @@ struct snd_sof_widget {
|
|||||||
|
|
||||||
struct snd_soc_dapm_widget *widget;
|
struct snd_soc_dapm_widget *widget;
|
||||||
struct list_head list; /* list in sdev widget list */
|
struct list_head list; /* list in sdev widget list */
|
||||||
struct snd_sof_widget *pipe_widget;
|
struct snd_sof_pipeline *spipe;
|
||||||
void *module_info;
|
void *module_info;
|
||||||
|
|
||||||
const guid_t uuid;
|
const guid_t uuid;
|
||||||
@@ -451,6 +446,22 @@ struct snd_sof_widget {
|
|||||||
void *private; /* core does not touch this */
|
void *private; /* core does not touch this */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** struct snd_sof_pipeline - ASoC SOF pipeline
|
||||||
|
* @pipe_widget: Pointer to the pipeline widget
|
||||||
|
* @started_count: Count of number of PCM's that have started this pipeline
|
||||||
|
* @paused_count: Count of number of PCM's that have started and have currently paused this
|
||||||
|
pipeline
|
||||||
|
* @complete: flag used to indicate that pipeline set up is complete.
|
||||||
|
* @list: List item in sdev pipeline_list
|
||||||
|
*/
|
||||||
|
struct snd_sof_pipeline {
|
||||||
|
struct snd_sof_widget *pipe_widget;
|
||||||
|
int started_count;
|
||||||
|
int paused_count;
|
||||||
|
int complete;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
/* ASoC SOF DAPM route */
|
/* ASoC SOF DAPM route */
|
||||||
struct snd_sof_route {
|
struct snd_sof_route {
|
||||||
struct snd_soc_component *scomp;
|
struct snd_soc_component *scomp;
|
||||||
|
|||||||
@@ -578,6 +578,7 @@ struct snd_sof_dev {
|
|||||||
struct list_head pcm_list;
|
struct list_head pcm_list;
|
||||||
struct list_head kcontrol_list;
|
struct list_head kcontrol_list;
|
||||||
struct list_head widget_list;
|
struct list_head widget_list;
|
||||||
|
struct list_head pipeline_list;
|
||||||
struct list_head dai_list;
|
struct list_head dai_list;
|
||||||
struct list_head dai_link_list;
|
struct list_head dai_link_list;
|
||||||
struct list_head route_list;
|
struct list_head route_list;
|
||||||
|
|||||||
@@ -1402,7 +1402,6 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
|
|||||||
swidget->scomp = scomp;
|
swidget->scomp = scomp;
|
||||||
swidget->widget = w;
|
swidget->widget = w;
|
||||||
swidget->comp_id = sdev->next_comp_id++;
|
swidget->comp_id = sdev->next_comp_id++;
|
||||||
swidget->complete = 0;
|
|
||||||
swidget->id = w->id;
|
swidget->id = w->id;
|
||||||
swidget->pipeline_id = index;
|
swidget->pipeline_id = index;
|
||||||
swidget->private = NULL;
|
swidget->private = NULL;
|
||||||
@@ -1553,6 +1552,23 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create and add pipeline for scheduler type widgets */
|
||||||
|
if (w->id == snd_soc_dapm_scheduler) {
|
||||||
|
struct snd_sof_pipeline *spipe;
|
||||||
|
|
||||||
|
spipe = kzalloc(sizeof(*spipe), GFP_KERNEL);
|
||||||
|
if (!spipe) {
|
||||||
|
kfree(swidget->private);
|
||||||
|
kfree(swidget->tuples);
|
||||||
|
kfree(swidget);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
spipe->pipe_widget = swidget;
|
||||||
|
swidget->spipe = spipe;
|
||||||
|
list_add(&spipe->list, &sdev->pipeline_list);
|
||||||
|
}
|
||||||
|
|
||||||
w->dobj.private = swidget;
|
w->dobj.private = swidget;
|
||||||
list_add(&swidget->list, &sdev->widget_list);
|
list_add(&swidget->list, &sdev->widget_list);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1608,6 +1624,15 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
|
|||||||
sof_disconnect_dai_widget(scomp, widget);
|
sof_disconnect_dai_widget(scomp, widget);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case snd_soc_dapm_scheduler:
|
||||||
|
{
|
||||||
|
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||||
|
|
||||||
|
list_del(&spipe->list);
|
||||||
|
kfree(spipe);
|
||||||
|
swidget->spipe = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2082,18 +2107,19 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sof_set_pipe_widget - Set pipe_widget for a component
|
* sof_set_widget_pipeline - Set pipeline for a component
|
||||||
* @sdev: pointer to struct snd_sof_dev
|
* @sdev: pointer to struct snd_sof_dev
|
||||||
* @pipe_widget: pointer to struct snd_sof_widget of type snd_soc_dapm_scheduler
|
* @spipe: pointer to struct snd_sof_pipeline
|
||||||
* @swidget: pointer to struct snd_sof_widget that has the same pipeline ID as @pipe_widget
|
* @swidget: pointer to struct snd_sof_widget that has the same pipeline ID as @pipe_widget
|
||||||
*
|
*
|
||||||
* Return: 0 if successful, -EINVAL on error.
|
* Return: 0 if successful, -EINVAL on error.
|
||||||
* The function checks if @swidget is associated with any volatile controls. If so, setting
|
* The function checks if @swidget is associated with any volatile controls. If so, setting
|
||||||
* the dynamic_pipeline_widget is disallowed.
|
* the dynamic_pipeline_widget is disallowed.
|
||||||
*/
|
*/
|
||||||
static int sof_set_pipe_widget(struct snd_sof_dev *sdev, struct snd_sof_widget *pipe_widget,
|
static int sof_set_widget_pipeline(struct snd_sof_dev *sdev, struct snd_sof_pipeline *spipe,
|
||||||
struct snd_sof_widget *swidget)
|
struct snd_sof_widget *swidget)
|
||||||
{
|
{
|
||||||
|
struct snd_sof_widget *pipe_widget = spipe->pipe_widget;
|
||||||
struct snd_sof_control *scontrol;
|
struct snd_sof_control *scontrol;
|
||||||
|
|
||||||
if (pipe_widget->dynamic_pipeline_widget) {
|
if (pipe_widget->dynamic_pipeline_widget) {
|
||||||
@@ -2108,8 +2134,8 @@ static int sof_set_pipe_widget(struct snd_sof_dev *sdev, struct snd_sof_widget *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the pipe_widget and apply the dynamic_pipeline_widget_flag */
|
/* set the pipeline and apply the dynamic_pipeline_widget_flag */
|
||||||
swidget->pipe_widget = pipe_widget;
|
swidget->spipe = spipe;
|
||||||
swidget->dynamic_pipeline_widget = pipe_widget->dynamic_pipeline_widget;
|
swidget->dynamic_pipeline_widget = pipe_widget->dynamic_pipeline_widget;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2123,6 +2149,7 @@ static int sof_complete(struct snd_soc_component *scomp)
|
|||||||
struct snd_sof_widget *swidget, *comp_swidget;
|
struct snd_sof_widget *swidget, *comp_swidget;
|
||||||
const struct sof_ipc_tplg_widget_ops *widget_ops;
|
const struct sof_ipc_tplg_widget_ops *widget_ops;
|
||||||
struct snd_sof_control *scontrol;
|
struct snd_sof_control *scontrol;
|
||||||
|
struct snd_sof_pipeline *spipe;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
widget_ops = tplg_ops ? tplg_ops->widget : NULL;
|
widget_ops = tplg_ops ? tplg_ops->widget : NULL;
|
||||||
@@ -2155,23 +2182,21 @@ static int sof_complete(struct snd_soc_component *scomp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set the pipe_widget and apply the dynamic_pipeline_widget_flag */
|
/* set the pipe_widget and apply the dynamic_pipeline_widget_flag */
|
||||||
list_for_each_entry(swidget, &sdev->widget_list, list) {
|
list_for_each_entry(spipe, &sdev->pipeline_list, list) {
|
||||||
switch (swidget->id) {
|
struct snd_sof_widget *pipe_widget = spipe->pipe_widget;
|
||||||
case snd_soc_dapm_scheduler:
|
|
||||||
/*
|
/*
|
||||||
* Apply the dynamic_pipeline_widget flag and set the pipe_widget field
|
* Apply the dynamic_pipeline_widget flag and set the pipe_widget field
|
||||||
* for all widgets that have the same pipeline ID as the scheduler widget
|
* for all widgets that have the same pipeline ID as the scheduler widget.
|
||||||
*/
|
* Skip the scheduler widgets as they have their pipeline set during widget_ready
|
||||||
list_for_each_entry(comp_swidget, &sdev->widget_list, list)
|
*/
|
||||||
if (comp_swidget->pipeline_id == swidget->pipeline_id) {
|
list_for_each_entry(comp_swidget, &sdev->widget_list, list)
|
||||||
ret = sof_set_pipe_widget(sdev, swidget, comp_swidget);
|
if (comp_swidget->widget->id != snd_soc_dapm_scheduler &&
|
||||||
if (ret < 0)
|
comp_swidget->pipeline_id == pipe_widget->pipeline_id) {
|
||||||
return ret;
|
ret = sof_set_widget_pipeline(sdev, spipe, comp_swidget);
|
||||||
}
|
if (ret < 0)
|
||||||
break;
|
return ret;
|
||||||
default:
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* verify topology components loading including dynamic pipelines */
|
/* verify topology components loading including dynamic pipelines */
|
||||||
|
|||||||
Reference in New Issue
Block a user