Commit 285880a2 authored by Daniel Baluta's avatar Daniel Baluta Committed by Mark Brown

ASoC: SOF: 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 restriction, 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 Device Tree platforms to decouple
the SOF core from machine driver probing.

Along with this, it also consolidates the machine driver selection
for Intel platforms by defining optional ops for selecting the machine
driver based on the ACPI match for HDA and non-HDA platforms and
setting the mach params.
Signed-off-by: default avatarDaniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20191204211556.12671-11-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 80acdd4f
...@@ -92,47 +92,9 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code, ...@@ -92,47 +92,9 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
} }
EXPORT_SYMBOL(snd_sof_get_status); EXPORT_SYMBOL(snd_sof_get_status);
/*
* 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) static int sof_probe_continue(struct snd_sof_dev *sdev)
{ {
struct snd_sof_pdata *plat_data = sdev->pdata; struct snd_sof_pdata *plat_data = sdev->pdata;
const char *drv_name;
const void *mach;
int size;
int ret; int ret;
/* probe the DSP hardware */ /* probe the DSP hardware */
...@@ -218,22 +180,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) ...@@ -218,22 +180,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
goto fw_run_err; goto fw_run_err;
} }
drv_name = plat_data->machine->drv_name; ret = snd_sof_machine_register(sdev, plat_data);
mach = (const void *)plat_data->machine; if (ret < 0)
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; 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 * Some platforms in SOF, ex: BYT, may not have their platform PM
...@@ -363,9 +312,7 @@ int snd_sof_device_remove(struct device *dev) ...@@ -363,9 +312,7 @@ int snd_sof_device_remove(struct device *dev)
* will remove the component driver and unload the topology * will remove the component driver and unload the topology
* before freeing the snd_card. * before freeing the snd_card.
*/ */
if (!IS_ERR_OR_NULL(pdata->pdev_mach)) snd_sof_machine_unregister(sdev, pdata);
platform_device_unregister(pdata->pdev_mach);
/* /*
* Unregistering the machine driver results in unloading the topology. * Unregistering the machine driver results in unloading the topology.
* Some widgets, ex: scheduler, attempt to power down the core they are * Some widgets, ex: scheduler, attempt to power down the core they are
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "../sof-priv.h" #include "../sof-priv.h"
#include "hda.h" #include "hda.h"
#include "../sof-audio.h"
static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = { static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
...@@ -52,6 +53,12 @@ const struct snd_sof_dsp_ops sof_apl_ops = { ...@@ -52,6 +53,12 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
.ipc_msg_data = hda_ipc_msg_data, .ipc_msg_data = hda_ipc_msg_data,
.ipc_pcm_params = hda_ipc_pcm_params, .ipc_pcm_params = hda_ipc_pcm_params,
/* machine driver */
.machine_select = hda_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = hda_set_mach_params,
/* debug */ /* debug */
.debug_map = apl_dsp_debugfs, .debug_map = apl_dsp_debugfs,
.debug_map_count = ARRAY_SIZE(apl_dsp_debugfs), .debug_map_count = ARRAY_SIZE(apl_dsp_debugfs),
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <sound/sof/xtensa.h> #include <sound/sof/xtensa.h>
#include "../ops.h" #include "../ops.h"
#include "shim.h" #include "shim.h"
#include "../sof-audio.h"
/* BARs */ /* BARs */
#define BDW_DSP_BAR 0 #define BDW_DSP_BAR 0
...@@ -536,6 +537,32 @@ static int bdw_probe(struct snd_sof_dev *sdev) ...@@ -536,6 +537,32 @@ static int bdw_probe(struct snd_sof_dev *sdev)
return ret; return ret;
} }
static void bdw_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
struct snd_soc_acpi_mach *mach;
mach = snd_soc_acpi_find_machine(desc->machines);
if (!mach) {
dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
return;
}
sof_pdata->tplg_filename = mach->sof_tplg_filename;
mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
sof_pdata->machine = mach;
}
static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach,
struct device *dev)
{
struct snd_soc_acpi_mach_params *mach_params;
mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
mach_params->platform = dev_name(dev);
}
/* Broadwell DAIs */ /* Broadwell DAIs */
static struct snd_soc_dai_driver bdw_dai[] = { static struct snd_soc_dai_driver bdw_dai[] = {
{ {
...@@ -574,6 +601,12 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { ...@@ -574,6 +601,12 @@ const struct snd_sof_dsp_ops sof_bdw_ops = {
.ipc_msg_data = intel_ipc_msg_data, .ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params, .ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
.machine_select = bdw_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = bdw_set_mach_params,
/* debug */ /* debug */
.debug_map = bdw_debugfs, .debug_map = bdw_debugfs,
.debug_map_count = ARRAY_SIZE(bdw_debugfs), .debug_map_count = ARRAY_SIZE(bdw_debugfs),
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <sound/sof/xtensa.h> #include <sound/sof/xtensa.h>
#include "../ops.h" #include "../ops.h"
#include "shim.h" #include "shim.h"
#include "../sof-audio.h"
/* DSP memories */ /* DSP memories */
#define IRAM_OFFSET 0x0C0000 #define IRAM_OFFSET 0x0C0000
...@@ -382,6 +383,32 @@ static int byt_reset(struct snd_sof_dev *sdev) ...@@ -382,6 +383,32 @@ static int byt_reset(struct snd_sof_dev *sdev)
return 0; return 0;
} }
static void byt_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
struct snd_soc_acpi_mach *mach;
mach = snd_soc_acpi_find_machine(desc->machines);
if (!mach) {
dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
return;
}
sof_pdata->tplg_filename = mach->sof_tplg_filename;
mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
sof_pdata->machine = mach;
}
static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach,
struct device *dev)
{
struct snd_soc_acpi_mach_params *mach_params;
mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
mach_params->platform = dev_name(dev);
}
/* Baytrail DAIs */ /* Baytrail DAIs */
static struct snd_soc_dai_driver byt_dai[] = { static struct snd_soc_dai_driver byt_dai[] = {
{ {
...@@ -514,6 +541,12 @@ const struct snd_sof_dsp_ops sof_tng_ops = { ...@@ -514,6 +541,12 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
.ipc_msg_data = intel_ipc_msg_data, .ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params, .ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
.machine_select = byt_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = byt_set_mach_params,
/* debug */ /* debug */
.debug_map = byt_debugfs, .debug_map = byt_debugfs,
.debug_map_count = ARRAY_SIZE(byt_debugfs), .debug_map_count = ARRAY_SIZE(byt_debugfs),
...@@ -682,6 +715,12 @@ const struct snd_sof_dsp_ops sof_byt_ops = { ...@@ -682,6 +715,12 @@ const struct snd_sof_dsp_ops sof_byt_ops = {
.ipc_msg_data = intel_ipc_msg_data, .ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params, .ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
.machine_select = byt_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = byt_set_mach_params,
/* debug */ /* debug */
.debug_map = byt_debugfs, .debug_map = byt_debugfs,
.debug_map_count = ARRAY_SIZE(byt_debugfs), .debug_map_count = ARRAY_SIZE(byt_debugfs),
...@@ -748,6 +787,12 @@ const struct snd_sof_dsp_ops sof_cht_ops = { ...@@ -748,6 +787,12 @@ const struct snd_sof_dsp_ops sof_cht_ops = {
.ipc_msg_data = intel_ipc_msg_data, .ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params, .ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
.machine_select = byt_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = byt_set_mach_params,
/* debug */ /* debug */
.debug_map = cht_debugfs, .debug_map = cht_debugfs,
.debug_map_count = ARRAY_SIZE(cht_debugfs), .debug_map_count = ARRAY_SIZE(cht_debugfs),
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "../ops.h" #include "../ops.h"
#include "hda.h" #include "hda.h"
#include "hda-ipc.h" #include "hda-ipc.h"
#include "../sof-audio.h"
static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
...@@ -238,6 +239,12 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { ...@@ -238,6 +239,12 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
.ipc_msg_data = hda_ipc_msg_data, .ipc_msg_data = hda_ipc_msg_data,
.ipc_pcm_params = hda_ipc_pcm_params, .ipc_pcm_params = hda_ipc_pcm_params,
/* machine driver */
.machine_select = hda_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = hda_set_mach_params,
/* debug */ /* debug */
.debug_map = cnl_dsp_debugfs, .debug_map = cnl_dsp_debugfs,
.debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs), .debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs),
......
...@@ -344,16 +344,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -344,16 +344,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
struct hdac_ext_link *hlink; struct hdac_ext_link *hlink;
struct snd_soc_acpi_mach_params *mach_params;
struct snd_soc_acpi_mach *hda_mach;
struct snd_sof_pdata *pdata = sdev->pdata;
struct snd_soc_acpi_mach *mach;
const char *tplg_filename;
const char *idisp_str;
const char *dmic_str;
int dmic_num = 0;
int codec_num = 0;
int i;
#endif #endif
int ret = 0; int ret = 0;
...@@ -387,94 +377,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -387,94 +377,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
if (bus->mlcap) if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(bus); snd_hdac_ext_bus_get_ml_capabilities(bus);
/* codec detection */
if (!bus->codec_mask) {
dev_info(bus->dev, "no hda codecs found!\n");
} else {
dev_info(bus->dev, "hda codecs found, mask %lx\n",
bus->codec_mask);
for (i = 0; i < HDA_MAX_CODECS; i++) {
if (bus->codec_mask & (1 << i))
codec_num++;
}
/*
* If no machine driver is found, then:
*
* hda machine driver is used if :
* 1. there is one HDMI codec and one external HDAudio codec
* 2. only HDMI codec
*/
if (!pdata->machine && codec_num <= 2 &&
HDA_IDISP_CODEC(bus->codec_mask)) {
hda_mach = snd_soc_acpi_intel_hda_machines;
pdata->machine = hda_mach;
/* topology: use the info from hda_machines */
pdata->tplg_filename =
hda_mach->sof_tplg_filename;
/*
* firmware: pick the first in machine list,
* or use nocodec firmware name if list is empty
*/
mach = pdata->desc->machines;
if (mach->id[0])
pdata->fw_filename = mach->sof_fw_filename;
else
pdata->fw_filename =
pdata->desc->nocodec_fw_filename;
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
if (codec_num == 1)
idisp_str = "-idisp";
else
idisp_str = "";
/* first check NHLT for DMICs */
dmic_num = check_nhlt_dmic(sdev);
/* allow for module parameter override */
if (hda_dmic_num != -1)
dmic_num = hda_dmic_num;
switch (dmic_num) {
case 2:
dmic_str = "-2ch";
break;
case 4:
dmic_str = "-4ch";
break;
default:
dmic_num = 0;
dmic_str = "";
break;
}
tplg_filename = pdata->tplg_filename;
tplg_filename = fixup_tplg_name(sdev, tplg_filename,
idisp_str, dmic_str);
if (!tplg_filename) {
hda_codec_i915_exit(sdev);
return ret;
}
pdata->tplg_filename = tplg_filename;
}
}
/* used by hda machine driver to create dai links */
if (pdata->machine) {
mach_params = (struct snd_soc_acpi_mach_params *)
&pdata->machine->mach_params;
mach_params->codec_mask = bus->codec_mask;
mach_params->platform = dev_name(sdev->dev);
mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
mach_params->dmic_num = dmic_num;
}
/* create codec instances */ /* create codec instances */
hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
...@@ -763,4 +665,133 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) ...@@ -763,4 +665,133 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
static int hda_generic_machine_select(struct snd_sof_dev *sdev)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_acpi_mach_params *mach_params;
struct snd_soc_acpi_mach *hda_mach;
struct snd_sof_pdata *pdata = sdev->pdata;
const char *tplg_filename;
const char *idisp_str;
const char *dmic_str;
int dmic_num = 0;
int codec_num = 0;
int i;
/* codec detection */
if (!bus->codec_mask) {
dev_info(bus->dev, "no hda codecs found!\n");
} else {
dev_info(bus->dev, "hda codecs found, mask %lx\n",
bus->codec_mask);
for (i = 0; i < HDA_MAX_CODECS; i++) {
if (bus->codec_mask & (1 << i))
codec_num++;
}
/*
* If no machine driver is found, then:
*
* hda machine driver is used if :
* 1. there is one HDMI codec and one external HDAudio codec
* 2. only HDMI codec
*/
if (!pdata->machine && codec_num <= 2 &&
HDA_IDISP_CODEC(bus->codec_mask)) {
hda_mach = snd_soc_acpi_intel_hda_machines;
/* topology: use the info from hda_machines */
pdata->tplg_filename =
hda_mach->sof_tplg_filename;
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
if (codec_num == 1)
idisp_str = "-idisp";
else
idisp_str = "";
/* first check NHLT for DMICs */
dmic_num = check_nhlt_dmic(sdev);
/* allow for module parameter override */
if (hda_dmic_num != -1)
dmic_num = hda_dmic_num;
switch (dmic_num) {
case 2:
dmic_str = "-2ch";
break;
case 4:
dmic_str = "-4ch";
break;
default:
dmic_num = 0;
dmic_str = "";
break;
}
tplg_filename = pdata->tplg_filename;
tplg_filename = fixup_tplg_name(sdev, tplg_filename,
idisp_str, dmic_str);
if (!tplg_filename)
return -EINVAL;
pdata->machine = hda_mach;
pdata->tplg_filename = tplg_filename;
}
}
/* used by hda machine driver to create dai links */
if (pdata->machine) {
mach_params = (struct snd_soc_acpi_mach_params *)
&pdata->machine->mach_params;
mach_params->codec_mask = bus->codec_mask;
mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
mach_params->dmic_num = dmic_num;
}
return 0;
}
#else
static int hda_generic_machine_select(struct snd_sof_dev *sdev)
{
return 0;
}
#endif
void hda_set_mach_params(const struct snd_soc_acpi_mach *mach,
struct device *dev)
{
struct snd_soc_acpi_mach_params *mach_params;
mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
mach_params->platform = dev_name(dev);
}
void hda_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
struct snd_soc_acpi_mach *mach;
mach = snd_soc_acpi_find_machine(desc->machines);
if (mach) {
sof_pdata->tplg_filename = mach->sof_tplg_filename;
sof_pdata->machine = mach;
}
/*
* Choose HDA generic machine driver if mach is NULL.
* Otherwise, set certain mach params.
*/
hda_generic_machine_select(sdev);
if (!sof_pdata->machine)
dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
}
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
...@@ -624,4 +624,9 @@ extern const struct sof_intel_dsp_desc tgl_chip_info; ...@@ -624,4 +624,9 @@ extern const struct sof_intel_dsp_desc tgl_chip_info;
extern const struct sof_intel_dsp_desc ehl_chip_info; extern const struct sof_intel_dsp_desc ehl_chip_info;
extern const struct sof_intel_dsp_desc jsl_chip_info; extern const struct sof_intel_dsp_desc jsl_chip_info;
/* machine driver select */
void hda_machine_select(struct snd_sof_dev *sdev);
void hda_set_mach_params(const struct snd_soc_acpi_mach *mach,
struct device *dev);
#endif #endif
...@@ -77,7 +77,6 @@ int sof_nocodec_setup(struct device *dev, ...@@ -77,7 +77,6 @@ int sof_nocodec_setup(struct device *dev,
sof_pdata->drv_name = "sof-nocodec"; sof_pdata->drv_name = "sof-nocodec";
mach->drv_name = "sof-nocodec"; mach->drv_name = "sof-nocodec";
sof_pdata->fw_filename = desc->nocodec_fw_filename;
sof_pdata->tplg_filename = desc->nocodec_tplg_filename; sof_pdata->tplg_filename = desc->nocodec_tplg_filename;
/* create dummy BE dai_links */ /* create dummy BE dai_links */
......
...@@ -391,6 +391,40 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, ...@@ -391,6 +391,40 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
return 0; 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 void
snd_sof_machine_select(struct snd_sof_dev *sdev)
{
if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
sof_ops(sdev)->machine_select(sdev);
}
static inline void
snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach,
struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
sof_ops(sdev)->set_mach_params(mach, dev);
}
static inline const struct snd_sof_dsp_ops static inline const struct snd_sof_dsp_ops
*sof_get_ops(const struct sof_dev_desc *d, *sof_get_ops(const struct sof_dev_desc *d,
const struct sof_ops_table mach_ops[], int asize) const struct sof_ops_table mach_ops[], int asize)
......
...@@ -145,7 +145,6 @@ static int sof_acpi_probe(struct platform_device *pdev) ...@@ -145,7 +145,6 @@ static int sof_acpi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct sof_dev_desc *desc; const struct sof_dev_desc *desc;
struct snd_soc_acpi_mach *mach;
struct snd_sof_pdata *sof_pdata; struct snd_sof_pdata *sof_pdata;
const struct snd_sof_dsp_ops *ops; const struct snd_sof_dsp_ops *ops;
int ret; int ret;
...@@ -172,35 +171,9 @@ static int sof_acpi_probe(struct platform_device *pdev) ...@@ -172,35 +171,9 @@ static int sof_acpi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
/* force nocodec mode */
dev_warn(dev, "Force to use nocodec mode\n");
mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
if (!mach)
return -ENOMEM;
ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
if (ret < 0)
return ret;
#else
/* find machine */
mach = snd_soc_acpi_find_machine(desc->machines);
if (!mach) {
dev_warn(dev, "warning: No matching ASoC machine driver found\n");
} else {
sof_pdata->fw_filename = mach->sof_fw_filename;
sof_pdata->tplg_filename = mach->sof_tplg_filename;
}
#endif
if (mach) {
mach->mach_params.platform = dev_name(dev);
mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
}
sof_pdata->machine = mach;
sof_pdata->desc = desc; sof_pdata->desc = desc;
sof_pdata->dev = &pdev->dev; sof_pdata->dev = &pdev->dev;
sof_pdata->platform = dev_name(dev); sof_pdata->fw_filename = desc->default_fw_filename;
/* alternate fw and tplg filenames ? */ /* alternate fw and tplg filenames ? */
if (fw_path) if (fw_path)
......
...@@ -360,3 +360,83 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, ...@@ -360,3 +360,83 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
return NULL; return NULL;
} }
/*
* SOF Driver enumeration.
*/
int sof_machine_check(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
struct snd_soc_acpi_mach *mach;
int ret;
/* force nocodec mode */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
dev_warn(sdev->dev, "Force to use nocodec mode\n");
goto nocodec;
#endif
/* find machine */
snd_sof_machine_select(sdev);
if (sof_pdata->machine) {
snd_sof_set_mach_params(sof_pdata->machine, sdev->dev);
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;
#endif
#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
nocodec:
#endif
/* select nocodec mode */
dev_warn(sdev->dev, "Using nocodec machine driver\n");
mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL);
if (!mach)
return -ENOMEM;
ret = sof_nocodec_setup(sdev->dev, sof_pdata, mach, desc, desc->ops);
if (ret < 0)
return ret;
sof_pdata->machine = mach;
snd_sof_set_mach_params(sof_pdata->machine, sdev->dev);
return 0;
}
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);
...@@ -204,4 +204,8 @@ int sof_restore_pipelines(struct device *dev); ...@@ -204,4 +204,8 @@ int sof_restore_pipelines(struct device *dev);
int sof_set_hw_params_upon_resume(struct device *dev); int sof_set_hw_params_upon_resume(struct device *dev);
bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev); bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev);
/* Machine driver enumeration */
int sof_machine_register(struct snd_sof_dev *sdev, void *pdata);
void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata);
#endif #endif
...@@ -44,8 +44,6 @@ static int sof_of_probe(struct platform_device *pdev) ...@@ -44,8 +44,6 @@ static int sof_of_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct sof_dev_desc *desc; const struct sof_dev_desc *desc;
/*TODO: create a generic snd_soc_xxx_mach */
struct snd_soc_acpi_mach *mach;
struct snd_sof_pdata *sof_pdata; struct snd_sof_pdata *sof_pdata;
const struct snd_sof_dsp_ops *ops; const struct snd_sof_dsp_ops *ops;
int ret; int ret;
...@@ -67,27 +65,9 @@ static int sof_of_probe(struct platform_device *pdev) ...@@ -67,27 +65,9 @@ static int sof_of_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
/* force nocodec mode */
dev_warn(dev, "Force to use nocodec mode\n");
mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
if (!mach)
return -ENOMEM;
ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
if (ret < 0)
return ret;
#else
/* TODO: implement case where we actually have a codec */
return -ENODEV;
#endif
if (mach)
mach->mach_params.platform = dev_name(dev);
sof_pdata->machine = mach;
sof_pdata->desc = desc; sof_pdata->desc = desc;
sof_pdata->dev = &pdev->dev; sof_pdata->dev = &pdev->dev;
sof_pdata->platform = dev_name(dev); sof_pdata->fw_filename = desc->default_fw_filename;
/* TODO: read alternate fw and tplg filenames from DT */ /* TODO: read alternate fw and tplg filenames from DT */
sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path;
......
...@@ -275,7 +275,6 @@ static int sof_pci_probe(struct pci_dev *pci, ...@@ -275,7 +275,6 @@ static int sof_pci_probe(struct pci_dev *pci,
struct device *dev = &pci->dev; struct device *dev = &pci->dev;
const struct sof_dev_desc *desc = const struct sof_dev_desc *desc =
(const struct sof_dev_desc *)pci_id->driver_data; (const struct sof_dev_desc *)pci_id->driver_data;
struct snd_soc_acpi_mach *mach;
struct snd_sof_pdata *sof_pdata; struct snd_sof_pdata *sof_pdata;
const struct snd_sof_dsp_ops *ops; const struct snd_sof_dsp_ops *ops;
int ret; int ret;
...@@ -306,35 +305,10 @@ static int sof_pci_probe(struct pci_dev *pci, ...@@ -306,35 +305,10 @@ static int sof_pci_probe(struct pci_dev *pci,
if (ret < 0) if (ret < 0)
return ret; return ret;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
/* force nocodec mode */
dev_warn(dev, "Force to use nocodec mode\n");
mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
if (!mach) {
ret = -ENOMEM;
goto release_regions;
}
ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
if (ret < 0)
goto release_regions;
#else
/* find machine */
mach = snd_soc_acpi_find_machine(desc->machines);
if (!mach) {
dev_warn(dev, "warning: No matching ASoC machine driver found\n");
} else {
mach->mach_params.platform = dev_name(dev);
sof_pdata->fw_filename = mach->sof_fw_filename;
sof_pdata->tplg_filename = mach->sof_tplg_filename;
}
#endif /* CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE */
sof_pdata->name = pci_name(pci); sof_pdata->name = pci_name(pci);
sof_pdata->machine = mach;
sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data; sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
sof_pdata->dev = dev; sof_pdata->dev = dev;
sof_pdata->platform = dev_name(dev); sof_pdata->fw_filename = desc->default_fw_filename;
/* alternate fw and tplg filenames ? */ /* alternate fw and tplg filenames ? */
if (fw_path) if (fw_path)
......
...@@ -202,6 +202,15 @@ struct snd_sof_dsp_ops { ...@@ -202,6 +202,15 @@ struct snd_sof_dsp_ops {
int (*get_window_offset)(struct snd_sof_dev *sdev, int (*get_window_offset)(struct snd_sof_dev *sdev,
u32 id);/* mandatory for common loader code */ 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 */
void (*machine_select)(struct snd_sof_dev *sdev); /* optional */
void (*set_mach_params)(const struct snd_soc_acpi_mach *mach,
struct device *dev); /* optional */
/* DAI ops */ /* DAI ops */
struct snd_soc_dai_driver *drv; struct snd_soc_dai_driver *drv;
int num_drv; int num_drv;
...@@ -511,4 +520,6 @@ int intel_pcm_open(struct snd_sof_dev *sdev, ...@@ -511,4 +520,6 @@ int intel_pcm_open(struct snd_sof_dev *sdev,
int intel_pcm_close(struct snd_sof_dev *sdev, int intel_pcm_close(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream); struct snd_pcm_substream *substream);
int sof_machine_check(struct snd_sof_dev *sdev);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment