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