ASoC: Improve machine driver selection based on quirk data
[sfrench/cifs-2.6.git] / sound / soc / intel / skylake / skl.c
index 6df3b317a4768e008b539f0a619308e9545a3992..ceb7734d74ed7b9a04755cb2fce8a38ca5c3952e 100644 (file)
@@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
        struct skl *skl  = ebus_to_skl(ebus);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
 
-       skl->init_failed = 1; /* to be sure */
+       skl->init_done = 0; /* to be sure */
 
        snd_hdac_ext_stop_streams(ebus);
 
@@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus)
 
        snd_hdac_ext_bus_exit(ebus);
 
+       cancel_work_sync(&skl->probe_work);
        if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
                snd_hdac_i915_exit(&ebus->bus);
+
        return 0;
 }
 
@@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = {
        .get_response = snd_hdac_bus_get_response,
 };
 
+static int skl_i915_init(struct hdac_bus *bus)
+{
+       int err;
+
+       /*
+        * The HDMI codec is in GPU so we need to ensure that it is powered
+        * up and ready for probe
+        */
+       err = snd_hdac_i915_init(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");
+
+       return err;
+}
+
+static void skl_probe_work(struct work_struct *work)
+{
+       struct skl *skl = container_of(work, struct skl, probe_work);
+       struct hdac_ext_bus *ebus = &skl->ebus;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct hdac_ext_link *hlink = NULL;
+       int err;
+
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = skl_i915_init(bus);
+               if (err < 0)
+                       return;
+       }
+
+       err = skl_init_chip(bus, true);
+       if (err < 0) {
+               dev_err(bus->dev, "Init chip failed with err: %d\n", err);
+               goto out_err;
+       }
+
+       /* codec detection */
+       if (!bus->codec_mask)
+               dev_info(bus->dev, "no hda codecs found!\n");
+
+       /* create codec instances */
+       err = skl_codec_create(ebus);
+       if (err < 0)
+               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");
+                       return;
+               }
+       }
+
+       /* register platform dai and controls */
+       err = skl_platform_register(bus->dev);
+       if (err < 0)
+               return;
+       /*
+        * we are done probing so decrement link counts
+        */
+       list_for_each_entry(hlink, &ebus->hlink_list, list)
+               snd_hdac_ext_bus_link_put(ebus, hlink);
+
+       /* configure PM */
+       pm_runtime_put_noidle(bus->dev);
+       pm_runtime_allow(bus->dev);
+       skl->init_done = 1;
+
+       return;
+
+out_err:
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+               err = snd_hdac_display_power(bus, false);
+}
+
 /*
  * constructor
  */
@@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci,
        snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops);
        ebus->bus.use_posbuf = 1;
        skl->pci = pci;
+       INIT_WORK(&skl->probe_work, skl_probe_work);
 
        ebus->bus.bdl_pos_adj = 0;
 
@@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci,
        return 0;
 }
 
-static int skl_i915_init(struct hdac_bus *bus)
-{
-       int err;
-
-       /*
-        * The HDMI codec is in GPU so we need to ensure that it is powered
-        * up and ready for probe
-        */
-       err = snd_hdac_i915_init(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");
-               return err;
-       }
-
-       return err;
-}
-
 static int skl_first_init(struct hdac_ext_bus *ebus)
 {
        struct skl *skl = ebus_to_skl(ebus);
@@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
        /* initialize chip */
        skl_init_pci(skl);
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-               err = skl_i915_init(bus);
-               if (err < 0)
-                       return err;
-       }
-
-       skl_init_chip(bus, true);
-
-       /* codec detection */
-       if (!bus->codec_mask) {
-               dev_info(bus->dev, "no hda codecs found!\n");
-       }
-
-       return 0;
+       return skl_init_chip(bus, true);
 }
 
 static int skl_probe(struct pci_dev *pci,
@@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci,
        struct skl *skl;
        struct hdac_ext_bus *ebus = NULL;
        struct hdac_bus *bus = NULL;
-       struct hdac_ext_link *hlink = NULL;
        int err;
 
        /* we use ext core ops, so provide NULL for ops here */
@@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci,
 
        if (skl->nhlt == NULL) {
                err = -ENODEV;
-               goto out_display_power_off;
+               goto out_free;
        }
 
        err = skl_nhlt_create_sysfs(skl);
@@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci,
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(ebus);
 
+       snd_hdac_bus_stop_chip(bus);
+
        /* create device for soc dmic */
        err = skl_dmic_device_register(skl);
        if (err < 0)
                goto out_dsp_free;
 
-       /* register platform dai and controls */
-       err = skl_platform_register(bus->dev);
-       if (err < 0)
-               goto out_dmic_free;
-
-       /* create codec instances */
-       err = skl_codec_create(ebus);
-       if (err < 0)
-               goto out_unregister;
-
-       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");
-                       return err;
-               }
-       }
-
-       /*
-        * we are done probling so decrement link counts
-        */
-       list_for_each_entry(hlink, &ebus->hlink_list, list)
-               snd_hdac_ext_bus_link_put(ebus, hlink);
-
-       /* configure PM */
-       pm_runtime_put_noidle(bus->dev);
-       pm_runtime_allow(bus->dev);
+       schedule_work(&skl->probe_work);
 
        return 0;
 
-out_unregister:
-       skl_platform_unregister(bus->dev);
-out_dmic_free:
-       skl_dmic_device_unregister(skl);
 out_dsp_free:
        skl_free_dsp(skl);
 out_mach_free:
        skl_machine_device_unregister(skl);
 out_nhlt_free:
        skl_nhlt_free(skl->nhlt);
-out_display_power_off:
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, false);
 out_free:
-       skl->init_failed = 1;
        skl_free(ebus);
 
        return err;
@@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci)
 
        skl = ebus_to_skl(ebus);
 
-       if (skl->init_failed)
+       if (!skl->init_done)
                return;
 
        snd_hdac_ext_stop_streams(ebus);
@@ -862,29 +876,81 @@ static void skl_remove(struct pci_dev *pci)
        dev_set_drvdata(&pci->dev, NULL);
 }
 
+static struct sst_codecs skl_codecs = { 1, {"NAU88L25"} };
+static struct sst_codecs kbl_codecs = { 1, {"NAU88L25"} };
+static struct sst_codecs bxt_codecs = { 1, {"MX98357A"} };
+
 static struct sst_acpi_mach sst_skl_devdata[] = {
-       { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL },
-       { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin",
-                               NULL, NULL, &skl_dmic_data },
-       { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin",
-                               NULL, NULL, &skl_dmic_data },
+       {
+               .id = "INT343A",
+               .drv_name = "skl_alc286s_i2s",
+               .fw_filename = "intel/dsp_fw_release.bin",
+       },
+       {
+               .id = "INT343B",
+               .drv_name = "skl_n88l25_s4567",
+               .fw_filename = "intel/dsp_fw_release.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &skl_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98357A",
+               .drv_name = "skl_n88l25_m98357a",
+               .fw_filename = "intel/dsp_fw_release.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &skl_codecs,
+               .pdata = &skl_dmic_data
+       },
        {}
 };
 
 static struct sst_acpi_mach sst_bxtp_devdata[] = {
-       { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
-       { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
+       {
+               .id = "INT343A",
+               .drv_name = "bxt_alc298s_i2s",
+               .fw_filename = "intel/dsp_fw_bxtn.bin",
+       },
+       {
+               .id = "DLGS7219",
+               .drv_name = "bxt_da7219_max98357a_i2s",
+               .fw_filename = "intel/dsp_fw_bxtn.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &bxt_codecs,
+       },
 };
 
 static struct sst_acpi_mach sst_kbl_devdata[] = {
-       { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL },
-       { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
-       { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
+       {
+               .id = "INT343A",
+               .drv_name = "kbl_alc286s_i2s",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+       },
+       {
+               .id = "INT343B",
+               .drv_name = "kbl_n88l25_s4567",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98357A",
+               .drv_name = "kbl_n88l25_m98357a",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_codecs,
+               .pdata = &skl_dmic_data
+       },
        {}
 };
 
 static struct sst_acpi_mach sst_glk_devdata[] = {
-       { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL },
+       {
+               .id = "INT343A",
+               .drv_name = "glk_alc298s_i2s",
+               .fw_filename = "intel/dsp_fw_glk.bin",
+       },
 };
 
 /* PCI IDs */