[ALSA] hda-intel - Improve HD-audio codec probing robustness
[firefly-linux-kernel-4.4.55.git] / sound / pci / hda / hda_codec.c
index b1eee9a044fee52ab0a9ebdaa62d473c839254de..535bcb7601b5bc3dd580ad7ca1ff4a422f10bf06 100644 (file)
@@ -155,6 +155,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
        unsigned int parm;
 
        parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
+       if (parm == -1)
+               return 0;
        *start_id = (parm >> 16) & 0x7fff;
        return (int)(parm & 0x7fff);
 }
@@ -514,7 +516,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
 
 static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
-static inline void free_hda_cache(struct hda_cache_rec *cache);
+static void free_hda_cache(struct hda_cache_rec *cache);
 
 /*
  * codec destructor
@@ -707,7 +709,7 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache,
        cache->record_size = record_size;
 }
 
-static inline void free_hda_cache(struct hda_cache_rec *cache)
+static void free_hda_cache(struct hda_cache_rec *cache)
 {
        kfree(cache->buffer);
 }
@@ -2195,8 +2197,10 @@ static void hda_power_work(struct work_struct *work)
        struct hda_codec *codec =
                container_of(work, struct hda_codec, power_work.work);
 
-       if (!codec->power_on || codec->power_count)
+       if (!codec->power_on || codec->power_count) {
+               codec->power_transition = 0;
                return;
+       }
 
        hda_call_codec_suspend(codec);
        if (codec->bus->ops.pm_notify)
@@ -2785,7 +2789,6 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
        return 0;
 }
 
-#ifndef CONFIG_SND_HDA_POWER_SAVE
 /**
  * snd_hda_resume - resume the codecs
  * @bus: the HDA bus
@@ -2801,10 +2804,21 @@ int snd_hda_resume(struct hda_bus *bus)
        struct hda_codec *codec;
 
        list_for_each_entry(codec, &bus->codec_list, list) {
-               hda_call_codec_resume(codec);
+               if (snd_hda_codec_needs_resume(codec))
+                       hda_call_codec_resume(codec);
        }
        return 0;
 }
-#endif /* !CONFIG_SND_HDA_POWER_SAVE */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+int snd_hda_codecs_inuse(struct hda_bus *bus)
+{
+       struct hda_codec *codec;
 
+       list_for_each_entry(codec, &bus->codec_list, list) {
+               if (snd_hda_codec_needs_resume(codec))
+                       return 1;
+       }
+       return 0;
+}
+#endif
 #endif