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: Daniel Baluta <daniel.baluta@nxp.com> Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20191204211556.12671-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
80acdd4f8f
Коммит
285880a23d
|
@ -92,47 +92,9 @@ out:
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct snd_sof_pdata *plat_data = sdev->pdata;
|
||||
const char *drv_name;
|
||||
const void *mach;
|
||||
int size;
|
||||
int ret;
|
||||
|
||||
/* probe the DSP hardware */
|
||||
|
@ -218,22 +180,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
|
||||
|
@ -363,9 +312,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
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "../sof-priv.h"
|
||||
#include "hda.h"
|
||||
#include "../sof-audio.h"
|
||||
|
||||
static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = {
|
||||
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
|
||||
|
@ -52,6 +53,12 @@ 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_select = hda_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = hda_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = apl_dsp_debugfs,
|
||||
.debug_map_count = ARRAY_SIZE(apl_dsp_debugfs),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <sound/sof/xtensa.h>
|
||||
#include "../ops.h"
|
||||
#include "shim.h"
|
||||
#include "../sof-audio.h"
|
||||
|
||||
/* BARs */
|
||||
#define BDW_DSP_BAR 0
|
||||
|
@ -536,6 +537,32 @@ static int bdw_probe(struct snd_sof_dev *sdev)
|
|||
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 */
|
||||
static struct snd_soc_dai_driver bdw_dai[] = {
|
||||
{
|
||||
|
@ -574,6 +601,12 @@ 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_select = bdw_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = bdw_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = bdw_debugfs,
|
||||
.debug_map_count = ARRAY_SIZE(bdw_debugfs),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <sound/sof/xtensa.h>
|
||||
#include "../ops.h"
|
||||
#include "shim.h"
|
||||
#include "../sof-audio.h"
|
||||
|
||||
/* DSP memories */
|
||||
#define IRAM_OFFSET 0x0C0000
|
||||
|
@ -382,6 +383,32 @@ static int byt_reset(struct snd_sof_dev *sdev)
|
|||
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 */
|
||||
static struct snd_soc_dai_driver byt_dai[] = {
|
||||
{
|
||||
|
@ -514,6 +541,12 @@ 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_select = byt_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = byt_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = byt_debugfs,
|
||||
.debug_map_count = ARRAY_SIZE(byt_debugfs),
|
||||
|
@ -682,6 +715,12 @@ 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_select = byt_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = byt_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = byt_debugfs,
|
||||
.debug_map_count = ARRAY_SIZE(byt_debugfs),
|
||||
|
@ -748,6 +787,12 @@ 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_select = byt_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = byt_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = cht_debugfs,
|
||||
.debug_map_count = ARRAY_SIZE(cht_debugfs),
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "../ops.h"
|
||||
#include "hda.h"
|
||||
#include "hda-ipc.h"
|
||||
#include "../sof-audio.h"
|
||||
|
||||
static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
|
||||
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
|
||||
|
@ -238,6 +239,12 @@ 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_select = hda_machine_select,
|
||||
.machine_register = sof_machine_register,
|
||||
.machine_unregister = sof_machine_unregister,
|
||||
.set_mach_params = hda_set_mach_params,
|
||||
|
||||
/* debug */
|
||||
.debug_map = 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)
|
|||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
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
|
||||
int ret = 0;
|
||||
|
||||
|
@ -387,94 +377,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
if (bus->mlcap)
|
||||
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 */
|
||||
hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
|
||||
|
||||
|
@ -763,4 +665,133 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
|
|||
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");
|
||||
|
|
|
@ -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 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
|
||||
|
|
|
@ -77,7 +77,6 @@ int sof_nocodec_setup(struct device *dev,
|
|||
sof_pdata->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;
|
||||
|
||||
/* create dummy BE dai_links */
|
||||
|
|
|
@ -391,6 +391,40 @@ 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 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
|
||||
*sof_get_ops(const struct sof_dev_desc *d,
|
||||
const struct sof_ops_table mach_ops[], int asize)
|
||||
|
|
|
@ -145,7 +145,6 @@ static int sof_acpi_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct sof_dev_desc *desc;
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
struct snd_sof_pdata *sof_pdata;
|
||||
const struct snd_sof_dsp_ops *ops;
|
||||
int ret;
|
||||
|
@ -172,35 +171,9 @@ static int sof_acpi_probe(struct platform_device *pdev)
|
|||
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->dev = &pdev->dev;
|
||||
sof_pdata->platform = dev_name(dev);
|
||||
sof_pdata->fw_filename = desc->default_fw_filename;
|
||||
|
||||
/* alternate fw and tplg filenames ? */
|
||||
if (fw_path)
|
||||
|
|
|
@ -360,3 +360,83 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
|
|||
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);
|
|||
int sof_set_hw_params_upon_resume(struct device *dev);
|
||||
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
|
||||
|
|
|
@ -44,8 +44,6 @@ static int sof_of_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
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;
|
||||
const struct snd_sof_dsp_ops *ops;
|
||||
int ret;
|
||||
|
@ -67,27 +65,9 @@ static int sof_of_probe(struct platform_device *pdev)
|
|||
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->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 */
|
||||
sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path;
|
||||
|
|
|
@ -275,7 +275,6 @@ static int sof_pci_probe(struct pci_dev *pci,
|
|||
struct device *dev = &pci->dev;
|
||||
const struct sof_dev_desc *desc =
|
||||
(const struct sof_dev_desc *)pci_id->driver_data;
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
struct snd_sof_pdata *sof_pdata;
|
||||
const struct snd_sof_dsp_ops *ops;
|
||||
int ret;
|
||||
|
@ -306,35 +305,10 @@ static int sof_pci_probe(struct pci_dev *pci,
|
|||
if (ret < 0)
|
||||
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->machine = mach;
|
||||
sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
|
||||
sof_pdata->dev = dev;
|
||||
sof_pdata->platform = dev_name(dev);
|
||||
sof_pdata->fw_filename = desc->default_fw_filename;
|
||||
|
||||
/* alternate fw and tplg filenames ? */
|
||||
if (fw_path)
|
||||
|
|
|
@ -202,6 +202,15 @@ 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 */
|
||||
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 */
|
||||
struct snd_soc_dai_driver *drv;
|
||||
int num_drv;
|
||||
|
@ -511,4 +520,6 @@ int intel_pcm_open(struct snd_sof_dev *sdev,
|
|||
int intel_pcm_close(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream);
|
||||
|
||||
int sof_machine_check(struct snd_sof_dev *sdev);
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче