1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
4*4882a593Smuzhiyun * (derived from bytcr_rt5640.c)
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2015 Intel Corp
7*4882a593Smuzhiyun * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/i2c.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/property.h>
17*4882a593Smuzhiyun #include <linux/acpi.h>
18*4882a593Smuzhiyun #include <linux/clk.h>
19*4882a593Smuzhiyun #include <linux/device.h>
20*4882a593Smuzhiyun #include <linux/dmi.h>
21*4882a593Smuzhiyun #include <linux/input.h>
22*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
23*4882a593Smuzhiyun #include <linux/gpio/machine.h>
24*4882a593Smuzhiyun #include <linux/slab.h>
25*4882a593Smuzhiyun #include <sound/pcm.h>
26*4882a593Smuzhiyun #include <sound/pcm_params.h>
27*4882a593Smuzhiyun #include <sound/soc.h>
28*4882a593Smuzhiyun #include <sound/jack.h>
29*4882a593Smuzhiyun #include <sound/soc-acpi.h>
30*4882a593Smuzhiyun #include "../../codecs/rt5651.h"
31*4882a593Smuzhiyun #include "../atom/sst-atom-controls.h"
32*4882a593Smuzhiyun #include "../common/soc-intel-quirks.h"
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun enum {
35*4882a593Smuzhiyun BYT_RT5651_DMIC_MAP,
36*4882a593Smuzhiyun BYT_RT5651_IN1_MAP,
37*4882a593Smuzhiyun BYT_RT5651_IN2_MAP,
38*4882a593Smuzhiyun BYT_RT5651_IN1_IN2_MAP,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun enum {
42*4882a593Smuzhiyun BYT_RT5651_JD_NULL = (RT5651_JD_NULL << 4),
43*4882a593Smuzhiyun BYT_RT5651_JD1_1 = (RT5651_JD1_1 << 4),
44*4882a593Smuzhiyun BYT_RT5651_JD1_2 = (RT5651_JD1_2 << 4),
45*4882a593Smuzhiyun BYT_RT5651_JD2 = (RT5651_JD2 << 4),
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun enum {
49*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_600UA = (6 << 8),
50*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_1500UA = (15 << 8),
51*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_2000UA = (20 << 8),
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun enum {
55*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_0P5 = (RT5651_OVCD_SF_0P5 << 13),
56*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_0P75 = (RT5651_OVCD_SF_0P75 << 13),
57*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_1P0 = (RT5651_OVCD_SF_1P0 << 13),
58*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 13),
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0))
62*4882a593Smuzhiyun #define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)
63*4882a593Smuzhiyun #define BYT_RT5651_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)
64*4882a593Smuzhiyun #define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)
65*4882a593Smuzhiyun #define BYT_RT5651_DMIC_EN BIT(16)
66*4882a593Smuzhiyun #define BYT_RT5651_MCLK_EN BIT(17)
67*4882a593Smuzhiyun #define BYT_RT5651_MCLK_25MHZ BIT(18)
68*4882a593Smuzhiyun #define BYT_RT5651_SSP2_AIF2 BIT(19) /* default is using AIF1 */
69*4882a593Smuzhiyun #define BYT_RT5651_SSP0_AIF1 BIT(20)
70*4882a593Smuzhiyun #define BYT_RT5651_SSP0_AIF2 BIT(21)
71*4882a593Smuzhiyun #define BYT_RT5651_HP_LR_SWAPPED BIT(22)
72*4882a593Smuzhiyun #define BYT_RT5651_MONO_SPEAKER BIT(23)
73*4882a593Smuzhiyun #define BYT_RT5651_JD_NOT_INV BIT(24)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define BYT_RT5651_DEFAULT_QUIRKS (BYT_RT5651_MCLK_EN | \
76*4882a593Smuzhiyun BYT_RT5651_JD1_1 | \
77*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_2000UA | \
78*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_0P75)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* jack-detect-source + inv + dmic-en + ovcd-th + -sf + terminating entry */
81*4882a593Smuzhiyun #define MAX_NO_PROPS 6
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun struct byt_rt5651_private {
84*4882a593Smuzhiyun struct clk *mclk;
85*4882a593Smuzhiyun struct gpio_desc *ext_amp_gpio;
86*4882a593Smuzhiyun struct gpio_desc *hp_detect;
87*4882a593Smuzhiyun struct snd_soc_jack jack;
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun static const struct acpi_gpio_mapping *byt_rt5651_gpios;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */
93*4882a593Smuzhiyun static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
94*4882a593Smuzhiyun BYT_RT5651_IN2_MAP;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun static int quirk_override = -1;
97*4882a593Smuzhiyun module_param_named(quirk, quirk_override, int, 0444);
98*4882a593Smuzhiyun MODULE_PARM_DESC(quirk, "Board-specific quirk override");
99*4882a593Smuzhiyun
log_quirks(struct device * dev)100*4882a593Smuzhiyun static void log_quirks(struct device *dev)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
103*4882a593Smuzhiyun dev_info(dev, "quirk DMIC_MAP enabled");
104*4882a593Smuzhiyun if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
105*4882a593Smuzhiyun dev_info(dev, "quirk IN1_MAP enabled");
106*4882a593Smuzhiyun if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
107*4882a593Smuzhiyun dev_info(dev, "quirk IN2_MAP enabled");
108*4882a593Smuzhiyun if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_IN2_MAP)
109*4882a593Smuzhiyun dev_info(dev, "quirk IN1_IN2_MAP enabled");
110*4882a593Smuzhiyun if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
111*4882a593Smuzhiyun dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
112*4882a593Smuzhiyun BYT_RT5651_JDSRC(byt_rt5651_quirk));
113*4882a593Smuzhiyun dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",
114*4882a593Smuzhiyun BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
115*4882a593Smuzhiyun dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",
116*4882a593Smuzhiyun BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
119*4882a593Smuzhiyun dev_info(dev, "quirk DMIC enabled");
120*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
121*4882a593Smuzhiyun dev_info(dev, "quirk MCLK_EN enabled");
122*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
123*4882a593Smuzhiyun dev_info(dev, "quirk MCLK_25MHZ enabled");
124*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
125*4882a593Smuzhiyun dev_info(dev, "quirk SSP2_AIF2 enabled\n");
126*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
127*4882a593Smuzhiyun dev_info(dev, "quirk SSP0_AIF1 enabled\n");
128*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
129*4882a593Smuzhiyun dev_info(dev, "quirk SSP0_AIF2 enabled\n");
130*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER)
131*4882a593Smuzhiyun dev_info(dev, "quirk MONO_SPEAKER enabled\n");
132*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
133*4882a593Smuzhiyun dev_info(dev, "quirk JD_NOT_INV enabled\n");
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun #define BYT_CODEC_DAI1 "rt5651-aif1"
137*4882a593Smuzhiyun #define BYT_CODEC_DAI2 "rt5651-aif2"
138*4882a593Smuzhiyun
byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai * codec_dai,int rate,int bclk_ratio)139*4882a593Smuzhiyun static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
140*4882a593Smuzhiyun int rate, int bclk_ratio)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun int clk_id, clk_freq, ret;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /* Configure the PLL before selecting it */
145*4882a593Smuzhiyun if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
146*4882a593Smuzhiyun clk_id = RT5651_PLL1_S_BCLK1,
147*4882a593Smuzhiyun clk_freq = rate * bclk_ratio;
148*4882a593Smuzhiyun } else {
149*4882a593Smuzhiyun clk_id = RT5651_PLL1_S_MCLK;
150*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
151*4882a593Smuzhiyun clk_freq = 25000000;
152*4882a593Smuzhiyun else
153*4882a593Smuzhiyun clk_freq = 19200000;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, rate * 512);
156*4882a593Smuzhiyun if (ret < 0) {
157*4882a593Smuzhiyun dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);
158*4882a593Smuzhiyun return ret;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
162*4882a593Smuzhiyun rate * 512, SND_SOC_CLOCK_IN);
163*4882a593Smuzhiyun if (ret < 0) {
164*4882a593Smuzhiyun dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);
165*4882a593Smuzhiyun return ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun return 0;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)171*4882a593Smuzhiyun static int platform_clock_control(struct snd_soc_dapm_widget *w,
172*4882a593Smuzhiyun struct snd_kcontrol *k, int event)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm = w->dapm;
175*4882a593Smuzhiyun struct snd_soc_card *card = dapm->card;
176*4882a593Smuzhiyun struct snd_soc_dai *codec_dai;
177*4882a593Smuzhiyun struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
178*4882a593Smuzhiyun int ret;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
181*4882a593Smuzhiyun if (!codec_dai)
182*4882a593Smuzhiyun codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
183*4882a593Smuzhiyun if (!codec_dai) {
184*4882a593Smuzhiyun dev_err(card->dev,
185*4882a593Smuzhiyun "Codec dai not found; Unable to set platform clock\n");
186*4882a593Smuzhiyun return -EIO;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (SND_SOC_DAPM_EVENT_ON(event)) {
190*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
191*4882a593Smuzhiyun ret = clk_prepare_enable(priv->mclk);
192*4882a593Smuzhiyun if (ret < 0) {
193*4882a593Smuzhiyun dev_err(card->dev,
194*4882a593Smuzhiyun "could not configure MCLK state");
195*4882a593Smuzhiyun return ret;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun ret = byt_rt5651_prepare_and_enable_pll1(codec_dai, 48000, 50);
199*4882a593Smuzhiyun } else {
200*4882a593Smuzhiyun /*
201*4882a593Smuzhiyun * Set codec clock source to internal clock before
202*4882a593Smuzhiyun * turning off the platform clock. Codec needs clock
203*4882a593Smuzhiyun * for Jack detection and button press
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
206*4882a593Smuzhiyun 48000 * 512,
207*4882a593Smuzhiyun SND_SOC_CLOCK_IN);
208*4882a593Smuzhiyun if (!ret)
209*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
210*4882a593Smuzhiyun clk_disable_unprepare(priv->mclk);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (ret < 0) {
214*4882a593Smuzhiyun dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
215*4882a593Smuzhiyun return ret;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
rt5651_ext_amp_power_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)221*4882a593Smuzhiyun static int rt5651_ext_amp_power_event(struct snd_soc_dapm_widget *w,
222*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun struct snd_soc_card *card = w->dapm->card;
225*4882a593Smuzhiyun struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (SND_SOC_DAPM_EVENT_ON(event))
228*4882a593Smuzhiyun gpiod_set_value_cansleep(priv->ext_amp_gpio, 1);
229*4882a593Smuzhiyun else
230*4882a593Smuzhiyun gpiod_set_value_cansleep(priv->ext_amp_gpio, 0);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
236*4882a593Smuzhiyun SND_SOC_DAPM_HP("Headphone", NULL),
237*4882a593Smuzhiyun SND_SOC_DAPM_MIC("Headset Mic", NULL),
238*4882a593Smuzhiyun SND_SOC_DAPM_MIC("Internal Mic", NULL),
239*4882a593Smuzhiyun SND_SOC_DAPM_SPK("Speaker", NULL),
240*4882a593Smuzhiyun SND_SOC_DAPM_LINE("Line In", NULL),
241*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
242*4882a593Smuzhiyun platform_clock_control, SND_SOC_DAPM_PRE_PMU |
243*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMD),
244*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("Ext Amp Power", SND_SOC_NOPM, 0, 0,
245*4882a593Smuzhiyun rt5651_ext_amp_power_event,
246*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
247*4882a593Smuzhiyun };
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
250*4882a593Smuzhiyun {"Headphone", NULL, "Platform Clock"},
251*4882a593Smuzhiyun {"Headset Mic", NULL, "Platform Clock"},
252*4882a593Smuzhiyun {"Internal Mic", NULL, "Platform Clock"},
253*4882a593Smuzhiyun {"Speaker", NULL, "Platform Clock"},
254*4882a593Smuzhiyun {"Speaker", NULL, "Ext Amp Power"},
255*4882a593Smuzhiyun {"Line In", NULL, "Platform Clock"},
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
258*4882a593Smuzhiyun {"Headphone", NULL, "HPOL"},
259*4882a593Smuzhiyun {"Headphone", NULL, "HPOR"},
260*4882a593Smuzhiyun {"Speaker", NULL, "LOUTL"},
261*4882a593Smuzhiyun {"Speaker", NULL, "LOUTR"},
262*4882a593Smuzhiyun {"IN2P", NULL, "Line In"},
263*4882a593Smuzhiyun {"IN2N", NULL, "Line In"},
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun };
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
268*4882a593Smuzhiyun {"DMIC L1", NULL, "Internal Mic"},
269*4882a593Smuzhiyun {"DMIC R1", NULL, "Internal Mic"},
270*4882a593Smuzhiyun {"IN2P", NULL, "Headset Mic"},
271*4882a593Smuzhiyun };
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
274*4882a593Smuzhiyun {"Internal Mic", NULL, "micbias1"},
275*4882a593Smuzhiyun {"IN1P", NULL, "Internal Mic"},
276*4882a593Smuzhiyun {"IN3P", NULL, "Headset Mic"},
277*4882a593Smuzhiyun };
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
280*4882a593Smuzhiyun {"Internal Mic", NULL, "micbias1"},
281*4882a593Smuzhiyun {"IN2P", NULL, "Internal Mic"},
282*4882a593Smuzhiyun {"IN3P", NULL, "Headset Mic"},
283*4882a593Smuzhiyun };
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
286*4882a593Smuzhiyun {"Internal Mic", NULL, "micbias1"},
287*4882a593Smuzhiyun {"IN1P", NULL, "Internal Mic"},
288*4882a593Smuzhiyun {"IN2P", NULL, "Internal Mic"},
289*4882a593Smuzhiyun {"IN3P", NULL, "Headset Mic"},
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
293*4882a593Smuzhiyun {"ssp0 Tx", NULL, "modem_out"},
294*4882a593Smuzhiyun {"modem_in", NULL, "ssp0 Rx"},
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun {"AIF1 Playback", NULL, "ssp0 Tx"},
297*4882a593Smuzhiyun {"ssp0 Rx", NULL, "AIF1 Capture"},
298*4882a593Smuzhiyun };
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
301*4882a593Smuzhiyun {"ssp0 Tx", NULL, "modem_out"},
302*4882a593Smuzhiyun {"modem_in", NULL, "ssp0 Rx"},
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun {"AIF2 Playback", NULL, "ssp0 Tx"},
305*4882a593Smuzhiyun {"ssp0 Rx", NULL, "AIF2 Capture"},
306*4882a593Smuzhiyun };
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
309*4882a593Smuzhiyun {"ssp2 Tx", NULL, "codec_out0"},
310*4882a593Smuzhiyun {"ssp2 Tx", NULL, "codec_out1"},
311*4882a593Smuzhiyun {"codec_in0", NULL, "ssp2 Rx"},
312*4882a593Smuzhiyun {"codec_in1", NULL, "ssp2 Rx"},
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun {"AIF1 Playback", NULL, "ssp2 Tx"},
315*4882a593Smuzhiyun {"ssp2 Rx", NULL, "AIF1 Capture"},
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
319*4882a593Smuzhiyun {"ssp2 Tx", NULL, "codec_out0"},
320*4882a593Smuzhiyun {"ssp2 Tx", NULL, "codec_out1"},
321*4882a593Smuzhiyun {"codec_in0", NULL, "ssp2 Rx"},
322*4882a593Smuzhiyun {"codec_in1", NULL, "ssp2 Rx"},
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun {"AIF2 Playback", NULL, "ssp2 Tx"},
325*4882a593Smuzhiyun {"ssp2 Rx", NULL, "AIF2 Capture"},
326*4882a593Smuzhiyun };
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun static const struct snd_kcontrol_new byt_rt5651_controls[] = {
329*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Headphone"),
330*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Headset Mic"),
331*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Internal Mic"),
332*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Speaker"),
333*4882a593Smuzhiyun SOC_DAPM_PIN_SWITCH("Line In"),
334*4882a593Smuzhiyun };
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun static struct snd_soc_jack_pin bytcr_jack_pins[] = {
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun .pin = "Headphone",
339*4882a593Smuzhiyun .mask = SND_JACK_HEADPHONE,
340*4882a593Smuzhiyun },
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun .pin = "Headset Mic",
343*4882a593Smuzhiyun .mask = SND_JACK_MICROPHONE,
344*4882a593Smuzhiyun },
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun
byt_rt5651_aif1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)347*4882a593Smuzhiyun static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
348*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
351*4882a593Smuzhiyun struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
352*4882a593Smuzhiyun snd_pcm_format_t format = params_format(params);
353*4882a593Smuzhiyun int rate = params_rate(params);
354*4882a593Smuzhiyun int bclk_ratio;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (format == SNDRV_PCM_FORMAT_S16_LE)
357*4882a593Smuzhiyun bclk_ratio = 32;
358*4882a593Smuzhiyun else
359*4882a593Smuzhiyun bclk_ratio = 50;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate, bclk_ratio);
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun static const struct acpi_gpio_params pov_p1006w_hp_detect = { 1, 0, false };
365*4882a593Smuzhiyun static const struct acpi_gpio_params pov_p1006w_ext_amp_en = { 2, 0, true };
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun static const struct acpi_gpio_mapping byt_rt5651_pov_p1006w_gpios[] = {
368*4882a593Smuzhiyun { "hp-detect-gpios", &pov_p1006w_hp_detect, 1, },
369*4882a593Smuzhiyun { "ext-amp-enable-gpios", &pov_p1006w_ext_amp_en, 1, },
370*4882a593Smuzhiyun { },
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun
byt_rt5651_pov_p1006w_quirk_cb(const struct dmi_system_id * id)373*4882a593Smuzhiyun static int byt_rt5651_pov_p1006w_quirk_cb(const struct dmi_system_id *id)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun byt_rt5651_quirk = (unsigned long)id->driver_data;
376*4882a593Smuzhiyun byt_rt5651_gpios = byt_rt5651_pov_p1006w_gpios;
377*4882a593Smuzhiyun return 1;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
byt_rt5651_quirk_cb(const struct dmi_system_id * id)380*4882a593Smuzhiyun static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun byt_rt5651_quirk = (unsigned long)id->driver_data;
383*4882a593Smuzhiyun return 1;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun static const struct dmi_system_id byt_rt5651_quirk_table[] = {
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun /* Chuwi Hi8 Pro (CWI513) */
389*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
390*4882a593Smuzhiyun .matches = {
391*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
392*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
393*4882a593Smuzhiyun },
394*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
395*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
396*4882a593Smuzhiyun BYT_RT5651_HP_LR_SWAPPED |
397*4882a593Smuzhiyun BYT_RT5651_MONO_SPEAKER),
398*4882a593Smuzhiyun },
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun /* Chuwi Vi8 Plus (CWI519) */
401*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
402*4882a593Smuzhiyun .matches = {
403*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
404*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
405*4882a593Smuzhiyun },
406*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
407*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
408*4882a593Smuzhiyun BYT_RT5651_HP_LR_SWAPPED |
409*4882a593Smuzhiyun BYT_RT5651_MONO_SPEAKER),
410*4882a593Smuzhiyun },
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun /* Complet Electro Serv MY8307 */
413*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
414*4882a593Smuzhiyun .matches = {
415*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Complet Electro Serv"),
416*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "MY8307"),
417*4882a593Smuzhiyun },
418*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
419*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
420*4882a593Smuzhiyun BYT_RT5651_MONO_SPEAKER |
421*4882a593Smuzhiyun BYT_RT5651_JD_NOT_INV),
422*4882a593Smuzhiyun },
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun /* I.T.Works TW701, Ployer Momo7w and Trekstor ST70416-6
425*4882a593Smuzhiyun * (these all use the same mainboard) */
426*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
427*4882a593Smuzhiyun .matches = {
428*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VENDOR, "INSYDE Corp."),
429*4882a593Smuzhiyun /* Partial match for all of itWORKS.G.WI71C.JGBMRBA,
430*4882a593Smuzhiyun * TREK.G.WI71C.JGBMRBA0x and MOMO.G.WI71C.MABMRBA02 */
431*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VERSION, ".G.WI71C."),
432*4882a593Smuzhiyun },
433*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
434*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
435*4882a593Smuzhiyun BYT_RT5651_SSP0_AIF1 |
436*4882a593Smuzhiyun BYT_RT5651_MONO_SPEAKER),
437*4882a593Smuzhiyun },
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun /* Jumper EZpad 7 */
440*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
441*4882a593Smuzhiyun .matches = {
442*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
443*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
444*4882a593Smuzhiyun /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
445*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
446*4882a593Smuzhiyun },
447*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
448*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
449*4882a593Smuzhiyun BYT_RT5651_JD_NOT_INV),
450*4882a593Smuzhiyun },
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun /* KIANO SlimNote 14.2 */
453*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
454*4882a593Smuzhiyun .matches = {
455*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
456*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
457*4882a593Smuzhiyun },
458*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
459*4882a593Smuzhiyun BYT_RT5651_IN1_IN2_MAP),
460*4882a593Smuzhiyun },
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun /* Minnowboard Max B3 */
463*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
464*4882a593Smuzhiyun .matches = {
465*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
466*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
467*4882a593Smuzhiyun },
468*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_IN1_MAP),
469*4882a593Smuzhiyun },
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun /* Minnowboard Turbot */
472*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
473*4882a593Smuzhiyun .matches = {
474*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
475*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
476*4882a593Smuzhiyun },
477*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_MCLK_EN |
478*4882a593Smuzhiyun BYT_RT5651_IN1_MAP),
479*4882a593Smuzhiyun },
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun /* Point of View mobii wintab p1006w (v1.0) */
482*4882a593Smuzhiyun .callback = byt_rt5651_pov_p1006w_quirk_cb,
483*4882a593Smuzhiyun .matches = {
484*4882a593Smuzhiyun DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
485*4882a593Smuzhiyun DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
486*4882a593Smuzhiyun /* Note 105b is Foxcon's USB/PCI vendor id */
487*4882a593Smuzhiyun DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"),
488*4882a593Smuzhiyun DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
489*4882a593Smuzhiyun },
490*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DMIC_MAP |
491*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_2000UA |
492*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_0P75 |
493*4882a593Smuzhiyun BYT_RT5651_DMIC_EN |
494*4882a593Smuzhiyun BYT_RT5651_MCLK_EN |
495*4882a593Smuzhiyun BYT_RT5651_SSP0_AIF1),
496*4882a593Smuzhiyun },
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun /* VIOS LTH17 */
499*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
500*4882a593Smuzhiyun .matches = {
501*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "VIOS"),
502*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "LTH17"),
503*4882a593Smuzhiyun },
504*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_IN1_IN2_MAP |
505*4882a593Smuzhiyun BYT_RT5651_JD1_1 |
506*4882a593Smuzhiyun BYT_RT5651_OVCD_TH_2000UA |
507*4882a593Smuzhiyun BYT_RT5651_OVCD_SF_1P0 |
508*4882a593Smuzhiyun BYT_RT5651_MCLK_EN),
509*4882a593Smuzhiyun },
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun /* Yours Y8W81 (and others using the same mainboard) */
512*4882a593Smuzhiyun .callback = byt_rt5651_quirk_cb,
513*4882a593Smuzhiyun .matches = {
514*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VENDOR, "INSYDE Corp."),
515*4882a593Smuzhiyun /* Partial match for all devs with a W86C mainboard */
516*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VERSION, ".F.W86C."),
517*4882a593Smuzhiyun },
518*4882a593Smuzhiyun .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
519*4882a593Smuzhiyun BYT_RT5651_IN2_MAP |
520*4882a593Smuzhiyun BYT_RT5651_SSP0_AIF1 |
521*4882a593Smuzhiyun BYT_RT5651_MONO_SPEAKER),
522*4882a593Smuzhiyun },
523*4882a593Smuzhiyun {}
524*4882a593Smuzhiyun };
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun /*
527*4882a593Smuzhiyun * Note this MUST be called before snd_soc_register_card(), so that the props
528*4882a593Smuzhiyun * are in place before the codec component driver's probe function parses them.
529*4882a593Smuzhiyun */
byt_rt5651_add_codec_device_props(struct device * i2c_dev)530*4882a593Smuzhiyun static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun struct property_entry props[MAX_NO_PROPS] = {};
533*4882a593Smuzhiyun int cnt = 0;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
536*4882a593Smuzhiyun BYT_RT5651_JDSRC(byt_rt5651_quirk));
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-threshold-microamp",
539*4882a593Smuzhiyun BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-scale-factor",
542*4882a593Smuzhiyun BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
545*4882a593Smuzhiyun props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,dmic-en");
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
548*4882a593Smuzhiyun props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return device_add_properties(i2c_dev, props);
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
byt_rt5651_init(struct snd_soc_pcm_runtime * runtime)553*4882a593Smuzhiyun static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun struct snd_soc_card *card = runtime->card;
556*4882a593Smuzhiyun struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
557*4882a593Smuzhiyun struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
558*4882a593Smuzhiyun const struct snd_soc_dapm_route *custom_map;
559*4882a593Smuzhiyun int num_routes;
560*4882a593Smuzhiyun int report;
561*4882a593Smuzhiyun int ret;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun card->dapm.idle_bias_off = true;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun /* Start with RC clk for jack-detect (we disable MCLK below) */
566*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
567*4882a593Smuzhiyun snd_soc_component_update_bits(codec, RT5651_GLB_CLK,
568*4882a593Smuzhiyun RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
571*4882a593Smuzhiyun case BYT_RT5651_IN1_MAP:
572*4882a593Smuzhiyun custom_map = byt_rt5651_intmic_in1_map;
573*4882a593Smuzhiyun num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
574*4882a593Smuzhiyun break;
575*4882a593Smuzhiyun case BYT_RT5651_IN2_MAP:
576*4882a593Smuzhiyun custom_map = byt_rt5651_intmic_in2_map;
577*4882a593Smuzhiyun num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
578*4882a593Smuzhiyun break;
579*4882a593Smuzhiyun case BYT_RT5651_IN1_IN2_MAP:
580*4882a593Smuzhiyun custom_map = byt_rt5651_intmic_in1_in2_map;
581*4882a593Smuzhiyun num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
582*4882a593Smuzhiyun break;
583*4882a593Smuzhiyun default:
584*4882a593Smuzhiyun custom_map = byt_rt5651_intmic_dmic_map;
585*4882a593Smuzhiyun num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
588*4882a593Smuzhiyun if (ret)
589*4882a593Smuzhiyun return ret;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
592*4882a593Smuzhiyun ret = snd_soc_dapm_add_routes(&card->dapm,
593*4882a593Smuzhiyun byt_rt5651_ssp2_aif2_map,
594*4882a593Smuzhiyun ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
595*4882a593Smuzhiyun } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
596*4882a593Smuzhiyun ret = snd_soc_dapm_add_routes(&card->dapm,
597*4882a593Smuzhiyun byt_rt5651_ssp0_aif1_map,
598*4882a593Smuzhiyun ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
599*4882a593Smuzhiyun } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
600*4882a593Smuzhiyun ret = snd_soc_dapm_add_routes(&card->dapm,
601*4882a593Smuzhiyun byt_rt5651_ssp0_aif2_map,
602*4882a593Smuzhiyun ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
603*4882a593Smuzhiyun } else {
604*4882a593Smuzhiyun ret = snd_soc_dapm_add_routes(&card->dapm,
605*4882a593Smuzhiyun byt_rt5651_ssp2_aif1_map,
606*4882a593Smuzhiyun ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun if (ret)
609*4882a593Smuzhiyun return ret;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
612*4882a593Smuzhiyun ARRAY_SIZE(byt_rt5651_controls));
613*4882a593Smuzhiyun if (ret) {
614*4882a593Smuzhiyun dev_err(card->dev, "unable to add card controls\n");
615*4882a593Smuzhiyun return ret;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
619*4882a593Smuzhiyun /*
620*4882a593Smuzhiyun * The firmware might enable the clock at
621*4882a593Smuzhiyun * boot (this information may or may not
622*4882a593Smuzhiyun * be reflected in the enable clock register).
623*4882a593Smuzhiyun * To change the rate we must disable the clock
624*4882a593Smuzhiyun * first to cover these cases. Due to common
625*4882a593Smuzhiyun * clock framework restrictions that do not allow
626*4882a593Smuzhiyun * to disable a clock that has not been enabled,
627*4882a593Smuzhiyun * we need to enable the clock first.
628*4882a593Smuzhiyun */
629*4882a593Smuzhiyun ret = clk_prepare_enable(priv->mclk);
630*4882a593Smuzhiyun if (!ret)
631*4882a593Smuzhiyun clk_disable_unprepare(priv->mclk);
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
634*4882a593Smuzhiyun ret = clk_set_rate(priv->mclk, 25000000);
635*4882a593Smuzhiyun else
636*4882a593Smuzhiyun ret = clk_set_rate(priv->mclk, 19200000);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun if (ret)
639*4882a593Smuzhiyun dev_err(card->dev, "unable to set MCLK rate\n");
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun report = 0;
643*4882a593Smuzhiyun if (BYT_RT5651_JDSRC(byt_rt5651_quirk))
644*4882a593Smuzhiyun report = SND_JACK_HEADSET | SND_JACK_BTN_0;
645*4882a593Smuzhiyun else if (priv->hp_detect)
646*4882a593Smuzhiyun report = SND_JACK_HEADSET;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (report) {
649*4882a593Smuzhiyun ret = snd_soc_card_jack_new(runtime->card, "Headset",
650*4882a593Smuzhiyun report, &priv->jack, bytcr_jack_pins,
651*4882a593Smuzhiyun ARRAY_SIZE(bytcr_jack_pins));
652*4882a593Smuzhiyun if (ret) {
653*4882a593Smuzhiyun dev_err(runtime->dev, "jack creation failed %d\n", ret);
654*4882a593Smuzhiyun return ret;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (report & SND_JACK_BTN_0)
658*4882a593Smuzhiyun snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
659*4882a593Smuzhiyun KEY_PLAYPAUSE);
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun ret = snd_soc_component_set_jack(codec, &priv->jack,
662*4882a593Smuzhiyun priv->hp_detect);
663*4882a593Smuzhiyun if (ret)
664*4882a593Smuzhiyun return ret;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun return 0;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)670*4882a593Smuzhiyun static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
671*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun struct snd_interval *rate = hw_param_interval(params,
674*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE);
675*4882a593Smuzhiyun struct snd_interval *channels = hw_param_interval(params,
676*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_CHANNELS);
677*4882a593Smuzhiyun int ret, bits;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun /* The DSP will covert the FE rate to 48k, stereo */
680*4882a593Smuzhiyun rate->min = rate->max = 48000;
681*4882a593Smuzhiyun channels->min = channels->max = 2;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
684*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
685*4882a593Smuzhiyun /* set SSP0 to 16-bit */
686*4882a593Smuzhiyun params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
687*4882a593Smuzhiyun bits = 16;
688*4882a593Smuzhiyun } else {
689*4882a593Smuzhiyun /* set SSP2 to 24-bit */
690*4882a593Smuzhiyun params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
691*4882a593Smuzhiyun bits = 24;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun /*
695*4882a593Smuzhiyun * Default mode for SSP configuration is TDM 4 slot, override config
696*4882a593Smuzhiyun * with explicit setting to I2S 2ch. The word length is set with
697*4882a593Smuzhiyun * dai_set_tdm_slot() since there is no other API exposed
698*4882a593Smuzhiyun */
699*4882a593Smuzhiyun ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
700*4882a593Smuzhiyun SND_SOC_DAIFMT_I2S |
701*4882a593Smuzhiyun SND_SOC_DAIFMT_NB_NF |
702*4882a593Smuzhiyun SND_SOC_DAIFMT_CBS_CFS
703*4882a593Smuzhiyun );
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun if (ret < 0) {
706*4882a593Smuzhiyun dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
707*4882a593Smuzhiyun return ret;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
711*4882a593Smuzhiyun if (ret < 0) {
712*4882a593Smuzhiyun dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
713*4882a593Smuzhiyun return ret;
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun return 0;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun static const unsigned int rates_48000[] = {
720*4882a593Smuzhiyun 48000,
721*4882a593Smuzhiyun };
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun static const struct snd_pcm_hw_constraint_list constraints_48000 = {
724*4882a593Smuzhiyun .count = ARRAY_SIZE(rates_48000),
725*4882a593Smuzhiyun .list = rates_48000,
726*4882a593Smuzhiyun };
727*4882a593Smuzhiyun
byt_rt5651_aif1_startup(struct snd_pcm_substream * substream)728*4882a593Smuzhiyun static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun return snd_pcm_hw_constraint_list(substream->runtime, 0,
731*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE,
732*4882a593Smuzhiyun &constraints_48000);
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun static const struct snd_soc_ops byt_rt5651_aif1_ops = {
736*4882a593Smuzhiyun .startup = byt_rt5651_aif1_startup,
737*4882a593Smuzhiyun };
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
740*4882a593Smuzhiyun .hw_params = byt_rt5651_aif1_hw_params,
741*4882a593Smuzhiyun };
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(dummy,
744*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_DUMMY()));
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(media,
747*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(deepbuffer,
750*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp2_port,
753*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
754*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(ssp2_codec,
755*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5651:00", "rt5651-aif1")));
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun SND_SOC_DAILINK_DEF(platform,
758*4882a593Smuzhiyun DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun static struct snd_soc_dai_link byt_rt5651_dais[] = {
761*4882a593Smuzhiyun [MERR_DPCM_AUDIO] = {
762*4882a593Smuzhiyun .name = "Audio Port",
763*4882a593Smuzhiyun .stream_name = "Audio",
764*4882a593Smuzhiyun .nonatomic = true,
765*4882a593Smuzhiyun .dynamic = 1,
766*4882a593Smuzhiyun .dpcm_playback = 1,
767*4882a593Smuzhiyun .dpcm_capture = 1,
768*4882a593Smuzhiyun .ops = &byt_rt5651_aif1_ops,
769*4882a593Smuzhiyun SND_SOC_DAILINK_REG(media, dummy, platform),
770*4882a593Smuzhiyun },
771*4882a593Smuzhiyun [MERR_DPCM_DEEP_BUFFER] = {
772*4882a593Smuzhiyun .name = "Deep-Buffer Audio Port",
773*4882a593Smuzhiyun .stream_name = "Deep-Buffer Audio",
774*4882a593Smuzhiyun .nonatomic = true,
775*4882a593Smuzhiyun .dynamic = 1,
776*4882a593Smuzhiyun .dpcm_playback = 1,
777*4882a593Smuzhiyun .ops = &byt_rt5651_aif1_ops,
778*4882a593Smuzhiyun SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
779*4882a593Smuzhiyun },
780*4882a593Smuzhiyun /* CODEC<->CODEC link */
781*4882a593Smuzhiyun /* back ends */
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun .name = "SSP2-Codec",
784*4882a593Smuzhiyun .id = 0,
785*4882a593Smuzhiyun .no_pcm = 1,
786*4882a593Smuzhiyun .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
787*4882a593Smuzhiyun | SND_SOC_DAIFMT_CBS_CFS,
788*4882a593Smuzhiyun .be_hw_params_fixup = byt_rt5651_codec_fixup,
789*4882a593Smuzhiyun .nonatomic = true,
790*4882a593Smuzhiyun .dpcm_playback = 1,
791*4882a593Smuzhiyun .dpcm_capture = 1,
792*4882a593Smuzhiyun .init = byt_rt5651_init,
793*4882a593Smuzhiyun .ops = &byt_rt5651_be_ssp2_ops,
794*4882a593Smuzhiyun SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
795*4882a593Smuzhiyun },
796*4882a593Smuzhiyun };
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* SoC card */
799*4882a593Smuzhiyun static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
800*4882a593Smuzhiyun #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
801*4882a593Smuzhiyun static char byt_rt5651_long_name[50]; /* = "bytcr-rt5651-*-spk-*-mic[-swapped-hp]" */
802*4882a593Smuzhiyun #endif
803*4882a593Smuzhiyun static char byt_rt5651_components[50]; /* = "cfg-spk:* cfg-mic:*" */
804*4882a593Smuzhiyun
byt_rt5651_suspend(struct snd_soc_card * card)805*4882a593Smuzhiyun static int byt_rt5651_suspend(struct snd_soc_card *card)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun struct snd_soc_component *component;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
810*4882a593Smuzhiyun return 0;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun for_each_card_components(card, component) {
813*4882a593Smuzhiyun if (!strcmp(component->name, byt_rt5651_codec_name)) {
814*4882a593Smuzhiyun dev_dbg(component->dev, "disabling jack detect before suspend\n");
815*4882a593Smuzhiyun snd_soc_component_set_jack(component, NULL, NULL);
816*4882a593Smuzhiyun break;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun return 0;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
byt_rt5651_resume(struct snd_soc_card * card)823*4882a593Smuzhiyun static int byt_rt5651_resume(struct snd_soc_card *card)
824*4882a593Smuzhiyun {
825*4882a593Smuzhiyun struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
826*4882a593Smuzhiyun struct snd_soc_component *component;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
829*4882a593Smuzhiyun return 0;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun for_each_card_components(card, component) {
832*4882a593Smuzhiyun if (!strcmp(component->name, byt_rt5651_codec_name)) {
833*4882a593Smuzhiyun dev_dbg(component->dev, "re-enabling jack detect after resume\n");
834*4882a593Smuzhiyun snd_soc_component_set_jack(component, &priv->jack,
835*4882a593Smuzhiyun priv->hp_detect);
836*4882a593Smuzhiyun break;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun return 0;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
844*4882a593Smuzhiyun /* use space before codec name to simplify card ID, and simplify driver name */
845*4882a593Smuzhiyun #define CARD_NAME "bytcht rt5651" /* card name will be 'sof-bytcht rt5651' */
846*4882a593Smuzhiyun #define DRIVER_NAME "SOF"
847*4882a593Smuzhiyun #else
848*4882a593Smuzhiyun #define CARD_NAME "bytcr-rt5651"
849*4882a593Smuzhiyun #define DRIVER_NAME NULL /* card name will be used for driver name */
850*4882a593Smuzhiyun #endif
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun static struct snd_soc_card byt_rt5651_card = {
853*4882a593Smuzhiyun .name = CARD_NAME,
854*4882a593Smuzhiyun .driver_name = DRIVER_NAME,
855*4882a593Smuzhiyun .owner = THIS_MODULE,
856*4882a593Smuzhiyun .dai_link = byt_rt5651_dais,
857*4882a593Smuzhiyun .num_links = ARRAY_SIZE(byt_rt5651_dais),
858*4882a593Smuzhiyun .dapm_widgets = byt_rt5651_widgets,
859*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
860*4882a593Smuzhiyun .dapm_routes = byt_rt5651_audio_map,
861*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
862*4882a593Smuzhiyun .fully_routed = true,
863*4882a593Smuzhiyun .suspend_pre = byt_rt5651_suspend,
864*4882a593Smuzhiyun .resume_post = byt_rt5651_resume,
865*4882a593Smuzhiyun };
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun static const struct acpi_gpio_params ext_amp_enable_gpios = { 0, 0, false };
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun static const struct acpi_gpio_mapping cht_rt5651_gpios[] = {
870*4882a593Smuzhiyun /*
871*4882a593Smuzhiyun * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources,
872*4882a593Smuzhiyun * other boards may have I2cSerialBusV2, GpioInt, GpioIo instead.
873*4882a593Smuzhiyun * We want the GpioIo one for the ext-amp-enable-gpio.
874*4882a593Smuzhiyun */
875*4882a593Smuzhiyun { "ext-amp-enable-gpios", &ext_amp_enable_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
876*4882a593Smuzhiyun { },
877*4882a593Smuzhiyun };
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
880*4882a593Smuzhiyun u64 aif_value; /* 1: AIF1, 2: AIF2 */
881*4882a593Smuzhiyun u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
882*4882a593Smuzhiyun };
883*4882a593Smuzhiyun
snd_byt_rt5651_mc_probe(struct platform_device * pdev)884*4882a593Smuzhiyun static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
885*4882a593Smuzhiyun {
886*4882a593Smuzhiyun static const char * const mic_name[] = { "dmic", "in1", "in2", "in12" };
887*4882a593Smuzhiyun struct byt_rt5651_private *priv;
888*4882a593Smuzhiyun struct snd_soc_acpi_mach *mach;
889*4882a593Smuzhiyun const char *platform_name;
890*4882a593Smuzhiyun struct acpi_device *adev;
891*4882a593Smuzhiyun struct device *codec_dev;
892*4882a593Smuzhiyun bool is_bytcr = false;
893*4882a593Smuzhiyun int ret_val = 0;
894*4882a593Smuzhiyun int dai_index = 0;
895*4882a593Smuzhiyun int i;
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
898*4882a593Smuzhiyun if (!priv)
899*4882a593Smuzhiyun return -ENOMEM;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun /* register the soc card */
902*4882a593Smuzhiyun byt_rt5651_card.dev = &pdev->dev;
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun mach = byt_rt5651_card.dev->platform_data;
905*4882a593Smuzhiyun snd_soc_card_set_drvdata(&byt_rt5651_card, priv);
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /* fix index of codec dai */
908*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
909*4882a593Smuzhiyun if (!strcmp(byt_rt5651_dais[i].codecs->name,
910*4882a593Smuzhiyun "i2c-10EC5651:00")) {
911*4882a593Smuzhiyun dai_index = i;
912*4882a593Smuzhiyun break;
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun /* fixup codec name based on HID */
917*4882a593Smuzhiyun adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
918*4882a593Smuzhiyun if (adev) {
919*4882a593Smuzhiyun snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
920*4882a593Smuzhiyun "i2c-%s", acpi_dev_name(adev));
921*4882a593Smuzhiyun put_device(&adev->dev);
922*4882a593Smuzhiyun byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
923*4882a593Smuzhiyun } else {
924*4882a593Smuzhiyun dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
925*4882a593Smuzhiyun return -ENODEV;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
929*4882a593Smuzhiyun byt_rt5651_codec_name);
930*4882a593Smuzhiyun if (!codec_dev)
931*4882a593Smuzhiyun return -EPROBE_DEFER;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun /*
934*4882a593Smuzhiyun * swap SSP0 if bytcr is detected
935*4882a593Smuzhiyun * (will be overridden if DMI quirk is detected)
936*4882a593Smuzhiyun */
937*4882a593Smuzhiyun if (soc_intel_is_byt()) {
938*4882a593Smuzhiyun if (mach->mach_params.acpi_ipc_irq_index == 0)
939*4882a593Smuzhiyun is_bytcr = true;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (is_bytcr) {
943*4882a593Smuzhiyun /*
944*4882a593Smuzhiyun * Baytrail CR platforms may have CHAN package in BIOS, try
945*4882a593Smuzhiyun * to find relevant routing quirk based as done on Windows
946*4882a593Smuzhiyun * platforms. We have to read the information directly from the
947*4882a593Smuzhiyun * BIOS, at this stage the card is not created and the links
948*4882a593Smuzhiyun * with the codec driver/pdata are non-existent
949*4882a593Smuzhiyun */
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun struct acpi_chan_package chan_package;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun /* format specified: 2 64-bit integers */
954*4882a593Smuzhiyun struct acpi_buffer format = {sizeof("NN"), "NN"};
955*4882a593Smuzhiyun struct acpi_buffer state = {0, NULL};
956*4882a593Smuzhiyun struct snd_soc_acpi_package_context pkg_ctx;
957*4882a593Smuzhiyun bool pkg_found = false;
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun state.length = sizeof(chan_package);
960*4882a593Smuzhiyun state.pointer = &chan_package;
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun pkg_ctx.name = "CHAN";
963*4882a593Smuzhiyun pkg_ctx.length = 2;
964*4882a593Smuzhiyun pkg_ctx.format = &format;
965*4882a593Smuzhiyun pkg_ctx.state = &state;
966*4882a593Smuzhiyun pkg_ctx.data_valid = false;
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
969*4882a593Smuzhiyun &pkg_ctx);
970*4882a593Smuzhiyun if (pkg_found) {
971*4882a593Smuzhiyun if (chan_package.aif_value == 1) {
972*4882a593Smuzhiyun dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
973*4882a593Smuzhiyun byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
974*4882a593Smuzhiyun } else if (chan_package.aif_value == 2) {
975*4882a593Smuzhiyun dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
976*4882a593Smuzhiyun byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
977*4882a593Smuzhiyun } else {
978*4882a593Smuzhiyun dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
979*4882a593Smuzhiyun pkg_found = false;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun if (!pkg_found) {
984*4882a593Smuzhiyun /* no BIOS indications, assume SSP0-AIF2 connection */
985*4882a593Smuzhiyun byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun /* check quirks before creating card */
990*4882a593Smuzhiyun dmi_check_system(byt_rt5651_quirk_table);
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun if (quirk_override != -1) {
993*4882a593Smuzhiyun dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
994*4882a593Smuzhiyun byt_rt5651_quirk, quirk_override);
995*4882a593Smuzhiyun byt_rt5651_quirk = quirk_override;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun /* Must be called before register_card, also see declaration comment. */
999*4882a593Smuzhiyun ret_val = byt_rt5651_add_codec_device_props(codec_dev);
1000*4882a593Smuzhiyun if (ret_val) {
1001*4882a593Smuzhiyun put_device(codec_dev);
1002*4882a593Smuzhiyun return ret_val;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun /* Cherry Trail devices use an external amplifier enable gpio */
1006*4882a593Smuzhiyun if (soc_intel_is_cht() && !byt_rt5651_gpios)
1007*4882a593Smuzhiyun byt_rt5651_gpios = cht_rt5651_gpios;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun if (byt_rt5651_gpios) {
1010*4882a593Smuzhiyun devm_acpi_dev_add_driver_gpios(codec_dev, byt_rt5651_gpios);
1011*4882a593Smuzhiyun priv->ext_amp_gpio = devm_fwnode_gpiod_get(&pdev->dev,
1012*4882a593Smuzhiyun codec_dev->fwnode,
1013*4882a593Smuzhiyun "ext-amp-enable",
1014*4882a593Smuzhiyun GPIOD_OUT_LOW,
1015*4882a593Smuzhiyun "speaker-amp");
1016*4882a593Smuzhiyun if (IS_ERR(priv->ext_amp_gpio)) {
1017*4882a593Smuzhiyun ret_val = PTR_ERR(priv->ext_amp_gpio);
1018*4882a593Smuzhiyun switch (ret_val) {
1019*4882a593Smuzhiyun case -ENOENT:
1020*4882a593Smuzhiyun priv->ext_amp_gpio = NULL;
1021*4882a593Smuzhiyun break;
1022*4882a593Smuzhiyun default:
1023*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n",
1024*4882a593Smuzhiyun ret_val);
1025*4882a593Smuzhiyun fallthrough;
1026*4882a593Smuzhiyun case -EPROBE_DEFER:
1027*4882a593Smuzhiyun put_device(codec_dev);
1028*4882a593Smuzhiyun return ret_val;
1029*4882a593Smuzhiyun }
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev,
1032*4882a593Smuzhiyun codec_dev->fwnode,
1033*4882a593Smuzhiyun "hp-detect",
1034*4882a593Smuzhiyun GPIOD_IN,
1035*4882a593Smuzhiyun "hp-detect");
1036*4882a593Smuzhiyun if (IS_ERR(priv->hp_detect)) {
1037*4882a593Smuzhiyun ret_val = PTR_ERR(priv->hp_detect);
1038*4882a593Smuzhiyun switch (ret_val) {
1039*4882a593Smuzhiyun case -ENOENT:
1040*4882a593Smuzhiyun priv->hp_detect = NULL;
1041*4882a593Smuzhiyun break;
1042*4882a593Smuzhiyun default:
1043*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to get hp-detect GPIO: %d\n",
1044*4882a593Smuzhiyun ret_val);
1045*4882a593Smuzhiyun fallthrough;
1046*4882a593Smuzhiyun case -EPROBE_DEFER:
1047*4882a593Smuzhiyun put_device(codec_dev);
1048*4882a593Smuzhiyun return ret_val;
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun }
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun put_device(codec_dev);
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun log_quirks(&pdev->dev);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
1058*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2))
1059*4882a593Smuzhiyun byt_rt5651_dais[dai_index].codecs->dai_name = "rt5651-aif2";
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
1062*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2))
1063*4882a593Smuzhiyun byt_rt5651_dais[dai_index].cpus->dai_name = "ssp0-port";
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
1066*4882a593Smuzhiyun priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
1067*4882a593Smuzhiyun if (IS_ERR(priv->mclk)) {
1068*4882a593Smuzhiyun ret_val = PTR_ERR(priv->mclk);
1069*4882a593Smuzhiyun dev_err(&pdev->dev,
1070*4882a593Smuzhiyun "Failed to get MCLK from pmc_plt_clk_3: %d\n",
1071*4882a593Smuzhiyun ret_val);
1072*4882a593Smuzhiyun /*
1073*4882a593Smuzhiyun * Fall back to bit clock usage for -ENOENT (clock not
1074*4882a593Smuzhiyun * available likely due to missing dependencies), bail
1075*4882a593Smuzhiyun * for all other errors, including -EPROBE_DEFER
1076*4882a593Smuzhiyun */
1077*4882a593Smuzhiyun if (ret_val != -ENOENT)
1078*4882a593Smuzhiyun return ret_val;
1079*4882a593Smuzhiyun byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun snprintf(byt_rt5651_components, sizeof(byt_rt5651_components),
1084*4882a593Smuzhiyun "cfg-spk:%s cfg-mic:%s%s",
1085*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? "1" : "2",
1086*4882a593Smuzhiyun mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
1087*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
1088*4882a593Smuzhiyun " cfg-hp:lrswap" : "");
1089*4882a593Smuzhiyun byt_rt5651_card.components = byt_rt5651_components;
1090*4882a593Smuzhiyun #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1091*4882a593Smuzhiyun snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name),
1092*4882a593Smuzhiyun "bytcr-rt5651-%s-spk-%s-mic%s",
1093*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ?
1094*4882a593Smuzhiyun "mono" : "stereo",
1095*4882a593Smuzhiyun mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
1096*4882a593Smuzhiyun (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
1097*4882a593Smuzhiyun "-hp-swapped" : "");
1098*4882a593Smuzhiyun byt_rt5651_card.long_name = byt_rt5651_long_name;
1099*4882a593Smuzhiyun #endif
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun /* override plaform name, if required */
1102*4882a593Smuzhiyun platform_name = mach->mach_params.platform;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
1105*4882a593Smuzhiyun platform_name);
1106*4882a593Smuzhiyun if (ret_val)
1107*4882a593Smuzhiyun return ret_val;
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun if (ret_val) {
1112*4882a593Smuzhiyun dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1113*4882a593Smuzhiyun ret_val);
1114*4882a593Smuzhiyun return ret_val;
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun platform_set_drvdata(pdev, &byt_rt5651_card);
1117*4882a593Smuzhiyun return ret_val;
1118*4882a593Smuzhiyun }
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun static struct platform_driver snd_byt_rt5651_mc_driver = {
1121*4882a593Smuzhiyun .driver = {
1122*4882a593Smuzhiyun .name = "bytcr_rt5651",
1123*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
1124*4882a593Smuzhiyun .pm = &snd_soc_pm_ops,
1125*4882a593Smuzhiyun #endif
1126*4882a593Smuzhiyun },
1127*4882a593Smuzhiyun .probe = snd_byt_rt5651_mc_probe,
1128*4882a593Smuzhiyun };
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun module_platform_driver(snd_byt_rt5651_mc_driver);
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
1133*4882a593Smuzhiyun MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1134*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1135*4882a593Smuzhiyun MODULE_ALIAS("platform:bytcr_rt5651");
1136