linux-imx/sound/soc/sof/sof-of-dev.c
Daniel Baluta 0ab89baf64 ASoC: SOF: Introduce machine driver name
ACPI creates tables with information about the machine driver.
With DT there is no need for such tables because we can directly
get all the information needed from DT file.

This patch introduces machine driver property inside dsp node.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
2023-10-30 15:21:58 +08:00

136 lines
3.2 KiB
C

// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// Copyright 2019 NXP
//
// Author: Daniel Baluta <daniel.baluta@nxp.com>
//
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pm_runtime.h>
#include <sound/sof.h>
#include "sof-of-dev.h"
#include "ops.h"
static char *fw_path;
module_param(fw_path, charp, 0444);
MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
static char *tplg_path;
module_param(tplg_path, charp, 0444);
MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
const struct dev_pm_ops sof_of_pm = {
.prepare = snd_sof_prepare,
.complete = snd_sof_complete,
SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
NULL)
};
EXPORT_SYMBOL(sof_of_pm);
static void sof_of_probe_complete(struct device *dev)
{
/* allow runtime_pm */
pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
}
static int sof_of_parse(struct platform_device *pdev)
{
struct snd_sof_pdata *sof_pdata = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node;
int ret;
/* firmware-name is optional in DT */
of_property_read_string(np, "firmware-name", &sof_pdata->fw_filename);
ret = of_property_read_string(np, "tplg-name",
&sof_pdata->tplg_filename);
if (ret < 0)
return ret;
ret = of_property_read_string(np, "machine-drv-name",
&sof_pdata->machine_drv_name);
if (ret < 0)
return ret;
return 0;
}
int sof_of_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct sof_dev_desc *desc;
struct snd_sof_pdata *sof_pdata;
int ret;
dev_info(&pdev->dev, "DT DSP detected");
sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
if (!sof_pdata)
return -ENOMEM;
platform_set_drvdata(pdev, sof_pdata);
desc = device_get_match_data(dev);
if (!desc)
return -ENODEV;
if (!desc->ops) {
dev_err(dev, "error: no matching DT descriptor ops\n");
return -ENODEV;
}
sof_pdata->desc = desc;
sof_pdata->dev = &pdev->dev;
sof_pdata->fw_filename = desc->default_fw_filename[SOF_IPC];
if (fw_path)
sof_pdata->fw_filename_prefix = fw_path;
else
sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path[SOF_IPC];
if (tplg_path)
sof_pdata->tplg_filename_prefix = tplg_path;
else
sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path[SOF_IPC];
ret = sof_of_parse(pdev);
if (ret < 0) {
dev_err(dev, "Could not parse SOF OF DSP node\n");
return ret;
}
/* set callback to be called on successful device probe to enable runtime_pm */
sof_pdata->sof_probe_complete = sof_of_probe_complete;
/* call sof helper for DSP hardware probe */
return snd_sof_device_probe(dev, sof_pdata);
}
EXPORT_SYMBOL(sof_of_probe);
int sof_of_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
/* call sof helper for DSP hardware remove */
snd_sof_device_remove(&pdev->dev);
return 0;
}
EXPORT_SYMBOL(sof_of_remove);
void sof_of_shutdown(struct platform_device *pdev)
{
snd_sof_device_shutdown(&pdev->dev);
}
EXPORT_SYMBOL(sof_of_shutdown);
MODULE_LICENSE("Dual BSD/GPL");