ALSA: hda - Add DP-MST support for NVIDIA codecs
authorNikhil Mahale <nmahale@nvidia.com>
Tue, 19 Nov 2019 08:47:10 +0000 (14:17 +0530)
committerTakashi Iwai <tiwai@suse.de>
Tue, 19 Nov 2019 10:51:12 +0000 (11:51 +0100)
This patch adds DP-MST support for GK104+ NVIDIA codecs.

GK104+ NVIDIA codecs support DP-MST audio. These codecs have 4
output converters and 4 pin widgets, with 4 device entries per pin
widget for a total of 16 device entries.

This patch moves the existing patch_nvhdmi() definition to
patch_nvhdmi_legacy(), used by pre-GK104 NVIDIA codecs. Redefine
patch_nvhdmi() to enable DP-MST support by setting codec->dp_mst and
spec->dyn_pcm_assign.

Introduce fresh logic for dynamic pcm assignment, making
sure that new pcm assignments are compatible with the legacy static
per_pin-pmc assignment that existed in the days before DP-MST.

Signed-off-by: Nikhil Mahale <nmahale@nvidia.com>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com>
Link: https://lore.kernel.org/r/20191119084710.29267-5-nmahale@nvidia.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_hdmi.c

index 0a3045d492975fe0643fa8b0c8fa29d9467df30f..55d20e40a195695f672c9955d4467aeb4d929b38 100644 (file)
@@ -1321,15 +1321,32 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
 }
 
 static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
-                               struct hdmi_spec_per_pin *per_pin)
+                             struct hdmi_spec_per_pin *per_pin)
 {
        int i;
 
-       /* try the prefer PCM */
-       if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
+       /*
+        * generic_hdmi_build_pcms() allocates (num_nids + dev_num - 1)
+        * number of pcms.
+        *
+        * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n
+        * if m==0. This guarantees that dynamic pcm assignments are compatible
+        * with the legacy static per_pin-pmc assignment that existed in the
+        * days before DP-MST.
+        *
+        * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)).
+        */
+       if (per_pin->dev_id == 0 &&
+           !test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
                return per_pin->pin_nid_idx;
 
-       /* have a second try; check the "reserved area" over num_pins */
+       if (per_pin->dev_id != 0 &&
+           !(test_bit(spec->num_nids + (per_pin->dev_id - 1),
+               &spec->pcm_bitmap))) {
+               return spec->num_nids + (per_pin->dev_id - 1);
+       }
+
+       /* have a second try; check the area over num_nids */
        for (i = spec->num_nids; i < spec->pcm_used; i++) {
                if (!test_bit(i, &spec->pcm_bitmap))
                        return i;
@@ -3510,6 +3527,40 @@ static int patch_nvhdmi(struct hda_codec *codec)
        struct hdmi_spec *spec;
        int err;
 
+       err = alloc_generic_hdmi(codec);
+       if (err < 0)
+               return err;
+       codec->dp_mst = true;
+
+       spec = codec->spec;
+       spec->dyn_pcm_assign = true;
+
+       err = hdmi_parse_codec(codec);
+       if (err < 0) {
+               generic_spec_free(codec);
+               return err;
+       }
+
+       generic_hdmi_init_per_pins(codec);
+
+       spec->dyn_pin_out = true;
+
+       spec->chmap.ops.chmap_cea_alloc_validate_get_type =
+               nvhdmi_chmap_cea_alloc_validate_get_type;
+       spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+
+       codec->link_down_at_suspend = 1;
+
+       generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin);
+
+       return 0;
+}
+
+static int patch_nvhdmi_legacy(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+       int err;
+
        err = patch_generic_hdmi(codec);
        if (err)
                return err;
@@ -4118,25 +4169,25 @@ HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI",      patch_nvhdmi_8ch_7x),
 HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI",   patch_nvhdmi_8ch_7x),
 HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI",   patch_nvhdmi_8ch_7x),
 HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI",   patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI",      patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI",      patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP",  patch_nvhdmi_legacy),
 /* 17 is known to be absent */
-HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP",  patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP",  patch_nvhdmi_legacy),
+HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP",  patch_nvhdmi_legacy),
 HDA_CODEC_ENTRY(0x10de0020, "Tegra30 HDMI",    patch_tegra_hdmi),
 HDA_CODEC_ENTRY(0x10de0022, "Tegra114 HDMI",   patch_tegra_hdmi),
 HDA_CODEC_ENTRY(0x10de0028, "Tegra124 HDMI",   patch_tegra_hdmi),