xref: /OK3568_Linux_fs/kernel/sound/soc/intel/boards/sof_da7219_max98373.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun // Copyright(c) 2019 Intel Corporation.
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  * Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/input.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <sound/pcm.h>
11*4882a593Smuzhiyun #include <sound/pcm_params.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include <sound/soc.h>
14*4882a593Smuzhiyun #include <sound/soc-acpi.h>
15*4882a593Smuzhiyun #include "../../codecs/da7219.h"
16*4882a593Smuzhiyun #include "../../codecs/da7219-aad.h"
17*4882a593Smuzhiyun #include "hda_dsp_common.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define DIALOG_CODEC_DAI	"da7219-hifi"
20*4882a593Smuzhiyun #define MAX98373_CODEC_DAI	"max98373-aif1"
21*4882a593Smuzhiyun #define MAXIM_DEV0_NAME		"i2c-MX98373:00"
22*4882a593Smuzhiyun #define MAXIM_DEV1_NAME		"i2c-MX98373:01"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun struct hdmi_pcm {
25*4882a593Smuzhiyun 	struct list_head head;
26*4882a593Smuzhiyun 	struct snd_soc_dai *codec_dai;
27*4882a593Smuzhiyun 	int device;
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct card_private {
31*4882a593Smuzhiyun 	struct snd_soc_jack headset;
32*4882a593Smuzhiyun 	struct list_head hdmi_pcm_list;
33*4882a593Smuzhiyun 	struct snd_soc_jack hdmi[3];
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)36*4882a593Smuzhiyun static int platform_clock_control(struct snd_soc_dapm_widget *w,
37*4882a593Smuzhiyun 				  struct snd_kcontrol *k, int  event)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = w->dapm;
40*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
41*4882a593Smuzhiyun 	struct snd_soc_dai *codec_dai;
42*4882a593Smuzhiyun 	int ret = 0;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	codec_dai = snd_soc_card_get_codec_dai(card, DIALOG_CODEC_DAI);
45*4882a593Smuzhiyun 	if (!codec_dai) {
46*4882a593Smuzhiyun 		dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
47*4882a593Smuzhiyun 		return -EIO;
48*4882a593Smuzhiyun 	}
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	if (SND_SOC_DAPM_EVENT_OFF(event)) {
51*4882a593Smuzhiyun 		ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK,
52*4882a593Smuzhiyun 					  0, 0);
53*4882a593Smuzhiyun 		if (ret)
54*4882a593Smuzhiyun 			dev_err(card->dev, "failed to stop PLL: %d\n", ret);
55*4882a593Smuzhiyun 	} else if (SND_SOC_DAPM_EVENT_ON(event)) {
56*4882a593Smuzhiyun 		ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
57*4882a593Smuzhiyun 					  0, DA7219_PLL_FREQ_OUT_98304);
58*4882a593Smuzhiyun 		if (ret)
59*4882a593Smuzhiyun 			dev_err(card->dev, "failed to start PLL: %d\n", ret);
60*4882a593Smuzhiyun 	}
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	return ret;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun static const struct snd_kcontrol_new controls[] = {
66*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
67*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
68*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Left Spk"),
69*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Right Spk"),
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static const struct snd_kcontrol_new m98360a_controls[] = {
73*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
74*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
75*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Spk"),
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* For MAX98373 amp */
79*4882a593Smuzhiyun static const struct snd_soc_dapm_widget widgets[] = {
80*4882a593Smuzhiyun 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
81*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	SND_SOC_DAPM_SPK("Left Spk", NULL),
84*4882a593Smuzhiyun 	SND_SOC_DAPM_SPK("Right Spk", NULL),
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
87*4882a593Smuzhiyun 			    platform_clock_control, SND_SOC_DAPM_POST_PMD |
88*4882a593Smuzhiyun 			    SND_SOC_DAPM_PRE_PMU),
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static const struct snd_soc_dapm_route audio_map[] = {
94*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "HPL" },
95*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "HPR" },
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	{ "MIC", NULL, "Headset Mic" },
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "Platform Clock" },
100*4882a593Smuzhiyun 	{ "Headset Mic", NULL, "Platform Clock" },
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	{ "Left Spk", NULL, "Left BE_OUT" },
103*4882a593Smuzhiyun 	{ "Right Spk", NULL, "Right BE_OUT" },
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* digital mics */
106*4882a593Smuzhiyun 	{"DMic", NULL, "SoC DMIC"},
107*4882a593Smuzhiyun };
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /* For MAX98360A amp */
110*4882a593Smuzhiyun static const struct snd_soc_dapm_widget max98360a_widgets[] = {
111*4882a593Smuzhiyun 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
112*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	SND_SOC_DAPM_SPK("Spk", NULL),
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
117*4882a593Smuzhiyun 			    platform_clock_control, SND_SOC_DAPM_POST_PMD |
118*4882a593Smuzhiyun 			    SND_SOC_DAPM_PRE_PMU),
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static const struct snd_soc_dapm_route max98360a_map[] = {
124*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "HPL" },
125*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "HPR" },
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	{ "MIC", NULL, "Headset Mic" },
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	{ "Headphone Jack", NULL, "Platform Clock" },
130*4882a593Smuzhiyun 	{ "Headset Mic", NULL, "Platform Clock" },
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	{"Spk", NULL, "Speaker"},
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* digital mics */
135*4882a593Smuzhiyun 	{"DMic", NULL, "SoC DMIC"},
136*4882a593Smuzhiyun };
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun static struct snd_soc_jack headset;
139*4882a593Smuzhiyun 
da7219_codec_init(struct snd_soc_pcm_runtime * rtd)140*4882a593Smuzhiyun static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
143*4882a593Smuzhiyun 	struct snd_soc_component *component = codec_dai->component;
144*4882a593Smuzhiyun 	struct snd_soc_jack *jack;
145*4882a593Smuzhiyun 	int ret;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	/* Configure sysclk for codec */
148*4882a593Smuzhiyun 	ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24000000,
149*4882a593Smuzhiyun 				     SND_SOC_CLOCK_IN);
150*4882a593Smuzhiyun 	if (ret) {
151*4882a593Smuzhiyun 		dev_err(rtd->dev, "can't set codec sysclk configuration\n");
152*4882a593Smuzhiyun 		return ret;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/*
156*4882a593Smuzhiyun 	 * Headset buttons map to the google Reference headset.
157*4882a593Smuzhiyun 	 * These can be configured by userspace.
158*4882a593Smuzhiyun 	 */
159*4882a593Smuzhiyun 	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
160*4882a593Smuzhiyun 				    SND_JACK_HEADSET | SND_JACK_BTN_0 |
161*4882a593Smuzhiyun 				    SND_JACK_BTN_1 | SND_JACK_BTN_2 |
162*4882a593Smuzhiyun 				    SND_JACK_BTN_3 | SND_JACK_LINEOUT,
163*4882a593Smuzhiyun 				    &headset, NULL, 0);
164*4882a593Smuzhiyun 	if (ret) {
165*4882a593Smuzhiyun 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
166*4882a593Smuzhiyun 		return ret;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	jack = &headset;
170*4882a593Smuzhiyun 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
171*4882a593Smuzhiyun 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
172*4882a593Smuzhiyun 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
173*4882a593Smuzhiyun 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
174*4882a593Smuzhiyun 	da7219_aad_jack_det(component, jack);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	return ret;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
ssp1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)179*4882a593Smuzhiyun static int ssp1_hw_params(struct snd_pcm_substream *substream,
180*4882a593Smuzhiyun 			      struct snd_pcm_hw_params *params)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream);
183*4882a593Smuzhiyun 	int ret, j;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	for (j = 0; j < runtime->num_codecs; j++) {
186*4882a593Smuzhiyun 		struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, j);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 		if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
189*4882a593Smuzhiyun 			/* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */
190*4882a593Smuzhiyun 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16);
191*4882a593Smuzhiyun 			if (ret < 0) {
192*4882a593Smuzhiyun 				dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret);
193*4882a593Smuzhiyun 				return ret;
194*4882a593Smuzhiyun 			}
195*4882a593Smuzhiyun 		}
196*4882a593Smuzhiyun 		if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
197*4882a593Smuzhiyun 			/* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */
198*4882a593Smuzhiyun 			ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16);
199*4882a593Smuzhiyun 			if (ret < 0) {
200*4882a593Smuzhiyun 				dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret);
201*4882a593Smuzhiyun 				return ret;
202*4882a593Smuzhiyun 			}
203*4882a593Smuzhiyun 		}
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun static struct snd_soc_ops ssp1_ops = {
210*4882a593Smuzhiyun 	.hw_params = ssp1_hw_params,
211*4882a593Smuzhiyun };
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun static struct snd_soc_codec_conf max98373_codec_conf[] = {
214*4882a593Smuzhiyun 	{
215*4882a593Smuzhiyun 		.dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME),
216*4882a593Smuzhiyun 		.name_prefix = "Right",
217*4882a593Smuzhiyun 	},
218*4882a593Smuzhiyun 	{
219*4882a593Smuzhiyun 		.dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME),
220*4882a593Smuzhiyun 		.name_prefix = "Left",
221*4882a593Smuzhiyun 	},
222*4882a593Smuzhiyun };
223*4882a593Smuzhiyun 
hdmi_init(struct snd_soc_pcm_runtime * rtd)224*4882a593Smuzhiyun static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
227*4882a593Smuzhiyun 	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
228*4882a593Smuzhiyun 	struct hdmi_pcm *pcm;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
231*4882a593Smuzhiyun 	if (!pcm)
232*4882a593Smuzhiyun 		return -ENOMEM;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	pcm->device = dai->id;
235*4882a593Smuzhiyun 	pcm->codec_dai = dai;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
card_late_probe(struct snd_soc_card * card)242*4882a593Smuzhiyun static int card_late_probe(struct snd_soc_card *card)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	struct card_private *ctx = snd_soc_card_get_drvdata(card);
245*4882a593Smuzhiyun 	struct snd_soc_acpi_mach *mach = (card->dev)->platform_data;
246*4882a593Smuzhiyun 	struct hdmi_pcm *pcm;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (mach->mach_params.common_hdmi_codec_drv) {
249*4882a593Smuzhiyun 		pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
250*4882a593Smuzhiyun 				       head);
251*4882a593Smuzhiyun 		return hda_dsp_hdmi_build_controls(card,
252*4882a593Smuzhiyun 						   pcm->codec_dai->component);
253*4882a593Smuzhiyun 	}
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	return -EINVAL;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp0_pin,
259*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
260*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp0_codec,
261*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", DIALOG_CODEC_DAI)));
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp1_pin,
264*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
265*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp1_amps,
266*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(
267*4882a593Smuzhiyun 	/* Left */	COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI),
268*4882a593Smuzhiyun 	/* Right */	COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI)));
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp1_m98360a,
271*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(dmic_pin,
274*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
275*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(dmic_codec,
276*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(dmic16k_pin,
279*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp1_pin,
282*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
283*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp1_codec,
284*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp2_pin,
287*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
288*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp2_codec,
289*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp3_pin,
292*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
293*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(idisp3_codec,
294*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */
297*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun static struct snd_soc_dai_link dais[] = {
300*4882a593Smuzhiyun 	/* Back End DAI links */
301*4882a593Smuzhiyun 	{
302*4882a593Smuzhiyun 		.name = "SSP1-Codec",
303*4882a593Smuzhiyun 		.id = 0,
304*4882a593Smuzhiyun 		.ignore_pmdown_time = 1,
305*4882a593Smuzhiyun 		.no_pcm = 1,
306*4882a593Smuzhiyun 		.dpcm_playback = 1,
307*4882a593Smuzhiyun 		.dpcm_capture = 1, /* IV feedback */
308*4882a593Smuzhiyun 		.ops = &ssp1_ops,
309*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_amps, platform),
310*4882a593Smuzhiyun 	},
311*4882a593Smuzhiyun 	{
312*4882a593Smuzhiyun 		.name = "SSP0-Codec",
313*4882a593Smuzhiyun 		.id = 1,
314*4882a593Smuzhiyun 		.no_pcm = 1,
315*4882a593Smuzhiyun 		.init = da7219_codec_init,
316*4882a593Smuzhiyun 		.ignore_pmdown_time = 1,
317*4882a593Smuzhiyun 		.dpcm_playback = 1,
318*4882a593Smuzhiyun 		.dpcm_capture = 1,
319*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
320*4882a593Smuzhiyun 	},
321*4882a593Smuzhiyun 	{
322*4882a593Smuzhiyun 		.name = "dmic01",
323*4882a593Smuzhiyun 		.id = 2,
324*4882a593Smuzhiyun 		.ignore_suspend = 1,
325*4882a593Smuzhiyun 		.dpcm_capture = 1,
326*4882a593Smuzhiyun 		.no_pcm = 1,
327*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
328*4882a593Smuzhiyun 	},
329*4882a593Smuzhiyun 	{
330*4882a593Smuzhiyun 		.name = "iDisp1",
331*4882a593Smuzhiyun 		.id = 3,
332*4882a593Smuzhiyun 		.init = hdmi_init,
333*4882a593Smuzhiyun 		.dpcm_playback = 1,
334*4882a593Smuzhiyun 		.no_pcm = 1,
335*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
336*4882a593Smuzhiyun 	},
337*4882a593Smuzhiyun 	{
338*4882a593Smuzhiyun 		.name = "iDisp2",
339*4882a593Smuzhiyun 		.id = 4,
340*4882a593Smuzhiyun 		.init = hdmi_init,
341*4882a593Smuzhiyun 		.dpcm_playback = 1,
342*4882a593Smuzhiyun 		.no_pcm = 1,
343*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
344*4882a593Smuzhiyun 	},
345*4882a593Smuzhiyun 	{
346*4882a593Smuzhiyun 		.name = "iDisp3",
347*4882a593Smuzhiyun 		.id = 5,
348*4882a593Smuzhiyun 		.init = hdmi_init,
349*4882a593Smuzhiyun 		.dpcm_playback = 1,
350*4882a593Smuzhiyun 		.no_pcm = 1,
351*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
352*4882a593Smuzhiyun 	},
353*4882a593Smuzhiyun 	{
354*4882a593Smuzhiyun 		.name = "dmic16k",
355*4882a593Smuzhiyun 		.id = 6,
356*4882a593Smuzhiyun 		.ignore_suspend = 1,
357*4882a593Smuzhiyun 		.dpcm_capture = 1,
358*4882a593Smuzhiyun 		.no_pcm = 1,
359*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
360*4882a593Smuzhiyun 	}
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun static struct snd_soc_card card_da7219_m98373 = {
364*4882a593Smuzhiyun 	.name = "da7219max",
365*4882a593Smuzhiyun 	.owner = THIS_MODULE,
366*4882a593Smuzhiyun 	.dai_link = dais,
367*4882a593Smuzhiyun 	.num_links = ARRAY_SIZE(dais),
368*4882a593Smuzhiyun 	.controls = controls,
369*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(controls),
370*4882a593Smuzhiyun 	.dapm_widgets = widgets,
371*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(widgets),
372*4882a593Smuzhiyun 	.dapm_routes = audio_map,
373*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(audio_map),
374*4882a593Smuzhiyun 	.codec_conf = max98373_codec_conf,
375*4882a593Smuzhiyun 	.num_configs = ARRAY_SIZE(max98373_codec_conf),
376*4882a593Smuzhiyun 	.fully_routed = true,
377*4882a593Smuzhiyun 	.late_probe = card_late_probe,
378*4882a593Smuzhiyun };
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun static struct snd_soc_card card_da7219_m98360a = {
381*4882a593Smuzhiyun 	.name = "da7219max98360a",
382*4882a593Smuzhiyun 	.owner = THIS_MODULE,
383*4882a593Smuzhiyun 	.dai_link = dais,
384*4882a593Smuzhiyun 	.num_links = ARRAY_SIZE(dais),
385*4882a593Smuzhiyun 	.controls = m98360a_controls,
386*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(m98360a_controls),
387*4882a593Smuzhiyun 	.dapm_widgets = max98360a_widgets,
388*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(max98360a_widgets),
389*4882a593Smuzhiyun 	.dapm_routes = max98360a_map,
390*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(max98360a_map),
391*4882a593Smuzhiyun 	.fully_routed = true,
392*4882a593Smuzhiyun 	.late_probe = card_late_probe,
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun 
audio_probe(struct platform_device * pdev)395*4882a593Smuzhiyun static int audio_probe(struct platform_device *pdev)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	static struct snd_soc_card *card;
398*4882a593Smuzhiyun 	struct snd_soc_acpi_mach *mach;
399*4882a593Smuzhiyun 	struct card_private *ctx;
400*4882a593Smuzhiyun 	int ret;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
403*4882a593Smuzhiyun 	if (!ctx)
404*4882a593Smuzhiyun 		return -ENOMEM;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	/* By default dais[0] is configured for max98373 */
407*4882a593Smuzhiyun 	if (!strcmp(pdev->name, "sof_da7219_max98360a")) {
408*4882a593Smuzhiyun 		dais[0] = (struct snd_soc_dai_link) {
409*4882a593Smuzhiyun 			.name = "SSP1-Codec",
410*4882a593Smuzhiyun 			.id = 0,
411*4882a593Smuzhiyun 			.no_pcm = 1,
412*4882a593Smuzhiyun 			.dpcm_playback = 1,
413*4882a593Smuzhiyun 			.ignore_pmdown_time = 1,
414*4882a593Smuzhiyun 			SND_SOC_DAILINK_REG(ssp1_pin, ssp1_m98360a, platform) };
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
418*4882a593Smuzhiyun 	card = (struct snd_soc_card *)pdev->id_entry->driver_data;
419*4882a593Smuzhiyun 	card->dev = &pdev->dev;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	mach = pdev->dev.platform_data;
422*4882a593Smuzhiyun 	ret = snd_soc_fixup_dai_links_platform_name(card,
423*4882a593Smuzhiyun 						    mach->mach_params.platform);
424*4882a593Smuzhiyun 	if (ret)
425*4882a593Smuzhiyun 		return ret;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	snd_soc_card_set_drvdata(card, ctx);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	return devm_snd_soc_register_card(&pdev->dev, card);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun static const struct platform_device_id board_ids[] = {
433*4882a593Smuzhiyun 	{
434*4882a593Smuzhiyun 		.name = "sof_da7219_max98373",
435*4882a593Smuzhiyun 		.driver_data = (kernel_ulong_t)&card_da7219_m98373,
436*4882a593Smuzhiyun 	},
437*4882a593Smuzhiyun 	{
438*4882a593Smuzhiyun 		.name = "sof_da7219_max98360a",
439*4882a593Smuzhiyun 		.driver_data = (kernel_ulong_t)&card_da7219_m98360a,
440*4882a593Smuzhiyun 	},
441*4882a593Smuzhiyun 	{ }
442*4882a593Smuzhiyun };
443*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, board_ids);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun static struct platform_driver audio = {
446*4882a593Smuzhiyun 	.probe = audio_probe,
447*4882a593Smuzhiyun 	.driver = {
448*4882a593Smuzhiyun 		.name = "sof_da7219_max98_360a_373",
449*4882a593Smuzhiyun 		.pm = &snd_soc_pm_ops,
450*4882a593Smuzhiyun 	},
451*4882a593Smuzhiyun 	.id_table = board_ids,
452*4882a593Smuzhiyun };
453*4882a593Smuzhiyun module_platform_driver(audio)
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun /* Module information */
456*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver");
457*4882a593Smuzhiyun MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
458*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
459*4882a593Smuzhiyun MODULE_ALIAS("platform:sof_da7219_max98360a");
460*4882a593Smuzhiyun MODULE_ALIAS("platform:sof_da7219_max98373");
461