xref: /openbmc/linux/sound/soc/intel/boards/sof_da7219_max98373.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only
235dc19adSYong Zhi // Copyright(c) 2019 Intel Corporation.
335dc19adSYong Zhi 
435dc19adSYong Zhi /*
53f32e596SYong Zhi  * Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec
635dc19adSYong Zhi  */
735dc19adSYong Zhi 
835dc19adSYong Zhi #include <linux/input.h>
935dc19adSYong Zhi #include <linux/module.h>
109a1fe79dSCezary Rojewski #include <sound/jack.h>
1135dc19adSYong Zhi #include <sound/pcm.h>
1235dc19adSYong Zhi #include <sound/pcm_params.h>
1335dc19adSYong Zhi #include <linux/platform_device.h>
1435dc19adSYong Zhi #include <sound/soc.h>
1535dc19adSYong Zhi #include <sound/soc-acpi.h>
1635dc19adSYong Zhi #include "../../codecs/da7219.h"
1735dc19adSYong Zhi #include "hda_dsp_common.h"
1835dc19adSYong Zhi 
1935dc19adSYong Zhi #define DIALOG_CODEC_DAI	"da7219-hifi"
2035dc19adSYong Zhi #define MAX98373_CODEC_DAI	"max98373-aif1"
2135dc19adSYong Zhi #define MAXIM_DEV0_NAME		"i2c-MX98373:00"
2235dc19adSYong Zhi #define MAXIM_DEV1_NAME		"i2c-MX98373:01"
2335dc19adSYong Zhi 
2435dc19adSYong Zhi struct hdmi_pcm {
2535dc19adSYong Zhi 	struct list_head head;
2635dc19adSYong Zhi 	struct snd_soc_dai *codec_dai;
2735dc19adSYong Zhi 	int device;
2835dc19adSYong Zhi };
2935dc19adSYong Zhi 
3035dc19adSYong Zhi struct card_private {
3135dc19adSYong Zhi 	struct snd_soc_jack headset;
3235dc19adSYong Zhi 	struct list_head hdmi_pcm_list;
3335dc19adSYong Zhi 	struct snd_soc_jack hdmi[3];
3435dc19adSYong Zhi };
3535dc19adSYong Zhi 
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)3635dc19adSYong Zhi static int platform_clock_control(struct snd_soc_dapm_widget *w,
3735dc19adSYong Zhi 				  struct snd_kcontrol *k, int  event)
3835dc19adSYong Zhi {
3935dc19adSYong Zhi 	struct snd_soc_dapm_context *dapm = w->dapm;
4035dc19adSYong Zhi 	struct snd_soc_card *card = dapm->card;
4135dc19adSYong Zhi 	struct snd_soc_dai *codec_dai;
4235dc19adSYong Zhi 	int ret = 0;
4335dc19adSYong Zhi 
4435dc19adSYong Zhi 	codec_dai = snd_soc_card_get_codec_dai(card, DIALOG_CODEC_DAI);
4535dc19adSYong Zhi 	if (!codec_dai) {
4635dc19adSYong Zhi 		dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
4735dc19adSYong Zhi 		return -EIO;
4835dc19adSYong Zhi 	}
4935dc19adSYong Zhi 
5035dc19adSYong Zhi 	if (SND_SOC_DAPM_EVENT_OFF(event)) {
5135dc19adSYong Zhi 		ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK,
5235dc19adSYong Zhi 					  0, 0);
5335dc19adSYong Zhi 		if (ret)
5435dc19adSYong Zhi 			dev_err(card->dev, "failed to stop PLL: %d\n", ret);
5535dc19adSYong Zhi 	} else if (SND_SOC_DAPM_EVENT_ON(event)) {
5635dc19adSYong Zhi 		ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
5735dc19adSYong Zhi 					  0, DA7219_PLL_FREQ_OUT_98304);
5835dc19adSYong Zhi 		if (ret)
5935dc19adSYong Zhi 			dev_err(card->dev, "failed to start PLL: %d\n", ret);
6035dc19adSYong Zhi 	}
6135dc19adSYong Zhi 
6235dc19adSYong Zhi 	return ret;
6335dc19adSYong Zhi }
6435dc19adSYong Zhi 
6535dc19adSYong Zhi static const struct snd_kcontrol_new controls[] = {
6635dc19adSYong Zhi 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
6735dc19adSYong Zhi 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
68*7265089aSAlper Nebi Yasak 	SOC_DAPM_PIN_SWITCH("Line Out"),
6935dc19adSYong Zhi 	SOC_DAPM_PIN_SWITCH("Left Spk"),
7035dc19adSYong Zhi 	SOC_DAPM_PIN_SWITCH("Right Spk"),
7135dc19adSYong Zhi };
7235dc19adSYong Zhi 
733f32e596SYong Zhi static const struct snd_kcontrol_new m98360a_controls[] = {
743f32e596SYong Zhi 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
753f32e596SYong Zhi 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
76*7265089aSAlper Nebi Yasak 	SOC_DAPM_PIN_SWITCH("Line Out"),
7790c49d6aSYong Zhi 	SOC_DAPM_PIN_SWITCH("Spk"),
783f32e596SYong Zhi };
793f32e596SYong Zhi 
8090c49d6aSYong Zhi /* For MAX98373 amp */
8135dc19adSYong Zhi static const struct snd_soc_dapm_widget widgets[] = {
8235dc19adSYong Zhi 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
8335dc19adSYong Zhi 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
84*7265089aSAlper Nebi Yasak 	SND_SOC_DAPM_LINE("Line Out", NULL),
8590c49d6aSYong Zhi 
8690c49d6aSYong Zhi 	SND_SOC_DAPM_SPK("Left Spk", NULL),
8790c49d6aSYong Zhi 	SND_SOC_DAPM_SPK("Right Spk", NULL),
8890c49d6aSYong Zhi 
8935dc19adSYong Zhi 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
9035dc19adSYong Zhi 			    platform_clock_control, SND_SOC_DAPM_POST_PMD |
9135dc19adSYong Zhi 			    SND_SOC_DAPM_PRE_PMU),
9235e648ccSKeyon Jie 
9335e648ccSKeyon Jie 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
9435dc19adSYong Zhi };
9535dc19adSYong Zhi 
9635dc19adSYong Zhi static const struct snd_soc_dapm_route audio_map[] = {
9735dc19adSYong Zhi 	{ "Headphone Jack", NULL, "HPL" },
9835dc19adSYong Zhi 	{ "Headphone Jack", NULL, "HPR" },
9935dc19adSYong Zhi 
10035dc19adSYong Zhi 	{ "MIC", NULL, "Headset Mic" },
10135dc19adSYong Zhi 
10235dc19adSYong Zhi 	{ "Headphone Jack", NULL, "Platform Clock" },
10335dc19adSYong Zhi 	{ "Headset Mic", NULL, "Platform Clock" },
104*7265089aSAlper Nebi Yasak 	{ "Line Out", NULL, "Platform Clock" },
10535dc19adSYong Zhi 
1063f32e596SYong Zhi 	{ "Left Spk", NULL, "Left BE_OUT" },
1073f32e596SYong Zhi 	{ "Right Spk", NULL, "Right BE_OUT" },
10835e648ccSKeyon Jie 
10935e648ccSKeyon Jie 	/* digital mics */
11035e648ccSKeyon Jie 	{"DMic", NULL, "SoC DMIC"},
1113f32e596SYong Zhi };
1123f32e596SYong Zhi 
11390c49d6aSYong Zhi /* For MAX98360A amp */
11490c49d6aSYong Zhi static const struct snd_soc_dapm_widget max98360a_widgets[] = {
11590c49d6aSYong Zhi 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
11690c49d6aSYong Zhi 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
117*7265089aSAlper Nebi Yasak 	SND_SOC_DAPM_LINE("Line Out", NULL),
11890c49d6aSYong Zhi 
11990c49d6aSYong Zhi 	SND_SOC_DAPM_SPK("Spk", NULL),
12090c49d6aSYong Zhi 
12190c49d6aSYong Zhi 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
12290c49d6aSYong Zhi 			    platform_clock_control, SND_SOC_DAPM_POST_PMD |
12390c49d6aSYong Zhi 			    SND_SOC_DAPM_PRE_PMU),
12435e648ccSKeyon Jie 
12535e648ccSKeyon Jie 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
12690c49d6aSYong Zhi };
12790c49d6aSYong Zhi 
12890c49d6aSYong Zhi static const struct snd_soc_dapm_route max98360a_map[] = {
12990c49d6aSYong Zhi 	{ "Headphone Jack", NULL, "HPL" },
13090c49d6aSYong Zhi 	{ "Headphone Jack", NULL, "HPR" },
13190c49d6aSYong Zhi 
13290c49d6aSYong Zhi 	{ "MIC", NULL, "Headset Mic" },
13390c49d6aSYong Zhi 
13490c49d6aSYong Zhi 	{ "Headphone Jack", NULL, "Platform Clock" },
13590c49d6aSYong Zhi 	{ "Headset Mic", NULL, "Platform Clock" },
136*7265089aSAlper Nebi Yasak 	{ "Line Out", NULL, "Platform Clock" },
13790c49d6aSYong Zhi 
13890c49d6aSYong Zhi 	{"Spk", NULL, "Speaker"},
13935e648ccSKeyon Jie 
14035e648ccSKeyon Jie 	/* digital mics */
14135e648ccSKeyon Jie 	{"DMic", NULL, "SoC DMIC"},
14290c49d6aSYong Zhi };
14390c49d6aSYong Zhi 
1442913bb1fSPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
1452913bb1fSPierre-Louis Bossart 	{
1462913bb1fSPierre-Louis Bossart 		.pin    = "Headphone Jack",
1472913bb1fSPierre-Louis Bossart 		.mask   = SND_JACK_HEADPHONE,
1482913bb1fSPierre-Louis Bossart 	},
1492913bb1fSPierre-Louis Bossart 	{
1502913bb1fSPierre-Louis Bossart 		.pin    = "Headset Mic",
1512913bb1fSPierre-Louis Bossart 		.mask   = SND_JACK_MICROPHONE,
1522913bb1fSPierre-Louis Bossart 	},
153*7265089aSAlper Nebi Yasak 	{
154*7265089aSAlper Nebi Yasak 		.pin    = "Line Out",
155*7265089aSAlper Nebi Yasak 		.mask   = SND_JACK_LINEOUT,
156*7265089aSAlper Nebi Yasak 	},
1572913bb1fSPierre-Louis Bossart };
1582913bb1fSPierre-Louis Bossart 
15935dc19adSYong Zhi static struct snd_soc_jack headset;
16035dc19adSYong Zhi 
da7219_codec_init(struct snd_soc_pcm_runtime * rtd)16135dc19adSYong Zhi static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
16235dc19adSYong Zhi {
1630d1571c1SKuninori Morimoto 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
1640d1571c1SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
16535dc19adSYong Zhi 	struct snd_soc_jack *jack;
16635dc19adSYong Zhi 	int ret;
16735dc19adSYong Zhi 
16835dc19adSYong Zhi 	/* Configure sysclk for codec */
16935dc19adSYong Zhi 	ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24000000,
17035dc19adSYong Zhi 				     SND_SOC_CLOCK_IN);
17135dc19adSYong Zhi 	if (ret) {
17235dc19adSYong Zhi 		dev_err(rtd->dev, "can't set codec sysclk configuration\n");
17335dc19adSYong Zhi 		return ret;
17435dc19adSYong Zhi 	}
17535dc19adSYong Zhi 
17635dc19adSYong Zhi 	/*
17735dc19adSYong Zhi 	 * Headset buttons map to the google Reference headset.
17835dc19adSYong Zhi 	 * These can be configured by userspace.
17935dc19adSYong Zhi 	 */
1802913bb1fSPierre-Louis Bossart 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
18135dc19adSYong Zhi 					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
18235dc19adSYong Zhi 					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
18335dc19adSYong Zhi 					 SND_JACK_BTN_3 | SND_JACK_LINEOUT,
1842913bb1fSPierre-Louis Bossart 					 &headset,
1852913bb1fSPierre-Louis Bossart 					 jack_pins,
1862913bb1fSPierre-Louis Bossart 					 ARRAY_SIZE(jack_pins));
18735dc19adSYong Zhi 	if (ret) {
18835dc19adSYong Zhi 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
18935dc19adSYong Zhi 		return ret;
19035dc19adSYong Zhi 	}
19135dc19adSYong Zhi 
19235dc19adSYong Zhi 	jack = &headset;
19335dc19adSYong Zhi 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
19435dc19adSYong Zhi 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
19535dc19adSYong Zhi 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
19635dc19adSYong Zhi 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
1979a1fe79dSCezary Rojewski 	snd_soc_component_set_jack(component, jack, NULL);
19835dc19adSYong Zhi 
19935dc19adSYong Zhi 	return ret;
20035dc19adSYong Zhi }
20135dc19adSYong Zhi 
ssp1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)20235dc19adSYong Zhi static int ssp1_hw_params(struct snd_pcm_substream *substream,
20335dc19adSYong Zhi 			      struct snd_pcm_hw_params *params)
20435dc19adSYong Zhi {
2052207b93bSKuninori Morimoto 	struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream);
20635dc19adSYong Zhi 	int ret, j;
20735dc19adSYong Zhi 
2080402cca4SNathan Chancellor 	for (j = 0; j < runtime->dai_link->num_codecs; j++) {
2090d1571c1SKuninori Morimoto 		struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, j);
21035dc19adSYong Zhi 
21135dc19adSYong Zhi 		if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
21235dc19adSYong Zhi 			/* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */
21335dc19adSYong Zhi 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16);
21435dc19adSYong Zhi 			if (ret < 0) {
21535dc19adSYong Zhi 				dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret);
21635dc19adSYong Zhi 				return ret;
21735dc19adSYong Zhi 			}
21835dc19adSYong Zhi 		}
21935dc19adSYong Zhi 		if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
22035dc19adSYong Zhi 			/* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */
22135dc19adSYong Zhi 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16);
22235dc19adSYong Zhi 			if (ret < 0) {
22335dc19adSYong Zhi 				dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret);
22435dc19adSYong Zhi 				return ret;
22535dc19adSYong Zhi 			}
22635dc19adSYong Zhi 		}
22735dc19adSYong Zhi 	}
22835dc19adSYong Zhi 
22935dc19adSYong Zhi 	return 0;
23035dc19adSYong Zhi }
23135dc19adSYong Zhi 
23235dc19adSYong Zhi static struct snd_soc_ops ssp1_ops = {
23335dc19adSYong Zhi 	.hw_params = ssp1_hw_params,
23435dc19adSYong Zhi };
23535dc19adSYong Zhi 
23635dc19adSYong Zhi static struct snd_soc_codec_conf max98373_codec_conf[] = {
23735dc19adSYong Zhi 	{
23835dc19adSYong Zhi 		.dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME),
23935dc19adSYong Zhi 		.name_prefix = "Right",
24035dc19adSYong Zhi 	},
24135dc19adSYong Zhi 	{
24235dc19adSYong Zhi 		.dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME),
24335dc19adSYong Zhi 		.name_prefix = "Left",
24435dc19adSYong Zhi 	},
24535dc19adSYong Zhi };
24635dc19adSYong Zhi 
hdmi_init(struct snd_soc_pcm_runtime * rtd)24735dc19adSYong Zhi static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
24835dc19adSYong Zhi {
24935dc19adSYong Zhi 	struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
2500d1571c1SKuninori Morimoto 	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
25135dc19adSYong Zhi 	struct hdmi_pcm *pcm;
25235dc19adSYong Zhi 
25335dc19adSYong Zhi 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
25435dc19adSYong Zhi 	if (!pcm)
25535dc19adSYong Zhi 		return -ENOMEM;
25635dc19adSYong Zhi 
25735dc19adSYong Zhi 	pcm->device = dai->id;
25835dc19adSYong Zhi 	pcm->codec_dai = dai;
25935dc19adSYong Zhi 
26035dc19adSYong Zhi 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
26135dc19adSYong Zhi 
26235dc19adSYong Zhi 	return 0;
26335dc19adSYong Zhi }
26435dc19adSYong Zhi 
card_late_probe(struct snd_soc_card * card)26535dc19adSYong Zhi static int card_late_probe(struct snd_soc_card *card)
26635dc19adSYong Zhi {
26735dc19adSYong Zhi 	struct card_private *ctx = snd_soc_card_get_drvdata(card);
26835dc19adSYong Zhi 	struct snd_soc_acpi_mach *mach = (card->dev)->platform_data;
26935dc19adSYong Zhi 	struct hdmi_pcm *pcm;
27035dc19adSYong Zhi 
27135dc19adSYong Zhi 	if (mach->mach_params.common_hdmi_codec_drv) {
27235dc19adSYong Zhi 		pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
27335dc19adSYong Zhi 				       head);
27435dc19adSYong Zhi 		return hda_dsp_hdmi_build_controls(card,
27535dc19adSYong Zhi 						   pcm->codec_dai->component);
27635dc19adSYong Zhi 	}
27735dc19adSYong Zhi 
27835dc19adSYong Zhi 	return -EINVAL;
27935dc19adSYong Zhi }
28035dc19adSYong Zhi 
28135dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp0_pin,
28235dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
28335dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp0_codec,
28435dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", DIALOG_CODEC_DAI)));
28535dc19adSYong Zhi 
28635dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp1_pin,
28735dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
28835dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp1_amps,
28935dc19adSYong Zhi 	DAILINK_COMP_ARRAY(
29035dc19adSYong Zhi 	/* Left */	COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI),
29135dc19adSYong Zhi 	/* Right */	COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI)));
29290c49d6aSYong Zhi 
29390c49d6aSYong Zhi SND_SOC_DAILINK_DEF(ssp1_m98360a,
29490c49d6aSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
29535dc19adSYong Zhi 
29635dc19adSYong Zhi SND_SOC_DAILINK_DEF(dmic_pin,
29735dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
29835dc19adSYong Zhi SND_SOC_DAILINK_DEF(dmic_codec,
29935dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
30035dc19adSYong Zhi 
301a8bb72f1SYong Zhi SND_SOC_DAILINK_DEF(dmic16k_pin,
302a8bb72f1SYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
303a8bb72f1SYong Zhi 
30435dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp1_pin,
30535dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
30635dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp1_codec,
30735dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
30835dc19adSYong Zhi 
30935dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp2_pin,
31035dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
31135dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp2_codec,
31235dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
31335dc19adSYong Zhi 
31435dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp3_pin,
31535dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
31635dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp3_codec,
31735dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
31835dc19adSYong Zhi 
31935dc19adSYong Zhi SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */
32035dc19adSYong Zhi 	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
32135dc19adSYong Zhi 
32235dc19adSYong Zhi static struct snd_soc_dai_link dais[] = {
32335dc19adSYong Zhi 	/* Back End DAI links */
32435dc19adSYong Zhi 	{
32535dc19adSYong Zhi 		.name = "SSP1-Codec",
32635dc19adSYong Zhi 		.id = 0,
32735dc19adSYong Zhi 		.ignore_pmdown_time = 1,
32835dc19adSYong Zhi 		.no_pcm = 1,
32935dc19adSYong Zhi 		.dpcm_playback = 1,
33035dc19adSYong Zhi 		.dpcm_capture = 1, /* IV feedback */
33135dc19adSYong Zhi 		.ops = &ssp1_ops,
33235dc19adSYong Zhi 		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_amps, platform),
33335dc19adSYong Zhi 	},
33435dc19adSYong Zhi 	{
33535dc19adSYong Zhi 		.name = "SSP0-Codec",
33635dc19adSYong Zhi 		.id = 1,
33735dc19adSYong Zhi 		.no_pcm = 1,
33835dc19adSYong Zhi 		.init = da7219_codec_init,
33935dc19adSYong Zhi 		.ignore_pmdown_time = 1,
34035dc19adSYong Zhi 		.dpcm_playback = 1,
34135dc19adSYong Zhi 		.dpcm_capture = 1,
34235dc19adSYong Zhi 		SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
34335dc19adSYong Zhi 	},
34435dc19adSYong Zhi 	{
34535dc19adSYong Zhi 		.name = "dmic01",
34635dc19adSYong Zhi 		.id = 2,
34735dc19adSYong Zhi 		.ignore_suspend = 1,
34835dc19adSYong Zhi 		.dpcm_capture = 1,
34935dc19adSYong Zhi 		.no_pcm = 1,
35035dc19adSYong Zhi 		SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
35135dc19adSYong Zhi 	},
35235dc19adSYong Zhi 	{
35335dc19adSYong Zhi 		.name = "iDisp1",
35435dc19adSYong Zhi 		.id = 3,
35535dc19adSYong Zhi 		.init = hdmi_init,
35635dc19adSYong Zhi 		.dpcm_playback = 1,
35735dc19adSYong Zhi 		.no_pcm = 1,
35835dc19adSYong Zhi 		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
35935dc19adSYong Zhi 	},
36035dc19adSYong Zhi 	{
36135dc19adSYong Zhi 		.name = "iDisp2",
36235dc19adSYong Zhi 		.id = 4,
36335dc19adSYong Zhi 		.init = hdmi_init,
36435dc19adSYong Zhi 		.dpcm_playback = 1,
36535dc19adSYong Zhi 		.no_pcm = 1,
36635dc19adSYong Zhi 		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
36735dc19adSYong Zhi 	},
36835dc19adSYong Zhi 	{
36935dc19adSYong Zhi 		.name = "iDisp3",
37035dc19adSYong Zhi 		.id = 5,
37135dc19adSYong Zhi 		.init = hdmi_init,
37235dc19adSYong Zhi 		.dpcm_playback = 1,
37335dc19adSYong Zhi 		.no_pcm = 1,
37435dc19adSYong Zhi 		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
37535dc19adSYong Zhi 	},
376a8bb72f1SYong Zhi 	{
377a8bb72f1SYong Zhi 		.name = "dmic16k",
378a8bb72f1SYong Zhi 		.id = 6,
379a8bb72f1SYong Zhi 		.ignore_suspend = 1,
380a8bb72f1SYong Zhi 		.dpcm_capture = 1,
381a8bb72f1SYong Zhi 		.no_pcm = 1,
382a8bb72f1SYong Zhi 		SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
383a8bb72f1SYong Zhi 	}
38435dc19adSYong Zhi };
38535dc19adSYong Zhi 
38635dc19adSYong Zhi static struct snd_soc_card card_da7219_m98373 = {
38735dc19adSYong Zhi 	.name = "da7219max",
38835dc19adSYong Zhi 	.owner = THIS_MODULE,
38935dc19adSYong Zhi 	.dai_link = dais,
39035dc19adSYong Zhi 	.num_links = ARRAY_SIZE(dais),
39135dc19adSYong Zhi 	.controls = controls,
39235dc19adSYong Zhi 	.num_controls = ARRAY_SIZE(controls),
39335dc19adSYong Zhi 	.dapm_widgets = widgets,
39435dc19adSYong Zhi 	.num_dapm_widgets = ARRAY_SIZE(widgets),
39535dc19adSYong Zhi 	.dapm_routes = audio_map,
39635dc19adSYong Zhi 	.num_dapm_routes = ARRAY_SIZE(audio_map),
39735dc19adSYong Zhi 	.codec_conf = max98373_codec_conf,
39835dc19adSYong Zhi 	.num_configs = ARRAY_SIZE(max98373_codec_conf),
39935dc19adSYong Zhi 	.fully_routed = true,
40035dc19adSYong Zhi 	.late_probe = card_late_probe,
40135dc19adSYong Zhi };
40235dc19adSYong Zhi 
4033f32e596SYong Zhi static struct snd_soc_card card_da7219_m98360a = {
4043f32e596SYong Zhi 	.name = "da7219max98360a",
4053f32e596SYong Zhi 	.owner = THIS_MODULE,
4063f32e596SYong Zhi 	.dai_link = dais,
4073f32e596SYong Zhi 	.num_links = ARRAY_SIZE(dais),
4083f32e596SYong Zhi 	.controls = m98360a_controls,
4093f32e596SYong Zhi 	.num_controls = ARRAY_SIZE(m98360a_controls),
41090c49d6aSYong Zhi 	.dapm_widgets = max98360a_widgets,
41190c49d6aSYong Zhi 	.num_dapm_widgets = ARRAY_SIZE(max98360a_widgets),
41290c49d6aSYong Zhi 	.dapm_routes = max98360a_map,
41390c49d6aSYong Zhi 	.num_dapm_routes = ARRAY_SIZE(max98360a_map),
4143f32e596SYong Zhi 	.fully_routed = true,
4153f32e596SYong Zhi 	.late_probe = card_late_probe,
4163f32e596SYong Zhi };
4173f32e596SYong Zhi 
audio_probe(struct platform_device * pdev)41835dc19adSYong Zhi static int audio_probe(struct platform_device *pdev)
41935dc19adSYong Zhi {
42035dc19adSYong Zhi 	static struct snd_soc_card *card;
42135dc19adSYong Zhi 	struct snd_soc_acpi_mach *mach;
42235dc19adSYong Zhi 	struct card_private *ctx;
42335dc19adSYong Zhi 	int ret;
42435dc19adSYong Zhi 
4252e6529a5SPierre-Louis Bossart 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
42635dc19adSYong Zhi 	if (!ctx)
42735dc19adSYong Zhi 		return -ENOMEM;
42835dc19adSYong Zhi 
4293f32e596SYong Zhi 	/* By default dais[0] is configured for max98373 */
4300f32d9ebSBrent Lu 	if (!strcmp(pdev->name, "sof_da7219_mx98360a")) {
4313f32e596SYong Zhi 		dais[0] = (struct snd_soc_dai_link) {
4323f32e596SYong Zhi 			.name = "SSP1-Codec",
4333f32e596SYong Zhi 			.id = 0,
4343f32e596SYong Zhi 			.no_pcm = 1,
4353f32e596SYong Zhi 			.dpcm_playback = 1,
4363f32e596SYong Zhi 			.ignore_pmdown_time = 1,
43790c49d6aSYong Zhi 			SND_SOC_DAILINK_REG(ssp1_pin, ssp1_m98360a, platform) };
4383f32e596SYong Zhi 	}
4393f32e596SYong Zhi 
44035dc19adSYong Zhi 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
44135dc19adSYong Zhi 	card = (struct snd_soc_card *)pdev->id_entry->driver_data;
44235dc19adSYong Zhi 	card->dev = &pdev->dev;
44335dc19adSYong Zhi 
44442432196SGuennadi Liakhovetski 	mach = pdev->dev.platform_data;
44535dc19adSYong Zhi 	ret = snd_soc_fixup_dai_links_platform_name(card,
44635dc19adSYong Zhi 						    mach->mach_params.platform);
44735dc19adSYong Zhi 	if (ret)
44835dc19adSYong Zhi 		return ret;
44935dc19adSYong Zhi 
45035dc19adSYong Zhi 	snd_soc_card_set_drvdata(card, ctx);
45135dc19adSYong Zhi 
45235dc19adSYong Zhi 	return devm_snd_soc_register_card(&pdev->dev, card);
45335dc19adSYong Zhi }
45435dc19adSYong Zhi 
45535dc19adSYong Zhi static const struct platform_device_id board_ids[] = {
45635dc19adSYong Zhi 	{
4571cc04d19SPierre-Louis Bossart 		.name = "sof_da7219_mx98373",
45835dc19adSYong Zhi 		.driver_data = (kernel_ulong_t)&card_da7219_m98373,
45935dc19adSYong Zhi 	},
4603f32e596SYong Zhi 	{
4611cc04d19SPierre-Louis Bossart 		.name = "sof_da7219_mx98360a",
4623f32e596SYong Zhi 		.driver_data = (kernel_ulong_t)&card_da7219_m98360a,
4633f32e596SYong Zhi 	},
46435dc19adSYong Zhi 	{ }
46535dc19adSYong Zhi };
466a75e5cdfSZou Wei MODULE_DEVICE_TABLE(platform, board_ids);
46735dc19adSYong Zhi 
46835dc19adSYong Zhi static struct platform_driver audio = {
46935dc19adSYong Zhi 	.probe = audio_probe,
47035dc19adSYong Zhi 	.driver = {
4713f32e596SYong Zhi 		.name = "sof_da7219_max98_360a_373",
47235dc19adSYong Zhi 		.pm = &snd_soc_pm_ops,
47335dc19adSYong Zhi 	},
47435dc19adSYong Zhi 	.id_table = board_ids,
47535dc19adSYong Zhi };
47635dc19adSYong Zhi module_platform_driver(audio)
47735dc19adSYong Zhi 
47835dc19adSYong Zhi /* Module information */
47935dc19adSYong Zhi MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver");
48035dc19adSYong Zhi MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
48135dc19adSYong Zhi MODULE_LICENSE("GPL v2");
482f6081af6SPierre-Louis Bossart MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
483