xref: /openbmc/linux/sound/soc/sof/sof-of-dev.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2b9132b89SDaniel Baluta //
3b9132b89SDaniel Baluta // Copyright 2019 NXP
4b9132b89SDaniel Baluta //
5b9132b89SDaniel Baluta // Author: Daniel Baluta <daniel.baluta@nxp.com>
6b9132b89SDaniel Baluta //
7b9132b89SDaniel Baluta 
8b9132b89SDaniel Baluta #include <linux/firmware.h>
9b9132b89SDaniel Baluta #include <linux/module.h>
107b84fd26SDaniel Baluta #include <linux/moduleparam.h>
11b9132b89SDaniel Baluta #include <linux/pm_runtime.h>
12b9132b89SDaniel Baluta #include <sound/sof.h>
13b9132b89SDaniel Baluta 
1428084f4aSDaniel Baluta #include "sof-of-dev.h"
15b9132b89SDaniel Baluta #include "ops.h"
16b9132b89SDaniel Baluta 
177b84fd26SDaniel Baluta static char *fw_path;
187b84fd26SDaniel Baluta module_param(fw_path, charp, 0444);
197b84fd26SDaniel Baluta MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
207b84fd26SDaniel Baluta 
217b84fd26SDaniel Baluta static char *tplg_path;
227b84fd26SDaniel Baluta module_param(tplg_path, charp, 0444);
237b84fd26SDaniel Baluta MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
247b84fd26SDaniel Baluta 
2528084f4aSDaniel Baluta const struct dev_pm_ops sof_of_pm = {
26dd759805SDaniel Baluta 	.prepare = snd_sof_prepare,
27dd759805SDaniel Baluta 	.complete = snd_sof_complete,
28b9132b89SDaniel Baluta 	SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
29b9132b89SDaniel Baluta 	SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
30b9132b89SDaniel Baluta 			   NULL)
31b9132b89SDaniel Baluta };
3228084f4aSDaniel Baluta EXPORT_SYMBOL(sof_of_pm);
33b9132b89SDaniel Baluta 
sof_of_probe_complete(struct device * dev)34b9132b89SDaniel Baluta static void sof_of_probe_complete(struct device *dev)
35b9132b89SDaniel Baluta {
36b9132b89SDaniel Baluta 	/* allow runtime_pm */
37b9132b89SDaniel Baluta 	pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
38b9132b89SDaniel Baluta 	pm_runtime_use_autosuspend(dev);
39475b17b4SAllen-KH Cheng 	pm_runtime_mark_last_busy(dev);
404fefc398SDaniel Baluta 	pm_runtime_set_active(dev);
41b9132b89SDaniel Baluta 	pm_runtime_enable(dev);
42b9132b89SDaniel Baluta }
43b9132b89SDaniel Baluta 
sof_of_probe(struct platform_device * pdev)4428084f4aSDaniel Baluta int sof_of_probe(struct platform_device *pdev)
45b9132b89SDaniel Baluta {
46b9132b89SDaniel Baluta 	struct device *dev = &pdev->dev;
47b9132b89SDaniel Baluta 	const struct sof_dev_desc *desc;
48b9132b89SDaniel Baluta 	struct snd_sof_pdata *sof_pdata;
49b9132b89SDaniel Baluta 
50b9132b89SDaniel Baluta 	dev_info(&pdev->dev, "DT DSP detected");
51b9132b89SDaniel Baluta 
52b9132b89SDaniel Baluta 	sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
53b9132b89SDaniel Baluta 	if (!sof_pdata)
54b9132b89SDaniel Baluta 		return -ENOMEM;
55b9132b89SDaniel Baluta 
56b9132b89SDaniel Baluta 	desc = device_get_match_data(dev);
57b9132b89SDaniel Baluta 	if (!desc)
58b9132b89SDaniel Baluta 		return -ENODEV;
59b9132b89SDaniel Baluta 
60fd979ec1SPeter Ujfalusi 	if (!desc->ops) {
61b9132b89SDaniel Baluta 		dev_err(dev, "error: no matching DT descriptor ops\n");
62b9132b89SDaniel Baluta 		return -ENODEV;
63b9132b89SDaniel Baluta 	}
64b9132b89SDaniel Baluta 
65b9132b89SDaniel Baluta 	sof_pdata->desc = desc;
66b9132b89SDaniel Baluta 	sof_pdata->dev = &pdev->dev;
67*a97abb3cSPierre-Louis Bossart 	sof_pdata->fw_filename = desc->default_fw_filename[SOF_IPC];
68b9132b89SDaniel Baluta 
697b84fd26SDaniel Baluta 	if (fw_path)
707b84fd26SDaniel Baluta 		sof_pdata->fw_filename_prefix = fw_path;
717b84fd26SDaniel Baluta 	else
72a3757915SPierre-Louis Bossart 		sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path[SOF_IPC];
737b84fd26SDaniel Baluta 
747b84fd26SDaniel Baluta 	if (tplg_path)
757b84fd26SDaniel Baluta 		sof_pdata->tplg_filename_prefix = tplg_path;
767b84fd26SDaniel Baluta 	else
77a3757915SPierre-Louis Bossart 		sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path[SOF_IPC];
78b9132b89SDaniel Baluta 
794d1284cdSPeter Ujfalusi 	/* set callback to be called on successful device probe to enable runtime_pm */
80b9132b89SDaniel Baluta 	sof_pdata->sof_probe_complete = sof_of_probe_complete;
814d1284cdSPeter Ujfalusi 
82b9132b89SDaniel Baluta 	/* call sof helper for DSP hardware probe */
834d1284cdSPeter Ujfalusi 	return snd_sof_device_probe(dev, sof_pdata);
84b9132b89SDaniel Baluta }
8528084f4aSDaniel Baluta EXPORT_SYMBOL(sof_of_probe);
86b9132b89SDaniel Baluta 
sof_of_remove(struct platform_device * pdev)8728084f4aSDaniel Baluta int sof_of_remove(struct platform_device *pdev)
88b9132b89SDaniel Baluta {
89b9132b89SDaniel Baluta 	pm_runtime_disable(&pdev->dev);
90b9132b89SDaniel Baluta 
91b9132b89SDaniel Baluta 	/* call sof helper for DSP hardware remove */
92b9132b89SDaniel Baluta 	snd_sof_device_remove(&pdev->dev);
93b9132b89SDaniel Baluta 
94b9132b89SDaniel Baluta 	return 0;
95b9132b89SDaniel Baluta }
9628084f4aSDaniel Baluta EXPORT_SYMBOL(sof_of_remove);
97b9132b89SDaniel Baluta 
sof_of_shutdown(struct platform_device * pdev)98fe70300cSYC Hung void sof_of_shutdown(struct platform_device *pdev)
99fe70300cSYC Hung {
100fe70300cSYC Hung 	snd_sof_device_shutdown(&pdev->dev);
101fe70300cSYC Hung }
102fe70300cSYC Hung EXPORT_SYMBOL(sof_of_shutdown);
103fe70300cSYC Hung 
104b9132b89SDaniel Baluta MODULE_LICENSE("Dual BSD/GPL");
105