From 8e3acbaf350cb468ca8522206216246f680dc949 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 19 Sep 2019 23:42:46 -0700 Subject: [PATCH] ASoC: SOF: Add MFD support Add MFD support in SOF with a single client device for audio. The audio client is a registered as a separate platform device under the SOF PCI device. This patch deals with partitioning the DSP hardware initialisation parts and the audio specific code. The hardware initialization, FW load/boot, IPC init is done at the top-level PCI device probe. The audio client platform device's probe deals with registering the component driver, creating the machine driver and loading the topology. The device hierarchy is altered with the addition of the platform device for the audio client. The machine driver and the component driver will now be children of the sof-audio platform device. Signed-off-by: Ranjani Sridharan --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/core.c | 82 ++------------------- sound/soc/sof/sof-audio.c | 137 ++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-mfd.c | 41 +++++++++++ sound/soc/sof/sof-mfd.h | 21 ++++++ sound/soc/sof/sof-pci-dev.c | 2 +- sound/soc/sof/sof-priv.h | 8 +++ sound/soc/sof/topology.c | 4 +- 8 files changed, 218 insertions(+), 79 deletions(-) create mode 100644 sound/soc/sof/sof-audio.c create mode 100644 sound/soc/sof/sof-mfd.c create mode 100644 sound/soc/sof/sof-mfd.h diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 3639f7c006600b..d65f8ab2c893de 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -3,7 +3,7 @@ ccflags-y += -DDEBUG snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ - control.o trace.o utils.o + control.o trace.o utils.o sof-mfd.o sof-audio.o snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 8661c2cca76b9a..fd3bd576a141fc 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -15,6 +15,7 @@ #include #include "sof-priv.h" #include "ops.h" +#include "sof-mfd.h" /* see SOF_DBG_ flags */ int sof_core_debug; @@ -258,47 +259,9 @@ int snd_sof_create_page_table(struct snd_sof_dev *sdev, return pages; } -/* - * SOF Driver enumeration. - */ -static int sof_machine_check(struct snd_sof_dev *sdev) -{ - struct snd_sof_pdata *plat_data = sdev->pdata; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - struct snd_soc_acpi_mach *machine; - int ret; -#endif - - if (plat_data->machine) - return 0; - -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); - return -ENODEV; -#else - /* fallback to nocodec mode */ - dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n"); - machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL); - if (!machine) - return -ENOMEM; - - ret = sof_nocodec_setup(sdev->dev, plat_data, machine, - plat_data->desc, plat_data->desc->ops); - if (ret < 0) - return ret; - - plat_data->machine = machine; - - return 0; -#endif -} - static int sof_probe_continue(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; - const char *drv_name; - const void *mach; - int size; int ret; /* probe the DSP hardware */ @@ -308,17 +271,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) return ret; } - /* check machine info */ - ret = sof_machine_check(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to get machine info %d\n", - ret); - goto dbg_err; - } - - /* set up platform component driver */ - snd_sof_new_platform_drv(sdev); - /* register any debug/trace capabilities */ ret = snd_sof_dbg_init(sdev); if (ret < 0) { @@ -374,32 +326,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) /* hereafter all FW boot flows are for PM reasons */ sdev->first_boot = false; - /* now register audio DSP platform driver and dai */ - ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv, - sof_ops(sdev)->drv, - sof_ops(sdev)->num_drv); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to register DSP DAI driver %d\n", ret); - goto fw_run_err; - } - - drv_name = plat_data->machine->drv_name; - mach = (const void *)plat_data->machine; - size = sizeof(*plat_data->machine); - - /* register machine driver, pass machine info as pdata */ - plat_data->pdev_mach = - platform_device_register_data(sdev->dev, drv_name, - PLATFORM_DEVID_NONE, mach, size); - - if (IS_ERR(plat_data->pdev_mach)) { - ret = PTR_ERR(plat_data->pdev_mach); - goto fw_run_err; - } - - dev_dbg(sdev->dev, "created machine %s\n", - dev_name(&plat_data->pdev_mach->dev)); + /* register audio client */ + sof_client_dev_register(sdev, "sof-audio", &sdev->sof_audio.pdev); if (plat_data->sof_probe_complete) plat_data->sof_probe_complete(sdev->dev); @@ -423,7 +351,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) * They will be released with an explicit call to * snd_sof_device_remove() when the PCI/ACPI device is removed */ - fw_run_err: fw_load_err: ipc_err: @@ -511,6 +438,9 @@ int snd_sof_device_remove(struct device *dev) if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) cancel_work_sync(&sdev->probe_work); + /* unregister audio client device */ + sof_client_dev_unregister(&sdev->sof_audio.pdev); + snd_sof_fw_unload(sdev); snd_sof_ipc_free(sdev); snd_sof_free_debug(sdev); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c new file mode 100644 index 00000000000000..100806e4ddf0b1 --- /dev/null +++ b/sound/soc/sof/sof-audio.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include +#include +#include +#include +#include +#include "sof-priv.h" +#include "ops.h" + +/* + * SOF Driver enumeration. + */ +static int sof_machine_check(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) + struct snd_soc_acpi_mach *machine; + int ret; +#endif + + if (plat_data->machine) + return 0; + +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) + dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); + return -ENODEV; +#else + /* fallback to nocodec mode */ + dev_warn(sdev->dev, "No ASoC machine driver found - using nocodec\n"); + machine = devm_kzalloc(sdev->dev, sizeof(*machine), GFP_KERNEL); + if (!machine) + return -ENOMEM; + + ret = sof_nocodec_setup(sdev->dev, plat_data, machine, + plat_data->desc, plat_data->desc->ops); + if (ret < 0) + return ret; + + plat_data->machine = machine; + + return 0; +#endif +} + +static int sof_audio_probe(struct platform_device *pdev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(&pdev->dev); + struct snd_sof_pdata *plat_data = sdev->pdata; + struct snd_soc_acpi_mach *machine = plat_data->machine; + const char *drv_name; + int size; + int ret; + + /* check machine info */ + ret = sof_machine_check(sdev); + if (ret < 0) { + dev_err(&pdev->dev, "error: failed to get machine info %d\n", + ret); + goto err; + } + + /* set platform name */ + machine->mach_params.platform = dev_name(&pdev->dev); + plat_data->platform = dev_name(&pdev->dev); + + /* set up platform component driver */ + snd_sof_new_platform_drv(sdev); + + /* now register audio DSP platform driver and dai */ + ret = devm_snd_soc_register_component(&pdev->dev, &sdev->plat_drv, + sof_ops(sdev)->drv, + sof_ops(sdev)->num_drv); + if (ret < 0) { + dev_err(&pdev->dev, + "error: failed to register DSP DAI driver %d\n", ret); + goto err; + } + + drv_name = plat_data->machine->drv_name; + size = sizeof(*plat_data->machine); + + /* register machine driver, pass machine info as pdata */ + plat_data->pdev_mach = + platform_device_register_data(&pdev->dev, drv_name, + PLATFORM_DEVID_NONE, + (const void *)machine, size); + + if (IS_ERR(plat_data->pdev_mach)) { + ret = PTR_ERR(plat_data->pdev_mach); + goto err; + } + + dev_dbg(&pdev->dev, "created machine %s\n", + dev_name(&plat_data->pdev_mach->dev)); + + /* enable runtime PM */ + pm_runtime_set_autosuspend_delay(&pdev->dev, SND_SOF_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + + pm_runtime_enable(&pdev->dev); + + pm_runtime_mark_last_busy(&pdev->dev); + + pm_runtime_put_noidle(&pdev->dev); + + return 0; + +err: + snd_sof_remove(sdev); + snd_sof_fw_unload(sdev); + snd_sof_ipc_free(sdev); + snd_sof_free_debug(sdev); + return ret; +} + +static struct platform_driver sof_audio_driver = { + .driver = { + .name = "sof-audio", + }, + + .probe = sof_audio_probe, +}; + +module_platform_driver(sof_audio_driver); + +MODULE_DESCRIPTION("SOF Audio Client Platform Driver"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("platform:sof-audio"); diff --git a/sound/soc/sof/sof-mfd.c b/sound/soc/sof/sof-mfd.c new file mode 100644 index 00000000000000..138eefd424650c --- /dev/null +++ b/sound/soc/sof/sof-mfd.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// +#include +#include "sof-mfd.h" + +void sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, + struct platform_device *pdev) +{ + int ret; + + pdev = platform_device_alloc(name, -1); + if (!pdev) { + dev_err(sdev->dev, "error: Failed to allocate %s\n", name); + return; + } + + pdev->dev.parent = sdev->dev; + dev_set_drvdata(&pdev->dev, sdev); + ret = platform_device_add(pdev); + if (ret) { + dev_err(sdev->dev, "error: Failed to register %s: %d\n", name, + ret); + platform_device_put(pdev); + pdev = NULL; + } + dev_dbg(sdev->dev, "%s client registered\n", name); +} +EXPORT_SYMBOL(sof_client_dev_register); + +void sof_client_dev_unregister(struct platform_device *pdev) +{ + platform_device_del(pdev); +} +EXPORT_SYMBOL(sof_client_dev_unregister); diff --git a/sound/soc/sof/sof-mfd.h b/sound/soc/sof/sof-mfd.h new file mode 100644 index 00000000000000..30899031b8d92d --- /dev/null +++ b/sound/soc/sof/sof-mfd.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan + */ +#include +#include "sof-priv.h" + +#ifndef __SOUND_SOC_SOF_MFD_H +#define __SOUND_SOC_SOF_MFD_H + +/* client register/unregister */ +void sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, + struct platform_device *pdev); +void sof_client_dev_unregister(struct platform_device *pdev); + +#endif diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 25537e23ec4bf3..202ef7be074dd2 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -326,6 +326,7 @@ static int sof_pci_probe(struct pci_dev *pci, dev_warn(dev, "warning: No matching ASoC machine driver found\n"); } else { mach->mach_params.platform = dev_name(dev); + dev_dbg(dev, "ranjani %s\n", dev_name(dev)); sof_pdata->fw_filename = mach->sof_fw_filename; sof_pdata->tplg_filename = mach->sof_tplg_filename; } @@ -335,7 +336,6 @@ static int sof_pci_probe(struct pci_dev *pci, sof_pdata->machine = mach; sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; sof_pdata->dev = dev; - sof_pdata->platform = dev_name(dev); /* alternate fw and tplg filenames ? */ if (fw_path) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 9d5151f7cc2fc8..b29c1f947ddf2b 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -370,6 +370,11 @@ struct snd_sof_dai { struct list_head list; /* list in sdev dai list */ }; +/* SOF MFD client device */ +struct sof_mfd_client { + struct platform_device pdev; +}; + /* * SOF Device Level. */ @@ -458,6 +463,9 @@ struct snd_sof_dev { bool msi_enabled; + /* client devices */ + struct sof_mfd_client sof_audio; + void *private; /* core does not touch this */ }; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 46aab02977530c..b9132d0dbfdf69 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2844,7 +2844,9 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, dev_err(sdev->dev, "error: no platforms\n"); return -EINVAL; } - link->platforms->name = dev_name(sdev->dev); + + /* set platform name */ + link->platforms->name = dev_name(scomp->dev); /* * Set nonatomic property for FE dai links as their trigger action