ALSA: hda/tegra: Add Tegra234 hda driver support
authorMohan Kumar <mkumard@nvidia.com>
Wed, 16 Feb 2022 09:22:35 +0000 (14:52 +0530)
committerTakashi Iwai <tiwai@suse.de>
Mon, 21 Feb 2022 10:03:34 +0000 (11:03 +0100)
Add hda driver support for the Tegra234 chip. The hdacodec
on this chip now supports DP MST feature, HDA block contains
azalia controller and one hda-codec instance by supporting
4 independent output streams over DP MST mode. There is no
input stream support.

Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Link: https://lore.kernel.org/r/20220216092240.26464-2-mkumard@nvidia.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_hdmi.c

index 773f490..95df52b 100644 (file)
@@ -70,6 +70,7 @@
 
 struct hda_tegra_soc {
        bool has_hda2codec_2x_reset;
+       bool has_hda2hdmi;
 };
 
 struct hda_tegra {
@@ -435,15 +436,23 @@ static int hda_tegra_create(struct snd_card *card,
 
 static const struct hda_tegra_soc tegra30_data = {
        .has_hda2codec_2x_reset = true,
+       .has_hda2hdmi = true,
 };
 
 static const struct hda_tegra_soc tegra194_data = {
        .has_hda2codec_2x_reset = false,
+       .has_hda2hdmi = true,
+};
+
+static const struct hda_tegra_soc tegra234_data = {
+       .has_hda2codec_2x_reset = true,
+       .has_hda2hdmi = false,
 };
 
 static const struct of_device_id hda_tegra_match[] = {
        { .compatible = "nvidia,tegra30-hda", .data = &tegra30_data },
        { .compatible = "nvidia,tegra194-hda", .data = &tegra194_data },
+       { .compatible = "nvidia,tegra234-hda", .data = &tegra234_data },
        {},
 };
 MODULE_DEVICE_TABLE(of, hda_tegra_match);
@@ -473,7 +482,14 @@ static int hda_tegra_probe(struct platform_device *pdev)
        }
 
        hda->resets[hda->nresets++].id = "hda";
-       hda->resets[hda->nresets++].id = "hda2hdmi";
+
+       /*
+        * "hda2hdmi" is not applicable for Tegra234. This is because the
+        * codec is separate IP and not under display SOR partition now.
+        */
+       if (hda->soc->has_hda2hdmi)
+               hda->resets[hda->nresets++].id = "hda2hdmi";
+
        /*
         * "hda2codec_2x" reset is not present on Tegra194. Though DT would
         * be updated to reflect this, but to have backward compatibility
@@ -488,7 +504,8 @@ static int hda_tegra_probe(struct platform_device *pdev)
                goto out_free;
 
        hda->clocks[hda->nclocks++].id = "hda";
-       hda->clocks[hda->nclocks++].id = "hda2hdmi";
+       if (hda->soc->has_hda2hdmi)
+               hda->clocks[hda->nclocks++].id = "hda2hdmi";
        hda->clocks[hda->nclocks++].id = "hda2codec_2x";
 
        err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks);
index 69a912c..a134d91 100644 (file)
@@ -3927,17 +3927,29 @@ static int tegra_hdmi_build_pcms(struct hda_codec *codec)
        return 0;
 }
 
-static int patch_tegra_hdmi(struct hda_codec *codec)
+static int tegra_hdmi_init(struct hda_codec *codec)
 {
-       struct hdmi_spec *spec;
-       int err;
+       struct hdmi_spec *spec = codec->spec;
+       int i, err;
 
-       err = patch_generic_hdmi(codec);
-       if (err)
+       err = hdmi_parse_codec(codec);
+       if (err < 0) {
+               generic_spec_free(codec);
                return err;
+       }
+
+       for (i = 0; i < spec->num_cvts; i++)
+               snd_hda_codec_write(codec, spec->cvt_nids[i], 0,
+                                       AC_VERB_SET_DIGI_CONVERT_1,
+                                       AC_DIG1_ENABLE);
+
+       generic_hdmi_init_per_pins(codec);
 
        codec->patch_ops.build_pcms = tegra_hdmi_build_pcms;
-       spec = codec->spec;
+       spec->chmap.ops.chmap_cea_alloc_validate_get_type =
+               nvhdmi_chmap_cea_alloc_validate_get_type;
+       spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+
        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
@@ -3945,6 +3957,35 @@ static int patch_tegra_hdmi(struct hda_codec *codec)
        return 0;
 }
 
+static int patch_tegra_hdmi(struct hda_codec *codec)
+{
+       int err;
+
+       err = alloc_generic_hdmi(codec);
+       if (err < 0)
+               return err;
+
+       return tegra_hdmi_init(codec);
+}
+
+static int patch_tegra234_hdmi(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+       int err;
+
+       err = alloc_generic_hdmi(codec);
+       if (err < 0)
+               return err;
+
+       codec->dp_mst = true;
+       codec->mst_no_extra_pcms = true;
+       spec = codec->spec;
+       spec->dyn_pin_out = true;
+       spec->dyn_pcm_assign = true;
+
+       return tegra_hdmi_init(codec);
+}
+
 /*
  * ATI/AMD-specific implementations
  */
@@ -4398,6 +4439,7 @@ HDA_CODEC_ENTRY(0x10de002d, "Tegra186 HDMI/DP0", patch_tegra_hdmi),
 HDA_CODEC_ENTRY(0x10de002e, "Tegra186 HDMI/DP1", patch_tegra_hdmi),
 HDA_CODEC_ENTRY(0x10de002f, "Tegra194 HDMI/DP2", patch_tegra_hdmi),
 HDA_CODEC_ENTRY(0x10de0030, "Tegra194 HDMI/DP3", patch_tegra_hdmi),
+HDA_CODEC_ENTRY(0x10de0031, "Tegra234 HDMI/DP", patch_tegra234_hdmi),
 HDA_CODEC_ENTRY(0x10de0040, "GPU 40 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP",  patch_nvhdmi),