]> Pileus Git - ~andy/linux/blobdiff - sound/pci/hda/hda_codec.c
Merge remote-tracking branches 'spi/fix/ath79', 'spi/fix/atmel', 'spi/fix/coldfire...
[~andy/linux] / sound / pci / hda / hda_codec.c
index 69178c4f4113fad7fb3111b57d49247c8f2ebe5c..dafcf82139e2bbdcdb4bad0539ad6c616661d892 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/async.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include <sound/asoundef.h>
@@ -83,7 +84,7 @@ int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
        mutex_unlock(&preset_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_add_codec_preset);
 
 int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 {
@@ -92,23 +93,31 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
        mutex_unlock(&preset_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
 #define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
-static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
+
+static void hda_call_pm_notify(struct hda_codec *codec, bool power_up)
 {
+       struct hda_bus *bus = codec->bus;
+
+       if ((power_up && codec->pm_up_notified) ||
+           (!power_up && !codec->pm_up_notified))
+               return;
        if (bus->ops.pm_notify)
                bus->ops.pm_notify(bus, power_up);
+       codec->pm_up_notified = power_up;
 }
+
 #else
 #define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
-#define hda_call_pm_notify(bus, state) {}
+#define hda_call_pm_notify(codec, state) {}
 #endif
 
 /**
@@ -143,7 +152,7 @@ const char *snd_hda_get_jack_location(u32 cfg)
        }
        return "UNKNOWN";
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_location);
 
 /**
  * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
@@ -158,7 +167,7 @@ const char *snd_hda_get_jack_connectivity(u32 cfg)
 
        return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_connectivity);
 
 /**
  * snd_hda_get_jack_type - Give a type string of the jack
@@ -179,7 +188,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
        return jack_types[(cfg & AC_DEFCFG_DEVICE)
                                >> AC_DEFCFG_DEVICE_SHIFT];
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_type);
 
 /*
  * Compose a 32bit command word to be sent to the HD-audio controller
@@ -275,7 +284,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
                return -1;
        return res;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_read);
 
 /**
  * snd_hda_codec_write - send a single command without waiting for response
@@ -297,7 +306,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
        return codec_exec_verb(codec, cmd, flags,
                               codec->bus->sync_write ? &res : NULL);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_write);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write);
 
 /**
  * snd_hda_sequence_write - sequence writes
@@ -312,7 +321,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
        for (; seq->nid; seq++)
                snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
 }
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
 
 /**
  * snd_hda_get_sub_nodes - get the range of sub nodes
@@ -334,7 +343,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
        *start_id = (parm >> 16) & 0x7fff;
        return (int)(parm & 0x7fff);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
+EXPORT_SYMBOL_GPL(snd_hda_get_sub_nodes);
 
 /* connection list element */
 struct hda_conn_list {
@@ -444,7 +453,7 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
                added = true;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
 
 /**
  * snd_hda_get_connections - copy connection list
@@ -476,7 +485,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 
        return len;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+EXPORT_SYMBOL_GPL(snd_hda_get_connections);
 
 /* return CONNLIST_LEN parameter of the given widget */
 static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
@@ -625,7 +634,7 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
 
        return add_conn_list(codec, nid, len, list);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
 
 /**
  * snd_hda_get_conn_index - get the connection index of the given NID
@@ -664,7 +673,7 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
 
 
 /* return DEVLIST_LEN parameter of the given widget */
@@ -760,7 +769,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
+EXPORT_SYMBOL_GPL(snd_hda_queue_unsol_event);
 
 /*
  * process queued unsolicited events
@@ -831,6 +840,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
                bus->ops.private_free(bus);
        if (bus->workq)
                destroy_workqueue(bus->workq);
+
        kfree(bus);
        return 0;
 }
@@ -920,9 +930,9 @@ int snd_hda_bus_new(struct snd_card *card,
                *busp = bus;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_bus_new);
+EXPORT_SYMBOL_GPL(snd_hda_bus_new);
 
-#ifdef CONFIG_SND_HDA_GENERIC
+#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
 #define is_generic_config(codec) \
        (codec->modelname && !strcmp(codec->modelname, "generic"))
 #else
@@ -945,9 +955,6 @@ find_codec_preset(struct hda_codec *codec)
        const struct hda_codec_preset *preset;
        unsigned int mod_requested = 0;
 
-       if (is_generic_config(codec))
-               return NULL; /* use the generic parser */
-
  again:
        mutex_lock(&preset_mutex);
        list_for_each_entry(tbl, &hda_preset_tables, list) {
@@ -1163,7 +1170,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec,
 {
        return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pincfg);
 
 /**
  * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
@@ -1198,7 +1205,7 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
                return pin->cfg;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pincfg);
 
 /* remember the current pinctl target value */
 int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
@@ -1212,7 +1219,7 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
        pin->target = val;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pin_target);
 
 /* return the current pinctl target value */
 int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
@@ -1224,7 +1231,7 @@ int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
                return 0;
        return pin->target;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
 
 /**
  * snd_hda_shutup_pins - Shut up all pins
@@ -1249,7 +1256,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
        }
        codec->pins_shutup = 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
+EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
 
 #ifdef CONFIG_PM
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
@@ -1329,6 +1336,20 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
        return p;
 }
 
+/*
+ * Dynamic symbol binding for the codec parsers
+ */
+
+#define load_parser(codec, sym) \
+       ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym))
+
+static void unload_parser(struct hda_codec *codec)
+{
+       if (codec->parser)
+               symbol_put_addr(codec->parser);
+       codec->parser = NULL;
+}
+
 /*
  * codec destructor
  */
@@ -1352,10 +1373,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        codec->bus->caddr_tbl[codec->addr] = NULL;
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
-#ifdef CONFIG_PM
-       if (!codec->pm_down_notified) /* cancel leftover refcounts */
-               hda_call_pm_notify(codec->bus, false);
-#endif
+       hda_call_pm_notify(codec, false); /* cancel leftover refcounts */
+       unload_parser(codec);
        module_put(codec->owner);
        free_hda_cache(&codec->amp_cache);
        free_hda_cache(&codec->cmd_cache);
@@ -1363,6 +1382,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        kfree(codec->chip_name);
        kfree(codec->modelname);
        kfree(codec->wcaps);
+       codec->bus->num_codecs--;
        kfree(codec);
 }
 
@@ -1424,6 +1444,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
        INIT_LIST_HEAD(&codec->conn_list);
 
        INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
+       codec->depop_delay = -1;
 
 #ifdef CONFIG_PM
        spin_lock_init(&codec->power_lock);
@@ -1433,7 +1454,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
         * phase.
         */
        hda_keep_power_on(codec);
-       hda_call_pm_notify(bus, true);
 #endif
 
        if (codec->bus->modelname) {
@@ -1445,6 +1465,8 @@ int snd_hda_codec_new(struct hda_bus *bus,
        }
 
        list_add_tail(&codec->list, &bus->codec_list);
+       bus->num_codecs++;
+
        bus->caddr_tbl[codec_addr] = codec;
 
        codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
@@ -1486,11 +1508,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
 #ifdef CONFIG_PM
        codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_CLKSTOP);
-       if (!codec->d3_stop_clk)
-               bus->power_keep_link_on = 1;
 #endif
        codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_EPSS);
+#ifdef CONFIG_PM
+       if (!codec->d3_stop_clk || !codec->epss)
+               bus->power_keep_link_on = 1;
+#endif
+
 
        /* power-up all before initialization */
        hda_set_power_state(codec, AC_PWRST_D0);
@@ -1511,7 +1536,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
        snd_hda_codec_free(codec);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_new);
+EXPORT_SYMBOL_GPL(snd_hda_codec_new);
 
 int snd_hda_codec_update_widgets(struct hda_codec *codec)
 {
@@ -1534,9 +1559,34 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
 
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
 
 
+#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
+/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
+static bool is_likely_hdmi_codec(struct hda_codec *codec)
+{
+       hda_nid_t nid = codec->start_nid;
+       int i;
+
+       for (i = 0; i < codec->num_nodes; i++, nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               switch (get_wcaps_type(wcaps)) {
+               case AC_WID_AUD_IN:
+                       return false; /* HDMI parser supports only HDMI out */
+               case AC_WID_AUD_OUT:
+                       if (!(wcaps & AC_WCAP_DIGITAL))
+                               return false;
+                       break;
+               }
+       }
+       return true;
+}
+#else
+/* no HDMI codec parser support */
+#define is_likely_hdmi_codec(codec)    false
+#endif /* CONFIG_SND_HDA_CODEC_HDMI */
+
 /**
  * snd_hda_codec_configure - (Re-)configure the HD-audio codec
  * @codec: the HDA codec
@@ -1548,6 +1598,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
  */
 int snd_hda_codec_configure(struct hda_codec *codec)
 {
+       int (*patch)(struct hda_codec *) = NULL;
        int err;
 
        codec->preset = find_codec_preset(codec);
@@ -1557,31 +1608,50 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                        return err;
        }
 
-       if (is_generic_config(codec)) {
-               err = snd_hda_parse_generic_codec(codec);
-               goto patched;
-       }
-       if (codec->preset && codec->preset->patch) {
-               err = codec->preset->patch(codec);
-               goto patched;
+       if (!is_generic_config(codec) && codec->preset)
+               patch = codec->preset->patch;
+       if (!patch) {
+               unload_parser(codec); /* to be sure */
+               if (is_likely_hdmi_codec(codec)) {
+#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
+                       patch = load_parser(codec, snd_hda_parse_hdmi_codec);
+#elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI)
+                       patch = snd_hda_parse_hdmi_codec;
+#endif
+               }
+               if (!patch) {
+#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
+                       patch = load_parser(codec, snd_hda_parse_generic_codec);
+#elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC)
+                       patch = snd_hda_parse_generic_codec;
+#endif
+               }
+               if (!patch) {
+                       printk(KERN_ERR "hda-codec: No codec parser is available\n");
+                       return -ENODEV;
+               }
        }
 
-       /* call the default parser */
-       err = snd_hda_parse_generic_codec(codec);
-       if (err < 0)
-               printk(KERN_ERR "hda-codec: No codec parser is available\n");
+       err = patch(codec);
+       if (err < 0) {
+               unload_parser(codec);
+               return err;
+       }
 
- patched:
-       if (!err && codec->patch_ops.unsol_event)
+       if (codec->patch_ops.unsol_event) {
                err = init_unsol_queue(codec->bus);
+               if (err < 0)
+                       return err;
+       }
+
        /* audio codec should override the mixer name */
-       if (!err && (codec->afg || !*codec->bus->card->mixername))
+       if (codec->afg || !*codec->bus->card->mixername)
                snprintf(codec->bus->card->mixername,
                         sizeof(codec->bus->card->mixername),
                         "%s %s", codec->vendor_name, codec->chip_name);
-       return err;
+       return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
+EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
 
 /* update the stream-id if changed */
 static void update_pcm_stream_id(struct hda_codec *codec,
@@ -1668,7 +1738,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                }
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
+EXPORT_SYMBOL_GPL(snd_hda_codec_setup_stream);
 
 static void really_cleanup_stream(struct hda_codec *codec,
                                  struct hda_cvt_setup *q);
@@ -1703,7 +1773,7 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
                        p->active = 0;
        }
 }
-EXPORT_SYMBOL_HDA(__snd_hda_codec_cleanup_stream);
+EXPORT_SYMBOL_GPL(__snd_hda_codec_cleanup_stream);
 
 static void really_cleanup_stream(struct hda_codec *codec,
                                  struct hda_cvt_setup *q)
@@ -1891,7 +1961,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
                               HDA_HASH_KEY(nid, direction, 0),
                               read_amp_cap);
 }
-EXPORT_SYMBOL_HDA(query_amp_caps);
+EXPORT_SYMBOL_GPL(query_amp_caps);
 
 /**
  * snd_hda_override_amp_caps - Override the AMP capabilities
@@ -1911,7 +1981,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 {
        return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
 
 static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,
                                 int dir)
@@ -1935,7 +2005,7 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
        return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),
                               read_pin_cap);
 }
-EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_query_pin_caps);
 
 /**
  * snd_hda_override_pin_caps - Override the pin capabilities
@@ -1952,7 +2022,7 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
 {
        return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps);
 
 /* read or sync the hash value with the current value;
  * call within hash_mutex
@@ -2033,7 +2103,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
        mutex_unlock(&codec->hash_mutex);
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
 
 static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
                            int direction, int idx, int mask, int val,
@@ -2085,7 +2155,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
 {
        return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
 
 /**
  * snd_hda_codec_amp_stereo - update the AMP stereo values
@@ -2111,7 +2181,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
                                                idx, mask, val);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
 
 /* Works like snd_hda_codec_amp_update() but it writes the value only at
  * the first access.  If the amp was already initialized / updated beforehand,
@@ -2122,7 +2192,7 @@ int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
 {
        return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
 
 int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
                                  int dir, int idx, int mask, int val)
@@ -2136,7 +2206,7 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
                                              idx, mask, val);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
 
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
@@ -2179,7 +2249,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
        }
        mutex_unlock(&codec->hash_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp);
 
 static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
                             unsigned int ofs)
@@ -2219,7 +2289,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_info);
 
 
 static inline unsigned int
@@ -2276,7 +2346,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
                *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_get);
 
 /**
  * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
@@ -2306,7 +2376,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
        snd_hda_power_down(codec);
        return change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 
 /**
  * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
@@ -2344,7 +2414,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
 
 /**
  * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
@@ -2372,7 +2442,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
        tlv[2] = -nums * step;
        tlv[3] = step;
 }
-EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
 
 /* find a mixer control element with the given name */
 static struct snd_kcontrol *
@@ -2401,7 +2471,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
 {
        return find_mixer_ctl(codec, name, 0, 0);
 }
-EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_find_mixer_ctl);
 
 static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
                                    int start_idx)
@@ -2461,7 +2531,7 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
        item->flags = flags;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
+EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
 
 /**
  * snd_hda_add_nid - Assign a NID to a control element
@@ -2492,7 +2562,7 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
               kctl->id.name, kctl->id.index, index);
        return -EINVAL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_nid);
+EXPORT_SYMBOL_GPL(snd_hda_add_nid);
 
 /**
  * snd_hda_ctls_clear - Clear all controls assigned to the given codec
@@ -2543,7 +2613,7 @@ int snd_hda_lock_devices(struct hda_bus *bus)
        spin_unlock(&card->files_lock);
        return -EINVAL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_lock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_lock_devices);
 
 void snd_hda_unlock_devices(struct hda_bus *bus)
 {
@@ -2554,7 +2624,7 @@ void snd_hda_unlock_devices(struct hda_bus *bus)
        card->shutdown = 0;
        spin_unlock(&card->files_lock);
 }
-EXPORT_SYMBOL_HDA(snd_hda_unlock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
 
 /**
  * snd_hda_codec_reset - Clear all objects assigned to the codec
@@ -2610,6 +2680,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        codec->preset = NULL;
        codec->slave_dig_outs = NULL;
        codec->spdif_status_reset = 0;
+       unload_parser(codec);
        module_put(codec->owner);
        codec->owner = NULL;
 
@@ -2777,7 +2848,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
                *ctl_ret = kctl;
        return 0;
 }
-EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
 
 /*
  * mute-LED control using vmaster
@@ -2854,7 +2925,7 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
                return -ENOMEM;
        return snd_hda_ctl_add(codec, 0, kctl);
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
 
 /*
  * Call the hook with the current value for synchronization
@@ -2878,7 +2949,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
                break;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
 
 
 /**
@@ -2898,7 +2969,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 1;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_info);
 
 /**
  * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
@@ -2924,7 +2995,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
                         HDA_AMP_MUTE) ? 0 : 1;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get);
 
 /**
  * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
@@ -2958,7 +3029,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
        snd_hda_power_down(codec);
        return change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
 
 /*
  * bound volume controls
@@ -2990,7 +3061,7 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get);
 
 /**
  * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
@@ -3020,7 +3091,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put);
 
 /**
  * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
@@ -3043,7 +3114,7 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info);
 
 /**
  * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
@@ -3066,7 +3137,7 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get);
 
 /**
  * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
@@ -3095,7 +3166,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
 
 /**
  * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
@@ -3118,7 +3189,7 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv);
 
 struct hda_ctl_ops snd_hda_bind_vol = {
        .info = snd_hda_mixer_amp_volume_info,
@@ -3126,7 +3197,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
        .put = snd_hda_mixer_amp_volume_put,
        .tlv = snd_hda_mixer_amp_tlv
 };
-EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
+EXPORT_SYMBOL_GPL(snd_hda_bind_vol);
 
 struct hda_ctl_ops snd_hda_bind_sw = {
        .info = snd_hda_mixer_amp_switch_info,
@@ -3134,7 +3205,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
        .put = snd_hda_mixer_amp_switch_put,
        .tlv = snd_hda_mixer_amp_tlv
 };
-EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
+EXPORT_SYMBOL_GPL(snd_hda_bind_sw);
 
 /*
  * SPDIF out controls
@@ -3438,7 +3509,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
        spdif->status = convert_to_spdif_status(spdif->ctls);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
 
 /* get the hda_spdif_out entry from the given NID
  * call within spdif_mutex lock
@@ -3455,7 +3526,7 @@ struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
        }
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_out_of_nid);
 
 void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
 {
@@ -3466,7 +3537,7 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
        spdif->nid = (u16)-1;
        mutex_unlock(&codec->spdif_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign);
 
 void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
 {
@@ -3482,7 +3553,7 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
        }
        mutex_unlock(&codec->spdif_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign);
 
 /*
  * SPDIF sharing with analog output
@@ -3530,7 +3601,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
        /* ATTENTION: here mout is passed as private_data, instead of codec */
        return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw);
 
 /*
  * SPDIF input
@@ -3638,7 +3709,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
                AC_DIG1_ENABLE;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls);
 
 /*
  * command cache
@@ -3689,7 +3760,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
        mutex_unlock(&codec->bus->cmd_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write_cache);
 
 /**
  * snd_hda_codec_update_cache - check cache and write the cmd only when needed
@@ -3724,7 +3795,7 @@ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
        mutex_unlock(&codec->bus->cmd_mutex);
        return snd_hda_codec_write_cache(codec, nid, flags, verb, parm);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_cache);
 
 /**
  * snd_hda_codec_resume_cache - Resume the all commands from the cache
@@ -3756,7 +3827,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
        }
        mutex_unlock(&codec->hash_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_cache);
 
 /**
  * snd_hda_sequence_write_cache - sequence writes with caching
@@ -3774,7 +3845,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
                snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
                                          seq->param);
 }
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache);
 
 /**
  * snd_hda_codec_flush_cache - Execute all pending (cached) amps / verbs
@@ -3785,7 +3856,7 @@ void snd_hda_codec_flush_cache(struct hda_codec *codec)
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache);
 
 void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
                                    unsigned int power_state)
@@ -3807,7 +3878,7 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
                                    state);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
 
 /*
  *  supported power states check
@@ -3856,6 +3927,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
                                             hda_nid_t nid,
                                             unsigned int power_state)
 {
+       if (nid == codec->afg || nid == codec->mfg)
+               return power_state;
        if (power_state == AC_PWRST_D3 &&
            get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
            (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
@@ -3866,7 +3939,7 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
        }
        return power_state;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
+EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
 
 /*
  * set power state of the codec, and return the power state
@@ -3881,8 +3954,10 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
 
        /* this delay seems necessary to avoid click noise at power-down */
        if (power_state == AC_PWRST_D3) {
-               /* transition time less than 10ms for power down */
-               msleep(codec->epss ? 10 : 100);
+               if (codec->depop_delay < 0)
+                       msleep(codec->epss ? 10 : 100);
+               else if (codec->depop_delay > 0)
+                       msleep(codec->depop_delay);
                flags = HDA_RW_NO_RESPONSE_FALLBACK;
        }
 
@@ -3892,9 +3967,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
                        codec->patch_ops.set_power_state(codec, fg,
                                                         power_state);
                else {
-                       snd_hda_codec_read(codec, fg, flags,
-                                          AC_VERB_SET_POWER_STATE,
-                                          power_state);
+                       state = power_state;
+                       if (codec->power_filter)
+                               state = codec->power_filter(codec, fg, state);
+                       if (state == power_state || power_state != AC_PWRST_D3)
+                               snd_hda_codec_read(codec, fg, flags,
+                                                  AC_VERB_SET_POWER_STATE,
+                                                  state);
                        snd_hda_codec_set_power_to_all(codec, fg, power_state);
                }
                state = hda_sync_power_state(codec, fg, power_state);
@@ -4000,10 +4079,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
         * in the resume / power-save sequence
         */
        hda_keep_power_on(codec);
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(codec->bus, true);
-       }
        hda_set_power_state(codec, AC_PWRST_D0);
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
@@ -4055,7 +4130,7 @@ int snd_hda_build_controls(struct hda_bus *bus)
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_build_controls);
+EXPORT_SYMBOL_GPL(snd_hda_build_controls);
 
 /*
  * add standard channel maps if not specified
@@ -4228,7 +4303,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
+EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format);
 
 static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
                                  int dir)
@@ -4374,7 +4449,7 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm);
+EXPORT_SYMBOL_GPL(snd_hda_query_supported_pcm);
 
 /**
  * snd_hda_is_supported_format - Check the validity of the format
@@ -4441,7 +4516,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
 
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
+EXPORT_SYMBOL_GPL(snd_hda_is_supported_format);
 
 /*
  * PCM stuff
@@ -4519,7 +4594,7 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
        mutex_unlock(&codec->bus->prepare_mutex);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_codec_prepare);
 
 void snd_hda_codec_cleanup(struct hda_codec *codec,
                           struct hda_pcm_stream *hinfo,
@@ -4529,7 +4604,7 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
        hinfo->ops.cleanup(hinfo, codec, substream);
        mutex_unlock(&codec->bus->prepare_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
 
 /* global */
 const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
@@ -4687,7 +4762,7 @@ int snd_hda_build_pcms(struct hda_bus *bus)
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
+EXPORT_SYMBOL_GPL(snd_hda_build_pcms);
 
 /**
  * snd_hda_check_board_config - compare the current codec with the config table
@@ -4743,7 +4818,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_config);
 
 /**
  * snd_hda_check_board_codec_sid_config - compare the current codec
@@ -4804,7 +4879,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_codec_sid_config);
 
 /**
  * snd_hda_add_new_ctls - create controls from the array
@@ -4854,7 +4929,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
 
 #ifdef CONFIG_PM
 static void hda_power_work(struct work_struct *work)
@@ -4877,11 +4952,8 @@ static void hda_power_work(struct work_struct *work)
        spin_unlock(&codec->power_lock);
 
        state = hda_call_codec_suspend(codec, true);
-       if (!codec->pm_down_notified &&
-           !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
-               codec->pm_down_notified = 1;
-               hda_call_pm_notify(bus, false);
-       }
+       if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK))
+               hda_call_pm_notify(codec, false);
 }
 
 static void hda_keep_power_on(struct hda_codec *codec)
@@ -4891,6 +4963,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
        codec->power_on = 1;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       hda_call_pm_notify(codec, true);
 }
 
 /* update the power on/off account with the current jiffies */
@@ -4910,8 +4983,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
 /* call this with codec->power_lock held! */
 static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
 {
-       struct hda_bus *bus = codec->bus;
-
        /* Return if power_on or transitioning to power_on, unless currently
         * powering down. */
        if ((codec->power_on || codec->power_transition > 0) &&
@@ -4938,11 +5009,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
        codec->power_transition = 1; /* avoid reentrance */
        spin_unlock(&codec->power_lock);
 
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(bus, true);
-       }
-
        hda_call_codec_resume(codec);
 
        spin_lock(&codec->power_lock);
@@ -4985,7 +5051,7 @@ void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
                __snd_hda_power_down(codec);
        spin_unlock(&codec->power_lock);
 }
-EXPORT_SYMBOL_HDA(snd_hda_power_save);
+EXPORT_SYMBOL_GPL(snd_hda_power_save);
 
 /**
  * snd_hda_check_amp_list_power - Check the amp list and update the power
@@ -5035,7 +5101,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
+EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
 #endif
 
 /*
@@ -5059,7 +5125,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
                chmode[uinfo->value.enumerated.item].channels);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_info);
 
 /**
  * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
@@ -5080,7 +5146,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_get);
 
 /**
  * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
@@ -5104,7 +5170,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
                snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_put);
 
 /*
  * input MUX helper
@@ -5129,7 +5195,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
        strcpy(uinfo->value.enumerated.name, imux->items[index].label);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_info);
 
 /**
  * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
@@ -5154,7 +5220,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
        *cur_val = idx;
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_put);
 
 
 /*
@@ -5183,7 +5249,7 @@ int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
               texts[uinfo->value.enumerated.item]);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
+EXPORT_SYMBOL_GPL(snd_hda_enum_helper_info);
 
 /*
  * Multi-channel / digital-out PCM helper functions
@@ -5249,7 +5315,7 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
                        codec->patch_ops.reboot_notify(codec);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
+EXPORT_SYMBOL_GPL(snd_hda_bus_reboot_notify);
 
 /**
  * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
@@ -5265,7 +5331,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open);
 
 /**
  * snd_hda_multi_out_dig_prepare - prepare the digital out stream
@@ -5281,7 +5347,7 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare);
 
 /**
  * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
@@ -5294,7 +5360,7 @@ int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup);
 
 /**
  * snd_hda_multi_out_dig_close - release the digital out stream
@@ -5307,7 +5373,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close);
 
 /**
  * snd_hda_multi_out_analog_open - open analog outputs
@@ -5357,7 +5423,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
        return snd_pcm_hw_constraint_step(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_open);
 
 /**
  * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
@@ -5434,7 +5500,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_prepare);
 
 /**
  * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
@@ -5465,7 +5531,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup);
 
 /**
  * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
@@ -5492,7 +5558,7 @@ unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
                return AC_PINCTL_VREF_GRD;
        return AC_PINCTL_VREF_HIZ;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
+EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
 
 /* correct the pin ctl value for matching with the pin cap */
 unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
@@ -5543,7 +5609,7 @@ unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
 
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_correct_pin_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl);
 
 int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int val, bool cached)
@@ -5557,7 +5623,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                return snd_hda_codec_write(codec, pin, 0,
                                           AC_VERB_SET_PIN_WIDGET_CONTROL, val);
 }
-EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
+EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
 
 /**
  * snd_hda_add_imux_item - Add an item to input_mux
@@ -5591,7 +5657,7 @@ int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
        imux->num_items++;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
+EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
 
 
 #ifdef CONFIG_PM
@@ -5599,6 +5665,17 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
  * power management
  */
 
+
+static void hda_async_suspend(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_suspend(data, false);
+}
+
+static void hda_async_resume(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_resume(data);
+}
+
 /**
  * snd_hda_suspend - suspend the codecs
  * @bus: the HDA bus
@@ -5608,15 +5685,25 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
 int snd_hda_suspend(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
                cancel_delayed_work_sync(&codec->jackpoll_work);
-               if (hda_codec_is_power_on(codec))
-                       hda_call_codec_suspend(codec, false);
+               if (hda_codec_is_power_on(codec)) {
+                       if (bus->num_codecs > 1)
+                               async_schedule_domain(hda_async_suspend, codec,
+                                                     &domain);
+                       else
+                               hda_call_codec_suspend(codec, false);
+               }
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_suspend);
+EXPORT_SYMBOL_GPL(snd_hda_suspend);
 
 /**
  * snd_hda_resume - resume the codecs
@@ -5627,13 +5714,21 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend);
 int snd_hda_resume(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
-               hda_call_codec_resume(codec);
+               if (bus->num_codecs > 1)
+                       async_schedule_domain(hda_async_resume, codec, &domain);
+               else
+                       hda_call_codec_resume(codec);
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_resume);
+EXPORT_SYMBOL_GPL(snd_hda_resume);
 #endif /* CONFIG_PM */
 
 /*
@@ -5667,7 +5762,7 @@ void *snd_array_new(struct snd_array *array)
        }
        return snd_array_elem(array, array->used++);
 }
-EXPORT_SYMBOL_HDA(snd_array_new);
+EXPORT_SYMBOL_GPL(snd_array_new);
 
 /**
  * snd_array_free - free the given array elements
@@ -5680,7 +5775,7 @@ void snd_array_free(struct snd_array *array)
        array->alloced = 0;
        array->list = NULL;
 }
-EXPORT_SYMBOL_HDA(snd_array_free);
+EXPORT_SYMBOL_GPL(snd_array_free);
 
 /**
  * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
@@ -5701,7 +5796,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 
        buf[j] = '\0'; /* necessary when j == 0 */
 }
-EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
+EXPORT_SYMBOL_GPL(snd_print_pcm_bits);
 
 MODULE_DESCRIPTION("HDA codec core");
 MODULE_LICENSE("GPL");