18d0872f6SMac Chiang // SPDX-License-Identifier: GPL-2.0-only
28d0872f6SMac Chiang // Copyright(c) 2021 Intel Corporation.
38d0872f6SMac Chiang // Copyright(c) 2021 Nuvoton Corporation.
48d0872f6SMac Chiang 
58d0872f6SMac Chiang /*
68d0872f6SMac Chiang  * Intel SOF Machine Driver with Nuvoton headphone codec NAU8825
78d0872f6SMac Chiang  * and speaker codec RT1019P MAX98360a or MAX98373
88d0872f6SMac Chiang  */
98d0872f6SMac Chiang #include <linux/i2c.h>
108d0872f6SMac Chiang #include <linux/input.h>
118d0872f6SMac Chiang #include <linux/module.h>
128d0872f6SMac Chiang #include <linux/platform_device.h>
138d0872f6SMac Chiang #include <linux/dmi.h>
148d0872f6SMac Chiang #include <sound/core.h>
158d0872f6SMac Chiang #include <sound/jack.h>
168d0872f6SMac Chiang #include <sound/pcm.h>
178d0872f6SMac Chiang #include <sound/pcm_params.h>
188d0872f6SMac Chiang #include <sound/soc.h>
198d0872f6SMac Chiang #include <sound/sof.h>
208d0872f6SMac Chiang #include <sound/soc-acpi.h>
218d0872f6SMac Chiang #include "../../codecs/nau8825.h"
228d0872f6SMac Chiang #include "../common/soc-intel-quirks.h"
238d0872f6SMac Chiang #include "hda_dsp_common.h"
248d0872f6SMac Chiang #include "sof_realtek_common.h"
258d0872f6SMac Chiang #include "sof_maxim_common.h"
268d0872f6SMac Chiang 
278d0872f6SMac Chiang #define NAME_SIZE 32
288d0872f6SMac Chiang 
298d0872f6SMac Chiang #define SOF_NAU8825_SSP_CODEC(quirk)		((quirk) & GENMASK(2, 0))
308d0872f6SMac Chiang #define SOF_NAU8825_SSP_CODEC_MASK		(GENMASK(2, 0))
318d0872f6SMac Chiang #define SOF_SPEAKER_AMP_PRESENT		BIT(3)
328d0872f6SMac Chiang #define SOF_NAU8825_SSP_AMP_SHIFT		4
338d0872f6SMac Chiang #define SOF_NAU8825_SSP_AMP_MASK		(GENMASK(6, 4))
348d0872f6SMac Chiang #define SOF_NAU8825_SSP_AMP(quirk)	\
358d0872f6SMac Chiang 	(((quirk) << SOF_NAU8825_SSP_AMP_SHIFT) & SOF_NAU8825_SSP_AMP_MASK)
368d0872f6SMac Chiang #define SOF_NAU8825_NUM_HDMIDEV_SHIFT		7
378d0872f6SMac Chiang #define SOF_NAU8825_NUM_HDMIDEV_MASK		(GENMASK(9, 7))
388d0872f6SMac Chiang #define SOF_NAU8825_NUM_HDMIDEV(quirk)	\
398d0872f6SMac Chiang 	(((quirk) << SOF_NAU8825_NUM_HDMIDEV_SHIFT) & SOF_NAU8825_NUM_HDMIDEV_MASK)
408d0872f6SMac Chiang 
418d0872f6SMac Chiang /* BT audio offload: reserve 3 bits for future */
428d0872f6SMac Chiang #define SOF_BT_OFFLOAD_SSP_SHIFT		10
438d0872f6SMac Chiang #define SOF_BT_OFFLOAD_SSP_MASK		(GENMASK(12, 10))
448d0872f6SMac Chiang #define SOF_BT_OFFLOAD_SSP(quirk)	\
458d0872f6SMac Chiang 	(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
468d0872f6SMac Chiang #define SOF_SSP_BT_OFFLOAD_PRESENT		BIT(13)
478d0872f6SMac Chiang #define SOF_RT1019P_SPEAKER_AMP_PRESENT	BIT(14)
488d0872f6SMac Chiang #define SOF_MAX98373_SPEAKER_AMP_PRESENT	BIT(15)
498d0872f6SMac Chiang #define SOF_MAX98360A_SPEAKER_AMP_PRESENT	BIT(16)
5013c459faSBrent Lu #define SOF_RT1015P_SPEAKER_AMP_PRESENT	BIT(17)
51ba7523bbSAjye Huang #define SOF_NAU8318_SPEAKER_AMP_PRESENT	BIT(18)
528d0872f6SMac Chiang 
538d0872f6SMac Chiang static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
548d0872f6SMac Chiang 
558d0872f6SMac Chiang struct sof_hdmi_pcm {
568d0872f6SMac Chiang 	struct list_head head;
578d0872f6SMac Chiang 	struct snd_soc_dai *codec_dai;
588d0872f6SMac Chiang 	int device;
598d0872f6SMac Chiang };
608d0872f6SMac Chiang 
618d0872f6SMac Chiang struct sof_card_private {
628d0872f6SMac Chiang 	struct clk *mclk;
638d0872f6SMac Chiang 	struct snd_soc_jack sof_headset;
648d0872f6SMac Chiang 	struct list_head hdmi_pcm_list;
658d0872f6SMac Chiang };
668d0872f6SMac Chiang 
sof_hdmi_init(struct snd_soc_pcm_runtime * rtd)678d0872f6SMac Chiang static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
688d0872f6SMac Chiang {
698d0872f6SMac Chiang 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
708d0872f6SMac Chiang 	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
718d0872f6SMac Chiang 	struct sof_hdmi_pcm *pcm;
728d0872f6SMac Chiang 
738d0872f6SMac Chiang 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
748d0872f6SMac Chiang 	if (!pcm)
758d0872f6SMac Chiang 		return -ENOMEM;
768d0872f6SMac Chiang 
778d0872f6SMac Chiang 	/* dai_link id is 1:1 mapped to the PCM device */
788d0872f6SMac Chiang 	pcm->device = rtd->dai_link->id;
798d0872f6SMac Chiang 	pcm->codec_dai = dai;
808d0872f6SMac Chiang 
818d0872f6SMac Chiang 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
828d0872f6SMac Chiang 
838d0872f6SMac Chiang 	return 0;
848d0872f6SMac Chiang }
858d0872f6SMac Chiang 
862a172d2fSPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
872a172d2fSPierre-Louis Bossart 	{
882a172d2fSPierre-Louis Bossart 		.pin    = "Headphone Jack",
892a172d2fSPierre-Louis Bossart 		.mask   = SND_JACK_HEADPHONE,
902a172d2fSPierre-Louis Bossart 	},
912a172d2fSPierre-Louis Bossart 	{
922a172d2fSPierre-Louis Bossart 		.pin    = "Headset Mic",
932a172d2fSPierre-Louis Bossart 		.mask   = SND_JACK_MICROPHONE,
942a172d2fSPierre-Louis Bossart 	},
952a172d2fSPierre-Louis Bossart };
962a172d2fSPierre-Louis Bossart 
sof_nau8825_codec_init(struct snd_soc_pcm_runtime * rtd)978d0872f6SMac Chiang static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
988d0872f6SMac Chiang {
998d0872f6SMac Chiang 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
1008d0872f6SMac Chiang 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
1018d0872f6SMac Chiang 
1028d0872f6SMac Chiang 	struct snd_soc_jack *jack;
1038d0872f6SMac Chiang 	int ret;
1048d0872f6SMac Chiang 
1058d0872f6SMac Chiang 	/*
1068d0872f6SMac Chiang 	 * Headset buttons map to the google Reference headset.
1078d0872f6SMac Chiang 	 * These can be configured by userspace.
1088d0872f6SMac Chiang 	 */
1092a172d2fSPierre-Louis Bossart 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
1108d0872f6SMac Chiang 					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
1118d0872f6SMac Chiang 					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
1128d0872f6SMac Chiang 					 SND_JACK_BTN_3,
1132a172d2fSPierre-Louis Bossart 					 &ctx->sof_headset,
1142a172d2fSPierre-Louis Bossart 					 jack_pins,
1152a172d2fSPierre-Louis Bossart 					 ARRAY_SIZE(jack_pins));
1168d0872f6SMac Chiang 	if (ret) {
1178d0872f6SMac Chiang 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
1188d0872f6SMac Chiang 		return ret;
1198d0872f6SMac Chiang 	}
1208d0872f6SMac Chiang 
1218d0872f6SMac Chiang 	jack = &ctx->sof_headset;
1228d0872f6SMac Chiang 
1238d0872f6SMac Chiang 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
1248d0872f6SMac Chiang 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
1258d0872f6SMac Chiang 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
1268d0872f6SMac Chiang 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
1278d0872f6SMac Chiang 	ret = snd_soc_component_set_jack(component, jack, NULL);
1288d0872f6SMac Chiang 
1298d0872f6SMac Chiang 	if (ret) {
1308d0872f6SMac Chiang 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
1318d0872f6SMac Chiang 		return ret;
1328d0872f6SMac Chiang 	}
1338d0872f6SMac Chiang 
1348d0872f6SMac Chiang 	return ret;
1358d0872f6SMac Chiang };
1368d0872f6SMac Chiang 
sof_nau8825_codec_exit(struct snd_soc_pcm_runtime * rtd)1378d0872f6SMac Chiang static void sof_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd)
1388d0872f6SMac Chiang {
1398d0872f6SMac Chiang 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
1408d0872f6SMac Chiang 
1418d0872f6SMac Chiang 	snd_soc_component_set_jack(component, NULL, NULL);
1428d0872f6SMac Chiang }
1438d0872f6SMac Chiang 
sof_nau8825_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)1448d0872f6SMac Chiang static int sof_nau8825_hw_params(struct snd_pcm_substream *substream,
1458d0872f6SMac Chiang 				 struct snd_pcm_hw_params *params)
1468d0872f6SMac Chiang {
1478d0872f6SMac Chiang 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1488d0872f6SMac Chiang 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
1498d0872f6SMac Chiang 	int clk_freq, ret;
1508d0872f6SMac Chiang 
1518d0872f6SMac Chiang 	clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */
1528d0872f6SMac Chiang 
1538d0872f6SMac Chiang 	if (clk_freq <= 0) {
1548d0872f6SMac Chiang 		dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq);
1558d0872f6SMac Chiang 		return -EINVAL;
1568d0872f6SMac Chiang 	}
1578d0872f6SMac Chiang 
1588d0872f6SMac Chiang 	/* Configure clock for codec */
1598d0872f6SMac Chiang 	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0,
1608d0872f6SMac Chiang 				     SND_SOC_CLOCK_IN);
1618d0872f6SMac Chiang 	if (ret < 0) {
1628d0872f6SMac Chiang 		dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret);
1638d0872f6SMac Chiang 		return ret;
1648d0872f6SMac Chiang 	}
1658d0872f6SMac Chiang 
1668d0872f6SMac Chiang 	/* Configure pll for codec */
1678d0872f6SMac Chiang 	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq,
1688d0872f6SMac Chiang 				  params_rate(params) * 256);
1698d0872f6SMac Chiang 	if (ret < 0) {
1708d0872f6SMac Chiang 		dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret);
1718d0872f6SMac Chiang 		return ret;
1728d0872f6SMac Chiang 	}
1738d0872f6SMac Chiang 
1748d0872f6SMac Chiang 	return ret;
1758d0872f6SMac Chiang }
1768d0872f6SMac Chiang 
1778d0872f6SMac Chiang static struct snd_soc_ops sof_nau8825_ops = {
1788d0872f6SMac Chiang 	.hw_params = sof_nau8825_hw_params,
1798d0872f6SMac Chiang };
1808d0872f6SMac Chiang 
1818d0872f6SMac Chiang static struct snd_soc_dai_link_component platform_component[] = {
1828d0872f6SMac Chiang 	{
1838d0872f6SMac Chiang 		/* name might be overridden during probe */
1848d0872f6SMac Chiang 		.name = "0000:00:1f.3"
1858d0872f6SMac Chiang 	}
1868d0872f6SMac Chiang };
1878d0872f6SMac Chiang 
sof_card_late_probe(struct snd_soc_card * card)1888d0872f6SMac Chiang static int sof_card_late_probe(struct snd_soc_card *card)
1898d0872f6SMac Chiang {
1908d0872f6SMac Chiang 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
1918d0872f6SMac Chiang 	struct snd_soc_dapm_context *dapm = &card->dapm;
1928d0872f6SMac Chiang 	struct sof_hdmi_pcm *pcm;
1938d0872f6SMac Chiang 	int err;
1948d0872f6SMac Chiang 
1958d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
1968d0872f6SMac Chiang 		/* Disable Left and Right Spk pin after boot */
1978d0872f6SMac Chiang 		snd_soc_dapm_disable_pin(dapm, "Left Spk");
1988d0872f6SMac Chiang 		snd_soc_dapm_disable_pin(dapm, "Right Spk");
1998d0872f6SMac Chiang 		err = snd_soc_dapm_sync(dapm);
2008d0872f6SMac Chiang 		if (err < 0)
2018d0872f6SMac Chiang 			return err;
2028d0872f6SMac Chiang 	}
2038d0872f6SMac Chiang 
2045b56db90SYong Zhi 	if (list_empty(&ctx->hdmi_pcm_list))
2055b56db90SYong Zhi 		return -EINVAL;
2065b56db90SYong Zhi 
2075b56db90SYong Zhi 	pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
2085b56db90SYong Zhi 
2098d0872f6SMac Chiang 	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
2108d0872f6SMac Chiang }
2118d0872f6SMac Chiang 
2128d0872f6SMac Chiang static const struct snd_kcontrol_new sof_controls[] = {
2138d0872f6SMac Chiang 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
2148d0872f6SMac Chiang 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
2158d0872f6SMac Chiang 	SOC_DAPM_PIN_SWITCH("Left Spk"),
2168d0872f6SMac Chiang 	SOC_DAPM_PIN_SWITCH("Right Spk"),
2178d0872f6SMac Chiang };
2188d0872f6SMac Chiang 
2198d0872f6SMac Chiang static const struct snd_kcontrol_new speaker_controls[] = {
2208d0872f6SMac Chiang 	SOC_DAPM_PIN_SWITCH("Spk"),
2218d0872f6SMac Chiang };
2228d0872f6SMac Chiang 
2238d0872f6SMac Chiang static const struct snd_soc_dapm_widget sof_widgets[] = {
2248d0872f6SMac Chiang 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
2258d0872f6SMac Chiang 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
2268d0872f6SMac Chiang 	SND_SOC_DAPM_SPK("Left Spk", NULL),
2278d0872f6SMac Chiang 	SND_SOC_DAPM_SPK("Right Spk", NULL),
2288d0872f6SMac Chiang };
2298d0872f6SMac Chiang 
2308d0872f6SMac Chiang static const struct snd_soc_dapm_widget speaker_widgets[] = {
2318d0872f6SMac Chiang 	SND_SOC_DAPM_SPK("Spk", NULL),
2328d0872f6SMac Chiang };
2338d0872f6SMac Chiang 
2348d0872f6SMac Chiang static const struct snd_soc_dapm_widget dmic_widgets[] = {
2358d0872f6SMac Chiang 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
2368d0872f6SMac Chiang };
2378d0872f6SMac Chiang 
2388d0872f6SMac Chiang static const struct snd_soc_dapm_route sof_map[] = {
2398d0872f6SMac Chiang 	/* HP jack connectors - unknown if we have jack detection */
2408d0872f6SMac Chiang 	{ "Headphone Jack", NULL, "HPOL" },
2418d0872f6SMac Chiang 	{ "Headphone Jack", NULL, "HPOR" },
2428d0872f6SMac Chiang 
2438d0872f6SMac Chiang 	/* other jacks */
2448d0872f6SMac Chiang 	{ "MIC", NULL, "Headset Mic" },
2458d0872f6SMac Chiang };
2468d0872f6SMac Chiang 
2478d0872f6SMac Chiang static const struct snd_soc_dapm_route speaker_map[] = {
2488d0872f6SMac Chiang 	/* speaker */
2498d0872f6SMac Chiang 	{ "Spk", NULL, "Speaker" },
2508d0872f6SMac Chiang };
2518d0872f6SMac Chiang 
2528d0872f6SMac Chiang static const struct snd_soc_dapm_route dmic_map[] = {
2538d0872f6SMac Chiang 	/* digital mics */
2548d0872f6SMac Chiang 	{"DMic", NULL, "SoC DMIC"},
2558d0872f6SMac Chiang };
2568d0872f6SMac Chiang 
speaker_codec_init(struct snd_soc_pcm_runtime * rtd)2578d0872f6SMac Chiang static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
2588d0872f6SMac Chiang {
2598d0872f6SMac Chiang 	struct snd_soc_card *card = rtd->card;
2608d0872f6SMac Chiang 	int ret;
2618d0872f6SMac Chiang 
2628d0872f6SMac Chiang 	ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
2638d0872f6SMac Chiang 					ARRAY_SIZE(speaker_widgets));
2648d0872f6SMac Chiang 	if (ret) {
2658d0872f6SMac Chiang 		dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
2668d0872f6SMac Chiang 		/* Don't need to add routes if widget addition failed */
2678d0872f6SMac Chiang 		return ret;
2688d0872f6SMac Chiang 	}
2698d0872f6SMac Chiang 
2708d0872f6SMac Chiang 	ret = snd_soc_add_card_controls(card, speaker_controls,
2718d0872f6SMac Chiang 					ARRAY_SIZE(speaker_controls));
2728d0872f6SMac Chiang 	if (ret) {
2738d0872f6SMac Chiang 		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
2748d0872f6SMac Chiang 		return ret;
2758d0872f6SMac Chiang 	}
2768d0872f6SMac Chiang 
2778d0872f6SMac Chiang 	ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
2788d0872f6SMac Chiang 				      ARRAY_SIZE(speaker_map));
2798d0872f6SMac Chiang 
2808d0872f6SMac Chiang 	if (ret)
2818d0872f6SMac Chiang 		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
2828d0872f6SMac Chiang 	return ret;
2838d0872f6SMac Chiang }
2848d0872f6SMac Chiang 
dmic_init(struct snd_soc_pcm_runtime * rtd)2858d0872f6SMac Chiang static int dmic_init(struct snd_soc_pcm_runtime *rtd)
2868d0872f6SMac Chiang {
2878d0872f6SMac Chiang 	struct snd_soc_card *card = rtd->card;
2888d0872f6SMac Chiang 	int ret;
2898d0872f6SMac Chiang 
2908d0872f6SMac Chiang 	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
2918d0872f6SMac Chiang 					ARRAY_SIZE(dmic_widgets));
2928d0872f6SMac Chiang 	if (ret) {
2938d0872f6SMac Chiang 		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
2948d0872f6SMac Chiang 		/* Don't need to add routes if widget addition failed */
2958d0872f6SMac Chiang 		return ret;
2968d0872f6SMac Chiang 	}
2978d0872f6SMac Chiang 
2988d0872f6SMac Chiang 	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
2998d0872f6SMac Chiang 				      ARRAY_SIZE(dmic_map));
3008d0872f6SMac Chiang 
3018d0872f6SMac Chiang 	if (ret)
3028d0872f6SMac Chiang 		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
3038d0872f6SMac Chiang 
3048d0872f6SMac Chiang 	return ret;
3058d0872f6SMac Chiang }
3068d0872f6SMac Chiang 
3078d0872f6SMac Chiang /* sof audio machine driver for nau8825 codec */
3088d0872f6SMac Chiang static struct snd_soc_card sof_audio_card_nau8825 = {
3098d0872f6SMac Chiang 	.name = "nau8825", /* the sof- prefix is added by the core */
3108d0872f6SMac Chiang 	.owner = THIS_MODULE,
3118d0872f6SMac Chiang 	.controls = sof_controls,
3128d0872f6SMac Chiang 	.num_controls = ARRAY_SIZE(sof_controls),
3138d0872f6SMac Chiang 	.dapm_widgets = sof_widgets,
3148d0872f6SMac Chiang 	.num_dapm_widgets = ARRAY_SIZE(sof_widgets),
3158d0872f6SMac Chiang 	.dapm_routes = sof_map,
3168d0872f6SMac Chiang 	.num_dapm_routes = ARRAY_SIZE(sof_map),
3178d0872f6SMac Chiang 	.fully_routed = true,
3188d0872f6SMac Chiang 	.late_probe = sof_card_late_probe,
3198d0872f6SMac Chiang };
3208d0872f6SMac Chiang 
3218d0872f6SMac Chiang static struct snd_soc_dai_link_component nau8825_component[] = {
3228d0872f6SMac Chiang 	{
3238d0872f6SMac Chiang 		.name = "i2c-10508825:00",
3248d0872f6SMac Chiang 		.dai_name = "nau8825-hifi",
3258d0872f6SMac Chiang 	}
3268d0872f6SMac Chiang };
3278d0872f6SMac Chiang 
3288d0872f6SMac Chiang static struct snd_soc_dai_link_component dmic_component[] = {
3298d0872f6SMac Chiang 	{
3308d0872f6SMac Chiang 		.name = "dmic-codec",
3318d0872f6SMac Chiang 		.dai_name = "dmic-hifi",
3328d0872f6SMac Chiang 	}
3338d0872f6SMac Chiang };
3348d0872f6SMac Chiang 
3358d0872f6SMac Chiang static struct snd_soc_dai_link_component rt1019p_component[] = {
3368d0872f6SMac Chiang 	{
3378d0872f6SMac Chiang 		.name = "RTL1019:00",
3388d0872f6SMac Chiang 		.dai_name = "HiFi",
3398d0872f6SMac Chiang 	}
3408d0872f6SMac Chiang };
3418d0872f6SMac Chiang 
342ba7523bbSAjye Huang static struct snd_soc_dai_link_component nau8318_components[] = {
343ba7523bbSAjye Huang 	{
344ba7523bbSAjye Huang 		.name = "NVTN2012:00",
345ba7523bbSAjye Huang 		.dai_name = "nau8315-hifi",
346ba7523bbSAjye Huang 	}
347ba7523bbSAjye Huang };
348ba7523bbSAjye Huang 
sof_card_dai_links_create(struct device * dev,int ssp_codec,int ssp_amp,int dmic_be_num,int hdmi_num)3498d0872f6SMac Chiang static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
3508d0872f6SMac Chiang 							  int ssp_codec,
3518d0872f6SMac Chiang 							  int ssp_amp,
3528d0872f6SMac Chiang 							  int dmic_be_num,
3538d0872f6SMac Chiang 							  int hdmi_num)
3548d0872f6SMac Chiang {
3558d0872f6SMac Chiang 	struct snd_soc_dai_link_component *idisp_components;
3568d0872f6SMac Chiang 	struct snd_soc_dai_link_component *cpus;
3578d0872f6SMac Chiang 	struct snd_soc_dai_link *links;
3588d0872f6SMac Chiang 	int i, id = 0;
3598d0872f6SMac Chiang 
360b60200d7Sye xingchen 	links = devm_kcalloc(dev, sof_audio_card_nau8825.num_links,
361b60200d7Sye xingchen 			    sizeof(struct snd_soc_dai_link), GFP_KERNEL);
362b60200d7Sye xingchen 	cpus = devm_kcalloc(dev, sof_audio_card_nau8825.num_links,
363b60200d7Sye xingchen 			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
3648d0872f6SMac Chiang 	if (!links || !cpus)
3658d0872f6SMac Chiang 		goto devm_err;
3668d0872f6SMac Chiang 
3678d0872f6SMac Chiang 	/* codec SSP */
3688d0872f6SMac Chiang 	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
3698d0872f6SMac Chiang 					"SSP%d-Codec", ssp_codec);
3708d0872f6SMac Chiang 	if (!links[id].name)
3718d0872f6SMac Chiang 		goto devm_err;
3728d0872f6SMac Chiang 
3738d0872f6SMac Chiang 	links[id].id = id;
3748d0872f6SMac Chiang 	links[id].codecs = nau8825_component;
3758d0872f6SMac Chiang 	links[id].num_codecs = ARRAY_SIZE(nau8825_component);
3768d0872f6SMac Chiang 	links[id].platforms = platform_component;
3778d0872f6SMac Chiang 	links[id].num_platforms = ARRAY_SIZE(platform_component);
3788d0872f6SMac Chiang 	links[id].init = sof_nau8825_codec_init;
3798d0872f6SMac Chiang 	links[id].exit = sof_nau8825_codec_exit;
3808d0872f6SMac Chiang 	links[id].ops = &sof_nau8825_ops;
3818d0872f6SMac Chiang 	links[id].dpcm_playback = 1;
3828d0872f6SMac Chiang 	links[id].dpcm_capture = 1;
3838d0872f6SMac Chiang 	links[id].no_pcm = 1;
3848d0872f6SMac Chiang 	links[id].cpus = &cpus[id];
3858d0872f6SMac Chiang 	links[id].num_cpus = 1;
3868d0872f6SMac Chiang 
3878d0872f6SMac Chiang 	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
3888d0872f6SMac Chiang 						  "SSP%d Pin",
3898d0872f6SMac Chiang 						  ssp_codec);
3908d0872f6SMac Chiang 	if (!links[id].cpus->dai_name)
3918d0872f6SMac Chiang 		goto devm_err;
3928d0872f6SMac Chiang 
3938d0872f6SMac Chiang 	id++;
3948d0872f6SMac Chiang 
3958d0872f6SMac Chiang 	/* dmic */
3968d0872f6SMac Chiang 	if (dmic_be_num > 0) {
3978d0872f6SMac Chiang 		/* at least we have dmic01 */
3988d0872f6SMac Chiang 		links[id].name = "dmic01";
3998d0872f6SMac Chiang 		links[id].cpus = &cpus[id];
4008d0872f6SMac Chiang 		links[id].cpus->dai_name = "DMIC01 Pin";
4018d0872f6SMac Chiang 		links[id].init = dmic_init;
4028d0872f6SMac Chiang 		if (dmic_be_num > 1) {
4038d0872f6SMac Chiang 			/* set up 2 BE links at most */
4048d0872f6SMac Chiang 			links[id + 1].name = "dmic16k";
4058d0872f6SMac Chiang 			links[id + 1].cpus = &cpus[id + 1];
4068d0872f6SMac Chiang 			links[id + 1].cpus->dai_name = "DMIC16k Pin";
4078d0872f6SMac Chiang 			dmic_be_num = 2;
4088d0872f6SMac Chiang 		}
4098d0872f6SMac Chiang 	}
4108d0872f6SMac Chiang 
4118d0872f6SMac Chiang 	for (i = 0; i < dmic_be_num; i++) {
4128d0872f6SMac Chiang 		links[id].id = id;
4138d0872f6SMac Chiang 		links[id].num_cpus = 1;
4148d0872f6SMac Chiang 		links[id].codecs = dmic_component;
4158d0872f6SMac Chiang 		links[id].num_codecs = ARRAY_SIZE(dmic_component);
4168d0872f6SMac Chiang 		links[id].platforms = platform_component;
4178d0872f6SMac Chiang 		links[id].num_platforms = ARRAY_SIZE(platform_component);
4188d0872f6SMac Chiang 		links[id].ignore_suspend = 1;
4198d0872f6SMac Chiang 		links[id].dpcm_capture = 1;
4208d0872f6SMac Chiang 		links[id].no_pcm = 1;
4218d0872f6SMac Chiang 		id++;
4228d0872f6SMac Chiang 	}
4238d0872f6SMac Chiang 
4248d0872f6SMac Chiang 	/* HDMI */
4258d0872f6SMac Chiang 	if (hdmi_num > 0) {
426b60200d7Sye xingchen 		idisp_components = devm_kcalloc(dev,
427b60200d7Sye xingchen 						hdmi_num,
428b60200d7Sye xingchen 						sizeof(struct snd_soc_dai_link_component),
429b60200d7Sye xingchen 						GFP_KERNEL);
4308d0872f6SMac Chiang 		if (!idisp_components)
4318d0872f6SMac Chiang 			goto devm_err;
4328d0872f6SMac Chiang 	}
4338d0872f6SMac Chiang 	for (i = 1; i <= hdmi_num; i++) {
4348d0872f6SMac Chiang 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
4358d0872f6SMac Chiang 						"iDisp%d", i);
4368d0872f6SMac Chiang 		if (!links[id].name)
4378d0872f6SMac Chiang 			goto devm_err;
4388d0872f6SMac Chiang 
4398d0872f6SMac Chiang 		links[id].id = id;
4408d0872f6SMac Chiang 		links[id].cpus = &cpus[id];
4418d0872f6SMac Chiang 		links[id].num_cpus = 1;
4428d0872f6SMac Chiang 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
4438d0872f6SMac Chiang 							  "iDisp%d Pin", i);
4448d0872f6SMac Chiang 		if (!links[id].cpus->dai_name)
4458d0872f6SMac Chiang 			goto devm_err;
4468d0872f6SMac Chiang 
4478d0872f6SMac Chiang 		idisp_components[i - 1].name = "ehdaudio0D2";
4488d0872f6SMac Chiang 		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
4498d0872f6SMac Chiang 								  GFP_KERNEL,
4508d0872f6SMac Chiang 								  "intel-hdmi-hifi%d",
4518d0872f6SMac Chiang 								  i);
4528d0872f6SMac Chiang 		if (!idisp_components[i - 1].dai_name)
4538d0872f6SMac Chiang 			goto devm_err;
4548d0872f6SMac Chiang 
4558d0872f6SMac Chiang 		links[id].codecs = &idisp_components[i - 1];
4568d0872f6SMac Chiang 		links[id].num_codecs = 1;
4578d0872f6SMac Chiang 		links[id].platforms = platform_component;
4588d0872f6SMac Chiang 		links[id].num_platforms = ARRAY_SIZE(platform_component);
4598d0872f6SMac Chiang 		links[id].init = sof_hdmi_init;
4608d0872f6SMac Chiang 		links[id].dpcm_playback = 1;
4618d0872f6SMac Chiang 		links[id].no_pcm = 1;
4628d0872f6SMac Chiang 		id++;
4638d0872f6SMac Chiang 	}
4648d0872f6SMac Chiang 
4658d0872f6SMac Chiang 	/* speaker amp */
4668d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) {
4678d0872f6SMac Chiang 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
4688d0872f6SMac Chiang 						"SSP%d-Codec", ssp_amp);
4698d0872f6SMac Chiang 		if (!links[id].name)
4708d0872f6SMac Chiang 			goto devm_err;
4718d0872f6SMac Chiang 
4728d0872f6SMac Chiang 		links[id].id = id;
4738d0872f6SMac Chiang 		if (sof_nau8825_quirk & SOF_RT1019P_SPEAKER_AMP_PRESENT) {
4748d0872f6SMac Chiang 			links[id].codecs = rt1019p_component;
4758d0872f6SMac Chiang 			links[id].num_codecs = ARRAY_SIZE(rt1019p_component);
4768d0872f6SMac Chiang 			links[id].init = speaker_codec_init;
4778d0872f6SMac Chiang 		} else if (sof_nau8825_quirk &
4788d0872f6SMac Chiang 				SOF_MAX98373_SPEAKER_AMP_PRESENT) {
4798d0872f6SMac Chiang 			links[id].codecs = max_98373_components;
4808d0872f6SMac Chiang 			links[id].num_codecs = ARRAY_SIZE(max_98373_components);
4818d0872f6SMac Chiang 			links[id].init = max_98373_spk_codec_init;
4828d0872f6SMac Chiang 			links[id].ops = &max_98373_ops;
4838d0872f6SMac Chiang 		} else if (sof_nau8825_quirk &
4848d0872f6SMac Chiang 				SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
4858d0872f6SMac Chiang 			max_98360a_dai_link(&links[id]);
48613c459faSBrent Lu 		} else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
48713c459faSBrent Lu 			sof_rt1015p_dai_link(&links[id]);
488ba7523bbSAjye Huang 		} else if (sof_nau8825_quirk &
489ba7523bbSAjye Huang 				SOF_NAU8318_SPEAKER_AMP_PRESENT) {
490ba7523bbSAjye Huang 			links[id].codecs = nau8318_components;
491ba7523bbSAjye Huang 			links[id].num_codecs = ARRAY_SIZE(nau8318_components);
492ba7523bbSAjye Huang 			links[id].init = speaker_codec_init;
4938d0872f6SMac Chiang 		} else {
4948d0872f6SMac Chiang 			goto devm_err;
4958d0872f6SMac Chiang 		}
4968d0872f6SMac Chiang 
4978d0872f6SMac Chiang 		links[id].platforms = platform_component;
4988d0872f6SMac Chiang 		links[id].num_platforms = ARRAY_SIZE(platform_component);
4998d0872f6SMac Chiang 		links[id].dpcm_playback = 1;
50036a71a0eSPierre-Louis Bossart 		/* feedback stream or firmware-generated echo reference */
50136a71a0eSPierre-Louis Bossart 		links[id].dpcm_capture = 1;
50236a71a0eSPierre-Louis Bossart 
5038d0872f6SMac Chiang 		links[id].no_pcm = 1;
5048d0872f6SMac Chiang 		links[id].cpus = &cpus[id];
5058d0872f6SMac Chiang 		links[id].num_cpus = 1;
5068d0872f6SMac Chiang 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
5078d0872f6SMac Chiang 							  "SSP%d Pin",
5088d0872f6SMac Chiang 							  ssp_amp);
5098d0872f6SMac Chiang 		if (!links[id].cpus->dai_name)
5108d0872f6SMac Chiang 			goto devm_err;
5118d0872f6SMac Chiang 		id++;
5128d0872f6SMac Chiang 	}
5138d0872f6SMac Chiang 
5148d0872f6SMac Chiang 	/* BT audio offload */
5158d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
5168d0872f6SMac Chiang 		int port = (sof_nau8825_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
5178d0872f6SMac Chiang 				SOF_BT_OFFLOAD_SSP_SHIFT;
5188d0872f6SMac Chiang 
5198d0872f6SMac Chiang 		links[id].id = id;
5208d0872f6SMac Chiang 		links[id].cpus = &cpus[id];
5218d0872f6SMac Chiang 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
5228d0872f6SMac Chiang 							  "SSP%d Pin", port);
5238d0872f6SMac Chiang 		if (!links[id].cpus->dai_name)
5248d0872f6SMac Chiang 			goto devm_err;
5258d0872f6SMac Chiang 		links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
5268d0872f6SMac Chiang 		if (!links[id].name)
5278d0872f6SMac Chiang 			goto devm_err;
5281785af9fSKuninori Morimoto 		links[id].codecs = &asoc_dummy_dlc;
5291785af9fSKuninori Morimoto 		links[id].num_codecs = 1;
5308d0872f6SMac Chiang 		links[id].platforms = platform_component;
5318d0872f6SMac Chiang 		links[id].num_platforms = ARRAY_SIZE(platform_component);
5328d0872f6SMac Chiang 		links[id].dpcm_playback = 1;
5338d0872f6SMac Chiang 		links[id].dpcm_capture = 1;
5348d0872f6SMac Chiang 		links[id].no_pcm = 1;
5358d0872f6SMac Chiang 		links[id].num_cpus = 1;
5368d0872f6SMac Chiang 	}
5378d0872f6SMac Chiang 
5388d0872f6SMac Chiang 	return links;
5398d0872f6SMac Chiang devm_err:
5408d0872f6SMac Chiang 	return NULL;
5418d0872f6SMac Chiang }
5428d0872f6SMac Chiang 
sof_audio_probe(struct platform_device * pdev)5438d0872f6SMac Chiang static int sof_audio_probe(struct platform_device *pdev)
5448d0872f6SMac Chiang {
5458d0872f6SMac Chiang 	struct snd_soc_dai_link *dai_links;
5468d0872f6SMac Chiang 	struct snd_soc_acpi_mach *mach;
5478d0872f6SMac Chiang 	struct sof_card_private *ctx;
5488d0872f6SMac Chiang 	int dmic_be_num, hdmi_num;
5498d0872f6SMac Chiang 	int ret, ssp_amp, ssp_codec;
5508d0872f6SMac Chiang 
5518d0872f6SMac Chiang 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
5528d0872f6SMac Chiang 	if (!ctx)
5538d0872f6SMac Chiang 		return -ENOMEM;
5548d0872f6SMac Chiang 
5558d0872f6SMac Chiang 	if (pdev->id_entry && pdev->id_entry->driver_data)
5568d0872f6SMac Chiang 		sof_nau8825_quirk = (unsigned long)pdev->id_entry->driver_data;
5578d0872f6SMac Chiang 
5588d0872f6SMac Chiang 	mach = pdev->dev.platform_data;
5598d0872f6SMac Chiang 
5608d0872f6SMac Chiang 	/* A speaker amp might not be present when the quirk claims one is.
5618d0872f6SMac Chiang 	 * Detect this via whether the machine driver match includes quirk_data.
5628d0872f6SMac Chiang 	 */
5638d0872f6SMac Chiang 	if ((sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
5648d0872f6SMac Chiang 		sof_nau8825_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
5658d0872f6SMac Chiang 
5668d0872f6SMac Chiang 	dev_dbg(&pdev->dev, "sof_nau8825_quirk = %lx\n", sof_nau8825_quirk);
5678d0872f6SMac Chiang 
5688d0872f6SMac Chiang 	/* default number of DMIC DAI's */
5698d0872f6SMac Chiang 	dmic_be_num = 2;
5708d0872f6SMac Chiang 	hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >>
5718d0872f6SMac Chiang 			SOF_NAU8825_NUM_HDMIDEV_SHIFT;
5728d0872f6SMac Chiang 	/* default number of HDMI DAI's */
5738d0872f6SMac Chiang 	if (!hdmi_num)
5748d0872f6SMac Chiang 		hdmi_num = 3;
5758d0872f6SMac Chiang 
5768d0872f6SMac Chiang 	ssp_amp = (sof_nau8825_quirk & SOF_NAU8825_SSP_AMP_MASK) >>
5778d0872f6SMac Chiang 			SOF_NAU8825_SSP_AMP_SHIFT;
5788d0872f6SMac Chiang 
5798d0872f6SMac Chiang 	ssp_codec = sof_nau8825_quirk & SOF_NAU8825_SSP_CODEC_MASK;
5808d0872f6SMac Chiang 
5818d0872f6SMac Chiang 	/* compute number of dai links */
5828d0872f6SMac Chiang 	sof_audio_card_nau8825.num_links = 1 + dmic_be_num + hdmi_num;
5838d0872f6SMac Chiang 
5848d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT)
5858d0872f6SMac Chiang 		sof_audio_card_nau8825.num_links++;
5868d0872f6SMac Chiang 
5878d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
5888d0872f6SMac Chiang 		max_98373_set_codec_conf(&sof_audio_card_nau8825);
58913c459faSBrent Lu 	else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
59013c459faSBrent Lu 		sof_rt1015p_codec_conf(&sof_audio_card_nau8825);
5918d0872f6SMac Chiang 
5928d0872f6SMac Chiang 	if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
5938d0872f6SMac Chiang 		sof_audio_card_nau8825.num_links++;
5948d0872f6SMac Chiang 
5958d0872f6SMac Chiang 	dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
5968d0872f6SMac Chiang 					      dmic_be_num, hdmi_num);
5978d0872f6SMac Chiang 	if (!dai_links)
5988d0872f6SMac Chiang 		return -ENOMEM;
5998d0872f6SMac Chiang 
6008d0872f6SMac Chiang 	sof_audio_card_nau8825.dai_link = dai_links;
6018d0872f6SMac Chiang 
6028d0872f6SMac Chiang 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
6038d0872f6SMac Chiang 
6048d0872f6SMac Chiang 	sof_audio_card_nau8825.dev = &pdev->dev;
6058d0872f6SMac Chiang 
6068d0872f6SMac Chiang 	/* set platform name for each dailink */
6078d0872f6SMac Chiang 	ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_nau8825,
6088d0872f6SMac Chiang 						    mach->mach_params.platform);
6098d0872f6SMac Chiang 	if (ret)
6108d0872f6SMac Chiang 		return ret;
6118d0872f6SMac Chiang 
6128d0872f6SMac Chiang 	snd_soc_card_set_drvdata(&sof_audio_card_nau8825, ctx);
6138d0872f6SMac Chiang 
6148d0872f6SMac Chiang 	return devm_snd_soc_register_card(&pdev->dev,
6158d0872f6SMac Chiang 					  &sof_audio_card_nau8825);
6168d0872f6SMac Chiang }
6178d0872f6SMac Chiang 
6188d0872f6SMac Chiang static const struct platform_device_id board_ids[] = {
6198d0872f6SMac Chiang 	{
6208d0872f6SMac Chiang 		.name = "sof_nau8825",
6218d0872f6SMac Chiang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
6228d0872f6SMac Chiang 					SOF_NAU8825_NUM_HDMIDEV(4) |
6238d0872f6SMac Chiang 					SOF_BT_OFFLOAD_SSP(2) |
6248d0872f6SMac Chiang 					SOF_SSP_BT_OFFLOAD_PRESENT),
6258d0872f6SMac Chiang 
6268d0872f6SMac Chiang 	},
6278d0872f6SMac Chiang 	{
6283e78986aSArnd Bergmann 		.name = "adl_rt1019p_8825",
6298d0872f6SMac Chiang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
6308d0872f6SMac Chiang 					SOF_SPEAKER_AMP_PRESENT |
6318d0872f6SMac Chiang 					SOF_RT1019P_SPEAKER_AMP_PRESENT |
6328d0872f6SMac Chiang 					SOF_NAU8825_SSP_AMP(2) |
6338d0872f6SMac Chiang 					SOF_NAU8825_NUM_HDMIDEV(4)),
6348d0872f6SMac Chiang 	},
6358d0872f6SMac Chiang 	{
6363e78986aSArnd Bergmann 		.name = "adl_max98373_8825",
6378d0872f6SMac Chiang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
6388d0872f6SMac Chiang 					SOF_SPEAKER_AMP_PRESENT |
6398d0872f6SMac Chiang 					SOF_MAX98373_SPEAKER_AMP_PRESENT |
6408d0872f6SMac Chiang 					SOF_NAU8825_SSP_AMP(1) |
6418d0872f6SMac Chiang 					SOF_NAU8825_NUM_HDMIDEV(4) |
6428d0872f6SMac Chiang 					SOF_BT_OFFLOAD_SSP(2) |
6438d0872f6SMac Chiang 					SOF_SSP_BT_OFFLOAD_PRESENT),
6448d0872f6SMac Chiang 	},
6458d0872f6SMac Chiang 	{
6468d0872f6SMac Chiang 		/* The limitation of length of char array, shorten the name */
6473e78986aSArnd Bergmann 		.name = "adl_mx98360a_8825",
6488d0872f6SMac Chiang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
6498d0872f6SMac Chiang 					SOF_SPEAKER_AMP_PRESENT |
6508d0872f6SMac Chiang 					SOF_MAX98360A_SPEAKER_AMP_PRESENT |
6518d0872f6SMac Chiang 					SOF_NAU8825_SSP_AMP(1) |
6528d0872f6SMac Chiang 					SOF_NAU8825_NUM_HDMIDEV(4) |
6538d0872f6SMac Chiang 					SOF_BT_OFFLOAD_SSP(2) |
6548d0872f6SMac Chiang 					SOF_SSP_BT_OFFLOAD_PRESENT),
6558d0872f6SMac Chiang 
6568d0872f6SMac Chiang 	},
65713c459faSBrent Lu 	{
6583e78986aSArnd Bergmann 		.name = "adl_rt1015p_8825",
65913c459faSBrent Lu 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
66013c459faSBrent Lu 					SOF_SPEAKER_AMP_PRESENT |
66113c459faSBrent Lu 					SOF_RT1015P_SPEAKER_AMP_PRESENT |
66213c459faSBrent Lu 					SOF_NAU8825_SSP_AMP(1) |
66313c459faSBrent Lu 					SOF_NAU8825_NUM_HDMIDEV(4) |
66413c459faSBrent Lu 					SOF_BT_OFFLOAD_SSP(2) |
66513c459faSBrent Lu 					SOF_SSP_BT_OFFLOAD_PRESENT),
66613c459faSBrent Lu 	},
667ba7523bbSAjye Huang 	{
668ba7523bbSAjye Huang 		.name = "adl_nau8318_8825",
669ba7523bbSAjye Huang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
670ba7523bbSAjye Huang 					SOF_SPEAKER_AMP_PRESENT |
671ba7523bbSAjye Huang 					SOF_NAU8318_SPEAKER_AMP_PRESENT |
672ba7523bbSAjye Huang 					SOF_NAU8825_SSP_AMP(1) |
673ba7523bbSAjye Huang 					SOF_NAU8825_NUM_HDMIDEV(4) |
674ba7523bbSAjye Huang 					SOF_BT_OFFLOAD_SSP(2) |
675ba7523bbSAjye Huang 					SOF_SSP_BT_OFFLOAD_PRESENT),
676ba7523bbSAjye Huang 	},
6778899672fSTerry Cheong 	{
6788899672fSTerry Cheong 		.name = "rpl_max98373_8825",
6798899672fSTerry Cheong 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
6808899672fSTerry Cheong 					SOF_SPEAKER_AMP_PRESENT |
6818899672fSTerry Cheong 					SOF_MAX98373_SPEAKER_AMP_PRESENT |
6828899672fSTerry Cheong 					SOF_NAU8825_SSP_AMP(1) |
6838899672fSTerry Cheong 					SOF_NAU8825_NUM_HDMIDEV(4) |
6848899672fSTerry Cheong 					SOF_BT_OFFLOAD_SSP(2) |
6858899672fSTerry Cheong 					SOF_SSP_BT_OFFLOAD_PRESENT),
6868899672fSTerry Cheong 	},
687*273bc8bfSAjye Huang 	{
688*273bc8bfSAjye Huang 		.name = "rpl_nau8318_8825",
689*273bc8bfSAjye Huang 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
690*273bc8bfSAjye Huang 					SOF_SPEAKER_AMP_PRESENT |
691*273bc8bfSAjye Huang 					SOF_NAU8318_SPEAKER_AMP_PRESENT |
692*273bc8bfSAjye Huang 					SOF_NAU8825_SSP_AMP(1) |
693*273bc8bfSAjye Huang 					SOF_NAU8825_NUM_HDMIDEV(4) |
694*273bc8bfSAjye Huang 					SOF_BT_OFFLOAD_SSP(2) |
695*273bc8bfSAjye Huang 					SOF_SSP_BT_OFFLOAD_PRESENT),
696*273bc8bfSAjye Huang 	},
6978d0872f6SMac Chiang 	{ }
6988d0872f6SMac Chiang };
6998d0872f6SMac Chiang MODULE_DEVICE_TABLE(platform, board_ids);
7008d0872f6SMac Chiang 
7018d0872f6SMac Chiang static struct platform_driver sof_audio = {
7028d0872f6SMac Chiang 	.probe = sof_audio_probe,
7038d0872f6SMac Chiang 	.driver = {
7048d0872f6SMac Chiang 		.name = "sof_nau8825",
7058d0872f6SMac Chiang 		.pm = &snd_soc_pm_ops,
7068d0872f6SMac Chiang 	},
7078d0872f6SMac Chiang 	.id_table = board_ids,
7088d0872f6SMac Chiang };
7098d0872f6SMac Chiang module_platform_driver(sof_audio)
7108d0872f6SMac Chiang 
7118d0872f6SMac Chiang /* Module information */
7128d0872f6SMac Chiang MODULE_DESCRIPTION("SOF Audio Machine driver for NAU8825");
7138d0872f6SMac Chiang MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
7148d0872f6SMac Chiang MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
7158d0872f6SMac Chiang MODULE_LICENSE("GPL");
7168d0872f6SMac Chiang MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
7178d0872f6SMac Chiang MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
71813c459faSBrent Lu MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
719