From 19fa41a7ab8226a7ca92eb72d40edc0f3a39ed63 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 7 Nov 2019 18:54:01 +0200 Subject: [PATCH] ASoC: Make creation of machine device from SOF core optional Currently, SOF probes machine drivers by creating a platform device and passing the machine description as private data. This is driven by the ACPI restrictions. Ideally, ACPI tables should contain the description for the machine driver. This is not possible because ACPI tables are frozen and used on multiple OS-es (e.g Windows). In the case, of Device Tree we don't have this restrictions, so we choose to probe the machine drivers by creating a DT node as is the standard ALSA way. This patch makes the probing of machine drivers from SOF core optional allowing for arm platforms to decouple the SOF core from machine driver probing. Signed-off-by: Daniel Baluta --- sound/soc/sof/core.c | 63 +++++++++++++++++++++++++-------------- sound/soc/sof/intel/apl.c | 5 ++++ sound/soc/sof/intel/bdw.c | 5 ++++ sound/soc/sof/intel/byt.c | 15 ++++++++++ sound/soc/sof/intel/cnl.c | 5 ++++ sound/soc/sof/ops.h | 26 ++++++++++++++++ sound/soc/sof/sof-priv.h | 11 +++++++ 7 files changed, 107 insertions(+), 23 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 2311c273441c..f4702b49e67b 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -197,7 +197,7 @@ EXPORT_SYMBOL(snd_sof_get_status); /* * SOF Driver enumeration. */ -static int sof_machine_check(struct snd_sof_dev *sdev) +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) @@ -228,13 +228,45 @@ static int sof_machine_check(struct snd_sof_dev *sdev) return 0; #endif } +EXPORT_SYMBOL(sof_machine_check); + +int sof_machine_register(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = (struct snd_sof_pdata *)pdata; + const char *drv_name; + const void *mach; + int size; + + 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)) + return PTR_ERR(plat_data->pdev_mach); + + dev_dbg(sdev->dev, "created machine %s\n", + dev_name(&plat_data->pdev_mach->dev)); + + return 0; +} +EXPORT_SYMBOL(sof_machine_register); + +void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) +{ + struct snd_sof_pdata *plat_data = (struct snd_sof_pdata *)pdata; + + if (!IS_ERR_OR_NULL(plat_data->pdev_mach)) + platform_device_unregister(plat_data->pdev_mach); +} +EXPORT_SYMBOL(sof_machine_unregister); 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 */ @@ -245,7 +277,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) } /* check machine info */ - ret = sof_machine_check(sdev); + ret = snd_sof_machine_check(sdev); if (ret < 0) { dev_err(sdev->dev, "error: failed to get machine info %d\n", ret); @@ -312,22 +344,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) 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); + ret = snd_sof_machine_register(sdev, plat_data); + if (ret < 0) goto fw_run_err; - } - - dev_dbg(sdev->dev, "created machine %s\n", - dev_name(&plat_data->pdev_mach->dev)); /* * Some platforms in SOF, ex: BYT, may not have their platform PM @@ -453,9 +472,7 @@ int snd_sof_device_remove(struct device *dev) * will remove the component driver and unload the topology * before freeing the snd_card. */ - if (!IS_ERR_OR_NULL(pdata->pdev_mach)) - platform_device_unregister(pdata->pdev_mach); - + snd_sof_machine_unregister(sdev, pdata); /* * Unregistering the machine driver results in unloading the topology. * Some widgets, ex: scheduler, attempt to power down the core they are diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 8dc7a5558da4..1f46bfba0f1b 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -53,6 +53,11 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = apl_dsp_debugfs, .debug_map_count = ARRAY_SIZE(apl_dsp_debugfs), diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 80e2826fb447..4e401fee8739 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -554,6 +554,11 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = bdw_debugfs, .debug_map_count = ARRAY_SIZE(bdw_debugfs), diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index a1e514f71739..1896b6aab94b 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -493,6 +493,11 @@ const struct snd_sof_dsp_ops sof_tng_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = byt_debugfs, .debug_map_count = ARRAY_SIZE(byt_debugfs), @@ -654,6 +659,11 @@ const struct snd_sof_dsp_ops sof_byt_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = byt_debugfs, .debug_map_count = ARRAY_SIZE(byt_debugfs), @@ -713,6 +723,11 @@ const struct snd_sof_dsp_ops sof_cht_ops = { .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = cht_debugfs, .debug_map_count = ARRAY_SIZE(cht_debugfs), diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 4ddd73762d81..eba1bf4624a2 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -211,6 +211,11 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, + /* machine driver */ + .machine_check = sof_machine_check, + .machine_register = sof_machine_register, + .machine_unregister = sof_machine_unregister, + /* debug */ .debug_map = cnl_dsp_debugfs, .debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs), diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 824d36fe59fd..97f4feb73368 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -381,6 +381,32 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, return 0; } +/* machine driver */ +static inline int +snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_register) + return sof_ops(sdev)->machine_register(sdev, pdata); + + return 0; +} + +static inline void +snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister) + sof_ops(sdev)->machine_unregister(sdev, pdata); +} + +static inline int +snd_sof_machine_check(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev) && sof_ops(sdev)->machine_check) + return sof_ops(sdev)->machine_check(sdev); + + return 0; +} + static inline const struct snd_sof_dsp_ops *sof_get_ops(const struct sof_dev_desc *d, const struct sof_ops_table mach_ops[], int asize) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index d65a2f061f29..8ee185bbf6f0 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -202,6 +202,13 @@ struct snd_sof_dsp_ops { int (*get_window_offset)(struct snd_sof_dev *sdev, u32 id);/* mandatory for common loader code */ + /* machine driver ops */ + int (*machine_register)(struct snd_sof_dev *sdev, + void *pdata); /* optional */ + void (*machine_unregister)(struct snd_sof_dev *sdev, + void *pdata); /* optional */ + int (*machine_check)(struct snd_sof_dev *sdev); /* optional */ + /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; @@ -462,6 +469,10 @@ int snd_sof_create_page_table(struct device *dev, struct snd_dma_buffer *dmab, unsigned char *page_table, size_t size); +int sof_machine_register(struct snd_sof_dev *sdev, void *pdata); +void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata); +int sof_machine_check(struct snd_sof_dev *sdev); + /* * Firmware loading. */