From bd477ff18c6bd35e80abd8848a6796203429b69a Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 14 Jan 2019 16:52:06 +0800 Subject: [PATCH 1/2] ASoC: SOF: select machine driver after hda detection It is ugly in pci probing function to check hda for machine driver. Now select hda machine driver in hda probing function and use nocodec machine driver if none of I2S or hda is selected after dsp probing Check following conditions to select machine driver 1. codec_num = 2 -> use hda with HDMI + HDAudio 2. codec_num = 1 -> use hda with HDMI if nocdec is disabled 3. codec_num = 1 -> use nocodec if enabled in the build (for validation) 4. codec_num = 0 -> use nocodec if enabled in the build step 2 is for on a headless device like Up2 Signed-off-by: Rander Wang --- sound/soc/sof/core.c | 42 ++++++++++++++++++++++++++-- sound/soc/sof/intel/hda.c | 56 +++++++++++++++++++++++++++++++++---- sound/soc/sof/intel/hda.h | 2 ++ sound/soc/sof/sof-pci-dev.c | 36 ++---------------------- 4 files changed, 93 insertions(+), 43 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 8df9e1e375a8e2..4b794575ec7693 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -224,7 +224,35 @@ int snd_sof_create_page_table(struct snd_sof_dev *sdev, /* * SOF Driver enumeration. */ +static int sof_machine_check(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = sdev->pdata; + + if (!plat_data->machine) { +#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) + struct snd_soc_acpi_mach *machine; + int ret; + + /* 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; +#else + dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); + return -ENODEV; +#endif + } + return 0; +} static int sof_probe(struct platform_device *pdev) { struct snd_sof_pdata *plat_data = dev_get_platdata(&pdev->dev); @@ -257,9 +285,6 @@ static int sof_probe(struct platform_device *pdev) spin_lock_init(&sdev->ipc_lock); spin_lock_init(&sdev->hw_lock); - /* set up platform component driver */ - snd_sof_new_platform_drv(sdev); - /* set default timeouts if none provided */ if (plat_data->desc->ipc_timeout == 0) sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS; @@ -277,6 +302,17 @@ static int sof_probe(struct platform_device *pdev) 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) { diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 007db62cebb2e5..69e9d18bd30cc7 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -25,6 +25,10 @@ #include "../../codecs/hdac_hda.h" #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#include +#endif + /* platform specific devices */ #include "shim.h" @@ -226,7 +230,12 @@ static int hda_init_caps(struct snd_sof_dev *sdev) struct pci_dev *pci = sdev->pci; struct hdac_ext_link *hlink = NULL; struct snd_soc_acpi_mach_params *mach_params; + struct snd_soc_acpi_mach *hda_mach = NULL; + struct snd_sof_pdata *pdata = sdev->pdata; + struct snd_soc_acpi_mach *mach; + int codec_num = 0; int ret = 0; + int i; device_disable_async_suspend(bus->dev); @@ -252,15 +261,50 @@ static int hda_init_caps(struct snd_sof_dev *sdev) } /* codec detection */ - if (!bus->codec_mask) + 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); + } 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 are HDMI codec and one external HDAudio codec + * 2. only HDMI codec and NOCODEC is not enabled + * + * nocodec machine driver would be used if: + * 1. only HDMI codec and but NOCODEC is enabled + * 2. there is no codec found + */ + if (!pdata->machine && codec_num <= 2 && + HDA_IDISP_CODEC(bus->codec_mask)) { + if (codec_num == 2 || + !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { + hda_mach = snd_soc_acpi_intel_hda_machines; + mach = pdata->desc->machines; + hda_mach->sof_fw_filename = + mach->sof_fw_filename; + pdata->machine = hda_mach; + + dev_info(bus->dev, "using HDA machine driver %s now\n", + hda_mach->drv_name); + } + } + } /* used by hda machine driver to create dai links */ - mach_params = (struct snd_soc_acpi_mach_params *) - &sdev->pdata->machine->mach_params; - mach_params->codec_mask = bus->codec_mask; + if (pdata->machine) { + mach_params = (struct snd_soc_acpi_mach_params *) + &pdata->machine->mach_params; + mach_params->codec_mask = bus->codec_mask; + } /* create codec instances */ hda_codec_probe_bus(sdev); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 105b720d5069bd..38ac2ccc3a4267 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -338,6 +338,8 @@ #define HDA_ADSP_FW_STATUS_SKL HDA_ADSP_SRAM0_BASE_SKL #define HDA_ADSP_ERROR_CODE_SKL (HDA_ADSP_FW_STATUS_SKL + 0x4) +#define HDA_IDISP_CODEC(x) ((x) & BIT(2)) + struct sof_intel_dsp_bdl { __le32 addr_l; __le32 addr_h; diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index a62ff9c337486e..20ebd9ac579046 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -203,42 +203,10 @@ static int sof_pci_probe(struct pci_dev *pci, #else /* find machine */ mach = snd_soc_acpi_find_machine(desc->machines); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - if (!mach) { - dev_warn(dev, "No matching ASoC machine driver found - falling back to HDA codec\n"); - mach = snd_soc_acpi_intel_hda_machines; - mach->sof_fw_filename = desc->nocodec_fw_filename; - - /* - * TODO: we need to find a way to check if codecs are actually - * present - */ - } -#endif /* CONFIG_SND_SOC_SOF_HDA */ - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - if (!mach) { - /* fallback to nocodec mode */ - dev_warn(dev, "No matching ASoC machine driver found - using nocodec\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; - } -#endif /* CONFIG_SND_SOC_SOF_NOCODEC */ - + if (!mach) + dev_warn(dev, "warning: No matching ASoC machine driver found\n"); #endif /* CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE */ - if (!mach) { - dev_err(dev, "error: no matching ASoC machine driver found - aborting probe\n"); - ret = -ENODEV; - goto release_regions; - } - sof_pdata->id = pci_id->device; sof_pdata->name = pci_name(pci); sof_pdata->machine = mach; From 556c6525b51c80502e65fbd160f6777f72638fa5 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Wed, 16 Jan 2019 14:16:25 +0800 Subject: [PATCH 2/2] ASoC: SOF: move sof_bes_setup to nocodec file The change for machine driver would make a error that sof and nocodec module are dependent on each other. Signed-off-by: Rander Wang --- sound/soc/sof/nocodec.c | 36 ++++++++++++++++++++++++++++++++++-- sound/soc/sof/utils.c | 33 --------------------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 4bb6a74093336d..9851ce7c1e8ec0 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -16,6 +16,38 @@ static struct snd_soc_card sof_nocodec_card = { .name = "nocodec", /* the sof- prefix is added by the core */ }; +int sof_nocodec_bes_setup(struct device *dev, const struct snd_sof_dsp_ops *ops, + struct snd_soc_dai_link *links, int link_num, + struct snd_soc_card *card) +{ + int i; + + if (!ops || !links || !card) + return -EINVAL; + + /* set up BE dai_links */ + for (i = 0; i < link_num; i++) { + links[i].name = devm_kasprintf(dev, GFP_KERNEL, + "NoCodec-%d", i); + if (!links[i].name) + return -ENOMEM; + + links[i].id = i; + links[i].no_pcm = 1; + links[i].cpu_dai_name = ops->drv[i].name; + links[i].platform_name = "sof-audio"; + links[i].codec_dai_name = "snd-soc-dummy-dai"; + links[i].codec_name = "snd-soc-dummy"; + links[i].dpcm_playback = 1; + links[i].dpcm_capture = 1; + } + + card->dai_link = links; + card->num_links = link_num; + + return 0; +} + int sof_nocodec_setup(struct device *dev, struct snd_sof_pdata *sof_pdata, struct snd_soc_acpi_mach *mach, @@ -40,8 +72,8 @@ int sof_nocodec_setup(struct device *dev, if (!links) return -ENOMEM; - ret = sof_bes_setup(dev, ops, links, ops->num_drv, - &sof_nocodec_card); + ret = sof_nocodec_bes_setup(dev, ops, links, ops->num_drv, + &sof_nocodec_card); return ret; } EXPORT_SYMBOL(sof_nocodec_setup); diff --git a/sound/soc/sof/utils.c b/sound/soc/sof/utils.c index 484f57e1554a49..6167e05d5a6dea 100644 --- a/sound/soc/sof/utils.c +++ b/sound/soc/sof/utils.c @@ -14,39 +14,6 @@ #include #include "sof-priv.h" -int sof_bes_setup(struct device *dev, const struct snd_sof_dsp_ops *ops, - struct snd_soc_dai_link *links, int link_num, - struct snd_soc_card *card) -{ - int i; - - if (!ops || !links || !card) - return -EINVAL; - - /* set up BE dai_links */ - for (i = 0; i < link_num; i++) { - links[i].name = devm_kasprintf(dev, GFP_KERNEL, - "NoCodec-%d", i); - if (!links[i].name) - return -ENOMEM; - - links[i].id = i; - links[i].no_pcm = 1; - links[i].cpu_dai_name = ops->drv[i].name; - links[i].platform_name = "sof-audio"; - links[i].codec_dai_name = "snd-soc-dummy-dai"; - links[i].codec_name = "snd-soc-dummy"; - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; - } - - card->dai_link = links; - card->num_links = link_num; - - return 0; -} -EXPORT_SYMBOL(sof_bes_setup); - /* register sof platform device */ int sof_create_platform_device(struct sof_platform_priv *priv) {