clear-pkgs-linux-iot-lts2018/0348-ASoC-Intel-board-Add-s...

204 lines
5.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Guneshwor Singh <guneshwor.o.singh@intel.com>
Date: Sun, 18 Jun 2017 09:52:40 +0530
Subject: [PATCH] ASoC: Intel: board: Add support for HDMI in cnl_rt274
To enable HDMI/iDisp, corresponding BE DAI links are defined in the
machine driver. FE links will come topology with an assumption that the
dai link name will consist the string "HDMI". This assumption is made to
distinguish other dai links from hdmi dai links.
Special handling is needed for hdmi dai links because hdmi jack is
mapped for each hdmi BE dai link with the corresponding pcm device. And
since FE links come from topology, they can come in any order. Hence the
need to keep a track of pcm_count.
Change-Id: I6fbdfbdb61d5fa58691cfe84abbd859209ccfce5
Signed-off-by: Guneshwor Singh <guneshwor.o.singh@intel.com>
---
sound/soc/intel/boards/cnl_rt274.c | 129 ++++++++++++++++++++++++++++-
1 file changed, 126 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/boards/cnl_rt274.c b/sound/soc/intel/boards/cnl_rt274.c
index ebfe74132da5..e9e5959e256a 100644
--- a/sound/soc/intel/boards/cnl_rt274.c
+++ b/sound/soc/intel/boards/cnl_rt274.c
@@ -33,11 +33,27 @@
#include <sound/jack.h>
#include <linux/input.h>
+#include "../../codecs/hdac_hdmi.h"
#include "../../codecs/rt274.h"
#define CNL_FREQ_OUT 19200000
#define CNL_BE_FIXUP_RATE 48000
#define RT274_CODEC_DAI "rt274-aif1"
+#define CNL_NAME_SIZE 32
+#define CNL_MAX_HDMI 3
+
+static struct snd_soc_jack cnl_hdmi[CNL_MAX_HDMI];
+
+struct cnl_hdmi_pcm {
+ struct list_head head;
+ struct snd_soc_dai *codec_dai;
+ int device;
+};
+
+struct cnl_rt274_private {
+ struct list_head hdmi_pcm_list;
+ int pcm_count;
+};
static struct snd_soc_dai *cnl_get_codec_dai(struct snd_soc_card *card,
const char *dai_name)
@@ -158,6 +174,13 @@ static const struct snd_soc_dapm_route cnl_map[] = {
{"Headphone Jack", NULL, "Platform Clock"},
{"MIC", NULL, "Platform Clock"},
+
+ {"hifi1", NULL, "iDisp1 Tx"},
+ {"iDisp1 Tx", NULL, "iDisp1_out"},
+ {"hifi2", NULL, "iDisp2 Tx"},
+ {"iDisp2 Tx", NULL, "iDisp2_out"},
+ {"hifi3", NULL, "iDisp3 Tx"},
+ {"iDisp3 Tx", NULL, "iDisp3_out"},
};
static int cnl_rt274_init(struct snd_soc_pcm_runtime *runtime)
@@ -307,6 +330,36 @@ static struct snd_soc_dai_link cnl_rt274_msic_dailink[] = {
.dpcm_capture = 1,
.be_hw_params_fixup = cnl_dmic_fixup,
},
+ {
+ .name = "iDisp1",
+ .id = 3,
+ .cpu_dai_name = "iDisp1 Pin",
+ .codec_name = "ehdaudio0D2",
+ .codec_dai_name = "intel-hdmi-hifi1",
+ .platform_name = pname,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ },
+ {
+ .name = "iDisp2",
+ .id = 4,
+ .cpu_dai_name = "iDisp2 Pin",
+ .codec_name = "ehdaudio0D2",
+ .codec_dai_name = "intel-hdmi-hifi2",
+ .platform_name = pname,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ },
+ {
+ .name = "iDisp3",
+ .id = 5,
+ .cpu_dai_name = "iDisp3 Pin",
+ .codec_name = "ehdaudio0D2",
+ .codec_dai_name = "intel-hdmi-hifi3",
+ .platform_name = pname,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ },
/* codec-codec link */
{
.name = "CNL SSP0-Loop Port",
@@ -326,10 +379,67 @@ static struct snd_soc_dai_link cnl_rt274_msic_dailink[] = {
static int
cnl_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
{
- link->platform_name = pname;
- link->nonatomic = 1;
+ struct cnl_rt274_private *ctx = snd_soc_card_get_drvdata(card);
+ char hdmi_dai_name[CNL_NAME_SIZE];
+ struct cnl_hdmi_pcm *pcm;
+
+ link->platform_name = pname;
+ link->nonatomic = 1;
+
+ /* Assuming HDMI dai link will consist the string "HDMI" */
+ if (strstr(link->name, "HDMI")) {
+ static int i = 1; /* hdmi codec dai name starts from index 1 */
+
+ pcm = devm_kzalloc(card->dev, sizeof(*pcm), GFP_KERNEL);
+ if (!pcm)
+ return -ENOMEM;
- return 0;
+ snprintf(hdmi_dai_name, sizeof(hdmi_dai_name), "intel-hdmi-hifi%d", i++);
+ pcm->codec_dai = cnl_get_codec_dai(card, hdmi_dai_name);
+ if (!pcm->codec_dai)
+ return -EINVAL;
+
+ pcm->device = ctx->pcm_count;
+ list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+ }
+ ctx->pcm_count++;
+
+ return 0;
+}
+
+static int cnl_card_late_probe(struct snd_soc_card *card)
+{
+ struct cnl_rt274_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component = NULL;
+ char jack_name[CNL_NAME_SIZE];
+ struct cnl_hdmi_pcm *pcm;
+ int err, i = 0;
+
+ if (list_empty(&ctx->hdmi_pcm_list))
+ return 0;
+
+ list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
+ component = pcm->codec_dai->component;
+ snprintf(jack_name, sizeof(jack_name),
+ "HDMI/DP, pcm=%d Jack", pcm->device);
+ err = snd_soc_card_jack_new(card, jack_name,
+ SND_JACK_AVOUT, &cnl_hdmi[i],
+ NULL, 0);
+ if (err)
+ return err;
+
+ err = hdac_hdmi_jack_init(pcm->codec_dai,
+ pcm->device, &cnl_hdmi[i]);
+ if (err < 0)
+ return err;
+
+ i++;
+ }
+
+ if (!component)
+ return -EINVAL;
+
+ return hdac_hdmi_jack_port_init(component, &card->dapm);
}
/* SoC card */
@@ -344,11 +454,24 @@ static struct snd_soc_card snd_soc_card_cnl = {
.controls = cnl_controls,
.num_controls = ARRAY_SIZE(cnl_controls),
.add_dai_link = cnl_add_dai_link,
+ .fully_routed = true,
+ .late_probe = cnl_card_late_probe,
};
static int snd_cnl_rt274_mc_probe(struct platform_device *pdev)
{
+ struct cnl_rt274_private *ctx;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->pcm_count = ARRAY_SIZE(cnl_rt274_msic_dailink);
+ INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
+
snd_soc_card_cnl.dev = &pdev->dev;
+ snd_soc_card_set_drvdata(&snd_soc_card_cnl, ctx);
+
return devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cnl);
}
--
https://clearlinux.org