Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
56 changes: 50 additions & 6 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include "../../codecs/hdac_hda.h"
#endif

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
#include <sound/soc-acpi-intel-match.h>
#endif

/* platform specific devices */
#include "shim.h"

Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 34 additions & 2 deletions sound/soc/sof/nocodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down
36 changes: 2 additions & 34 deletions sound/soc/sof/sof-pci-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to check the error flow. now there is no longer an error when no machine driver is found, so this is a new flow which needs to be checked

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I will refine it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I check the error flow and find that there is only one error label release_regions which is shared by many error checks. I will check the status in sof-probe and release_regions there.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plbossart I check machine in sof core and sof_probe would be failed if machine is NULL. Now the flow would be sof_probe failed -> pci_probe failed. I know this issue you are working with @libinyang @ranj063, so it is a generic issue.

}

sof_pdata->id = pci_id->device;
sof_pdata->name = pci_name(pci);
sof_pdata->machine = mach;
Expand Down
33 changes: 0 additions & 33 deletions sound/soc/sof/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,6 @@
#include <sound/sof.h>
#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)
{
Expand Down