Skip to content
Open
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
1 change: 1 addition & 0 deletions sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
mutex_init(&sdev->ipc_client_mutex);
mutex_init(&sdev->client_event_handler_mutex);
mutex_init(&sdev->dsp_fw_boot_mutex);
mutex_init(&sdev->loaded_tplg_names_mutex);

/* set default timeouts if none provided */
if (plat_data->desc->ipc_timeout == 0)
Expand Down
27 changes: 25 additions & 2 deletions sound/soc/sof/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <sound/sof/ext_manifest.h>
#include <sound/sof/debug.h>
#include "sof-priv.h"
Expand Down Expand Up @@ -313,6 +314,28 @@ int snd_sof_dbg_memory_info_init(struct snd_sof_dev *sdev)
}
EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init);

static int sof_dbg_tplg_name_show(struct seq_file *m, void *v)
{
struct snd_sof_dev *sdev = m->private;

/* fall back to the selected topology name while no topology is loaded */
mutex_lock(&sdev->loaded_tplg_names_mutex);
seq_printf(m, "%s\n", sdev->loaded_tplg_names ?: sdev->pdata->tplg_filename);
mutex_unlock(&sdev->loaded_tplg_names_mutex);

return 0;
}
DEFINE_SHOW_ATTRIBUTE(sof_dbg_tplg_name);

/* Takes ownership of the devm allocated tplg_names, NULL clears the list */
void sof_debug_set_tplg_name(struct snd_sof_dev *sdev, char *tplg_names)
{
mutex_lock(&sdev->loaded_tplg_names_mutex);
devm_kfree(sdev->dev, sdev->loaded_tplg_names);
sdev->loaded_tplg_names = tplg_names;
mutex_unlock(&sdev->loaded_tplg_names_mutex);
}

int snd_sof_dbg_init(struct snd_sof_dev *sdev)
{
const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
Expand Down Expand Up @@ -355,8 +378,8 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev)
(char **)&plat_data->tplg_filename_prefix);
debugfs_create_str("fw_name", 0444, fw_profile,
(char **)&plat_data->fw_filename);
debugfs_create_str("tplg_name", 0444, fw_profile,
(char **)&plat_data->tplg_filename);
debugfs_create_file("tplg_name", 0444, fw_profile, sdev,
&sof_dbg_tplg_name_fops);
debugfs_create_u32("ipc_type", 0444, fw_profile,
(u32 *)&plat_data->ipc_type);

Expand Down
3 changes: 3 additions & 0 deletions sound/soc/sof/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,11 @@ static int sof_pcm_probe(struct snd_soc_component *component)

static void sof_pcm_remove(struct snd_soc_component *component)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);

/* remove topology */
snd_soc_tplg_component_remove(component);
sof_debug_set_tplg_name(sdev, NULL);
}

static int sof_pcm_ack(struct snd_soc_component *component,
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/sof/sof-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,9 @@ struct snd_sof_dev {
struct snd_soc_component *component;
u32 enabled_cores_mask; /* keep track of enabled cores */
bool led_present;
/* newline separated list of the loaded topology files for debugfs */
char *loaded_tplg_names;
struct mutex loaded_tplg_names_mutex; /* protects loaded_tplg_names */

/* FW configuration */
struct sof_ipc_window *info_window;
Expand Down Expand Up @@ -798,6 +801,7 @@ static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_i
*/
int snd_sof_dbg_init(struct snd_sof_dev *sdev);
void snd_sof_free_debug(struct snd_sof_dev *sdev);
void sof_debug_set_tplg_name(struct snd_sof_dev *sdev, char *tplg_names);
int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev,
void *base, size_t size,
const char *name, mode_t mode);
Expand Down
67 changes: 55 additions & 12 deletions sound/soc/sof/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -2509,11 +2509,40 @@ static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = {
.bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops),
};

/*
* Append the name of a loaded topology file to the list exposed via debugfs.
* The topology path prefix is dropped as it is exposed separately.
*/
static int sof_tplg_names_append(struct snd_sof_dev *sdev, char **names,
const char *file)
{
const char *prefix = sdev->pdata->tplg_filename_prefix;
size_t prefix_len = strlen(prefix);
char *new_names;

if (!strncmp(file, prefix, prefix_len) && file[prefix_len] == '/')
file += prefix_len + 1;

if (*names)
new_names = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s\n%s",
*names, file);
else
new_names = devm_kstrdup(sdev->dev, file, GFP_KERNEL);
if (!new_names)
return -ENOMEM;

devm_kfree(sdev->dev, *names);
*names = new_names;

return 0;
}

int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const char *tplg_filename_prefix = sof_pdata->tplg_filename_prefix;
char *tplg_names = NULL;
int tplg_cnt = 0;
int ret;
int i;
Expand Down Expand Up @@ -2575,12 +2604,6 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
const struct firmware *fw __free(firmware) = NULL;
ret = request_firmware(&fw, tplg_files[i], scomp->dev);
if (ret < 0) {
/*
* snd_soc_tplg_component_remove(scomp) will be called
* if snd_soc_tplg_component_load(scomp) failed and all
* objects in the scomp will be removed. No need to call
* snd_soc_tplg_component_remove(scomp) here.
*/
dev_err(scomp->dev, "tplg request firmware %s failed err: %d\n",
tplg_files[i], ret);
goto out;
Expand All @@ -2596,6 +2619,10 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
tplg_files[i], ret);
goto out;
}

ret = sof_tplg_names_append(sdev, &tplg_names, tplg_files[i]);
if (ret < 0)
goto out;
}

/* Loading user defined topologies */
Expand All @@ -2613,12 +2640,6 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
const struct firmware *fw __free(firmware) = NULL;
ret = request_firmware(&fw, feature_topology, scomp->dev);
if (ret < 0) {
/*
* snd_soc_tplg_component_remove(scomp) will be called
* if snd_soc_tplg_component_load(scomp) failed and all
* objects in the scomp will be removed. No need to call
* snd_soc_tplg_component_remove(scomp) here.
*/
dev_warn(scomp->dev, "feature tplg request firmware %s failed err: %d\n",
feature_topologies[i], ret);
/*
Expand All @@ -2644,15 +2665,37 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
*/
goto out;
}

ret = sof_tplg_names_append(sdev, &tplg_names, feature_topology);
if (ret < 0)
goto out;
}

/* call sof_complete when topologies are loaded successfully */
ret = sof_complete(scomp);
if (ret < 0)
goto out;

/* Update the list of loaded topologies exposed via debugfs */
sof_debug_set_tplg_name(sdev, tplg_names);
tplg_names = NULL;

out:
devm_kfree(sdev->dev, tplg_names);

if (ret >= 0 && sdev->led_present)
ret = snd_ctl_led_request();

/*
* Remove the topology on any error as .remove is not called when the
* component probe fails. If snd_soc_tplg_component_load() failed, it
* has removed it already and this call is a no-op.
*/
if (ret < 0) {
snd_soc_tplg_component_remove(scomp);
sof_debug_set_tplg_name(sdev, NULL);
}

return ret;
}
EXPORT_SYMBOL(snd_sof_load_topology);
Loading