at v5.6 123 lines 3.0 kB view raw
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 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 15extern struct snd_sof_dsp_ops sof_imx8_ops; 16 17/* platform specific devices */ 18#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) 19static struct sof_dev_desc sof_of_imx8qxp_desc = { 20 .default_fw_path = "imx/sof", 21 .default_tplg_path = "imx/sof-tplg", 22 .default_fw_filename = "sof-imx8.ri", 23 .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", 24 .ops = &sof_imx8_ops, 25}; 26#endif 27 28static const struct dev_pm_ops sof_of_pm = { 29 SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) 30 SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, 31 NULL) 32}; 33 34static void sof_of_probe_complete(struct device *dev) 35{ 36 /* allow runtime_pm */ 37 pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); 38 pm_runtime_use_autosuspend(dev); 39 pm_runtime_enable(dev); 40} 41 42static int sof_of_probe(struct platform_device *pdev) 43{ 44 struct device *dev = &pdev->dev; 45 const struct sof_dev_desc *desc; 46 struct snd_sof_pdata *sof_pdata; 47 const struct snd_sof_dsp_ops *ops; 48 int ret; 49 50 dev_info(&pdev->dev, "DT DSP detected"); 51 52 sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); 53 if (!sof_pdata) 54 return -ENOMEM; 55 56 desc = device_get_match_data(dev); 57 if (!desc) 58 return -ENODEV; 59 60 /* get ops for platform */ 61 ops = desc->ops; 62 if (!ops) { 63 dev_err(dev, "error: no matching DT descriptor ops\n"); 64 return -ENODEV; 65 } 66 67 sof_pdata->desc = desc; 68 sof_pdata->dev = &pdev->dev; 69 sof_pdata->fw_filename = desc->default_fw_filename; 70 71 /* TODO: read alternate fw and tplg filenames from DT */ 72 sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; 73 sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; 74 75#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 76 /* set callback to enable runtime_pm */ 77 sof_pdata->sof_probe_complete = sof_of_probe_complete; 78#endif 79 /* call sof helper for DSP hardware probe */ 80 ret = snd_sof_device_probe(dev, sof_pdata); 81 if (ret) { 82 dev_err(dev, "error: failed to probe DSP hardware\n"); 83 return ret; 84 } 85 86#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) 87 sof_of_probe_complete(dev); 88#endif 89 90 return ret; 91} 92 93static int sof_of_remove(struct platform_device *pdev) 94{ 95 pm_runtime_disable(&pdev->dev); 96 97 /* call sof helper for DSP hardware remove */ 98 snd_sof_device_remove(&pdev->dev); 99 100 return 0; 101} 102 103static const struct of_device_id sof_of_ids[] = { 104#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) 105 { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, 106#endif 107 { } 108}; 109MODULE_DEVICE_TABLE(of, sof_of_ids); 110 111/* DT driver definition */ 112static struct platform_driver snd_sof_of_driver = { 113 .probe = sof_of_probe, 114 .remove = sof_of_remove, 115 .driver = { 116 .name = "sof-audio-of", 117 .pm = &sof_of_pm, 118 .of_match_table = sof_of_ids, 119 }, 120}; 121module_platform_driver(snd_sof_of_driver); 122 123MODULE_LICENSE("Dual BSD/GPL");