Merge branch 'asoc-4.19' into asoc-4.20 for rt5682 deps.
[muen/linux.git] / sound / soc / intel / skylake / skl.c
index 1d17be0f78a089e38a95ffbc3e84f0604ad6c2e3..29225623b4b40d1c8fea6822b85b007e57aba690 100644 (file)
 #include <sound/hda_register.h>
 #include <sound/hdaudio.h>
 #include <sound/hda_i915.h>
+#include <sound/hda_codec.h>
 #include "skl.h"
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
+#include "../../../soc/codecs/hdac_hda.h"
 
 /*
  * initialize the PCI registers
@@ -472,6 +474,25 @@ static struct skl_ssp_clk skl_ssp_clks[] = {
                                                {.name = "ssp5_sclkfs"},
 };
 
+static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl,
+                                       struct snd_soc_acpi_mach *machines)
+{
+       struct hdac_bus *bus = skl_to_bus(skl);
+       struct snd_soc_acpi_mach *mach;
+
+       /* check if we have any codecs detected on bus */
+       if (bus->codec_mask == 0)
+               return NULL;
+
+       /* point to common table */
+       mach = snd_soc_acpi_intel_hda_machines;
+
+       /* all entries in the machine table use the same firmware */
+       mach->fw_filename = machines->fw_filename;
+
+       return mach;
+}
+
 static int skl_find_machine(struct skl *skl, void *driver_data)
 {
        struct hdac_bus *bus = skl_to_bus(skl);
@@ -479,9 +500,13 @@ static int skl_find_machine(struct skl *skl, void *driver_data)
        struct skl_machine_pdata *pdata;
 
        mach = snd_soc_acpi_find_machine(mach);
-       if (mach == NULL) {
-               dev_err(bus->dev, "No matching machine driver found\n");
-               return -ENODEV;
+       if (!mach) {
+               dev_dbg(bus->dev, "No matching I2S machine driver found\n");
+               mach = skl_find_hda_machine(skl, driver_data);
+               if (!mach) {
+                       dev_err(bus->dev, "No matching machine driver found\n");
+                       return -ENODEV;
+               }
        }
 
        skl->mach = mach;
@@ -498,8 +523,9 @@ static int skl_find_machine(struct skl *skl, void *driver_data)
 
 static int skl_machine_device_register(struct skl *skl)
 {
-       struct hdac_bus *bus = skl_to_bus(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;
 
@@ -516,8 +542,12 @@ static int skl_machine_device_register(struct skl *skl)
                return -EIO;
        }
 
-       if (mach->pdata)
+       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;
 
@@ -628,6 +658,24 @@ static void skl_clock_device_unregister(struct skl *skl)
                platform_device_unregister(skl->clk_dev);
 }
 
+#define IDISP_INTEL_VENDOR_ID  0x80860000
+
+/*
+ * load the legacy codec driver
+ */
+static void load_codec_module(struct hda_codec *codec)
+{
+#ifdef MODULE
+       char modalias[MODULE_NAME_LEN];
+       const char *mod = NULL;
+
+       snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
+       mod = modalias;
+       dev_dbg(&codec->core.dev, "loading %s codec module\n", mod);
+       request_module(mod);
+#endif
+}
+
 /*
  * Probe the given codec address
  */
@@ -637,7 +685,9 @@ 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);
+       struct hdac_hda_priv *hda_codec;
        struct hdac_device *hdev;
+       int err;
 
        mutex_lock(&bus->cmd_mutex);
        snd_hdac_bus_send_cmd(bus, cmd);
@@ -645,13 +695,26 @@ static int probe_codec(struct hdac_bus *bus, int addr)
        mutex_unlock(&bus->cmd_mutex);
        if (res == -1)
                return -EIO;
-       dev_dbg(bus->dev, "codec #%d probed OK\n", addr);
+       dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
 
-       hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
-       if (!hdev)
+       hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
+                                GFP_KERNEL);
+       if (!hda_codec)
                return -ENOMEM;
 
-       return snd_hdac_ext_bus_device_init(bus, addr, hdev);
+       hda_codec->codec.bus = skl_to_hbus(skl);
+       hdev = &hda_codec->codec.core;
+
+       err = snd_hdac_ext_bus_device_init(bus, addr, hdev);
+       if (err < 0)
+               return err;
+
+       /* use legacy bus only for HDA codecs, idisp uses ext bus */
+       if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) {
+               hdev->type = HDA_DEV_LEGACY;
+               load_codec_module(&hda_codec->codec);
+       }
+       return 0;
 }
 
 /* Codec initialization */
@@ -786,9 +849,10 @@ static int skl_create(struct pci_dev *pci,
                      const struct hdac_io_ops *io_ops,
                      struct skl **rskl)
 {
+       struct hdac_ext_bus_ops *ext_ops = NULL;
        struct skl *skl;
        struct hdac_bus *bus;
-
+       struct hda_bus *hbus;
        int err;
 
        *rskl = NULL;
@@ -803,13 +867,23 @@ static int skl_create(struct pci_dev *pci,
                return -ENOMEM;
        }
 
+       hbus = skl_to_hbus(skl);
        bus = skl_to_bus(skl);
-       snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, NULL);
+
+#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA)
+       ext_ops = snd_soc_hdac_hda_get_ops();
+#endif
+       snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops);
        bus->use_posbuf = 1;
        skl->pci = pci;
        INIT_WORK(&skl->probe_work, skl_probe_work);
        bus->bdl_pos_adj = 0;
 
+       mutex_init(&hbus->prepare_mutex);
+       hbus->pci = pci;
+       hbus->mixer_assigned = -1;
+       hbus->modelname = "sklbus";
+
        *rskl = skl;
 
        return 0;