[PATCH v2 1/6] ALSA: hda/tegra: Add Tegra234 hda driver support

From: Mohan Kumar
Date: Thu Feb 10 2022 - 01:51:21 EST


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@xxxxxxxxxx>
---
sound/pci/hda/hda_tegra.c | 21 +++++++++++++--
sound/pci/hda/patch_hdmi.c | 54 +++++++++++++++++++++++++++++++++-----
2 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 773f4903550a..95df52b0505b 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -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);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 92df4f243ec6..879f886d2406 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3851,17 +3851,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;
@@ -3869,6 +3881,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
*/
@@ -4322,6 +4363,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),
--
2.17.1