]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blobdiff - sound/pci/hda/patch_hdmi.c
ALSA: hda: hdmi - add Tigerlake support
[mirror_ubuntu-eoan-kernel.git] / sound / pci / hda / patch_hdmi.c
index bea7b09610809f439fcf1e49b24ab6b0a10b3102..ff99f5feaace97bb11beeba3accc3f01d598700e 100644 (file)
@@ -1421,7 +1421,7 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec,
 /* update per_pin ELD from the given new ELD;
  * setup info frame and notification accordingly
  */
-static void update_eld(struct hda_codec *codec,
+static bool update_eld(struct hda_codec *codec,
                       struct hdmi_spec_per_pin *per_pin,
                       struct hdmi_eld *eld)
 {
@@ -1452,18 +1452,22 @@ static void update_eld(struct hda_codec *codec,
                snd_hdmi_show_eld(codec, &eld->info);
 
        eld_changed = (pin_eld->eld_valid != eld->eld_valid);
-       if (eld->eld_valid && pin_eld->eld_valid)
+       eld_changed |= (pin_eld->monitor_present != eld->monitor_present);
+       if (!eld_changed && eld->eld_valid && pin_eld->eld_valid)
                if (pin_eld->eld_size != eld->eld_size ||
                    memcmp(pin_eld->eld_buffer, eld->eld_buffer,
                           eld->eld_size) != 0)
                        eld_changed = true;
 
-       pin_eld->monitor_present = eld->monitor_present;
-       pin_eld->eld_valid = eld->eld_valid;
-       pin_eld->eld_size = eld->eld_size;
-       if (eld->eld_valid)
-               memcpy(pin_eld->eld_buffer, eld->eld_buffer, eld->eld_size);
-       pin_eld->info = eld->info;
+       if (eld_changed) {
+               pin_eld->monitor_present = eld->monitor_present;
+               pin_eld->eld_valid = eld->eld_valid;
+               pin_eld->eld_size = eld->eld_size;
+               if (eld->eld_valid)
+                       memcpy(pin_eld->eld_buffer, eld->eld_buffer,
+                              eld->eld_size);
+               pin_eld->info = eld->info;
+       }
 
        /*
         * Re-setup pin and infoframe. This is needed e.g. when
@@ -1481,6 +1485,7 @@ static void update_eld(struct hda_codec *codec,
                               SNDRV_CTL_EVENT_MASK_VALUE |
                               SNDRV_CTL_EVENT_MASK_INFO,
                               &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
+       return eld_changed;
 }
 
 /* update ELD and jack state via HD-audio verbs */
@@ -1582,6 +1587,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
        struct hdmi_spec *spec = codec->spec;
        struct hdmi_eld *eld = &spec->temp_eld;
        struct snd_jack *jack = NULL;
+       bool changed;
        int size;
 
        mutex_lock(&per_pin->lock);
@@ -1608,15 +1614,13 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
         * disconnected event. Jack must be fetched before update_eld()
         */
        jack = pin_idx_to_jack(codec, per_pin);
-       update_eld(codec, per_pin, eld);
+       changed = update_eld(codec, per_pin, eld);
        if (jack == NULL)
                jack = pin_idx_to_jack(codec, per_pin);
-       if (jack == NULL)
-               goto unlock;
-       snd_jack_report(jack,
-                       (eld->monitor_present && eld->eld_valid) ?
+       if (changed && jack)
+               snd_jack_report(jack,
+                               (eld->monitor_present && eld->eld_valid) ?
                                SND_JACK_AVOUT : 0);
- unlock:
        mutex_unlock(&per_pin->lock);
 }
 
@@ -2612,6 +2616,8 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec,
 /* precondition and allocation for Intel codecs */
 static int alloc_intel_hdmi(struct hda_codec *codec)
 {
+       int err;
+
        /* requires i915 binding */
        if (!codec->bus->core.audio_component) {
                codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
@@ -2620,7 +2626,12 @@ static int alloc_intel_hdmi(struct hda_codec *codec)
                return -ENODEV;
        }
 
-       return alloc_generic_hdmi(codec);
+       err = alloc_generic_hdmi(codec);
+       if (err < 0)
+               return err;
+       /* no need to handle unsol events */
+       codec->patch_ops.unsol_event = NULL;
+       return 0;
 }
 
 /* parse and post-process for Intel codecs */
@@ -2692,6 +2703,18 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
        return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
 }
 
+static int patch_i915_tgl_hdmi(struct hda_codec *codec)
+{
+       /*
+        * pin to port mapping table where the value indicate the pin number and
+        * the index indicate the port number with 1 base.
+        */
+       static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+
+       return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
+}
+
+
 /* Intel Baytrail and Braswell; with eld notifier */
 static int patch_i915_byt_hdmi(struct hda_codec *codec)
 {
@@ -3296,6 +3319,8 @@ static int patch_nvhdmi(struct hda_codec *codec)
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
 
+       codec->link_down_at_suspend = 1;
+
        return 0;
 }
 
@@ -3947,6 +3972,7 @@ HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI",      patch_i915_hsw_hdmi),
 HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",    patch_i915_icl_hdmi),
+HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",        patch_i915_byt_hdmi),
 HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",   patch_i915_byt_hdmi),