aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/skylake/skl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/skylake/skl.c')
-rw-r--r--sound/soc/intel/skylake/skl.c224
1 files changed, 147 insertions, 77 deletions
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 29225623b4b4..60c94836bf5b 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -37,7 +37,12 @@
#include "skl.h"
#include "skl-sst-dsp.h"
#include "skl-sst-ipc.h"
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
#include "../../../soc/codecs/hdac_hda.h"
+#endif
+static int skl_pci_binding;
+module_param_named(pci_binding, skl_pci_binding, int, 0444);
+MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc");
/*
* initialize the PCI registers
@@ -309,7 +314,7 @@ static int skl_suspend(struct device *dev)
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_bus *bus = pci_get_drvdata(pci);
struct skl *skl = bus_to_skl(bus);
- int ret = 0;
+ int ret;
/*
* Do not suspend if streams which are marked ignore suspend are
@@ -331,14 +336,10 @@ static int skl_suspend(struct device *dev)
skl->skl_sst->fw_loaded = false;
}
- if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
- ret = snd_hdac_display_power(bus, false);
- if (ret < 0)
- dev_err(bus->dev,
- "Cannot turn OFF display power on i915\n");
- }
+ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
- return ret;
+ return 0;
}
static int skl_resume(struct device *dev)
@@ -350,14 +351,8 @@ static int skl_resume(struct device *dev)
int ret;
/* Turned OFF in HDMI codec driver after codec reconfiguration */
- if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
- ret = snd_hdac_display_power(bus, true);
- if (ret < 0) {
- dev_err(bus->dev,
- "Cannot turn on display power on i915\n");
- return ret;
- }
- }
+ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
/*
* resume only when we are not in suspend active, otherwise need to
@@ -515,7 +510,7 @@ static int skl_find_machine(struct skl *skl, void *driver_data)
if (pdata) {
skl->use_tplg_pcm = pdata->use_tplg_pcm;
- pdata->dmic_num = skl_get_dmic_geo(skl);
+ mach->mach_params.dmic_num = skl_get_dmic_geo(skl);
}
return 0;
@@ -525,7 +520,6 @@ static int skl_machine_device_register(struct skl *skl)
{
struct snd_soc_acpi_mach *mach = skl->mach;
struct hdac_bus *bus = skl_to_bus(skl);
- struct skl_machine_pdata *pdata;
struct platform_device *pdev;
int ret;
@@ -535,6 +529,16 @@ static int skl_machine_device_register(struct skl *skl)
return -EIO;
}
+ mach->mach_params.platform = dev_name(bus->dev);
+ mach->mach_params.codec_mask = bus->codec_mask;
+
+ ret = platform_device_add_data(pdev, (const void *)mach, sizeof(*mach));
+ if (ret) {
+ dev_err(bus->dev, "failed to add machine device platform data\n");
+ platform_device_put(pdev);
+ return ret;
+ }
+
ret = platform_device_add(pdev);
if (ret) {
dev_err(bus->dev, "failed to add machine device\n");
@@ -542,12 +546,6 @@ static int skl_machine_device_register(struct skl *skl)
return -EIO;
}
- if (mach->pdata) {
- pdata = (struct skl_machine_pdata *)mach->pdata;
- pdata->platform = dev_name(bus->dev);
- pdata->codec_mask = bus->codec_mask;
- dev_set_drvdata(&pdev->dev, mach->pdata);
- }
skl->i2s_dev = pdev;
@@ -658,6 +656,8 @@ static void skl_clock_device_unregister(struct skl *skl)
platform_device_unregister(skl->clk_dev);
}
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
+
#define IDISP_INTEL_VENDOR_ID 0x80860000
/*
@@ -676,6 +676,8 @@ static void load_codec_module(struct hda_codec *codec)
#endif
}
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
+
/*
* Probe the given codec address
*/
@@ -685,9 +687,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
unsigned int res = -1;
struct skl *skl = bus_to_skl(bus);
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
struct hdac_hda_priv *hda_codec;
- struct hdac_device *hdev;
int err;
+#endif
+ struct hdac_device *hdev;
mutex_lock(&bus->cmd_mutex);
snd_hdac_bus_send_cmd(bus, cmd);
@@ -697,6 +701,7 @@ static int probe_codec(struct hdac_bus *bus, int addr)
return -EIO;
dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
GFP_KERNEL);
if (!hda_codec)
@@ -715,6 +720,13 @@ static int probe_codec(struct hdac_bus *bus, int addr)
load_codec_module(&hda_codec->codec);
}
return 0;
+#else
+ hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
+ if (!hdev)
+ return -ENOMEM;
+
+ return snd_hdac_ext_bus_device_init(bus, addr, hdev);
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
}
/* Codec initialization */
@@ -767,11 +779,9 @@ static int skl_i915_init(struct hdac_bus *bus)
if (err < 0)
return err;
- err = snd_hdac_display_power(bus, true);
- if (err < 0)
- dev_err(bus->dev, "Cannot turn on display power on i915\n");
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
- return err;
+ return 0;
}
static void skl_probe_work(struct work_struct *work)
@@ -807,21 +817,10 @@ static void skl_probe_work(struct work_struct *work)
return;
}
- if (bus->ppcap) {
- err = skl_machine_device_register(skl);
- if (err < 0) {
- dev_err(bus->dev, "machine register failed: %d\n", err);
- goto out_err;
- }
- }
-
- if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
- err = snd_hdac_display_power(bus, false);
- if (err < 0) {
- dev_err(bus->dev, "Cannot turn off display power on i915\n");
- skl_machine_device_unregister(skl);
- return;
- }
+ err = skl_machine_device_register(skl);
+ if (err < 0) {
+ dev_err(bus->dev, "machine register failed: %d\n", err);
+ goto out_err;
}
/*
@@ -830,6 +829,9 @@ static void skl_probe_work(struct work_struct *work)
list_for_each_entry(hlink, &bus->hlink_list, list)
snd_hdac_ext_bus_link_put(bus, hlink);
+ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
+
/* configure PM */
pm_runtime_put_noidle(bus->dev);
pm_runtime_allow(bus->dev);
@@ -839,7 +841,7 @@ static void skl_probe_work(struct work_struct *work)
out_err:
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
- err = snd_hdac_display_power(bus, false);
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
}
/*
@@ -870,7 +872,7 @@ static int skl_create(struct pci_dev *pci,
hbus = skl_to_hbus(skl);
bus = skl_to_bus(skl);
-#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
ext_ops = snd_soc_hdac_hda_get_ops();
#endif
snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops);
@@ -912,6 +914,12 @@ static int skl_first_init(struct hdac_bus *bus)
snd_hdac_bus_parse_capabilities(bus);
+ /* check if PPCAP exists */
+ if (!bus->ppcap) {
+ dev_err(bus->dev, "bus ppcap not set, HDaudio or DSP not present?\n");
+ return -ENODEV;
+ }
+
if (skl_acquire_irq(bus, 0) < 0)
return -EBUSY;
@@ -921,23 +929,25 @@ static int skl_first_init(struct hdac_bus *bus)
gcap = snd_hdac_chip_readw(bus, GCAP);
dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap);
- /* allow 64bit DMA address if supported by H/W */
- if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) {
- dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64));
- } else {
- dma_set_mask(bus->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32));
- }
-
/* read number of streams from GCAP register */
cp_streams = (gcap >> 8) & 0x0f;
pb_streams = (gcap >> 12) & 0x0f;
- if (!pb_streams && !cp_streams)
+ if (!pb_streams && !cp_streams) {
+ dev_err(bus->dev, "no streams found in GCAP definitions?\n");
return -EIO;
+ }
bus->num_streams = cp_streams + pb_streams;
+ /* allow 64bit DMA address if supported by H/W */
+ if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) {
+ dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64));
+ } else {
+ dma_set_mask(bus->dev, DMA_BIT_MASK(32));
+ dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32));
+ }
+
/* initialize streams */
snd_hdac_ext_stream_init_all
(bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE);
@@ -962,6 +972,36 @@ static int skl_probe(struct pci_dev *pci,
struct hdac_bus *bus = NULL;
int err;
+ switch (skl_pci_binding) {
+ case SND_SKL_PCI_BIND_AUTO:
+ /*
+ * detect DSP by checking class/subclass/prog-id information
+ * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
+ * class=04 subclass 01 prog-if 00: DSP is present
+ * (and may be required e.g. for DMIC or SSP support)
+ * class=04 subclass 03 prog-if 80: use DSP or legacy mode
+ */
+ if (pci->class == 0x040300) {
+ dev_info(&pci->dev, "The DSP is not enabled on this platform, aborting probe\n");
+ return -ENODEV;
+ }
+ if (pci->class != 0x040100 && pci->class != 0x040380) {
+ dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class);
+ return -ENODEV;
+ }
+ dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
+ break;
+ case SND_SKL_PCI_BIND_LEGACY:
+ dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, aborting probe\n");
+ return -ENODEV;
+ case SND_SKL_PCI_BIND_ASOC:
+ dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n");
+ break;
+ default:
+ dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n");
+ break;
+ }
+
/* we use ext core ops, so provide NULL for ops here */
err = skl_create(pci, NULL, &skl);
if (err < 0)
@@ -970,8 +1010,10 @@ static int skl_probe(struct pci_dev *pci,
bus = skl_to_bus(skl);
err = skl_first_init(bus);
- if (err < 0)
+ if (err < 0) {
+ dev_err(bus->dev, "skl_first_init failed with err: %d\n", err);
goto out_free;
+ }
skl->pci_id = pci->device;
@@ -980,37 +1022,48 @@ static int skl_probe(struct pci_dev *pci,
skl->nhlt = skl_nhlt_init(bus->dev);
if (skl->nhlt == NULL) {
+#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
+ dev_err(bus->dev, "no nhlt info found\n");
err = -ENODEV;
goto out_free;
- }
-
- err = skl_nhlt_create_sysfs(skl);
- if (err < 0)
- goto out_nhlt_free;
+#else
+ dev_warn(bus->dev, "no nhlt info found, continuing to try to enable HDaudio codec\n");
+#endif
+ } else {
- skl_nhlt_update_topology_bin(skl);
+ err = skl_nhlt_create_sysfs(skl);
+ if (err < 0) {
+ dev_err(bus->dev, "skl_nhlt_create_sysfs failed with err: %d\n", err);
+ goto out_nhlt_free;
+ }
- pci_set_drvdata(skl->pci, bus);
+ skl_nhlt_update_topology_bin(skl);
- /* check if dsp is there */
- if (bus->ppcap) {
/* create device for dsp clk */
err = skl_clock_device_register(skl);
- if (err < 0)
+ if (err < 0) {
+ dev_err(bus->dev, "skl_clock_device_register failed with err: %d\n", err);
goto out_clk_free;
+ }
+ }
- err = skl_find_machine(skl, (void *)pci_id->driver_data);
- if (err < 0)
- goto out_nhlt_free;
+ pci_set_drvdata(skl->pci, bus);
- err = skl_init_dsp(skl);
- if (err < 0) {
- dev_dbg(bus->dev, "error failed to register dsp\n");
- goto out_nhlt_free;
- }
- skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
- skl->skl_sst->clock_power_gating = skl_clock_power_gating;
+
+ err = skl_find_machine(skl, (void *)pci_id->driver_data);
+ if (err < 0) {
+ dev_err(bus->dev, "skl_find_machine failed with err: %d\n", err);
+ goto out_nhlt_free;
+ }
+
+ err = skl_init_dsp(skl);
+ if (err < 0) {
+ dev_dbg(bus->dev, "error failed to register dsp\n");
+ goto out_nhlt_free;
}
+ skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
+ skl->skl_sst->clock_power_gating = skl_clock_power_gating;
+
if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(bus);
@@ -1018,8 +1071,10 @@ static int skl_probe(struct pci_dev *pci,
/* create device for soc dmic */
err = skl_dmic_device_register(skl);
- if (err < 0)
+ if (err < 0) {
+ dev_err(bus->dev, "skl_dmic_device_register failed with err: %d\n", err);
goto out_dsp_free;
+ }
schedule_work(&skl->probe_work);
@@ -1087,21 +1142,36 @@ static void skl_remove(struct pci_dev *pci)
/* PCI IDs */
static const struct pci_device_id skl_ids[] = {
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL)
/* Sunrise Point-LP */
{ PCI_DEVICE(0x8086, 0x9d70),
.driver_data = (unsigned long)&snd_soc_acpi_intel_skl_machines},
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL)
/* BXT-P */
{ PCI_DEVICE(0x8086, 0x5a98),
.driver_data = (unsigned long)&snd_soc_acpi_intel_bxt_machines},
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL)
/* KBL */
{ PCI_DEVICE(0x8086, 0x9D71),
.driver_data = (unsigned long)&snd_soc_acpi_intel_kbl_machines},
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK)
/* GLK */
{ PCI_DEVICE(0x8086, 0x3198),
.driver_data = (unsigned long)&snd_soc_acpi_intel_glk_machines},
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL)
/* CNL */
{ PCI_DEVICE(0x8086, 0x9dc8),
.driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines},
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CFL)
+ /* CFL */
+ { PCI_DEVICE(0x8086, 0xa348),
+ .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines},
+#endif
{ 0, }
};
MODULE_DEVICE_TABLE(pci, skl_ids);