These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / pci / hda / hda_bind.c
index 00aa31c..6efadbf 100644 (file)
 #include "hda_local.h"
 
 /*
- * find a matching codec preset
+ * find a matching codec id
  */
 static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
 {
        struct hda_codec *codec = container_of(dev, struct hda_codec, core);
        struct hda_codec_driver *driver =
                container_of(drv, struct hda_codec_driver, core);
-       const struct hda_codec_preset *preset;
+       const struct hda_device_id *list;
        /* check probe_id instead of vendor_id if set */
        u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id;
+       u32 rev_id = codec->core.revision_id;
 
-       for (preset = driver->preset; preset->id; preset++) {
-               u32 mask = preset->mask;
-
-               if (preset->afg && preset->afg != codec->core.afg)
-                       continue;
-               if (preset->mfg && preset->mfg != codec->core.mfg)
-                       continue;
-               if (!mask)
-                       mask = ~0;
-               if (preset->id == (id & mask) &&
-                   (!preset->rev || preset->rev == codec->core.revision_id)) {
-                       codec->preset = preset;
+       for (list = driver->id; list->vendor_id; list++) {
+               if (list->vendor_id == id &&
+                   (!list->rev_id || list->rev_id == rev_id)) {
+                       codec->preset = list;
                        return 1;
                }
        }
@@ -53,26 +46,45 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
                codec->patch_ops.unsol_event(codec, ev);
 }
 
-/* reset the codec name from the preset */
-static int codec_refresh_name(struct hda_codec *codec, const char *name)
+/**
+ * snd_hda_codec_set_name - set the codec name
+ * @codec: the HDA codec
+ * @name: name string to set
+ */
+int snd_hda_codec_set_name(struct hda_codec *codec, const char *name)
 {
-       if (name) {
-               kfree(codec->core.chip_name);
-               codec->core.chip_name = kstrdup(name, GFP_KERNEL);
+       int err;
+
+       if (!name)
+               return 0;
+       err = snd_hdac_device_set_chip_name(&codec->core, name);
+       if (err < 0)
+               return err;
+
+       /* update the mixer name */
+       if (!*codec->card->mixername ||
+           codec->bus->mixer_assigned >= codec->core.addr) {
+               snprintf(codec->card->mixername,
+                        sizeof(codec->card->mixername), "%s %s",
+                        codec->core.vendor_name, codec->core.chip_name);
+               codec->bus->mixer_assigned = codec->core.addr;
        }
-       return codec->core.chip_name ? 0 : -ENOMEM;
+
+       return 0;
 }
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_name);
 
 static int hda_codec_driver_probe(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
        struct module *owner = dev->driver->owner;
+       hda_codec_patch_t patch;
        int err;
 
        if (WARN_ON(!codec->preset))
                return -EINVAL;
 
-       err = codec_refresh_name(codec, codec->preset->name);
+       err = snd_hda_codec_set_name(codec, codec->preset->name);
        if (err < 0)
                goto error;
        err = snd_hdac_regmap_init(&codec->core);
@@ -84,9 +96,12 @@ static int hda_codec_driver_probe(struct device *dev)
                goto error;
        }
 
-       err = codec->preset->patch(codec);
-       if (err < 0)
-               goto error_module;
+       patch = (hda_codec_patch_t)codec->preset->driver_data;
+       if (patch) {
+               err = patch(codec);
+               if (err < 0)
+                       goto error_module;
+       }
 
        err = snd_hda_codec_build_pcms(codec);
        if (err < 0)
@@ -159,15 +174,40 @@ static inline bool codec_probed(struct hda_codec *codec)
        return device_attach(hda_codec_dev(codec)) > 0 && codec->preset;
 }
 
+/* try to auto-load codec module */
+static void request_codec_module(struct hda_codec *codec)
+{
+#ifdef MODULE
+       char modalias[32];
+       const char *mod = NULL;
+
+       switch (codec->probe_id) {
+       case HDA_CODEC_ID_GENERIC_HDMI:
+#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
+               mod = "snd-hda-codec-hdmi";
+#endif
+               break;
+       case HDA_CODEC_ID_GENERIC:
+#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
+               mod = "snd-hda-codec-generic";
+#endif
+               break;
+       default:
+               snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
+               mod = modalias;
+               break;
+       }
+
+       if (mod)
+               request_module(mod);
+#endif /* MODULE */
+}
+
 /* try to auto-load and bind the codec module */
 static void codec_bind_module(struct hda_codec *codec)
 {
 #ifdef MODULE
-       request_module("snd-hda-codec-id:%08x", codec->core.vendor_id);
-       if (codec_probed(codec))
-               return;
-       request_module("snd-hda-codec-id:%04x*",
-                      (codec->core.vendor_id >> 16) & 0xffff);
+       request_codec_module(codec);
        if (codec_probed(codec))
                return;
 #endif
@@ -204,17 +244,13 @@ static int codec_bind_generic(struct hda_codec *codec)
 
        if (is_likely_hdmi_codec(codec)) {
                codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI;
-#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
-               request_module("snd-hda-codec-hdmi");
-#endif
+               request_codec_module(codec);
                if (codec_probed(codec))
                        return 0;
        }
 
        codec->probe_id = HDA_CODEC_ID_GENERIC;
-#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
-       request_module("snd-hda-codec-generic");
-#endif
+       request_codec_module(codec);
        if (codec_probed(codec))
                return 0;
        return -ENODEV;
@@ -259,11 +295,6 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                }
        }
 
-       /* audio codec should override the mixer name */
-       if (codec->core.afg || !*codec->card->mixername)
-               snprintf(codec->card->mixername,
-                        sizeof(codec->card->mixername), "%s %s",
-                        codec->core.vendor_name, codec->core.chip_name);
        return 0;
 
  error: