Commit 71cc8abb authored by Kai Vehmanen's avatar Kai Vehmanen Committed by Mark Brown

ASoC: SOF: Intel: hda: allow operation without i915 gfx

Add support to configure the HDA controller with an external HDA
codec even if iDisp codec in i915 is not available.

This can happen for multiple reasons:
 - internal graphics is disabled on the system
 - i915 driver is not enabled in kernel or it fails to init
 - i915 codec reports error in HDA codec probe
 - HDA codec driver probe fails

Address all these scenarios, but keep using the existing topology.
In case failures occur, HDMI PCM nodes are created, but they will
report error if application tries to use them. No ALSA mixer controls
are created. If the external HDA codec init fails as well, SOF probe
will return error as before.
Signed-off-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206085
BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1163677
BugLink: https://github.com/thesofproject/linux/issues/1658
Link: https://lore.kernel.org/r/20200220171028.22023-3-kai.vehmanen@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent d2ad9d6c
...@@ -113,8 +113,14 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, ...@@ -113,8 +113,14 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
if (ret < 0) if (ret < 0)
return ret; return ret;
if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) {
if (!hdev->bus->audio_component) {
dev_dbg(sdev->dev,
"iDisp hw present but no driver\n");
return -ENOENT;
}
hda_priv->need_display_power = true; hda_priv->need_display_power = true;
}
/* /*
* if common HDMI codec driver is not used, codec load * if common HDMI codec driver is not used, codec load
...@@ -203,6 +209,9 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) ...@@ -203,6 +209,9 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
int ret; int ret;
if (!bus->audio_component)
return 0;
/* power down unconditionally */ /* power down unconditionally */
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
......
...@@ -288,10 +288,8 @@ static int hda_init(struct snd_sof_dev *sdev) ...@@ -288,10 +288,8 @@ static int hda_init(struct snd_sof_dev *sdev)
/* init i915 and HDMI codecs */ /* init i915 and HDMI codecs */
ret = hda_codec_i915_init(sdev); ret = hda_codec_i915_init(sdev);
if (ret < 0) { if (ret < 0)
dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n"); dev_warn(sdev->dev, "init of i915 and HDMI codec failed\n");
return ret;
}
/* get controller capabilities */ /* get controller capabilities */
ret = hda_dsp_ctrl_get_caps(sdev); ret = hda_dsp_ctrl_get_caps(sdev);
...@@ -365,9 +363,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -365,9 +363,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
if (ret < 0) { if (ret < 0) {
dev_err(bus->dev, "error: init chip failed with ret: %d\n", dev_err(bus->dev, "error: init chip failed with ret: %d\n",
ret); ret);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
hda_codec_i915_exit(sdev);
#endif
return ret; return ret;
} }
...@@ -379,7 +374,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -379,7 +374,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
if (!HDA_IDISP_CODEC(bus->codec_mask)) if (!HDA_IDISP_CODEC(bus->codec_mask))
hda_codec_i915_exit(sdev); hda_codec_i915_display_power(sdev, false);
/* /*
* we are done probing so decrement link counts * we are done probing so decrement link counts
...@@ -699,12 +694,11 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -699,12 +694,11 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
/* /*
* If no machine driver is found, then: * If no machine driver is found, then:
* *
* hda machine driver is used if : * generic hda machine driver can handle:
* 1. there is one HDMI codec and one external HDAudio codec * - one HDMI codec, and/or
* 2. only HDMI codec * - one external HDAudio codec
*/ */
if (!pdata->machine && codec_num <= 2 && if (!pdata->machine && codec_num <= 2) {
HDA_IDISP_CODEC(bus->codec_mask)) {
hda_mach = snd_soc_acpi_intel_hda_machines; hda_mach = snd_soc_acpi_intel_hda_machines;
/* topology: use the info from hda_machines */ /* topology: use the info from hda_machines */
...@@ -714,7 +708,7 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -714,7 +708,7 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
dev_info(bus->dev, "using HDA machine driver %s now\n", dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name); hda_mach->drv_name);
if (codec_num == 1) if (codec_num == 1 && HDA_IDISP_CODEC(bus->codec_mask))
idisp_str = "-idisp"; idisp_str = "-idisp";
else else
idisp_str = ""; idisp_str = "";
......
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