Commit | Line | Data |
---|---|---|
996cc849 SP |
1 | /* |
2 | * byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform | |
3 | * | |
4 | * Copyright (C) 2014 Intel Corp | |
5 | * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> | |
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; version 2 of the License. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
18 | */ | |
19 | ||
6a7c05e5 | 20 | #include <linux/i2c.h> |
996cc849 SP |
21 | #include <linux/init.h> |
22 | #include <linux/module.h> | |
9f2cf73e | 23 | #include <linux/moduleparam.h> |
996cc849 | 24 | #include <linux/platform_device.h> |
a2d5563b | 25 | #include <linux/acpi.h> |
17b5273d | 26 | #include <linux/clk.h> |
996cc849 | 27 | #include <linux/device.h> |
a2d5563b | 28 | #include <linux/dmi.h> |
77323108 | 29 | #include <linux/input.h> |
996cc849 | 30 | #include <linux/slab.h> |
e214f5e7 PLB |
31 | #include <asm/cpu_device_id.h> |
32 | #include <asm/platform_sst_audio.h> | |
996cc849 SP |
33 | #include <sound/pcm.h> |
34 | #include <sound/pcm_params.h> | |
35 | #include <sound/soc.h> | |
a2d5563b | 36 | #include <sound/jack.h> |
7feb2f78 | 37 | #include <sound/soc-acpi.h> |
a3ad2911 | 38 | #include <dt-bindings/sound/rt5640.h> |
e56c72d5 | 39 | #include "../../codecs/rt5640.h" |
b97169da | 40 | #include "../atom/sst-atom-controls.h" |
e214f5e7 | 41 | #include "../common/sst-dsp.h" |
996cc849 | 42 | |
ab738e4e PLB |
43 | enum { |
44 | BYT_RT5640_DMIC1_MAP, | |
45 | BYT_RT5640_DMIC2_MAP, | |
46 | BYT_RT5640_IN1_MAP, | |
59e8b652 | 47 | BYT_RT5640_IN3_MAP, |
ab738e4e PLB |
48 | }; |
49 | ||
77323108 HG |
50 | enum { |
51 | BYT_RT5640_JD_SRC_GPIO1 = (RT5640_JD_SRC_GPIO1 << 4), | |
52 | BYT_RT5640_JD_SRC_JD1_IN4P = (RT5640_JD_SRC_JD1_IN4P << 4), | |
53 | BYT_RT5640_JD_SRC_JD2_IN4N = (RT5640_JD_SRC_JD2_IN4N << 4), | |
54 | BYT_RT5640_JD_SRC_GPIO2 = (RT5640_JD_SRC_GPIO2 << 4), | |
55 | BYT_RT5640_JD_SRC_GPIO3 = (RT5640_JD_SRC_GPIO3 << 4), | |
56 | BYT_RT5640_JD_SRC_GPIO4 = (RT5640_JD_SRC_GPIO4 << 4), | |
57 | }; | |
58 | ||
59 | enum { | |
60 | BYT_RT5640_OVCD_TH_600UA = (6 << 8), | |
61 | BYT_RT5640_OVCD_TH_1500UA = (15 << 8), | |
62 | BYT_RT5640_OVCD_TH_2000UA = (20 << 8), | |
63 | }; | |
64 | ||
65 | enum { | |
66 | BYT_RT5640_OVCD_SF_0P5 = (RT5640_OVCD_SF_0P5 << 13), | |
67 | BYT_RT5640_OVCD_SF_0P75 = (RT5640_OVCD_SF_0P75 << 13), | |
68 | BYT_RT5640_OVCD_SF_1P0 = (RT5640_OVCD_SF_1P0 << 13), | |
69 | BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13), | |
70 | }; | |
df1a2776 | 71 | |
77323108 HG |
72 | #define BYT_RT5640_MAP(quirk) ((quirk) & GENMASK(3, 0)) |
73 | #define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) | |
74 | #define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8) | |
75 | #define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13) | |
76 | #define BYT_RT5640_JD_NOT_INV BIT(16) | |
77 | #define BYT_RT5640_MONO_SPEAKER BIT(17) | |
78 | #define BYT_RT5640_DIFF_MIC BIT(18) /* default is single-ended */ | |
79 | #define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ | |
80 | #define BYT_RT5640_SSP0_AIF1 BIT(20) | |
81 | #define BYT_RT5640_SSP0_AIF2 BIT(21) | |
82 | #define BYT_RT5640_MCLK_EN BIT(22) | |
83 | #define BYT_RT5640_MCLK_25MHZ BIT(23) | |
84 | ||
96a388fe HG |
85 | #define BYTCR_INPUT_DEFAULTS \ |
86 | (BYT_RT5640_IN3_MAP | \ | |
56ff4409 HG |
87 | BYT_RT5640_JD_SRC_JD1_IN4P | \ |
88 | BYT_RT5640_OVCD_TH_2000UA | \ | |
89 | BYT_RT5640_OVCD_SF_0P75 | \ | |
96a388fe HG |
90 | BYT_RT5640_DIFF_MIC) |
91 | ||
77323108 HG |
92 | /* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */ |
93 | #define MAX_NO_PROPS 6 | |
6a7c05e5 | 94 | |
df1a2776 | 95 | struct byt_rt5640_private { |
77323108 | 96 | struct snd_soc_jack jack; |
df1a2776 IT |
97 | struct clk *mclk; |
98 | }; | |
cb67d765 | 99 | static bool is_bytcr; |
ab738e4e | 100 | |
bf46241b | 101 | static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN; |
9f2cf73e | 102 | static unsigned int quirk_override; |
0b2c9f88 | 103 | module_param_named(quirk, quirk_override, uint, 0444); |
9f2cf73e | 104 | MODULE_PARM_DESC(quirk, "Board-specific quirk override"); |
df1a2776 | 105 | |
d7e60d52 PLB |
106 | static void log_quirks(struct device *dev) |
107 | { | |
cb67d765 | 108 | int map; |
cb67d765 PLB |
109 | bool has_mclk = false; |
110 | bool has_ssp0 = false; | |
111 | bool has_ssp0_aif1 = false; | |
112 | bool has_ssp0_aif2 = false; | |
113 | bool has_ssp2_aif2 = false; | |
114 | ||
115 | map = BYT_RT5640_MAP(byt_rt5640_quirk); | |
116 | switch (map) { | |
117 | case BYT_RT5640_DMIC1_MAP: | |
118 | dev_info(dev, "quirk DMIC1_MAP enabled\n"); | |
cb67d765 PLB |
119 | break; |
120 | case BYT_RT5640_DMIC2_MAP: | |
121 | dev_info(dev, "quirk DMIC2_MAP enabled\n"); | |
cb67d765 PLB |
122 | break; |
123 | case BYT_RT5640_IN1_MAP: | |
124 | dev_info(dev, "quirk IN1_MAP enabled\n"); | |
125 | break; | |
126 | case BYT_RT5640_IN3_MAP: | |
127 | dev_info(dev, "quirk IN3_MAP enabled\n"); | |
128 | break; | |
129 | default: | |
130 | dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); | |
131 | break; | |
132 | } | |
77323108 HG |
133 | if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { |
134 | dev_info(dev, "quirk realtek,jack-detect-source %ld\n", | |
135 | BYT_RT5640_JDSRC(byt_rt5640_quirk)); | |
136 | dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n", | |
137 | BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); | |
138 | dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n", | |
139 | BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); | |
140 | } | |
141 | if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) | |
142 | dev_info(dev, "quirk JD_NOT_INV enabled\n"); | |
d7e60d52 | 143 | if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) |
cb67d765 | 144 | dev_info(dev, "quirk MONO_SPEAKER enabled\n"); |
a3ad2911 HG |
145 | if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) |
146 | dev_info(dev, "quirk DIFF_MIC enabled\n"); | |
cb67d765 PLB |
147 | if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { |
148 | dev_info(dev, "quirk SSP0_AIF1 enabled\n"); | |
149 | has_ssp0 = true; | |
150 | has_ssp0_aif1 = true; | |
151 | } | |
152 | if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { | |
153 | dev_info(dev, "quirk SSP0_AIF2 enabled\n"); | |
154 | has_ssp0 = true; | |
155 | has_ssp0_aif2 = true; | |
156 | } | |
157 | if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { | |
158 | dev_info(dev, "quirk SSP2_AIF2 enabled\n"); | |
159 | has_ssp2_aif2 = true; | |
160 | } | |
161 | if (is_bytcr && !has_ssp0) | |
162 | dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n"); | |
163 | if (has_ssp0_aif1 && has_ssp0_aif2) | |
164 | dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n"); | |
165 | if (has_ssp0 && has_ssp2_aif2) | |
166 | dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n"); | |
167 | ||
168 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { | |
169 | dev_info(dev, "quirk MCLK_EN enabled\n"); | |
170 | has_mclk = true; | |
171 | } | |
172 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { | |
173 | if (has_mclk) | |
174 | dev_info(dev, "quirk MCLK_25MHZ enabled\n"); | |
175 | else | |
176 | dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n"); | |
177 | } | |
d7e60d52 PLB |
178 | } |
179 | ||
bcd9a325 HG |
180 | static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, |
181 | int rate) | |
182 | { | |
183 | int ret; | |
184 | ||
185 | /* Configure the PLL before selecting it */ | |
186 | if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) { | |
187 | /* use bitclock as PLL input */ | |
188 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || | |
189 | (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { | |
190 | /* 2x16 bit slots on SSP0 */ | |
191 | ret = snd_soc_dai_set_pll(codec_dai, 0, | |
192 | RT5640_PLL1_S_BCLK1, | |
193 | rate * 32, rate * 512); | |
194 | } else { | |
195 | /* 2x15 bit slots on SSP2 */ | |
196 | ret = snd_soc_dai_set_pll(codec_dai, 0, | |
197 | RT5640_PLL1_S_BCLK1, | |
198 | rate * 50, rate * 512); | |
199 | } | |
200 | } else { | |
201 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { | |
202 | ret = snd_soc_dai_set_pll(codec_dai, 0, | |
203 | RT5640_PLL1_S_MCLK, | |
204 | 25000000, rate * 512); | |
205 | } else { | |
206 | ret = snd_soc_dai_set_pll(codec_dai, 0, | |
207 | RT5640_PLL1_S_MCLK, | |
208 | 19200000, rate * 512); | |
209 | } | |
210 | } | |
211 | ||
212 | if (ret < 0) { | |
a3a956a6 | 213 | dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret); |
bcd9a325 HG |
214 | return ret; |
215 | } | |
216 | ||
217 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, | |
218 | rate * 512, SND_SOC_CLOCK_IN); | |
219 | if (ret < 0) { | |
a3a956a6 | 220 | dev_err(codec_dai->component->dev, "can't set clock %d\n", ret); |
bcd9a325 HG |
221 | return ret; |
222 | } | |
223 | ||
224 | return 0; | |
225 | } | |
d7e60d52 | 226 | |
df1a2776 IT |
227 | #define BYT_CODEC_DAI1 "rt5640-aif1" |
228 | #define BYT_CODEC_DAI2 "rt5640-aif2" | |
229 | ||
df1a2776 IT |
230 | static int platform_clock_control(struct snd_soc_dapm_widget *w, |
231 | struct snd_kcontrol *k, int event) | |
232 | { | |
233 | struct snd_soc_dapm_context *dapm = w->dapm; | |
234 | struct snd_soc_card *card = dapm->card; | |
235 | struct snd_soc_dai *codec_dai; | |
236 | struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); | |
237 | int ret; | |
238 | ||
dfb6ec7a PLB |
239 | codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); |
240 | if (!codec_dai) | |
241 | codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); | |
242 | ||
df1a2776 IT |
243 | if (!codec_dai) { |
244 | dev_err(card->dev, | |
245 | "Codec dai not found; Unable to set platform clock\n"); | |
246 | return -EIO; | |
247 | } | |
248 | ||
249 | if (SND_SOC_DAPM_EVENT_ON(event)) { | |
17b5273d | 250 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
df1a2776 IT |
251 | ret = clk_prepare_enable(priv->mclk); |
252 | if (ret < 0) { | |
253 | dev_err(card->dev, | |
cb67d765 | 254 | "could not configure MCLK state\n"); |
df1a2776 IT |
255 | return ret; |
256 | } | |
257 | } | |
bcd9a325 | 258 | ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000); |
df1a2776 IT |
259 | } else { |
260 | /* | |
261 | * Set codec clock source to internal clock before | |
262 | * turning off the platform clock. Codec needs clock | |
263 | * for Jack detection and button press | |
264 | */ | |
265 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, | |
60448b07 | 266 | 48000 * 512, |
df1a2776 IT |
267 | SND_SOC_CLOCK_IN); |
268 | if (!ret) { | |
17b5273d | 269 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) |
df1a2776 IT |
270 | clk_disable_unprepare(priv->mclk); |
271 | } | |
272 | } | |
273 | ||
274 | if (ret < 0) { | |
275 | dev_err(card->dev, "can't set codec sysclk: %d\n", ret); | |
276 | return ret; | |
277 | } | |
278 | ||
279 | return 0; | |
280 | } | |
ab738e4e | 281 | |
a2d5563b | 282 | static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { |
996cc849 SP |
283 | SND_SOC_DAPM_HP("Headphone", NULL), |
284 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
e2be1da0 PLB |
285 | SND_SOC_DAPM_MIC("Internal Mic", NULL), |
286 | SND_SOC_DAPM_SPK("Speaker", NULL), | |
df1a2776 IT |
287 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, |
288 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | | |
289 | SND_SOC_DAPM_POST_PMD), | |
290 | ||
996cc849 SP |
291 | }; |
292 | ||
a2d5563b | 293 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { |
df1a2776 IT |
294 | {"Headphone", NULL, "Platform Clock"}, |
295 | {"Headset Mic", NULL, "Platform Clock"}, | |
296 | {"Internal Mic", NULL, "Platform Clock"}, | |
297 | {"Speaker", NULL, "Platform Clock"}, | |
298 | ||
996cc849 | 299 | {"Headset Mic", NULL, "MICBIAS1"}, |
e2be1da0 | 300 | {"IN2P", NULL, "Headset Mic"}, |
996cc849 SP |
301 | {"Headphone", NULL, "HPOL"}, |
302 | {"Headphone", NULL, "HPOR"}, | |
996cc849 SP |
303 | }; |
304 | ||
a2d5563b PLB |
305 | static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { |
306 | {"DMIC1", NULL, "Internal Mic"}, | |
307 | }; | |
308 | ||
309 | static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { | |
310 | {"DMIC2", NULL, "Internal Mic"}, | |
311 | }; | |
312 | ||
313 | static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { | |
314 | {"Internal Mic", NULL, "MICBIAS1"}, | |
315 | {"IN1P", NULL, "Internal Mic"}, | |
316 | }; | |
317 | ||
59e8b652 PLB |
318 | static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { |
319 | {"Internal Mic", NULL, "MICBIAS1"}, | |
320 | {"IN3P", NULL, "Internal Mic"}, | |
321 | }; | |
322 | ||
89b8907c PLB |
323 | static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { |
324 | {"ssp2 Tx", NULL, "codec_out0"}, | |
325 | {"ssp2 Tx", NULL, "codec_out1"}, | |
326 | {"codec_in0", NULL, "ssp2 Rx"}, | |
327 | {"codec_in1", NULL, "ssp2 Rx"}, | |
328 | ||
329 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | |
330 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | |
331 | }; | |
332 | ||
333 | static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { | |
334 | {"ssp2 Tx", NULL, "codec_out0"}, | |
335 | {"ssp2 Tx", NULL, "codec_out1"}, | |
336 | {"codec_in0", NULL, "ssp2 Rx"}, | |
337 | {"codec_in1", NULL, "ssp2 Rx"}, | |
338 | ||
339 | {"AIF2 Playback", NULL, "ssp2 Tx"}, | |
340 | {"ssp2 Rx", NULL, "AIF2 Capture"}, | |
341 | }; | |
342 | ||
f47088d5 PLB |
343 | static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = { |
344 | {"ssp0 Tx", NULL, "modem_out"}, | |
345 | {"modem_in", NULL, "ssp0 Rx"}, | |
346 | ||
347 | {"AIF1 Playback", NULL, "ssp0 Tx"}, | |
348 | {"ssp0 Rx", NULL, "AIF1 Capture"}, | |
349 | }; | |
350 | ||
351 | static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { | |
352 | {"ssp0 Tx", NULL, "modem_out"}, | |
353 | {"modem_in", NULL, "ssp0 Rx"}, | |
354 | ||
355 | {"AIF2 Playback", NULL, "ssp0 Tx"}, | |
356 | {"ssp0 Rx", NULL, "AIF2 Capture"}, | |
357 | }; | |
358 | ||
68817cdb PLB |
359 | static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { |
360 | {"Speaker", NULL, "SPOLP"}, | |
361 | {"Speaker", NULL, "SPOLN"}, | |
362 | {"Speaker", NULL, "SPORP"}, | |
363 | {"Speaker", NULL, "SPORN"}, | |
364 | }; | |
365 | ||
366 | static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { | |
367 | {"Speaker", NULL, "SPOLP"}, | |
368 | {"Speaker", NULL, "SPOLN"}, | |
369 | }; | |
370 | ||
a2d5563b | 371 | static const struct snd_kcontrol_new byt_rt5640_controls[] = { |
996cc849 SP |
372 | SOC_DAPM_PIN_SWITCH("Headphone"), |
373 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
e2be1da0 PLB |
374 | SOC_DAPM_PIN_SWITCH("Internal Mic"), |
375 | SOC_DAPM_PIN_SWITCH("Speaker"), | |
996cc849 SP |
376 | }; |
377 | ||
77323108 HG |
378 | static struct snd_soc_jack_pin rt5640_pins[] = { |
379 | { | |
380 | .pin = "Headphone", | |
381 | .mask = SND_JACK_HEADPHONE, | |
382 | }, | |
383 | { | |
384 | .pin = "Headset Mic", | |
385 | .mask = SND_JACK_MICROPHONE, | |
386 | }, | |
387 | }; | |
388 | ||
a2d5563b | 389 | static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, |
996cc849 SP |
390 | struct snd_pcm_hw_params *params) |
391 | { | |
392 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
bcd9a325 | 393 | struct snd_soc_dai *dai = rtd->codec_dai; |
996cc849 | 394 | |
bcd9a325 | 395 | return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); |
996cc849 SP |
396 | } |
397 | ||
3c0d0116 | 398 | /* Please keep this list alphabetically sorted */ |
a2d5563b | 399 | static const struct dmi_system_id byt_rt5640_quirk_table[] = { |
ec8e8418 HG |
400 | { /* Acer Iconia Tab 8 W1-810 */ |
401 | .matches = { | |
402 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), | |
403 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"), | |
404 | }, | |
405 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | | |
406 | BYT_RT5640_JD_SRC_JD1_IN4P | | |
f12a0a3c | 407 | BYT_RT5640_OVCD_TH_1500UA | |
ec8e8418 HG |
408 | BYT_RT5640_OVCD_SF_0P75 | |
409 | BYT_RT5640_SSP0_AIF1 | | |
410 | BYT_RT5640_MCLK_EN), | |
411 | }, | |
3c0d0116 | 412 | { |
3c0d0116 HG |
413 | .matches = { |
414 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | |
415 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), | |
416 | }, | |
417 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
418 | BYT_RT5640_MCLK_EN | | |
419 | BYT_RT5640_SSP0_AIF1), | |
420 | ||
421 | }, | |
bcf441ac HG |
422 | { |
423 | .matches = { | |
424 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), | |
425 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"), | |
426 | }, | |
427 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
428 | BYT_RT5640_MONO_SPEAKER | | |
429 | BYT_RT5640_SSP0_AIF1 | | |
430 | BYT_RT5640_MCLK_EN), | |
431 | }, | |
a2d5563b | 432 | { |
a2d5563b | 433 | .matches = { |
73442e3c PLB |
434 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
435 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), | |
a2d5563b | 436 | }, |
17b5273d | 437 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
77323108 HG |
438 | BYT_RT5640_JD_SRC_JD2_IN4N | |
439 | BYT_RT5640_OVCD_TH_2000UA | | |
440 | BYT_RT5640_OVCD_SF_0P75 | | |
17b5273d | 441 | BYT_RT5640_MCLK_EN), |
a2d5563b PLB |
442 | }, |
443 | { | |
a2d5563b | 444 | .matches = { |
73442e3c PLB |
445 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
446 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), | |
447 | }, | |
17b5273d PLB |
448 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
449 | BYT_RT5640_MONO_SPEAKER | | |
450 | BYT_RT5640_DIFF_MIC | | |
451 | BYT_RT5640_SSP0_AIF2 | | |
452 | BYT_RT5640_MCLK_EN), | |
73442e3c | 453 | }, |
ec8e8418 HG |
454 | { /* Chuwi Vi8 (CWI506) */ |
455 | .matches = { | |
456 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), | |
457 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"), | |
458 | /* The above are too generic, also match BIOS info */ | |
459 | DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"), | |
460 | }, | |
461 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
462 | BYT_RT5640_MONO_SPEAKER | | |
463 | BYT_RT5640_SSP0_AIF1 | | |
464 | BYT_RT5640_MCLK_EN), | |
465 | }, | |
d5a1826c HG |
466 | { |
467 | /* Chuwi Vi10 (CWI505) */ | |
468 | .matches = { | |
469 | DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), | |
470 | DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"), | |
471 | DMI_MATCH(DMI_SYS_VENDOR, "ilife"), | |
472 | DMI_MATCH(DMI_PRODUCT_NAME, "S165"), | |
473 | }, | |
474 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
475 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
476 | BYT_RT5640_OVCD_TH_2000UA | | |
477 | BYT_RT5640_OVCD_SF_0P75 | | |
478 | BYT_RT5640_DIFF_MIC | | |
479 | BYT_RT5640_SSP0_AIF1 | | |
480 | BYT_RT5640_MCLK_EN), | |
481 | }, | |
3c0d0116 | 482 | { |
3c0d0116 HG |
483 | .matches = { |
484 | DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), | |
485 | DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), | |
486 | }, | |
487 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP), | |
488 | }, | |
9ee6f8a8 HG |
489 | { /* Connect Tablet 9 */ |
490 | .matches = { | |
491 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"), | |
492 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"), | |
493 | }, | |
494 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
495 | BYT_RT5640_MONO_SPEAKER | | |
496 | BYT_RT5640_SSP0_AIF1 | | |
497 | BYT_RT5640_MCLK_EN), | |
498 | }, | |
73442e3c | 499 | { |
73442e3c | 500 | .matches = { |
6748fb7e | 501 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
73442e3c | 502 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), |
a2d5563b | 503 | }, |
6748fb7e | 504 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
77323108 HG |
505 | BYT_RT5640_JD_SRC_JD2_IN4N | |
506 | BYT_RT5640_OVCD_TH_2000UA | | |
507 | BYT_RT5640_OVCD_SF_0P75 | | |
6748fb7e | 508 | BYT_RT5640_MONO_SPEAKER | |
17b5273d | 509 | BYT_RT5640_MCLK_EN), |
a2d5563b | 510 | }, |
55fc2056 | 511 | { |
55fc2056 | 512 | .matches = { |
73442e3c PLB |
513 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
514 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), | |
55fc2056 | 515 | }, |
17b5273d PLB |
516 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
517 | BYT_RT5640_MCLK_EN), | |
55fc2056 | 518 | }, |
ec8e8418 HG |
519 | { /* HP Pavilion x2 10-n000nd */ |
520 | .matches = { | |
521 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | |
522 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), | |
523 | }, | |
524 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | | |
525 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
526 | BYT_RT5640_OVCD_TH_1500UA | | |
527 | BYT_RT5640_OVCD_SF_0P75 | | |
528 | BYT_RT5640_SSP0_AIF1 | | |
529 | BYT_RT5640_MCLK_EN), | |
530 | }, | |
531 | { /* HP Stream 7 */ | |
532 | .matches = { | |
533 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | |
534 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"), | |
535 | }, | |
536 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
537 | BYT_RT5640_MONO_SPEAKER | | |
538 | BYT_RT5640_JD_NOT_INV | | |
539 | BYT_RT5640_SSP0_AIF1 | | |
540 | BYT_RT5640_MCLK_EN), | |
541 | }, | |
542 | { /* I.T.Works TW891 */ | |
543 | .matches = { | |
544 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), | |
545 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"), | |
546 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), | |
547 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), | |
548 | }, | |
549 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
550 | BYT_RT5640_MONO_SPEAKER | | |
551 | BYT_RT5640_SSP0_AIF1 | | |
552 | BYT_RT5640_MCLK_EN), | |
553 | }, | |
554 | { /* Lamina I8270 / T701BR.SE */ | |
555 | .matches = { | |
556 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"), | |
557 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"), | |
558 | }, | |
559 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
560 | BYT_RT5640_MONO_SPEAKER | | |
561 | BYT_RT5640_JD_NOT_INV | | |
562 | BYT_RT5640_SSP0_AIF1 | | |
563 | BYT_RT5640_MCLK_EN), | |
564 | }, | |
81583afe HG |
565 | { /* Lenovo Miix 2 8 */ |
566 | .matches = { | |
567 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), | |
568 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"), | |
569 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"), | |
570 | }, | |
571 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | | |
572 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
573 | BYT_RT5640_OVCD_TH_2000UA | | |
574 | BYT_RT5640_OVCD_SF_0P75 | | |
575 | BYT_RT5640_MONO_SPEAKER | | |
576 | BYT_RT5640_MCLK_EN), | |
577 | }, | |
260c48b7 HG |
578 | { /* Linx Linx7 tablet */ |
579 | .matches = { | |
580 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"), | |
581 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"), | |
582 | }, | |
583 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
584 | BYT_RT5640_MONO_SPEAKER | | |
585 | BYT_RT5640_JD_NOT_INV | | |
586 | BYT_RT5640_SSP0_AIF1 | | |
587 | BYT_RT5640_MCLK_EN), | |
588 | }, | |
ec8e8418 HG |
589 | { /* MSI S100 tablet */ |
590 | .matches = { | |
591 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), | |
592 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"), | |
593 | }, | |
594 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
595 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
596 | BYT_RT5640_OVCD_TH_2000UA | | |
597 | BYT_RT5640_OVCD_SF_0P75 | | |
598 | BYT_RT5640_MONO_SPEAKER | | |
599 | BYT_RT5640_DIFF_MIC | | |
600 | BYT_RT5640_MCLK_EN), | |
601 | }, | |
6cea3590 HG |
602 | { /* Nuvison/TMax TM800W560 */ |
603 | .matches = { | |
604 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"), | |
605 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"), | |
606 | }, | |
607 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
608 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
609 | BYT_RT5640_OVCD_TH_2000UA | | |
610 | BYT_RT5640_OVCD_SF_0P75 | | |
611 | BYT_RT5640_JD_NOT_INV | | |
612 | BYT_RT5640_DIFF_MIC | | |
613 | BYT_RT5640_SSP0_AIF1 | | |
614 | BYT_RT5640_MCLK_EN), | |
615 | }, | |
260c48b7 HG |
616 | { /* Onda v975w */ |
617 | .matches = { | |
618 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | |
619 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), | |
620 | /* The above are too generic, also match BIOS info */ | |
621 | DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"), | |
622 | DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"), | |
623 | }, | |
624 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
625 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
626 | BYT_RT5640_OVCD_TH_2000UA | | |
627 | BYT_RT5640_OVCD_SF_0P75 | | |
628 | BYT_RT5640_DIFF_MIC | | |
629 | BYT_RT5640_MCLK_EN), | |
630 | }, | |
ec8e8418 HG |
631 | { /* Pipo W4 */ |
632 | .matches = { | |
633 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | |
634 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), | |
635 | /* The above are too generic, also match BIOS info */ | |
636 | DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"), | |
637 | }, | |
638 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | | |
639 | BYT_RT5640_MONO_SPEAKER | | |
640 | BYT_RT5640_SSP0_AIF1 | | |
641 | BYT_RT5640_MCLK_EN), | |
642 | }, | |
643 | { /* Point of View Mobii TAB-P800W (V2.0) */ | |
644 | .matches = { | |
645 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | |
646 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), | |
647 | /* The above are too generic, also match BIOS info */ | |
648 | DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"), | |
649 | DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"), | |
650 | }, | |
651 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
652 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
653 | BYT_RT5640_OVCD_TH_2000UA | | |
654 | BYT_RT5640_OVCD_SF_0P75 | | |
655 | BYT_RT5640_MONO_SPEAKER | | |
656 | BYT_RT5640_DIFF_MIC | | |
657 | BYT_RT5640_SSP0_AIF2 | | |
658 | BYT_RT5640_MCLK_EN), | |
659 | }, | |
660 | { /* Point of View Mobii TAB-P800W (V2.1) */ | |
661 | .matches = { | |
662 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | |
663 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), | |
664 | /* The above are too generic, also match BIOS info */ | |
665 | DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), | |
666 | DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"), | |
667 | }, | |
668 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | | |
669 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
670 | BYT_RT5640_OVCD_TH_2000UA | | |
671 | BYT_RT5640_OVCD_SF_0P75 | | |
672 | BYT_RT5640_MONO_SPEAKER | | |
673 | BYT_RT5640_DIFF_MIC | | |
674 | BYT_RT5640_SSP0_AIF2 | | |
675 | BYT_RT5640_MCLK_EN), | |
676 | }, | |
ec1c90e7 | 677 | { |
ec1c90e7 PLB |
678 | .matches = { |
679 | DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), | |
680 | DMI_MATCH(DMI_BOARD_NAME, "tPAD"), | |
681 | }, | |
17b5273d PLB |
682 | .driver_data = (void *)(BYT_RT5640_IN3_MAP | |
683 | BYT_RT5640_MCLK_EN | | |
684 | BYT_RT5640_SSP0_AIF1), | |
ec1c90e7 | 685 | }, |
ec8e8418 HG |
686 | { /* Toshiba Satellite Click Mini L9W-B */ |
687 | .matches = { | |
688 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | |
689 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), | |
690 | }, | |
691 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | | |
692 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
693 | BYT_RT5640_OVCD_TH_1500UA | | |
694 | BYT_RT5640_OVCD_SF_0P75 | | |
695 | BYT_RT5640_SSP0_AIF1 | | |
696 | BYT_RT5640_MCLK_EN), | |
697 | }, | |
3c0d0116 | 698 | { /* Catch-all for generic Insyde tablets, must be last */ |
57180048 | 699 | .matches = { |
700 | DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), | |
701 | }, | |
96a388fe | 702 | .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | |
17b5273d PLB |
703 | BYT_RT5640_MCLK_EN | |
704 | BYT_RT5640_SSP0_AIF1), | |
8f98307d PLB |
705 | |
706 | }, | |
a2d5563b PLB |
707 | {} |
708 | }; | |
709 | ||
6a7c05e5 HG |
710 | /* |
711 | * Note this MUST be called before snd_soc_register_card(), so that the props | |
712 | * are in place before the codec component driver's probe function parses them. | |
713 | */ | |
714 | static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) | |
715 | { | |
716 | struct property_entry props[MAX_NO_PROPS] = {}; | |
717 | struct device *i2c_dev; | |
718 | int ret, cnt = 0; | |
719 | ||
720 | i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name); | |
721 | if (!i2c_dev) | |
722 | return -EPROBE_DEFER; | |
723 | ||
724 | switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { | |
a3ad2911 HG |
725 | case BYT_RT5640_DMIC1_MAP: |
726 | props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin", | |
727 | RT5640_DMIC1_DATA_PIN_IN1P); | |
728 | break; | |
729 | case BYT_RT5640_DMIC2_MAP: | |
730 | props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin", | |
731 | RT5640_DMIC2_DATA_PIN_IN1N); | |
732 | break; | |
6a7c05e5 HG |
733 | case BYT_RT5640_IN1_MAP: |
734 | if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) | |
735 | props[cnt++] = | |
736 | PROPERTY_ENTRY_BOOL("realtek,in1-differential"); | |
737 | break; | |
738 | case BYT_RT5640_IN3_MAP: | |
739 | if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) | |
740 | props[cnt++] = | |
741 | PROPERTY_ENTRY_BOOL("realtek,in3-differential"); | |
742 | break; | |
743 | } | |
744 | ||
77323108 HG |
745 | if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { |
746 | props[cnt++] = PROPERTY_ENTRY_U32( | |
747 | "realtek,jack-detect-source", | |
748 | BYT_RT5640_JDSRC(byt_rt5640_quirk)); | |
749 | ||
750 | props[cnt++] = PROPERTY_ENTRY_U32( | |
751 | "realtek,over-current-threshold-microamp", | |
752 | BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); | |
753 | ||
754 | props[cnt++] = PROPERTY_ENTRY_U32( | |
755 | "realtek,over-current-scale-factor", | |
756 | BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); | |
757 | } | |
758 | ||
759 | if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) | |
760 | props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); | |
761 | ||
6a7c05e5 HG |
762 | ret = device_add_properties(i2c_dev, props); |
763 | put_device(i2c_dev); | |
764 | ||
765 | return ret; | |
766 | } | |
767 | ||
9fd57471 PLB |
768 | static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) |
769 | { | |
9fd57471 | 770 | struct snd_soc_card *card = runtime->card; |
df1a2776 | 771 | struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); |
d5a41b5d | 772 | struct snd_soc_component *component = runtime->codec_dai->component; |
17b5273d | 773 | const struct snd_soc_dapm_route *custom_map; |
9fd57471 | 774 | int num_routes; |
17b5273d | 775 | int ret; |
9fd57471 PLB |
776 | |
777 | card->dapm.idle_bias_off = true; | |
778 | ||
77323108 HG |
779 | /* Start with RC clk for jack-detect (we disable MCLK below) */ |
780 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) | |
781 | snd_soc_component_update_bits(component, RT5640_GLB_CLK, | |
782 | RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK); | |
783 | ||
d5a41b5d | 784 | rt5640_sel_asrc_clk_src(component, |
0ec66e2d | 785 | RT5640_DA_STEREO_FILTER | |
df1a2776 IT |
786 | RT5640_DA_MONO_L_FILTER | |
787 | RT5640_DA_MONO_R_FILTER | | |
788 | RT5640_AD_STEREO_FILTER | | |
789 | RT5640_AD_MONO_L_FILTER | | |
790 | RT5640_AD_MONO_R_FILTER, | |
0ec66e2d PLB |
791 | RT5640_CLK_SEL_ASRC); |
792 | ||
9fd57471 PLB |
793 | ret = snd_soc_add_card_controls(card, byt_rt5640_controls, |
794 | ARRAY_SIZE(byt_rt5640_controls)); | |
795 | if (ret) { | |
796 | dev_err(card->dev, "unable to add card controls\n"); | |
797 | return ret; | |
798 | } | |
799 | ||
9fd57471 PLB |
800 | switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { |
801 | case BYT_RT5640_IN1_MAP: | |
802 | custom_map = byt_rt5640_intmic_in1_map; | |
803 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); | |
804 | break; | |
59e8b652 PLB |
805 | case BYT_RT5640_IN3_MAP: |
806 | custom_map = byt_rt5640_intmic_in3_map; | |
807 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); | |
808 | break; | |
9fd57471 PLB |
809 | case BYT_RT5640_DMIC2_MAP: |
810 | custom_map = byt_rt5640_intmic_dmic2_map; | |
811 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); | |
812 | break; | |
813 | default: | |
814 | custom_map = byt_rt5640_intmic_dmic1_map; | |
815 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); | |
816 | } | |
817 | ||
818 | ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); | |
819 | if (ret) | |
820 | return ret; | |
821 | ||
89b8907c PLB |
822 | if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { |
823 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
824 | byt_rt5640_ssp2_aif2_map, | |
825 | ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); | |
f47088d5 PLB |
826 | } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { |
827 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
828 | byt_rt5640_ssp0_aif1_map, | |
829 | ARRAY_SIZE(byt_rt5640_ssp0_aif1_map)); | |
830 | } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { | |
831 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
832 | byt_rt5640_ssp0_aif2_map, | |
833 | ARRAY_SIZE(byt_rt5640_ssp0_aif2_map)); | |
89b8907c PLB |
834 | } else { |
835 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
836 | byt_rt5640_ssp2_aif1_map, | |
837 | ARRAY_SIZE(byt_rt5640_ssp2_aif1_map)); | |
838 | } | |
839 | if (ret) | |
840 | return ret; | |
841 | ||
68817cdb PLB |
842 | if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { |
843 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
844 | byt_rt5640_mono_spk_map, | |
845 | ARRAY_SIZE(byt_rt5640_mono_spk_map)); | |
846 | } else { | |
847 | ret = snd_soc_dapm_add_routes(&card->dapm, | |
848 | byt_rt5640_stereo_spk_map, | |
849 | ARRAY_SIZE(byt_rt5640_stereo_spk_map)); | |
850 | } | |
851 | if (ret) | |
852 | return ret; | |
853 | ||
9fd57471 PLB |
854 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
855 | snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); | |
856 | ||
17b5273d | 857 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
df1a2776 IT |
858 | /* |
859 | * The firmware might enable the clock at | |
860 | * boot (this information may or may not | |
861 | * be reflected in the enable clock register). | |
862 | * To change the rate we must disable the clock | |
863 | * first to cover these cases. Due to common | |
864 | * clock framework restrictions that do not allow | |
865 | * to disable a clock that has not been enabled, | |
866 | * we need to enable the clock first. | |
867 | */ | |
868 | ret = clk_prepare_enable(priv->mclk); | |
869 | if (!ret) | |
870 | clk_disable_unprepare(priv->mclk); | |
871 | ||
872 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) | |
873 | ret = clk_set_rate(priv->mclk, 25000000); | |
874 | else | |
875 | ret = clk_set_rate(priv->mclk, 19200000); | |
876 | ||
77323108 | 877 | if (ret) { |
df1a2776 | 878 | dev_err(card->dev, "unable to set MCLK rate\n"); |
77323108 HG |
879 | return ret; |
880 | } | |
df1a2776 IT |
881 | } |
882 | ||
77323108 HG |
883 | if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { |
884 | ret = snd_soc_card_jack_new(card, "Headset", | |
885 | SND_JACK_HEADSET | SND_JACK_BTN_0, | |
886 | &priv->jack, rt5640_pins, | |
887 | ARRAY_SIZE(rt5640_pins)); | |
888 | if (ret) { | |
889 | dev_err(card->dev, "Jack creation failed %d\n", ret); | |
890 | return ret; | |
891 | } | |
892 | snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, | |
893 | KEY_PLAYPAUSE); | |
894 | snd_soc_component_set_jack(component, &priv->jack, NULL); | |
895 | } | |
896 | ||
897 | return 0; | |
9fd57471 PLB |
898 | } |
899 | ||
a2d5563b | 900 | static const struct snd_soc_pcm_stream byt_rt5640_dai_params = { |
996cc849 SP |
901 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
902 | .rate_min = 48000, | |
903 | .rate_max = 48000, | |
904 | .channels_min = 2, | |
905 | .channels_max = 2, | |
906 | }; | |
907 | ||
a2d5563b | 908 | static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, |
996cc849 SP |
909 | struct snd_pcm_hw_params *params) |
910 | { | |
911 | struct snd_interval *rate = hw_param_interval(params, | |
912 | SNDRV_PCM_HW_PARAM_RATE); | |
913 | struct snd_interval *channels = hw_param_interval(params, | |
914 | SNDRV_PCM_HW_PARAM_CHANNELS); | |
3f27dedd | 915 | int ret; |
996cc849 | 916 | |
038a50e7 | 917 | /* The DSP will covert the FE rate to 48k, stereo */ |
996cc849 SP |
918 | rate->min = rate->max = 48000; |
919 | channels->min = channels->max = 2; | |
920 | ||
038a50e7 PLB |
921 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || |
922 | (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { | |
923 | ||
8f98307d | 924 | /* set SSP0 to 16-bit */ |
038a50e7 PLB |
925 | params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); |
926 | ||
927 | /* | |
928 | * Default mode for SSP configuration is TDM 4 slot, override config | |
929 | * with explicit setting to I2S 2ch 16-bit. The word length is set with | |
930 | * dai_set_tdm_slot() since there is no other API exposed | |
931 | */ | |
932 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | |
933 | SND_SOC_DAIFMT_I2S | | |
f12f5c84 | 934 | SND_SOC_DAIFMT_NB_NF | |
038a50e7 PLB |
935 | SND_SOC_DAIFMT_CBS_CFS |
936 | ); | |
937 | if (ret < 0) { | |
938 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | |
939 | return ret; | |
940 | } | |
3f27dedd | 941 | |
038a50e7 PLB |
942 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); |
943 | if (ret < 0) { | |
944 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); | |
945 | return ret; | |
946 | } | |
947 | ||
948 | } else { | |
3f27dedd | 949 | |
038a50e7 PLB |
950 | /* set SSP2 to 24-bit */ |
951 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | |
952 | ||
953 | /* | |
954 | * Default mode for SSP configuration is TDM 4 slot, override config | |
955 | * with explicit setting to I2S 2ch 24-bit. The word length is set with | |
956 | * dai_set_tdm_slot() since there is no other API exposed | |
957 | */ | |
958 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | |
959 | SND_SOC_DAIFMT_I2S | | |
f12f5c84 | 960 | SND_SOC_DAIFMT_NB_NF | |
038a50e7 PLB |
961 | SND_SOC_DAIFMT_CBS_CFS |
962 | ); | |
963 | if (ret < 0) { | |
964 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | |
965 | return ret; | |
966 | } | |
967 | ||
968 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); | |
969 | if (ret < 0) { | |
970 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); | |
971 | return ret; | |
972 | } | |
973 | } | |
996cc849 SP |
974 | return 0; |
975 | } | |
976 | ||
a2d5563b | 977 | static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream) |
996cc849 | 978 | { |
d0a1b660 LPC |
979 | return snd_pcm_hw_constraint_single(substream->runtime, |
980 | SNDRV_PCM_HW_PARAM_RATE, 48000); | |
996cc849 SP |
981 | } |
982 | ||
9b6fdef6 | 983 | static const struct snd_soc_ops byt_rt5640_aif1_ops = { |
a2d5563b | 984 | .startup = byt_rt5640_aif1_startup, |
996cc849 SP |
985 | }; |
986 | ||
9b6fdef6 | 987 | static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = { |
a2d5563b | 988 | .hw_params = byt_rt5640_aif1_hw_params, |
996cc849 SP |
989 | }; |
990 | ||
a2d5563b | 991 | static struct snd_soc_dai_link byt_rt5640_dais[] = { |
996cc849 SP |
992 | [MERR_DPCM_AUDIO] = { |
993 | .name = "Baytrail Audio Port", | |
994 | .stream_name = "Baytrail Audio", | |
995 | .cpu_dai_name = "media-cpu-dai", | |
996 | .codec_dai_name = "snd-soc-dummy-dai", | |
997 | .codec_name = "snd-soc-dummy", | |
998 | .platform_name = "sst-mfld-platform", | |
6e4cac23 | 999 | .nonatomic = true, |
996cc849 SP |
1000 | .dynamic = 1, |
1001 | .dpcm_playback = 1, | |
1002 | .dpcm_capture = 1, | |
a2d5563b | 1003 | .ops = &byt_rt5640_aif1_ops, |
996cc849 | 1004 | }, |
d35eb96a PLB |
1005 | [MERR_DPCM_DEEP_BUFFER] = { |
1006 | .name = "Deep-Buffer Audio Port", | |
1007 | .stream_name = "Deep-Buffer Audio", | |
1008 | .cpu_dai_name = "deepbuffer-cpu-dai", | |
1009 | .codec_dai_name = "snd-soc-dummy-dai", | |
1010 | .codec_name = "snd-soc-dummy", | |
1011 | .platform_name = "sst-mfld-platform", | |
d35eb96a PLB |
1012 | .nonatomic = true, |
1013 | .dynamic = 1, | |
1014 | .dpcm_playback = 1, | |
1015 | .ops = &byt_rt5640_aif1_ops, | |
996cc849 SP |
1016 | }, |
1017 | /* back ends */ | |
1018 | { | |
1019 | .name = "SSP2-Codec", | |
149f7757 | 1020 | .id = 0, |
f47088d5 | 1021 | .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ |
996cc849 SP |
1022 | .platform_name = "sst-mfld-platform", |
1023 | .no_pcm = 1, | |
89b8907c | 1024 | .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ |
7762ef42 | 1025 | .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ |
996cc849 SP |
1026 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
1027 | | SND_SOC_DAIFMT_CBS_CFS, | |
a2d5563b | 1028 | .be_hw_params_fixup = byt_rt5640_codec_fixup, |
996cc849 | 1029 | .ignore_suspend = 1, |
6e4cac23 | 1030 | .nonatomic = true, |
996cc849 SP |
1031 | .dpcm_playback = 1, |
1032 | .dpcm_capture = 1, | |
9fd57471 | 1033 | .init = byt_rt5640_init, |
a2d5563b | 1034 | .ops = &byt_rt5640_be_ssp2_ops, |
996cc849 SP |
1035 | }, |
1036 | }; | |
1037 | ||
1038 | /* SoC card */ | |
77323108 HG |
1039 | static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN]; |
1040 | static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ | |
1041 | static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ | |
063422ca | 1042 | static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ |
77323108 HG |
1043 | |
1044 | static int byt_rt5640_suspend(struct snd_soc_card *card) | |
1045 | { | |
1046 | struct snd_soc_component *component; | |
1047 | ||
1048 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) | |
1049 | return 0; | |
1050 | ||
1051 | list_for_each_entry(component, &card->component_dev_list, card_list) { | |
1052 | if (!strcmp(component->name, byt_rt5640_codec_name)) { | |
1053 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); | |
1054 | snd_soc_component_set_jack(component, NULL, NULL); | |
1055 | break; | |
1056 | } | |
1057 | } | |
1058 | ||
1059 | return 0; | |
1060 | } | |
1061 | ||
1062 | static int byt_rt5640_resume(struct snd_soc_card *card) | |
1063 | { | |
1064 | struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); | |
1065 | struct snd_soc_component *component; | |
1066 | ||
1067 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) | |
1068 | return 0; | |
1069 | ||
1070 | list_for_each_entry(component, &card->component_dev_list, card_list) { | |
1071 | if (!strcmp(component->name, byt_rt5640_codec_name)) { | |
1072 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); | |
1073 | snd_soc_component_set_jack(component, &priv->jack, NULL); | |
1074 | break; | |
1075 | } | |
1076 | } | |
1077 | ||
1078 | return 0; | |
1079 | } | |
1080 | ||
9fd57471 | 1081 | static struct snd_soc_card byt_rt5640_card = { |
a2d5563b | 1082 | .name = "bytcr-rt5640", |
54d8697f | 1083 | .owner = THIS_MODULE, |
a2d5563b PLB |
1084 | .dai_link = byt_rt5640_dais, |
1085 | .num_links = ARRAY_SIZE(byt_rt5640_dais), | |
1086 | .dapm_widgets = byt_rt5640_widgets, | |
1087 | .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), | |
1088 | .dapm_routes = byt_rt5640_audio_map, | |
1089 | .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), | |
9fd57471 | 1090 | .fully_routed = true, |
77323108 HG |
1091 | .suspend_pre = byt_rt5640_suspend, |
1092 | .resume_post = byt_rt5640_resume, | |
996cc849 SP |
1093 | }; |
1094 | ||
e214f5e7 PLB |
1095 | static bool is_valleyview(void) |
1096 | { | |
cac17731 | 1097 | static const struct x86_cpu_id cpu_ids[] = { |
e214f5e7 PLB |
1098 | { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ |
1099 | {} | |
1100 | }; | |
1101 | ||
1102 | if (!x86_match_cpu(cpu_ids)) | |
1103 | return false; | |
1104 | return true; | |
1105 | } | |
1106 | ||
64e84305 PLB |
1107 | struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ |
1108 | u64 aif_value; /* 1: AIF1, 2: AIF2 */ | |
1109 | u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ | |
1110 | }; | |
df1a2776 | 1111 | |
a2d5563b | 1112 | static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) |
996cc849 | 1113 | { |
063422ca | 1114 | const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; |
6d1bfcc5 | 1115 | const struct dmi_system_id *dmi_id; |
17b5273d | 1116 | struct byt_rt5640_private *priv; |
7feb2f78 | 1117 | struct snd_soc_acpi_mach *mach; |
a232b96d | 1118 | const char *i2c_name = NULL; |
17b5273d | 1119 | int ret_val = 0; |
2193eb96 | 1120 | int dai_index = 0; |
17b5273d | 1121 | int i; |
df1a2776 | 1122 | |
cb67d765 | 1123 | is_bytcr = false; |
7a3a6323 | 1124 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
df1a2776 IT |
1125 | if (!priv) |
1126 | return -ENOMEM; | |
996cc849 SP |
1127 | |
1128 | /* register the soc card */ | |
9fd57471 | 1129 | byt_rt5640_card.dev = &pdev->dev; |
caf94ed8 | 1130 | mach = byt_rt5640_card.dev->platform_data; |
df1a2776 | 1131 | snd_soc_card_set_drvdata(&byt_rt5640_card, priv); |
caf94ed8 | 1132 | |
a232b96d | 1133 | /* fix index of codec dai */ |
a232b96d PLB |
1134 | for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { |
1135 | if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) { | |
1136 | dai_index = i; | |
1137 | break; | |
1138 | } | |
1139 | } | |
1140 | ||
caf94ed8 | 1141 | /* fixup codec name based on HID */ |
3a147959 | 1142 | i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1); |
17b5273d | 1143 | if (i2c_name) { |
a232b96d PLB |
1144 | snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), |
1145 | "%s%s", "i2c-", i2c_name); | |
1146 | ||
1147 | byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name; | |
1148 | } | |
9fd57471 | 1149 | |
e214f5e7 PLB |
1150 | /* |
1151 | * swap SSP0 if bytcr is detected | |
1152 | * (will be overridden if DMI quirk is detected) | |
1153 | */ | |
1154 | if (is_valleyview()) { | |
1155 | struct sst_platform_info *p_info = mach->pdata; | |
1156 | const struct sst_res_info *res_info = p_info->res_info; | |
1157 | ||
64e84305 PLB |
1158 | if (res_info->acpi_ipc_irq_index == 0) |
1159 | is_bytcr = true; | |
1160 | } | |
1161 | ||
1162 | if (is_bytcr) { | |
1163 | /* | |
1164 | * Baytrail CR platforms may have CHAN package in BIOS, try | |
1165 | * to find relevant routing quirk based as done on Windows | |
1166 | * platforms. We have to read the information directly from the | |
1167 | * BIOS, at this stage the card is not created and the links | |
1168 | * with the codec driver/pdata are non-existent | |
1169 | */ | |
1170 | ||
1171 | struct acpi_chan_package chan_package; | |
1172 | ||
1173 | /* format specified: 2 64-bit integers */ | |
1174 | struct acpi_buffer format = {sizeof("NN"), "NN"}; | |
1175 | struct acpi_buffer state = {0, NULL}; | |
7feb2f78 | 1176 | struct snd_soc_acpi_package_context pkg_ctx; |
64e84305 PLB |
1177 | bool pkg_found = false; |
1178 | ||
1179 | state.length = sizeof(chan_package); | |
1180 | state.pointer = &chan_package; | |
1181 | ||
1182 | pkg_ctx.name = "CHAN"; | |
1183 | pkg_ctx.length = 2; | |
1184 | pkg_ctx.format = &format; | |
1185 | pkg_ctx.state = &state; | |
1186 | pkg_ctx.data_valid = false; | |
1187 | ||
7feb2f78 PLB |
1188 | pkg_found = snd_soc_acpi_find_package_from_hid(mach->id, |
1189 | &pkg_ctx); | |
64e84305 PLB |
1190 | if (pkg_found) { |
1191 | if (chan_package.aif_value == 1) { | |
1192 | dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); | |
1193 | byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1; | |
1194 | } else if (chan_package.aif_value == 2) { | |
1195 | dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); | |
1196 | byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; | |
1197 | } else { | |
1198 | dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); | |
1199 | pkg_found = false; | |
1200 | } | |
1201 | } | |
1202 | ||
1203 | if (!pkg_found) { | |
1204 | /* no BIOS indications, assume SSP0-AIF2 connection */ | |
e214f5e7 PLB |
1205 | byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; |
1206 | } | |
bf46241b PLB |
1207 | |
1208 | /* change defaults for Baytrail-CR capture */ | |
96a388fe | 1209 | byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS; |
bf46241b | 1210 | } else { |
56ff4409 HG |
1211 | byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP | |
1212 | BYT_RT5640_JD_SRC_JD2_IN4N | | |
1213 | BYT_RT5640_OVCD_TH_2000UA | | |
1214 | BYT_RT5640_OVCD_SF_0P75; | |
e214f5e7 PLB |
1215 | } |
1216 | ||
ab738e4e | 1217 | /* check quirks before creating card */ |
6d1bfcc5 HG |
1218 | dmi_id = dmi_first_match(byt_rt5640_quirk_table); |
1219 | if (dmi_id) | |
1220 | byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; | |
9f2cf73e | 1221 | if (quirk_override) { |
0b2c9f88 | 1222 | dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", |
9f2cf73e TI |
1223 | (unsigned int)byt_rt5640_quirk, quirk_override); |
1224 | byt_rt5640_quirk = quirk_override; | |
1225 | } | |
6a7c05e5 HG |
1226 | |
1227 | /* Must be called before register_card, also see declaration comment. */ | |
1228 | ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name); | |
1229 | if (ret_val) | |
1230 | return ret_val; | |
1231 | ||
d7e60d52 | 1232 | log_quirks(&pdev->dev); |
ab738e4e | 1233 | |
f47088d5 PLB |
1234 | if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || |
1235 | (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { | |
89b8907c PLB |
1236 | |
1237 | /* fixup codec aif name */ | |
1238 | snprintf(byt_rt5640_codec_aif_name, | |
1239 | sizeof(byt_rt5640_codec_aif_name), | |
1240 | "%s", "rt5640-aif2"); | |
1241 | ||
1242 | byt_rt5640_dais[dai_index].codec_dai_name = | |
1243 | byt_rt5640_codec_aif_name; | |
1244 | } | |
1245 | ||
f47088d5 PLB |
1246 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || |
1247 | (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { | |
1248 | ||
1249 | /* fixup cpu dai name name */ | |
1250 | snprintf(byt_rt5640_cpu_dai_name, | |
1251 | sizeof(byt_rt5640_cpu_dai_name), | |
1252 | "%s", "ssp0-port"); | |
1253 | ||
1254 | byt_rt5640_dais[dai_index].cpu_dai_name = | |
1255 | byt_rt5640_cpu_dai_name; | |
1256 | } | |
1257 | ||
7735bce0 | 1258 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
df1a2776 IT |
1259 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); |
1260 | if (IS_ERR(priv->mclk)) { | |
4a8b3a68 PLB |
1261 | ret_val = PTR_ERR(priv->mclk); |
1262 | ||
df1a2776 | 1263 | dev_err(&pdev->dev, |
4a8b3a68 PLB |
1264 | "Failed to get MCLK from pmc_plt_clk_3: %d\n", |
1265 | ret_val); | |
1266 | ||
1267 | /* | |
1268 | * Fall back to bit clock usage for -ENOENT (clock not | |
1269 | * available likely due to missing dependencies), bail | |
1270 | * for all other errors, including -EPROBE_DEFER | |
1271 | */ | |
1272 | if (ret_val != -ENOENT) | |
1273 | return ret_val; | |
1274 | byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; | |
df1a2776 IT |
1275 | } |
1276 | } | |
1277 | ||
063422ca HG |
1278 | snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), |
1279 | "bytcr-rt5640-%s-spk-%s-mic", | |
1280 | (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? | |
1281 | "mono" : "stereo", | |
1282 | map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); | |
1283 | byt_rt5640_card.long_name = byt_rt5640_long_name; | |
1284 | ||
9fd57471 | 1285 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); |
996cc849 | 1286 | |
996cc849 | 1287 | if (ret_val) { |
a2d5563b PLB |
1288 | dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", |
1289 | ret_val); | |
996cc849 SP |
1290 | return ret_val; |
1291 | } | |
9fd57471 | 1292 | platform_set_drvdata(pdev, &byt_rt5640_card); |
996cc849 SP |
1293 | return ret_val; |
1294 | } | |
1295 | ||
a2d5563b | 1296 | static struct platform_driver snd_byt_rt5640_mc_driver = { |
996cc849 | 1297 | .driver = { |
a2d5563b | 1298 | .name = "bytcr_rt5640", |
996cc849 | 1299 | }, |
a2d5563b | 1300 | .probe = snd_byt_rt5640_mc_probe, |
996cc849 SP |
1301 | }; |
1302 | ||
a2d5563b | 1303 | module_platform_driver(snd_byt_rt5640_mc_driver); |
996cc849 SP |
1304 | |
1305 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); | |
1306 | MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); | |
1307 | MODULE_LICENSE("GPL v2"); | |
a2d5563b | 1308 | MODULE_ALIAS("platform:bytcr_rt5640"); |