]>
Commit | Line | Data |
---|---|---|
e149ca29 | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
b9132b89 DB |
2 | // |
3 | // Copyright 2019 NXP | |
4 | // | |
5 | // Author: Daniel Baluta <daniel.baluta@nxp.com> | |
6 | // | |
7 | ||
8 | #include <linux/firmware.h> | |
9 | #include <linux/module.h> | |
10 | #include <linux/pm_runtime.h> | |
11 | #include <sound/sof.h> | |
12 | ||
13 | #include "ops.h" | |
14 | ||
15 | extern struct snd_sof_dsp_ops sof_imx8_ops; | |
f831ebf2 | 16 | extern struct snd_sof_dsp_ops sof_imx8x_ops; |
58825cc2 | 17 | extern struct snd_sof_dsp_ops sof_imx8m_ops; |
b9132b89 DB |
18 | |
19 | /* platform specific devices */ | |
20 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) | |
21 | static struct sof_dev_desc sof_of_imx8qxp_desc = { | |
22 | .default_fw_path = "imx/sof", | |
23 | .default_tplg_path = "imx/sof-tplg", | |
9da9ace2 | 24 | .default_fw_filename = "sof-imx8x.ri", |
b9132b89 | 25 | .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", |
9da9ace2 | 26 | .ops = &sof_imx8x_ops, |
b9132b89 | 27 | }; |
f831ebf2 PO |
28 | |
29 | static struct sof_dev_desc sof_of_imx8qm_desc = { | |
30 | .default_fw_path = "imx/sof", | |
31 | .default_tplg_path = "imx/sof-tplg", | |
32 | .default_fw_filename = "sof-imx8.ri", | |
33 | .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", | |
34 | .ops = &sof_imx8_ops, | |
35 | }; | |
b9132b89 DB |
36 | #endif |
37 | ||
58825cc2 DB |
38 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8M) |
39 | static struct sof_dev_desc sof_of_imx8mp_desc = { | |
40 | .default_fw_path = "imx/sof", | |
41 | .default_tplg_path = "imx/sof-tplg", | |
42 | .default_fw_filename = "sof-imx8m.ri", | |
43 | .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", | |
44 | .ops = &sof_imx8m_ops, | |
45 | }; | |
46 | #endif | |
47 | ||
b9132b89 DB |
48 | static const struct dev_pm_ops sof_of_pm = { |
49 | SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) | |
50 | SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, | |
51 | NULL) | |
52 | }; | |
53 | ||
54 | static void sof_of_probe_complete(struct device *dev) | |
55 | { | |
56 | /* allow runtime_pm */ | |
57 | pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); | |
58 | pm_runtime_use_autosuspend(dev); | |
59 | pm_runtime_enable(dev); | |
60 | } | |
61 | ||
62 | static int sof_of_probe(struct platform_device *pdev) | |
63 | { | |
64 | struct device *dev = &pdev->dev; | |
65 | const struct sof_dev_desc *desc; | |
b9132b89 DB |
66 | struct snd_sof_pdata *sof_pdata; |
67 | const struct snd_sof_dsp_ops *ops; | |
68 | int ret; | |
69 | ||
70 | dev_info(&pdev->dev, "DT DSP detected"); | |
71 | ||
72 | sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); | |
73 | if (!sof_pdata) | |
74 | return -ENOMEM; | |
75 | ||
76 | desc = device_get_match_data(dev); | |
77 | if (!desc) | |
78 | return -ENODEV; | |
79 | ||
80 | /* get ops for platform */ | |
81 | ops = desc->ops; | |
82 | if (!ops) { | |
83 | dev_err(dev, "error: no matching DT descriptor ops\n"); | |
84 | return -ENODEV; | |
85 | } | |
86 | ||
b9132b89 DB |
87 | sof_pdata->desc = desc; |
88 | sof_pdata->dev = &pdev->dev; | |
285880a2 | 89 | sof_pdata->fw_filename = desc->default_fw_filename; |
b9132b89 DB |
90 | |
91 | /* TODO: read alternate fw and tplg filenames from DT */ | |
92 | sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; | |
93 | sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; | |
94 | ||
95 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) | |
96 | /* set callback to enable runtime_pm */ | |
97 | sof_pdata->sof_probe_complete = sof_of_probe_complete; | |
98 | #endif | |
99 | /* call sof helper for DSP hardware probe */ | |
100 | ret = snd_sof_device_probe(dev, sof_pdata); | |
101 | if (ret) { | |
102 | dev_err(dev, "error: failed to probe DSP hardware\n"); | |
103 | return ret; | |
104 | } | |
105 | ||
106 | #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) | |
107 | sof_of_probe_complete(dev); | |
108 | #endif | |
109 | ||
110 | return ret; | |
111 | } | |
112 | ||
113 | static int sof_of_remove(struct platform_device *pdev) | |
114 | { | |
115 | pm_runtime_disable(&pdev->dev); | |
116 | ||
117 | /* call sof helper for DSP hardware remove */ | |
118 | snd_sof_device_remove(&pdev->dev); | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
123 | static const struct of_device_id sof_of_ids[] = { | |
124 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) | |
125 | { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, | |
f831ebf2 | 126 | { .compatible = "fsl,imx8qm-dsp", .data = &sof_of_imx8qm_desc}, |
58825cc2 DB |
127 | #endif |
128 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8M) | |
129 | { .compatible = "fsl,imx8mp-dsp", .data = &sof_of_imx8mp_desc}, | |
b9132b89 DB |
130 | #endif |
131 | { } | |
132 | }; | |
133 | MODULE_DEVICE_TABLE(of, sof_of_ids); | |
134 | ||
135 | /* DT driver definition */ | |
136 | static struct platform_driver snd_sof_of_driver = { | |
137 | .probe = sof_of_probe, | |
138 | .remove = sof_of_remove, | |
139 | .driver = { | |
140 | .name = "sof-audio-of", | |
141 | .pm = &sof_of_pm, | |
142 | .of_match_table = sof_of_ids, | |
143 | }, | |
144 | }; | |
145 | module_platform_driver(snd_sof_of_driver); | |
146 | ||
147 | MODULE_LICENSE("Dual BSD/GPL"); |