xref: /OK3568_Linux_fs/kernel/sound/soc/intel/boards/cht_bsw_rt5645.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  cht-bsw-rt5645.c - ASoc Machine driver for Intel Cherryview-based platforms
4*4882a593Smuzhiyun  *                     Cherrytrail and Braswell, with RT5645 codec.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *  Copyright (C) 2015 Intel Corp
7*4882a593Smuzhiyun  *  Author: Fang, Yang A <yang.a.fang@intel.com>
8*4882a593Smuzhiyun  *	        N,Harshapriya <harshapriya.n@intel.com>
9*4882a593Smuzhiyun  *  This file is modified from cht_bsw_rt5672.c
10*4882a593Smuzhiyun  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/acpi.h>
18*4882a593Smuzhiyun #include <linux/clk.h>
19*4882a593Smuzhiyun #include <linux/dmi.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <sound/pcm.h>
22*4882a593Smuzhiyun #include <sound/pcm_params.h>
23*4882a593Smuzhiyun #include <sound/soc.h>
24*4882a593Smuzhiyun #include <sound/jack.h>
25*4882a593Smuzhiyun #include <sound/soc-acpi.h>
26*4882a593Smuzhiyun #include "../../codecs/rt5645.h"
27*4882a593Smuzhiyun #include "../atom/sst-atom-controls.h"
28*4882a593Smuzhiyun #include "../common/soc-intel-quirks.h"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define CHT_PLAT_CLK_3_HZ	19200000
31*4882a593Smuzhiyun #define CHT_CODEC_DAI1	"rt5645-aif1"
32*4882a593Smuzhiyun #define CHT_CODEC_DAI2	"rt5645-aif2"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun struct cht_acpi_card {
35*4882a593Smuzhiyun 	char *codec_id;
36*4882a593Smuzhiyun 	int codec_type;
37*4882a593Smuzhiyun 	struct snd_soc_card *soc_card;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun struct cht_mc_private {
41*4882a593Smuzhiyun 	struct snd_soc_jack jack;
42*4882a593Smuzhiyun 	struct cht_acpi_card *acpi_card;
43*4882a593Smuzhiyun 	char codec_name[SND_ACPI_I2C_ID_LEN];
44*4882a593Smuzhiyun 	struct clk *mclk;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #define CHT_RT5645_MAP(quirk)	((quirk) & GENMASK(7, 0))
48*4882a593Smuzhiyun #define CHT_RT5645_SSP2_AIF2     BIT(16) /* default is using AIF1  */
49*4882a593Smuzhiyun #define CHT_RT5645_SSP0_AIF1     BIT(17)
50*4882a593Smuzhiyun #define CHT_RT5645_SSP0_AIF2     BIT(18)
51*4882a593Smuzhiyun #define CHT_RT5645_PMC_PLT_CLK_0 BIT(19)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static unsigned long cht_rt5645_quirk = 0;
54*4882a593Smuzhiyun 
log_quirks(struct device * dev)55*4882a593Smuzhiyun static void log_quirks(struct device *dev)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2)
58*4882a593Smuzhiyun 		dev_info(dev, "quirk SSP2_AIF2 enabled");
59*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1)
60*4882a593Smuzhiyun 		dev_info(dev, "quirk SSP0_AIF1 enabled");
61*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)
62*4882a593Smuzhiyun 		dev_info(dev, "quirk SSP0_AIF2 enabled");
63*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_PMC_PLT_CLK_0)
64*4882a593Smuzhiyun 		dev_info(dev, "quirk PMC_PLT_CLK_0 enabled");
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)67*4882a593Smuzhiyun static int platform_clock_control(struct snd_soc_dapm_widget *w,
68*4882a593Smuzhiyun 		struct snd_kcontrol *k, int  event)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = w->dapm;
71*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
72*4882a593Smuzhiyun 	struct snd_soc_dai *codec_dai;
73*4882a593Smuzhiyun 	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
74*4882a593Smuzhiyun 	int ret;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI1);
77*4882a593Smuzhiyun 	if (!codec_dai)
78*4882a593Smuzhiyun 		codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI2);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	if (!codec_dai) {
81*4882a593Smuzhiyun 		dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
82*4882a593Smuzhiyun 		return -EIO;
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (SND_SOC_DAPM_EVENT_ON(event)) {
86*4882a593Smuzhiyun 		ret = clk_prepare_enable(ctx->mclk);
87*4882a593Smuzhiyun 		if (ret < 0) {
88*4882a593Smuzhiyun 			dev_err(card->dev,
89*4882a593Smuzhiyun 				"could not configure MCLK state");
90*4882a593Smuzhiyun 			return ret;
91*4882a593Smuzhiyun 		}
92*4882a593Smuzhiyun 	} else {
93*4882a593Smuzhiyun 		/* Set codec sysclk source to its internal clock because codec PLL will
94*4882a593Smuzhiyun 		 * be off when idle and MCLK will also be off when codec is
95*4882a593Smuzhiyun 		 * runtime suspended. Codec needs clock for jack detection and button
96*4882a593Smuzhiyun 		 * press. MCLK is turned off with clock framework or ACPI.
97*4882a593Smuzhiyun 		 */
98*4882a593Smuzhiyun 		ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
99*4882a593Smuzhiyun 					48000 * 512, SND_SOC_CLOCK_IN);
100*4882a593Smuzhiyun 		if (ret < 0) {
101*4882a593Smuzhiyun 			dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
102*4882a593Smuzhiyun 			return ret;
103*4882a593Smuzhiyun 		}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 		clk_disable_unprepare(ctx->mclk);
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
112*4882a593Smuzhiyun 	SND_SOC_DAPM_HP("Headphone", NULL),
113*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
114*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("Int Mic", NULL),
115*4882a593Smuzhiyun 	SND_SOC_DAPM_MIC("Int Analog Mic", NULL),
116*4882a593Smuzhiyun 	SND_SOC_DAPM_SPK("Ext Spk", NULL),
117*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
118*4882a593Smuzhiyun 			platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = {
122*4882a593Smuzhiyun 	{"IN1P", NULL, "Headset Mic"},
123*4882a593Smuzhiyun 	{"IN1N", NULL, "Headset Mic"},
124*4882a593Smuzhiyun 	{"DMIC L1", NULL, "Int Mic"},
125*4882a593Smuzhiyun 	{"DMIC R1", NULL, "Int Mic"},
126*4882a593Smuzhiyun 	{"IN2P", NULL, "Int Analog Mic"},
127*4882a593Smuzhiyun 	{"IN2N", NULL, "Int Analog Mic"},
128*4882a593Smuzhiyun 	{"Headphone", NULL, "HPOL"},
129*4882a593Smuzhiyun 	{"Headphone", NULL, "HPOR"},
130*4882a593Smuzhiyun 	{"Ext Spk", NULL, "SPOL"},
131*4882a593Smuzhiyun 	{"Ext Spk", NULL, "SPOR"},
132*4882a593Smuzhiyun 	{"Headphone", NULL, "Platform Clock"},
133*4882a593Smuzhiyun 	{"Headset Mic", NULL, "Platform Clock"},
134*4882a593Smuzhiyun 	{"Int Mic", NULL, "Platform Clock"},
135*4882a593Smuzhiyun 	{"Int Analog Mic", NULL, "Platform Clock"},
136*4882a593Smuzhiyun 	{"Int Analog Mic", NULL, "micbias1"},
137*4882a593Smuzhiyun 	{"Int Analog Mic", NULL, "micbias2"},
138*4882a593Smuzhiyun 	{"Ext Spk", NULL, "Platform Clock"},
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5650_audio_map[] = {
142*4882a593Smuzhiyun 	{"IN1P", NULL, "Headset Mic"},
143*4882a593Smuzhiyun 	{"IN1N", NULL, "Headset Mic"},
144*4882a593Smuzhiyun 	{"DMIC L2", NULL, "Int Mic"},
145*4882a593Smuzhiyun 	{"DMIC R2", NULL, "Int Mic"},
146*4882a593Smuzhiyun 	{"Headphone", NULL, "HPOL"},
147*4882a593Smuzhiyun 	{"Headphone", NULL, "HPOR"},
148*4882a593Smuzhiyun 	{"Ext Spk", NULL, "SPOL"},
149*4882a593Smuzhiyun 	{"Ext Spk", NULL, "SPOR"},
150*4882a593Smuzhiyun 	{"Headphone", NULL, "Platform Clock"},
151*4882a593Smuzhiyun 	{"Headset Mic", NULL, "Platform Clock"},
152*4882a593Smuzhiyun 	{"Int Mic", NULL, "Platform Clock"},
153*4882a593Smuzhiyun 	{"Ext Spk", NULL, "Platform Clock"},
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif1_map[] = {
157*4882a593Smuzhiyun 	{"AIF1 Playback", NULL, "ssp2 Tx"},
158*4882a593Smuzhiyun 	{"ssp2 Tx", NULL, "codec_out0"},
159*4882a593Smuzhiyun 	{"ssp2 Tx", NULL, "codec_out1"},
160*4882a593Smuzhiyun 	{"codec_in0", NULL, "ssp2 Rx" },
161*4882a593Smuzhiyun 	{"codec_in1", NULL, "ssp2 Rx" },
162*4882a593Smuzhiyun 	{"ssp2 Rx", NULL, "AIF1 Capture"},
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif2_map[] = {
166*4882a593Smuzhiyun 	{"AIF2 Playback", NULL, "ssp2 Tx"},
167*4882a593Smuzhiyun 	{"ssp2 Tx", NULL, "codec_out0"},
168*4882a593Smuzhiyun 	{"ssp2 Tx", NULL, "codec_out1"},
169*4882a593Smuzhiyun 	{"codec_in0", NULL, "ssp2 Rx" },
170*4882a593Smuzhiyun 	{"codec_in1", NULL, "ssp2 Rx" },
171*4882a593Smuzhiyun 	{"ssp2 Rx", NULL, "AIF2 Capture"},
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif1_map[] = {
175*4882a593Smuzhiyun 	{"AIF1 Playback", NULL, "ssp0 Tx"},
176*4882a593Smuzhiyun 	{"ssp0 Tx", NULL, "modem_out"},
177*4882a593Smuzhiyun 	{"modem_in", NULL, "ssp0 Rx" },
178*4882a593Smuzhiyun 	{"ssp0 Rx", NULL, "AIF1 Capture"},
179*4882a593Smuzhiyun };
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif2_map[] = {
182*4882a593Smuzhiyun 	{"AIF2 Playback", NULL, "ssp0 Tx"},
183*4882a593Smuzhiyun 	{"ssp0 Tx", NULL, "modem_out"},
184*4882a593Smuzhiyun 	{"modem_in", NULL, "ssp0 Rx" },
185*4882a593Smuzhiyun 	{"ssp0 Rx", NULL, "AIF2 Capture"},
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun static const struct snd_kcontrol_new cht_mc_controls[] = {
189*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headphone"),
190*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
191*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Int Mic"),
192*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Int Analog Mic"),
193*4882a593Smuzhiyun 	SOC_DAPM_PIN_SWITCH("Ext Spk"),
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun static struct snd_soc_jack_pin cht_bsw_jack_pins[] = {
197*4882a593Smuzhiyun 	{
198*4882a593Smuzhiyun 		.pin	= "Headphone",
199*4882a593Smuzhiyun 		.mask	= SND_JACK_HEADPHONE,
200*4882a593Smuzhiyun 	},
201*4882a593Smuzhiyun 	{
202*4882a593Smuzhiyun 		.pin	= "Headset Mic",
203*4882a593Smuzhiyun 		.mask	= SND_JACK_MICROPHONE,
204*4882a593Smuzhiyun 	},
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun 
cht_aif1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)207*4882a593Smuzhiyun static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
208*4882a593Smuzhiyun 			     struct snd_pcm_hw_params *params)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
211*4882a593Smuzhiyun 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
212*4882a593Smuzhiyun 	int ret;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	/* set codec PLL source to the 19.2MHz platform clock (MCLK) */
215*4882a593Smuzhiyun 	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK,
216*4882a593Smuzhiyun 				  CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
217*4882a593Smuzhiyun 	if (ret < 0) {
218*4882a593Smuzhiyun 		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
219*4882a593Smuzhiyun 		return ret;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_PLL1,
223*4882a593Smuzhiyun 				params_rate(params) * 512, SND_SOC_CLOCK_IN);
224*4882a593Smuzhiyun 	if (ret < 0) {
225*4882a593Smuzhiyun 		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
226*4882a593Smuzhiyun 		return ret;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
cht_rt5645_quirk_cb(const struct dmi_system_id * id)232*4882a593Smuzhiyun static int cht_rt5645_quirk_cb(const struct dmi_system_id *id)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	cht_rt5645_quirk = (unsigned long)id->driver_data;
235*4882a593Smuzhiyun 	return 1;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun static const struct dmi_system_id cht_rt5645_quirk_table[] = {
239*4882a593Smuzhiyun 	{
240*4882a593Smuzhiyun 		/* Strago family Chromebooks */
241*4882a593Smuzhiyun 		.callback = cht_rt5645_quirk_cb,
242*4882a593Smuzhiyun 		.matches = {
243*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
244*4882a593Smuzhiyun 		},
245*4882a593Smuzhiyun 		.driver_data = (void *)CHT_RT5645_PMC_PLT_CLK_0,
246*4882a593Smuzhiyun 	},
247*4882a593Smuzhiyun 	{
248*4882a593Smuzhiyun 	},
249*4882a593Smuzhiyun };
250*4882a593Smuzhiyun 
cht_codec_init(struct snd_soc_pcm_runtime * runtime)251*4882a593Smuzhiyun static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct snd_soc_card *card = runtime->card;
254*4882a593Smuzhiyun 	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
255*4882a593Smuzhiyun 	struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component;
256*4882a593Smuzhiyun 	int jack_type;
257*4882a593Smuzhiyun 	int ret;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) ||
260*4882a593Smuzhiyun 	    (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
261*4882a593Smuzhiyun 		/* Select clk_i2s2_asrc as ASRC clock source */
262*4882a593Smuzhiyun 		rt5645_sel_asrc_clk_src(component,
263*4882a593Smuzhiyun 					RT5645_DA_STEREO_FILTER |
264*4882a593Smuzhiyun 					RT5645_DA_MONO_L_FILTER |
265*4882a593Smuzhiyun 					RT5645_DA_MONO_R_FILTER |
266*4882a593Smuzhiyun 					RT5645_AD_STEREO_FILTER,
267*4882a593Smuzhiyun 					RT5645_CLK_SEL_I2S2_ASRC);
268*4882a593Smuzhiyun 	} else {
269*4882a593Smuzhiyun 		/* Select clk_i2s1_asrc as ASRC clock source */
270*4882a593Smuzhiyun 		rt5645_sel_asrc_clk_src(component,
271*4882a593Smuzhiyun 					RT5645_DA_STEREO_FILTER |
272*4882a593Smuzhiyun 					RT5645_DA_MONO_L_FILTER |
273*4882a593Smuzhiyun 					RT5645_DA_MONO_R_FILTER |
274*4882a593Smuzhiyun 					RT5645_AD_STEREO_FILTER,
275*4882a593Smuzhiyun 					RT5645_CLK_SEL_I2S1_ASRC);
276*4882a593Smuzhiyun 	}
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) {
279*4882a593Smuzhiyun 		ret = snd_soc_dapm_add_routes(&card->dapm,
280*4882a593Smuzhiyun 					cht_rt5645_ssp2_aif2_map,
281*4882a593Smuzhiyun 					ARRAY_SIZE(cht_rt5645_ssp2_aif2_map));
282*4882a593Smuzhiyun 	} else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) {
283*4882a593Smuzhiyun 		ret = snd_soc_dapm_add_routes(&card->dapm,
284*4882a593Smuzhiyun 					cht_rt5645_ssp0_aif1_map,
285*4882a593Smuzhiyun 					ARRAY_SIZE(cht_rt5645_ssp0_aif1_map));
286*4882a593Smuzhiyun 	} else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2) {
287*4882a593Smuzhiyun 		ret = snd_soc_dapm_add_routes(&card->dapm,
288*4882a593Smuzhiyun 					cht_rt5645_ssp0_aif2_map,
289*4882a593Smuzhiyun 					ARRAY_SIZE(cht_rt5645_ssp0_aif2_map));
290*4882a593Smuzhiyun 	} else {
291*4882a593Smuzhiyun 		ret = snd_soc_dapm_add_routes(&card->dapm,
292*4882a593Smuzhiyun 					cht_rt5645_ssp2_aif1_map,
293*4882a593Smuzhiyun 					ARRAY_SIZE(cht_rt5645_ssp2_aif1_map));
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 	if (ret)
296*4882a593Smuzhiyun 		return ret;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	if (ctx->acpi_card->codec_type == CODEC_TYPE_RT5650)
299*4882a593Smuzhiyun 		jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
300*4882a593Smuzhiyun 					SND_JACK_BTN_0 | SND_JACK_BTN_1 |
301*4882a593Smuzhiyun 					SND_JACK_BTN_2 | SND_JACK_BTN_3;
302*4882a593Smuzhiyun 	else
303*4882a593Smuzhiyun 		jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	ret = snd_soc_card_jack_new(runtime->card, "Headset",
306*4882a593Smuzhiyun 				    jack_type, &ctx->jack,
307*4882a593Smuzhiyun 				    cht_bsw_jack_pins, ARRAY_SIZE(cht_bsw_jack_pins));
308*4882a593Smuzhiyun 	if (ret) {
309*4882a593Smuzhiyun 		dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
310*4882a593Smuzhiyun 		return ret;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	rt5645_set_jack_detect(component, &ctx->jack, &ctx->jack, &ctx->jack);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	/*
317*4882a593Smuzhiyun 	 * The firmware might enable the clock at
318*4882a593Smuzhiyun 	 * boot (this information may or may not
319*4882a593Smuzhiyun 	 * be reflected in the enable clock register).
320*4882a593Smuzhiyun 	 * To change the rate we must disable the clock
321*4882a593Smuzhiyun 	 * first to cover these cases. Due to common
322*4882a593Smuzhiyun 	 * clock framework restrictions that do not allow
323*4882a593Smuzhiyun 	 * to disable a clock that has not been enabled,
324*4882a593Smuzhiyun 	 * we need to enable the clock first.
325*4882a593Smuzhiyun 	 */
326*4882a593Smuzhiyun 	ret = clk_prepare_enable(ctx->mclk);
327*4882a593Smuzhiyun 	if (!ret)
328*4882a593Smuzhiyun 		clk_disable_unprepare(ctx->mclk);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	if (ret)
333*4882a593Smuzhiyun 		dev_err(runtime->dev, "unable to set MCLK rate\n");
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	return ret;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
cht_codec_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)338*4882a593Smuzhiyun static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
339*4882a593Smuzhiyun 			    struct snd_pcm_hw_params *params)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	int ret;
342*4882a593Smuzhiyun 	struct snd_interval *rate = hw_param_interval(params,
343*4882a593Smuzhiyun 			SNDRV_PCM_HW_PARAM_RATE);
344*4882a593Smuzhiyun 	struct snd_interval *channels = hw_param_interval(params,
345*4882a593Smuzhiyun 						SNDRV_PCM_HW_PARAM_CHANNELS);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
348*4882a593Smuzhiyun 	rate->min = rate->max = 48000;
349*4882a593Smuzhiyun 	channels->min = channels->max = 2;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) ||
352*4882a593Smuzhiyun 		(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		/* set SSP0 to 16-bit */
355*4882a593Smuzhiyun 		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 		/*
358*4882a593Smuzhiyun 		 * Default mode for SSP configuration is TDM 4 slot, override config
359*4882a593Smuzhiyun 		 * with explicit setting to I2S 2ch 16-bit. The word length is set with
360*4882a593Smuzhiyun 		 * dai_set_tdm_slot() since there is no other API exposed
361*4882a593Smuzhiyun 		 */
362*4882a593Smuzhiyun 		ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
363*4882a593Smuzhiyun 					SND_SOC_DAIFMT_I2S     |
364*4882a593Smuzhiyun 					SND_SOC_DAIFMT_NB_NF   |
365*4882a593Smuzhiyun 					SND_SOC_DAIFMT_CBS_CFS
366*4882a593Smuzhiyun 			);
367*4882a593Smuzhiyun 		if (ret < 0) {
368*4882a593Smuzhiyun 			dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
369*4882a593Smuzhiyun 			return ret;
370*4882a593Smuzhiyun 		}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 		ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
373*4882a593Smuzhiyun 					SND_SOC_DAIFMT_I2S     |
374*4882a593Smuzhiyun 					SND_SOC_DAIFMT_NB_NF   |
375*4882a593Smuzhiyun 					SND_SOC_DAIFMT_CBS_CFS
376*4882a593Smuzhiyun 			);
377*4882a593Smuzhiyun 		if (ret < 0) {
378*4882a593Smuzhiyun 			dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
379*4882a593Smuzhiyun 			return ret;
380*4882a593Smuzhiyun 		}
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 		ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
383*4882a593Smuzhiyun 		if (ret < 0) {
384*4882a593Smuzhiyun 			dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
385*4882a593Smuzhiyun 			return ret;
386*4882a593Smuzhiyun 		}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	} else {
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 		/* set SSP2 to 24-bit */
391*4882a593Smuzhiyun 		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 		/*
394*4882a593Smuzhiyun 		 * Default mode for SSP configuration is TDM 4 slot
395*4882a593Smuzhiyun 		 */
396*4882a593Smuzhiyun 		ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
397*4882a593Smuzhiyun 					SND_SOC_DAIFMT_DSP_B |
398*4882a593Smuzhiyun 					SND_SOC_DAIFMT_IB_NF |
399*4882a593Smuzhiyun 					SND_SOC_DAIFMT_CBS_CFS);
400*4882a593Smuzhiyun 		if (ret < 0) {
401*4882a593Smuzhiyun 			dev_err(rtd->dev, "can't set format to TDM %d\n", ret);
402*4882a593Smuzhiyun 			return ret;
403*4882a593Smuzhiyun 		}
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 		/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
406*4882a593Smuzhiyun 		ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24);
407*4882a593Smuzhiyun 		if (ret < 0) {
408*4882a593Smuzhiyun 			dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
409*4882a593Smuzhiyun 			return ret;
410*4882a593Smuzhiyun 		}
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 	return 0;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun 
cht_aif1_startup(struct snd_pcm_substream * substream)415*4882a593Smuzhiyun static int cht_aif1_startup(struct snd_pcm_substream *substream)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun 	return snd_pcm_hw_constraint_single(substream->runtime,
418*4882a593Smuzhiyun 			SNDRV_PCM_HW_PARAM_RATE, 48000);
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun static const struct snd_soc_ops cht_aif1_ops = {
422*4882a593Smuzhiyun 	.startup = cht_aif1_startup,
423*4882a593Smuzhiyun };
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun static const struct snd_soc_ops cht_be_ssp2_ops = {
426*4882a593Smuzhiyun 	.hw_params = cht_aif1_hw_params,
427*4882a593Smuzhiyun };
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(dummy,
430*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_DUMMY()));
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(media,
433*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(deepbuffer,
436*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp2_port,
439*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
440*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp2_codec,
441*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5645:00", "rt5645-aif1")));
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(platform,
444*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun static struct snd_soc_dai_link cht_dailink[] = {
447*4882a593Smuzhiyun 	[MERR_DPCM_AUDIO] = {
448*4882a593Smuzhiyun 		.name = "Audio Port",
449*4882a593Smuzhiyun 		.stream_name = "Audio",
450*4882a593Smuzhiyun 		.nonatomic = true,
451*4882a593Smuzhiyun 		.dynamic = 1,
452*4882a593Smuzhiyun 		.dpcm_playback = 1,
453*4882a593Smuzhiyun 		.dpcm_capture = 1,
454*4882a593Smuzhiyun 		.ops = &cht_aif1_ops,
455*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(media, dummy, platform),
456*4882a593Smuzhiyun 	},
457*4882a593Smuzhiyun 	[MERR_DPCM_DEEP_BUFFER] = {
458*4882a593Smuzhiyun 		.name = "Deep-Buffer Audio Port",
459*4882a593Smuzhiyun 		.stream_name = "Deep-Buffer Audio",
460*4882a593Smuzhiyun 		.nonatomic = true,
461*4882a593Smuzhiyun 		.dynamic = 1,
462*4882a593Smuzhiyun 		.dpcm_playback = 1,
463*4882a593Smuzhiyun 		.ops = &cht_aif1_ops,
464*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
465*4882a593Smuzhiyun 	},
466*4882a593Smuzhiyun 	/* CODEC<->CODEC link */
467*4882a593Smuzhiyun 	/* back ends */
468*4882a593Smuzhiyun 	{
469*4882a593Smuzhiyun 		.name = "SSP2-Codec",
470*4882a593Smuzhiyun 		.id = 0,
471*4882a593Smuzhiyun 		.no_pcm = 1,
472*4882a593Smuzhiyun 		.init = cht_codec_init,
473*4882a593Smuzhiyun 		.be_hw_params_fixup = cht_codec_fixup,
474*4882a593Smuzhiyun 		.nonatomic = true,
475*4882a593Smuzhiyun 		.dpcm_playback = 1,
476*4882a593Smuzhiyun 		.dpcm_capture = 1,
477*4882a593Smuzhiyun 		.ops = &cht_be_ssp2_ops,
478*4882a593Smuzhiyun 		SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
479*4882a593Smuzhiyun 	},
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
483*4882a593Smuzhiyun /* use space before codec name to simplify card ID, and simplify driver name */
484*4882a593Smuzhiyun #define CARD_RT5645_NAME "bytcht rt5645" /* card name 'sof-bytcht rt5645' */
485*4882a593Smuzhiyun #define CARD_RT5650_NAME "bytcht rt5650" /* card name 'sof-bytcht rt5650' */
486*4882a593Smuzhiyun #define DRIVER_NAME "SOF"
487*4882a593Smuzhiyun #else
488*4882a593Smuzhiyun #define CARD_RT5645_NAME "chtrt5645"
489*4882a593Smuzhiyun #define CARD_RT5650_NAME "chtrt5650"
490*4882a593Smuzhiyun #define DRIVER_NAME NULL /* card name will be used for driver name */
491*4882a593Smuzhiyun #endif
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun /* SoC card */
494*4882a593Smuzhiyun static struct snd_soc_card snd_soc_card_chtrt5645 = {
495*4882a593Smuzhiyun 	.name = CARD_RT5645_NAME,
496*4882a593Smuzhiyun 	.driver_name = DRIVER_NAME,
497*4882a593Smuzhiyun 	.owner = THIS_MODULE,
498*4882a593Smuzhiyun 	.dai_link = cht_dailink,
499*4882a593Smuzhiyun 	.num_links = ARRAY_SIZE(cht_dailink),
500*4882a593Smuzhiyun 	.dapm_widgets = cht_dapm_widgets,
501*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
502*4882a593Smuzhiyun 	.dapm_routes = cht_rt5645_audio_map,
503*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(cht_rt5645_audio_map),
504*4882a593Smuzhiyun 	.controls = cht_mc_controls,
505*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(cht_mc_controls),
506*4882a593Smuzhiyun };
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun static struct snd_soc_card snd_soc_card_chtrt5650 = {
509*4882a593Smuzhiyun 	.name = CARD_RT5650_NAME,
510*4882a593Smuzhiyun 	.driver_name = DRIVER_NAME,
511*4882a593Smuzhiyun 	.owner = THIS_MODULE,
512*4882a593Smuzhiyun 	.dai_link = cht_dailink,
513*4882a593Smuzhiyun 	.num_links = ARRAY_SIZE(cht_dailink),
514*4882a593Smuzhiyun 	.dapm_widgets = cht_dapm_widgets,
515*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
516*4882a593Smuzhiyun 	.dapm_routes = cht_rt5650_audio_map,
517*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(cht_rt5650_audio_map),
518*4882a593Smuzhiyun 	.controls = cht_mc_controls,
519*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(cht_mc_controls),
520*4882a593Smuzhiyun };
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun static struct cht_acpi_card snd_soc_cards[] = {
523*4882a593Smuzhiyun 	{"10EC5640", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
524*4882a593Smuzhiyun 	{"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
525*4882a593Smuzhiyun 	{"10EC5648", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
526*4882a593Smuzhiyun 	{"10EC3270", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
527*4882a593Smuzhiyun 	{"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
528*4882a593Smuzhiyun };
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun static char cht_rt5645_codec_name[SND_ACPI_I2C_ID_LEN];
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
533*4882a593Smuzhiyun 	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
534*4882a593Smuzhiyun 	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
535*4882a593Smuzhiyun };
536*4882a593Smuzhiyun 
snd_cht_mc_probe(struct platform_device * pdev)537*4882a593Smuzhiyun static int snd_cht_mc_probe(struct platform_device *pdev)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	struct snd_soc_card *card = snd_soc_cards[0].soc_card;
540*4882a593Smuzhiyun 	struct snd_soc_acpi_mach *mach;
541*4882a593Smuzhiyun 	const char *platform_name;
542*4882a593Smuzhiyun 	struct cht_mc_private *drv;
543*4882a593Smuzhiyun 	struct acpi_device *adev;
544*4882a593Smuzhiyun 	bool found = false;
545*4882a593Smuzhiyun 	bool is_bytcr = false;
546*4882a593Smuzhiyun 	int dai_index = 0;
547*4882a593Smuzhiyun 	int ret_val = 0;
548*4882a593Smuzhiyun 	int i;
549*4882a593Smuzhiyun 	const char *mclk_name;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
552*4882a593Smuzhiyun 	if (!drv)
553*4882a593Smuzhiyun 		return -ENOMEM;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	mach = pdev->dev.platform_data;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
558*4882a593Smuzhiyun 		if (acpi_dev_found(snd_soc_cards[i].codec_id) &&
559*4882a593Smuzhiyun 			(!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) {
560*4882a593Smuzhiyun 			dev_dbg(&pdev->dev,
561*4882a593Smuzhiyun 				"found codec %s\n", snd_soc_cards[i].codec_id);
562*4882a593Smuzhiyun 			card = snd_soc_cards[i].soc_card;
563*4882a593Smuzhiyun 			drv->acpi_card = &snd_soc_cards[i];
564*4882a593Smuzhiyun 			found = true;
565*4882a593Smuzhiyun 			break;
566*4882a593Smuzhiyun 		}
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	if (!found) {
570*4882a593Smuzhiyun 		dev_err(&pdev->dev, "No matching HID found in supported list\n");
571*4882a593Smuzhiyun 		return -ENODEV;
572*4882a593Smuzhiyun 	}
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	card->dev = &pdev->dev;
575*4882a593Smuzhiyun 	sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	/* set correct codec name */
578*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
579*4882a593Smuzhiyun 		if (!strcmp(card->dai_link[i].codecs->name,
580*4882a593Smuzhiyun 			    "i2c-10EC5645:00")) {
581*4882a593Smuzhiyun 			card->dai_link[i].codecs->name = drv->codec_name;
582*4882a593Smuzhiyun 			dai_index = i;
583*4882a593Smuzhiyun 		}
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	/* fixup codec name based on HID */
586*4882a593Smuzhiyun 	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
587*4882a593Smuzhiyun 	if (adev) {
588*4882a593Smuzhiyun 		snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
589*4882a593Smuzhiyun 			 "i2c-%s", acpi_dev_name(adev));
590*4882a593Smuzhiyun 		put_device(&adev->dev);
591*4882a593Smuzhiyun 		cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	/*
595*4882a593Smuzhiyun 	 * swap SSP0 if bytcr is detected
596*4882a593Smuzhiyun 	 * (will be overridden if DMI quirk is detected)
597*4882a593Smuzhiyun 	 */
598*4882a593Smuzhiyun 	if (soc_intel_is_byt()) {
599*4882a593Smuzhiyun 		if (mach->mach_params.acpi_ipc_irq_index == 0)
600*4882a593Smuzhiyun 			is_bytcr = true;
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	if (is_bytcr) {
604*4882a593Smuzhiyun 		/*
605*4882a593Smuzhiyun 		 * Baytrail CR platforms may have CHAN package in BIOS, try
606*4882a593Smuzhiyun 		 * to find relevant routing quirk based as done on Windows
607*4882a593Smuzhiyun 		 * platforms. We have to read the information directly from the
608*4882a593Smuzhiyun 		 * BIOS, at this stage the card is not created and the links
609*4882a593Smuzhiyun 		 * with the codec driver/pdata are non-existent
610*4882a593Smuzhiyun 		 */
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 		struct acpi_chan_package chan_package;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 		/* format specified: 2 64-bit integers */
615*4882a593Smuzhiyun 		struct acpi_buffer format = {sizeof("NN"), "NN"};
616*4882a593Smuzhiyun 		struct acpi_buffer state = {0, NULL};
617*4882a593Smuzhiyun 		struct snd_soc_acpi_package_context pkg_ctx;
618*4882a593Smuzhiyun 		bool pkg_found = false;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 		state.length = sizeof(chan_package);
621*4882a593Smuzhiyun 		state.pointer = &chan_package;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 		pkg_ctx.name = "CHAN";
624*4882a593Smuzhiyun 		pkg_ctx.length = 2;
625*4882a593Smuzhiyun 		pkg_ctx.format = &format;
626*4882a593Smuzhiyun 		pkg_ctx.state = &state;
627*4882a593Smuzhiyun 		pkg_ctx.data_valid = false;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 		pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
630*4882a593Smuzhiyun 							       &pkg_ctx);
631*4882a593Smuzhiyun 		if (pkg_found) {
632*4882a593Smuzhiyun 			if (chan_package.aif_value == 1) {
633*4882a593Smuzhiyun 				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
634*4882a593Smuzhiyun 				cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF1;
635*4882a593Smuzhiyun 			} else  if (chan_package.aif_value == 2) {
636*4882a593Smuzhiyun 				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
637*4882a593Smuzhiyun 				cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2;
638*4882a593Smuzhiyun 			} else {
639*4882a593Smuzhiyun 				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
640*4882a593Smuzhiyun 				pkg_found = false;
641*4882a593Smuzhiyun 			}
642*4882a593Smuzhiyun 		}
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 		if (!pkg_found) {
645*4882a593Smuzhiyun 			/* no BIOS indications, assume SSP0-AIF2 connection */
646*4882a593Smuzhiyun 			cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2;
647*4882a593Smuzhiyun 		}
648*4882a593Smuzhiyun 	}
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	/* check quirks before creating card */
651*4882a593Smuzhiyun 	dmi_check_system(cht_rt5645_quirk_table);
652*4882a593Smuzhiyun 	log_quirks(&pdev->dev);
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) ||
655*4882a593Smuzhiyun 	    (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2))
656*4882a593Smuzhiyun 		cht_dailink[dai_index].codecs->dai_name = "rt5645-aif2";
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) ||
659*4882a593Smuzhiyun 	    (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2))
660*4882a593Smuzhiyun 		cht_dailink[dai_index].cpus->dai_name = "ssp0-port";
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	/* override plaform name, if required */
663*4882a593Smuzhiyun 	platform_name = mach->mach_params.platform;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	ret_val = snd_soc_fixup_dai_links_platform_name(card,
666*4882a593Smuzhiyun 							platform_name);
667*4882a593Smuzhiyun 	if (ret_val)
668*4882a593Smuzhiyun 		return ret_val;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (cht_rt5645_quirk & CHT_RT5645_PMC_PLT_CLK_0)
671*4882a593Smuzhiyun 		mclk_name = "pmc_plt_clk_0";
672*4882a593Smuzhiyun 	else
673*4882a593Smuzhiyun 		mclk_name = "pmc_plt_clk_3";
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	drv->mclk = devm_clk_get(&pdev->dev, mclk_name);
676*4882a593Smuzhiyun 	if (IS_ERR(drv->mclk)) {
677*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to get MCLK from %s: %ld\n",
678*4882a593Smuzhiyun 			mclk_name, PTR_ERR(drv->mclk));
679*4882a593Smuzhiyun 		return PTR_ERR(drv->mclk);
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	snd_soc_card_set_drvdata(card, drv);
683*4882a593Smuzhiyun 	ret_val = devm_snd_soc_register_card(&pdev->dev, card);
684*4882a593Smuzhiyun 	if (ret_val) {
685*4882a593Smuzhiyun 		dev_err(&pdev->dev,
686*4882a593Smuzhiyun 			"snd_soc_register_card failed %d\n", ret_val);
687*4882a593Smuzhiyun 		return ret_val;
688*4882a593Smuzhiyun 	}
689*4882a593Smuzhiyun 	platform_set_drvdata(pdev, card);
690*4882a593Smuzhiyun 	return ret_val;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun static struct platform_driver snd_cht_mc_driver = {
694*4882a593Smuzhiyun 	.driver = {
695*4882a593Smuzhiyun 		.name = "cht-bsw-rt5645",
696*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
697*4882a593Smuzhiyun 		.pm = &snd_soc_pm_ops,
698*4882a593Smuzhiyun #endif
699*4882a593Smuzhiyun 	},
700*4882a593Smuzhiyun 	.probe = snd_cht_mc_probe,
701*4882a593Smuzhiyun };
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun module_platform_driver(snd_cht_mc_driver)
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver");
706*4882a593Smuzhiyun MODULE_AUTHOR("Fang, Yang A,N,Harshapriya");
707*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
708*4882a593Smuzhiyun MODULE_ALIAS("platform:cht-bsw-rt5645");
709