diff mbox series

[1/7] ASoC: Intel: board_helpers: support HDA link initialization

Message ID 20240912120308.134762-2-yung-chuan.liao@linux.intel.com (mailing list archive)
State Accepted
Commit bd07676ddade417c7cfefb58fb87c27751395bb3
Headers show
Series ASoC: Intel: boards: updates for 6.12 - part 2 | expand

Commit Message

Bard Liao Sept. 12, 2024, 12:03 p.m. UTC
From: Brent Lu <brent.lu@intel.com>

Add a helper function for machine drivers to initialize HDA external
codec DAI link.

Signed-off-by: Brent Lu <brent.lu@intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/intel/boards/sof_board_helpers.c | 152 +++++++++++++++++++++
 sound/soc/intel/boards/sof_board_helpers.h |   3 +
 2 files changed, 155 insertions(+)
diff mbox series

Patch

diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index 7519c545cbe2..24f716e42d6a 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -70,6 +70,64 @@  static int dmic_init(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+/*
+ * HDA External Codec DAI Link
+ */
+static const struct snd_soc_dapm_widget hda_widgets[] = {
+	SND_SOC_DAPM_MIC("Analog In", NULL),
+	SND_SOC_DAPM_MIC("Digital In", NULL),
+	SND_SOC_DAPM_MIC("Alt Analog In", NULL),
+
+	SND_SOC_DAPM_HP("Analog Out", NULL),
+	SND_SOC_DAPM_SPK("Digital Out", NULL),
+	SND_SOC_DAPM_HP("Alt Analog Out", NULL),
+};
+
+static const struct snd_soc_dapm_route hda_routes[] = {
+	{ "Codec Input Pin1", NULL, "Analog In" },
+	{ "Codec Input Pin2", NULL, "Digital In" },
+	{ "Codec Input Pin3", NULL, "Alt Analog In" },
+
+	{ "Analog Out", NULL, "Codec Output Pin1" },
+	{ "Digital Out", NULL, "Codec Output Pin2" },
+	{ "Alt Analog Out", NULL, "Codec Output Pin3" },
+
+	/* CODEC BE connections */
+	{ "codec0_in", NULL, "Analog CPU Capture" },
+	{ "Analog CPU Capture", NULL, "Analog Codec Capture" },
+	{ "codec1_in", NULL, "Digital CPU Capture" },
+	{ "Digital CPU Capture", NULL, "Digital Codec Capture" },
+	{ "codec2_in", NULL, "Alt Analog CPU Capture" },
+	{ "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" },
+
+	{ "Analog Codec Playback", NULL, "Analog CPU Playback" },
+	{ "Analog CPU Playback", NULL, "codec0_out" },
+	{ "Digital Codec Playback", NULL, "Digital CPU Playback" },
+	{ "Digital CPU Playback", NULL, "codec1_out" },
+	{ "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" },
+	{ "Alt Analog CPU Playback", NULL, "codec2_out" },
+};
+
+static int hda_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(&card->dapm, hda_widgets,
+					ARRAY_SIZE(hda_widgets));
+	if (ret) {
+		dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(&card->dapm, hda_routes,
+				      ARRAY_SIZE(hda_routes));
+	if (ret)
+		dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret);
+
+	return ret;
+}
+
 /*
  * DAI Link Helpers
  */
@@ -79,6 +137,11 @@  enum sof_dmic_be_type {
 	SOF_DMIC_16K,
 };
 
+enum sof_hda_be_type {
+	SOF_HDA_ANALOG,
+	SOF_HDA_DIGITAL,
+};
+
 /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
 #define DEFAULT_LINK_ORDER	SOF_LINK_ORDER(SOF_LINK_CODEC, \
 					SOF_LINK_DMIC01,       \
@@ -95,6 +158,16 @@  static struct snd_soc_dai_link_component dmic_component[] = {
 	}
 };
 
+SND_SOC_DAILINK_DEF(hda_analog_cpus,
+		    DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI")));
+SND_SOC_DAILINK_DEF(hda_analog_codecs,
+		    DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI")));
+
+SND_SOC_DAILINK_DEF(hda_digital_cpus,
+		    DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI")));
+SND_SOC_DAILINK_DEF(hda_digital_codecs,
+		    DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI")));
+
 static struct snd_soc_dai_link_component platform_component[] = {
 	{
 		/* name might be overridden during probe */
@@ -380,6 +453,55 @@  static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
 	return 0;
 }
 
+static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link,
+			      int be_id, enum sof_hda_be_type be_type)
+{
+	switch (be_type) {
+	case SOF_HDA_ANALOG:
+		dev_dbg(dev, "link %d: hda analog\n", be_id);
+
+		link->name = "Analog Playback and Capture";
+
+		/* cpus */
+		link->cpus = hda_analog_cpus;
+		link->num_cpus = ARRAY_SIZE(hda_analog_cpus);
+
+		/* codecs */
+		link->codecs = hda_analog_codecs;
+		link->num_codecs = ARRAY_SIZE(hda_analog_codecs);
+		break;
+	case SOF_HDA_DIGITAL:
+		dev_dbg(dev, "link %d: hda digital\n", be_id);
+
+		link->name = "Digital Playback and Capture";
+
+		/* cpus */
+		link->cpus = hda_digital_cpus;
+		link->num_cpus = ARRAY_SIZE(hda_digital_cpus);
+
+		/* codecs */
+		link->codecs = hda_digital_codecs;
+		link->num_codecs = ARRAY_SIZE(hda_digital_codecs);
+		break;
+	default:
+		dev_err(dev, "invalid be type %d\n", be_type);
+		return -EINVAL;
+	}
+
+	/* platforms */
+	link->platforms = platform_component;
+	link->num_platforms = ARRAY_SIZE(platform_component);
+
+	link->id = be_id;
+	if (be_type == SOF_HDA_ANALOG)
+		link->init = hda_init;
+	link->no_pcm = 1;
+	link->dpcm_capture = 1;
+	link->dpcm_playback = 1;
+
+	return 0;
+}
+
 static int calculate_num_links(struct sof_card_private *ctx)
 {
 	int num_links = 0;
@@ -409,6 +531,10 @@  static int calculate_num_links(struct sof_card_private *ctx)
 	/* HDMI-In */
 	num_links += hweight32(ctx->ssp_mask_hdmi_in);
 
+	/* HDA external codec */
+	if (ctx->hda_codec_present)
+		num_links += 2;
+
 	return num_links;
 }
 
@@ -566,6 +692,32 @@  int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
 				be_id++;
 			}
 			break;
+		case SOF_LINK_HDA:
+			/* HDA external codec */
+			if (!ctx->hda_codec_present)
+				continue;
+
+			ret = set_hda_codec_link(dev, &links[idx], be_id,
+						 SOF_HDA_ANALOG);
+			if (ret) {
+				dev_err(dev, "fail to set hda analog link, ret %d\n",
+					ret);
+				return ret;
+			}
+
+			idx++;
+			be_id++;
+
+			ret = set_hda_codec_link(dev, &links[idx], be_id,
+						 SOF_HDA_DIGITAL);
+			if (ret) {
+				dev_err(dev, "fail to set hda digital link, ret %d\n",
+					ret);
+				return ret;
+			}
+
+			idx++;
+			break;
 		case SOF_LINK_NONE:
 			/* caught here if it's not used as terminator in macro */
 			fallthrough;
diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h
index faba847bb7c9..33a9601b770c 100644
--- a/sound/soc/intel/boards/sof_board_helpers.h
+++ b/sound/soc/intel/boards/sof_board_helpers.h
@@ -57,6 +57,7 @@  enum {
 	SOF_LINK_AMP,
 	SOF_LINK_BT_OFFLOAD,
 	SOF_LINK_HDMI_IN,
+	SOF_LINK_HDA,
 };
 
 #define SOF_LINK_ORDER_MASK	(0xF)
@@ -121,6 +122,7 @@  struct sof_rt5682_private {
  * @ssp_bt: ssp port number of BT offload BE link
  * @ssp_mask_hdmi_in: ssp port mask of HDMI-IN BE link
  * @bt_offload_present: true to create BT offload BE link
+ * @hda_codec_present: true to create HDA codec BE links
  * @codec_link: pointer to headset codec dai link
  * @amp_link: pointer to speaker amplifier dai link
  * @link_order_overwrite: custom DAI link order
@@ -144,6 +146,7 @@  struct sof_card_private {
 	unsigned long ssp_mask_hdmi_in;
 
 	bool bt_offload_present;
+	bool hda_codec_present;
 
 	struct snd_soc_dai_link *codec_link;
 	struct snd_soc_dai_link *amp_link;