blob: 686d0040549396c25b120ca2f292d25f1ce43735 [file] [log] [blame]
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301/*
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
Hans de Goede6a7c05e2018-05-08 17:35:54 +020020#include <linux/i2c.h>
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053021#include <linux/init.h>
22#include <linux/module.h>
Takashi Iwai9f2cf732017-04-23 09:22:56 +020023#include <linux/moduleparam.h>
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053024#include <linux/platform_device.h>
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -060025#include <linux/acpi.h>
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -050026#include <linux/clk.h>
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053027#include <linux/device.h>
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -060028#include <linux/dmi.h>
Hans de Goede77323102018-05-13 09:24:28 +020029#include <linux/input.h>
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053030#include <linux/slab.h>
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -050031#include <asm/cpu_device_id.h>
32#include <asm/platform_sst_audio.h>
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053033#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35#include <sound/soc.h>
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -060036#include <sound/jack.h>
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -050037#include <sound/soc-acpi.h>
Hans de Goedea3ad2912018-05-13 09:24:26 +020038#include <dt-bindings/sound/rt5640.h>
Jie Yange56c72d2015-04-02 15:37:02 +080039#include "../../codecs/rt5640.h"
Jie Yangb97169d2015-04-02 15:37:04 +080040#include "../atom/sst-atom-controls.h"
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -050041#include "../common/sst-dsp.h"
Subhransu S. Prusty996cc842014-11-19 15:13:27 +053042
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -060043enum {
44 BYT_RT5640_DMIC1_MAP,
45 BYT_RT5640_DMIC2_MAP,
46 BYT_RT5640_IN1_MAP,
Pierre-Louis Bossart59e8b652016-08-12 16:27:54 -050047 BYT_RT5640_IN3_MAP,
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -060048};
49
Hans de Goede77323102018-05-13 09:24:28 +020050enum {
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};
Irina Tirdeadf1a2772016-08-12 16:27:57 -050058
Hans de Goede77323102018-05-13 09:24:28 +020059enum {
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
65enum {
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};
71
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
Hans de Goede96a388fe2018-05-13 09:24:30 +020085#define BYTCR_INPUT_DEFAULTS \
86 (BYT_RT5640_IN3_MAP | \
Hans de Goede56ff4402018-05-13 09:24:31 +020087 BYT_RT5640_JD_SRC_JD1_IN4P | \
88 BYT_RT5640_OVCD_TH_2000UA | \
89 BYT_RT5640_OVCD_SF_0P75 | \
Hans de Goede96a388fe2018-05-13 09:24:30 +020090 BYT_RT5640_DIFF_MIC)
91
Hans de Goede77323102018-05-13 09:24:28 +020092/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */
93#define MAX_NO_PROPS 6
Hans de Goede6a7c05e2018-05-08 17:35:54 +020094
Irina Tirdeadf1a2772016-08-12 16:27:57 -050095struct byt_rt5640_private {
Hans de Goede77323102018-05-13 09:24:28 +020096 struct snd_soc_jack jack;
Irina Tirdeadf1a2772016-08-12 16:27:57 -050097 struct clk *mclk;
98};
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -050099static bool is_bytcr;
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -0600100
Pierre-Louis Bossartbf462412016-11-12 18:07:46 -0600101static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
Takashi Iwai9f2cf732017-04-23 09:22:56 +0200102static unsigned int quirk_override;
Takashi Iwai0b2c9f82017-04-24 23:34:30 +0200103module_param_named(quirk, quirk_override, uint, 0444);
Takashi Iwai9f2cf732017-04-23 09:22:56 +0200104MODULE_PARM_DESC(quirk, "Board-specific quirk override");
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500105
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -0500106static void log_quirks(struct device *dev)
107{
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500108 int map;
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500109 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");
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500119 break;
120 case BYT_RT5640_DMIC2_MAP:
121 dev_info(dev, "quirk DMIC2_MAP enabled\n");
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500122 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 }
Hans de Goede77323102018-05-13 09:24:28 +0200133 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");
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -0500143 if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500144 dev_info(dev, "quirk MONO_SPEAKER enabled\n");
Hans de Goedea3ad2912018-05-13 09:24:26 +0200145 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
146 dev_info(dev, "quirk DIFF_MIC enabled\n");
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500147 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 }
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -0500178}
179
Hans de Goedebcd9a322018-05-08 17:35:53 +0200180static 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) {
Hans de Goedea3a956a2018-05-11 11:52:16 +0200213 dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);
Hans de Goedebcd9a322018-05-08 17:35:53 +0200214 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) {
Hans de Goedea3a956a2018-05-11 11:52:16 +0200220 dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);
Hans de Goedebcd9a322018-05-08 17:35:53 +0200221 return ret;
222 }
223
224 return 0;
225}
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -0500226
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500227#define BYT_CODEC_DAI1 "rt5640-aif1"
228#define BYT_CODEC_DAI2 "rt5640-aif2"
229
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500230static 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
Pierre-Louis Bossartdfb6ec72017-10-12 18:38:03 -0500239 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
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500243 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)) {
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500250 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500251 ret = clk_prepare_enable(priv->mclk);
252 if (ret < 0) {
253 dev_err(card->dev,
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -0500254 "could not configure MCLK state\n");
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500255 return ret;
256 }
257 }
Hans de Goedebcd9a322018-05-08 17:35:53 +0200258 ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000);
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500259 } 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,
Pierre-Louis Bossart60448b02017-01-04 15:44:52 -0600266 48000 * 512,
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500267 SND_SOC_CLOCK_IN);
268 if (!ret) {
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500269 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500270 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}
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -0600281
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600282static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530283 SND_SOC_DAPM_HP("Headphone", NULL),
284 SND_SOC_DAPM_MIC("Headset Mic", NULL),
Pierre-Louis Bossarte2be1da2015-12-17 20:35:40 -0600285 SND_SOC_DAPM_MIC("Internal Mic", NULL),
286 SND_SOC_DAPM_SPK("Speaker", NULL),
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500287 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
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530291};
292
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600293static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500294 {"Headphone", NULL, "Platform Clock"},
295 {"Headset Mic", NULL, "Platform Clock"},
296 {"Internal Mic", NULL, "Platform Clock"},
297 {"Speaker", NULL, "Platform Clock"},
298
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530299 {"Headset Mic", NULL, "MICBIAS1"},
Pierre-Louis Bossarte2be1da2015-12-17 20:35:40 -0600300 {"IN2P", NULL, "Headset Mic"},
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530301 {"Headphone", NULL, "HPOL"},
302 {"Headphone", NULL, "HPOR"},
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530303};
304
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600305static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
306 {"DMIC1", NULL, "Internal Mic"},
307};
308
309static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
310 {"DMIC2", NULL, "Internal Mic"},
311};
312
313static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
314 {"Internal Mic", NULL, "MICBIAS1"},
315 {"IN1P", NULL, "Internal Mic"},
316};
317
Pierre-Louis Bossart59e8b652016-08-12 16:27:54 -0500318static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
319 {"Internal Mic", NULL, "MICBIAS1"},
320 {"IN3P", NULL, "Internal Mic"},
321};
322
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500323static 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
333static 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
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -0500343static 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
351static 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
Pierre-Louis Bossart68817cd2016-08-12 16:27:45 -0500359static 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
366static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
367 {"Speaker", NULL, "SPOLP"},
368 {"Speaker", NULL, "SPOLN"},
369};
370
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600371static const struct snd_kcontrol_new byt_rt5640_controls[] = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530372 SOC_DAPM_PIN_SWITCH("Headphone"),
373 SOC_DAPM_PIN_SWITCH("Headset Mic"),
Pierre-Louis Bossarte2be1da2015-12-17 20:35:40 -0600374 SOC_DAPM_PIN_SWITCH("Internal Mic"),
375 SOC_DAPM_PIN_SWITCH("Speaker"),
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530376};
377
Hans de Goede77323102018-05-13 09:24:28 +0200378static 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
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600389static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530390 struct snd_pcm_hw_params *params)
391{
392 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Hans de Goedebcd9a322018-05-08 17:35:53 +0200393 struct snd_soc_dai *dai = rtd->codec_dai;
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530394
Hans de Goedebcd9a322018-05-08 17:35:53 +0200395 return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params));
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530396}
397
Hans de Goede3c0d0112018-05-13 09:24:32 +0200398/* Please keep this list alphabetically sorted */
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600399static const struct dmi_system_id byt_rt5640_quirk_table[] = {
Hans de Goedeec8e8412018-05-13 09:24:34 +0200400 { /* 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 |
407 BYT_RT5640_OVCD_TH_2000UA |
408 BYT_RT5640_OVCD_SF_0P75 |
409 BYT_RT5640_SSP0_AIF1 |
410 BYT_RT5640_MCLK_EN),
411 },
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600412 {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600413 .matches = {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200414 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 },
422 {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200423 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500424 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
425 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600426 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500427 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
Hans de Goede77323102018-05-13 09:24:28 +0200428 BYT_RT5640_JD_SRC_JD2_IN4N |
429 BYT_RT5640_OVCD_TH_2000UA |
430 BYT_RT5640_OVCD_SF_0P75 |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500431 BYT_RT5640_MCLK_EN),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600432 },
433 {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600434 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500435 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
436 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
437 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500438 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
439 BYT_RT5640_MONO_SPEAKER |
440 BYT_RT5640_DIFF_MIC |
441 BYT_RT5640_SSP0_AIF2 |
442 BYT_RT5640_MCLK_EN),
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500443 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200444 { /* Chuwi Vi8 (CWI506) */
445 .matches = {
446 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
447 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),
448 /* The above are too generic, also match BIOS info */
449 DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
450 },
451 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
452 BYT_RT5640_MONO_SPEAKER |
453 BYT_RT5640_SSP0_AIF1 |
454 BYT_RT5640_MCLK_EN),
455 },
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500456 {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500457 .matches = {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200458 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
459 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
460 },
461 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP),
462 },
463 {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200464 .matches = {
Hans de Goede6748fb72018-05-13 09:24:27 +0200465 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500466 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600467 },
Hans de Goede6748fb72018-05-13 09:24:27 +0200468 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
Hans de Goede77323102018-05-13 09:24:28 +0200469 BYT_RT5640_JD_SRC_JD2_IN4N |
470 BYT_RT5640_OVCD_TH_2000UA |
471 BYT_RT5640_OVCD_SF_0P75 |
Hans de Goede6748fb72018-05-13 09:24:27 +0200472 BYT_RT5640_MONO_SPEAKER |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500473 BYT_RT5640_MCLK_EN),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600474 },
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600475 {
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600476 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500477 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
478 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600479 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500480 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
481 BYT_RT5640_MCLK_EN),
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600482 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200483 { /* HP Pavilion x2 10-n000nd */
484 .matches = {
485 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
486 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
487 },
488 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
489 BYT_RT5640_JD_SRC_JD2_IN4N |
490 BYT_RT5640_OVCD_TH_1500UA |
491 BYT_RT5640_OVCD_SF_0P75 |
492 BYT_RT5640_SSP0_AIF1 |
493 BYT_RT5640_MCLK_EN),
494 },
495 { /* HP Stream 7 */
496 .matches = {
497 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
498 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),
499 },
500 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
501 BYT_RT5640_MONO_SPEAKER |
502 BYT_RT5640_JD_NOT_INV |
503 BYT_RT5640_SSP0_AIF1 |
504 BYT_RT5640_MCLK_EN),
505 },
506 { /* I.T.Works TW891 */
507 .matches = {
508 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
509 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
510 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
511 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
512 },
513 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
514 BYT_RT5640_MONO_SPEAKER |
515 BYT_RT5640_SSP0_AIF1 |
516 BYT_RT5640_MCLK_EN),
517 },
518 { /* Lamina I8270 / T701BR.SE */
519 .matches = {
520 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),
521 DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),
522 },
523 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
524 BYT_RT5640_MONO_SPEAKER |
525 BYT_RT5640_JD_NOT_INV |
526 BYT_RT5640_SSP0_AIF1 |
527 BYT_RT5640_MCLK_EN),
528 },
529 { /* MSI S100 tablet */
530 .matches = {
531 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
532 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),
533 },
534 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
535 BYT_RT5640_JD_SRC_JD2_IN4N |
536 BYT_RT5640_OVCD_TH_2000UA |
537 BYT_RT5640_OVCD_SF_0P75 |
538 BYT_RT5640_MONO_SPEAKER |
539 BYT_RT5640_DIFF_MIC |
540 BYT_RT5640_MCLK_EN),
541 },
542 { /* Pipo W4 */
543 .matches = {
544 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
545 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
546 /* The above are too generic, also match BIOS info */
547 DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),
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 { /* Point of View Mobii TAB-P800W (V2.0) */
555 .matches = {
556 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
557 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
558 /* The above are too generic, also match BIOS info */
559 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
560 DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),
561 },
562 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
563 BYT_RT5640_JD_SRC_JD2_IN4N |
564 BYT_RT5640_OVCD_TH_2000UA |
565 BYT_RT5640_OVCD_SF_0P75 |
566 BYT_RT5640_MONO_SPEAKER |
567 BYT_RT5640_DIFF_MIC |
568 BYT_RT5640_SSP0_AIF2 |
569 BYT_RT5640_MCLK_EN),
570 },
571 { /* Point of View Mobii TAB-P800W (V2.1) */
572 .matches = {
573 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
574 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
575 /* The above are too generic, also match BIOS info */
576 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
577 DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),
578 },
579 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
580 BYT_RT5640_JD_SRC_JD2_IN4N |
581 BYT_RT5640_OVCD_TH_2000UA |
582 BYT_RT5640_OVCD_SF_0P75 |
583 BYT_RT5640_MONO_SPEAKER |
584 BYT_RT5640_DIFF_MIC |
585 BYT_RT5640_SSP0_AIF2 |
586 BYT_RT5640_MCLK_EN),
587 },
Irina Tirdea0565e772016-08-12 16:27:58 -0500588 {
Irina Tirdea0565e772016-08-12 16:27:58 -0500589 .matches = {
Pierre-Louis Bossartec1c90e2016-08-12 16:27:59 -0500590 DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
591 DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
592 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500593 .driver_data = (void *)(BYT_RT5640_IN3_MAP |
594 BYT_RT5640_MCLK_EN |
595 BYT_RT5640_SSP0_AIF1),
Pierre-Louis Bossartec1c90e2016-08-12 16:27:59 -0500596 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200597 { /* Toshiba Satellite Click Mini L9W-B */
598 .matches = {
599 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
600 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),
601 },
602 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
603 BYT_RT5640_JD_SRC_JD2_IN4N |
604 BYT_RT5640_OVCD_TH_1500UA |
605 BYT_RT5640_OVCD_SF_0P75 |
606 BYT_RT5640_SSP0_AIF1 |
607 BYT_RT5640_MCLK_EN),
608 },
Hans de Goede3c0d0112018-05-13 09:24:32 +0200609 { /* Catch-all for generic Insyde tablets, must be last */
youling25757180042017-01-04 15:44:53 -0600610 .matches = {
611 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
612 },
Hans de Goede96a388fe2018-05-13 09:24:30 +0200613 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500614 BYT_RT5640_MCLK_EN |
615 BYT_RT5640_SSP0_AIF1),
youling25757180042017-01-04 15:44:53 -0600616
617 },
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600618 {}
619};
620
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200621/*
622 * Note this MUST be called before snd_soc_register_card(), so that the props
623 * are in place before the codec component driver's probe function parses them.
624 */
625static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
626{
627 struct property_entry props[MAX_NO_PROPS] = {};
628 struct device *i2c_dev;
629 int ret, cnt = 0;
630
631 i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
632 if (!i2c_dev)
633 return -EPROBE_DEFER;
634
635 switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
Hans de Goedea3ad2912018-05-13 09:24:26 +0200636 case BYT_RT5640_DMIC1_MAP:
637 props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",
638 RT5640_DMIC1_DATA_PIN_IN1P);
639 break;
640 case BYT_RT5640_DMIC2_MAP:
641 props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",
642 RT5640_DMIC2_DATA_PIN_IN1N);
643 break;
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200644 case BYT_RT5640_IN1_MAP:
645 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
646 props[cnt++] =
647 PROPERTY_ENTRY_BOOL("realtek,in1-differential");
648 break;
649 case BYT_RT5640_IN3_MAP:
650 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
651 props[cnt++] =
652 PROPERTY_ENTRY_BOOL("realtek,in3-differential");
653 break;
654 }
655
Hans de Goede77323102018-05-13 09:24:28 +0200656 if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
657 props[cnt++] = PROPERTY_ENTRY_U32(
658 "realtek,jack-detect-source",
659 BYT_RT5640_JDSRC(byt_rt5640_quirk));
660
661 props[cnt++] = PROPERTY_ENTRY_U32(
662 "realtek,over-current-threshold-microamp",
663 BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);
664
665 props[cnt++] = PROPERTY_ENTRY_U32(
666 "realtek,over-current-scale-factor",
667 BYT_RT5640_OVCD_SF(byt_rt5640_quirk));
668 }
669
670 if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
671 props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
672
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200673 ret = device_add_properties(i2c_dev, props);
674 put_device(i2c_dev);
675
676 return ret;
677}
678
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600679static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
680{
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600681 struct snd_soc_card *card = runtime->card;
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500682 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
Kuninori Morimotod5a41b52018-01-29 03:42:46 +0000683 struct snd_soc_component *component = runtime->codec_dai->component;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500684 const struct snd_soc_dapm_route *custom_map;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600685 int num_routes;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500686 int ret;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600687
688 card->dapm.idle_bias_off = true;
689
Hans de Goede77323102018-05-13 09:24:28 +0200690 /* Start with RC clk for jack-detect (we disable MCLK below) */
691 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
692 snd_soc_component_update_bits(component, RT5640_GLB_CLK,
693 RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);
694
Kuninori Morimotod5a41b52018-01-29 03:42:46 +0000695 rt5640_sel_asrc_clk_src(component,
Pierre-Louis Bossart0ec66e2d2016-01-04 17:20:27 -0600696 RT5640_DA_STEREO_FILTER |
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500697 RT5640_DA_MONO_L_FILTER |
698 RT5640_DA_MONO_R_FILTER |
699 RT5640_AD_STEREO_FILTER |
700 RT5640_AD_MONO_L_FILTER |
701 RT5640_AD_MONO_R_FILTER,
Pierre-Louis Bossart0ec66e2d2016-01-04 17:20:27 -0600702 RT5640_CLK_SEL_ASRC);
703
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600704 ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
705 ARRAY_SIZE(byt_rt5640_controls));
706 if (ret) {
707 dev_err(card->dev, "unable to add card controls\n");
708 return ret;
709 }
710
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600711 switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
712 case BYT_RT5640_IN1_MAP:
713 custom_map = byt_rt5640_intmic_in1_map;
714 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
715 break;
Pierre-Louis Bossart59e8b652016-08-12 16:27:54 -0500716 case BYT_RT5640_IN3_MAP:
717 custom_map = byt_rt5640_intmic_in3_map;
718 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
719 break;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600720 case BYT_RT5640_DMIC2_MAP:
721 custom_map = byt_rt5640_intmic_dmic2_map;
722 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
723 break;
724 default:
725 custom_map = byt_rt5640_intmic_dmic1_map;
726 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
727 }
728
729 ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
730 if (ret)
731 return ret;
732
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500733 if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
734 ret = snd_soc_dapm_add_routes(&card->dapm,
735 byt_rt5640_ssp2_aif2_map,
736 ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -0500737 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
738 ret = snd_soc_dapm_add_routes(&card->dapm,
739 byt_rt5640_ssp0_aif1_map,
740 ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));
741 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
742 ret = snd_soc_dapm_add_routes(&card->dapm,
743 byt_rt5640_ssp0_aif2_map,
744 ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500745 } else {
746 ret = snd_soc_dapm_add_routes(&card->dapm,
747 byt_rt5640_ssp2_aif1_map,
748 ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
749 }
750 if (ret)
751 return ret;
752
Pierre-Louis Bossart68817cd2016-08-12 16:27:45 -0500753 if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
754 ret = snd_soc_dapm_add_routes(&card->dapm,
755 byt_rt5640_mono_spk_map,
756 ARRAY_SIZE(byt_rt5640_mono_spk_map));
757 } else {
758 ret = snd_soc_dapm_add_routes(&card->dapm,
759 byt_rt5640_stereo_spk_map,
760 ARRAY_SIZE(byt_rt5640_stereo_spk_map));
761 }
762 if (ret)
763 return ret;
764
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600765 snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
766 snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
767
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500768 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500769 /*
770 * The firmware might enable the clock at
771 * boot (this information may or may not
772 * be reflected in the enable clock register).
773 * To change the rate we must disable the clock
774 * first to cover these cases. Due to common
775 * clock framework restrictions that do not allow
776 * to disable a clock that has not been enabled,
777 * we need to enable the clock first.
778 */
779 ret = clk_prepare_enable(priv->mclk);
780 if (!ret)
781 clk_disable_unprepare(priv->mclk);
782
783 if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
784 ret = clk_set_rate(priv->mclk, 25000000);
785 else
786 ret = clk_set_rate(priv->mclk, 19200000);
787
Hans de Goede77323102018-05-13 09:24:28 +0200788 if (ret) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500789 dev_err(card->dev, "unable to set MCLK rate\n");
Hans de Goede77323102018-05-13 09:24:28 +0200790 return ret;
791 }
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500792 }
793
Hans de Goede77323102018-05-13 09:24:28 +0200794 if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
795 ret = snd_soc_card_jack_new(card, "Headset",
796 SND_JACK_HEADSET | SND_JACK_BTN_0,
797 &priv->jack, rt5640_pins,
798 ARRAY_SIZE(rt5640_pins));
799 if (ret) {
800 dev_err(card->dev, "Jack creation failed %d\n", ret);
801 return ret;
802 }
803 snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
804 KEY_PLAYPAUSE);
805 snd_soc_component_set_jack(component, &priv->jack, NULL);
806 }
807
808 return 0;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600809}
810
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600811static const struct snd_soc_pcm_stream byt_rt5640_dai_params = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530812 .formats = SNDRV_PCM_FMTBIT_S24_LE,
813 .rate_min = 48000,
814 .rate_max = 48000,
815 .channels_min = 2,
816 .channels_max = 2,
817};
818
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600819static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530820 struct snd_pcm_hw_params *params)
821{
822 struct snd_interval *rate = hw_param_interval(params,
823 SNDRV_PCM_HW_PARAM_RATE);
824 struct snd_interval *channels = hw_param_interval(params,
825 SNDRV_PCM_HW_PARAM_CHANNELS);
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600826 int ret;
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530827
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500828 /* The DSP will covert the FE rate to 48k, stereo */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530829 rate->min = rate->max = 48000;
830 channels->min = channels->max = 2;
831
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500832 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
833 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600834
Pierre-Louis Bossart8f98307d2016-08-16 18:28:22 -0500835 /* set SSP0 to 16-bit */
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500836 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
837
838 /*
839 * Default mode for SSP configuration is TDM 4 slot, override config
840 * with explicit setting to I2S 2ch 16-bit. The word length is set with
841 * dai_set_tdm_slot() since there is no other API exposed
842 */
843 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
844 SND_SOC_DAIFMT_I2S |
Pierre-Louis Bossartf12f5c82017-01-26 14:09:29 -0600845 SND_SOC_DAIFMT_NB_NF |
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500846 SND_SOC_DAIFMT_CBS_CFS
847 );
848 if (ret < 0) {
849 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
850 return ret;
851 }
852
853 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16);
854 if (ret < 0) {
855 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
856 return ret;
857 }
858
859 } else {
860
861 /* set SSP2 to 24-bit */
862 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
863
864 /*
865 * Default mode for SSP configuration is TDM 4 slot, override config
866 * with explicit setting to I2S 2ch 24-bit. The word length is set with
867 * dai_set_tdm_slot() since there is no other API exposed
868 */
869 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
870 SND_SOC_DAIFMT_I2S |
Pierre-Louis Bossartf12f5c82017-01-26 14:09:29 -0600871 SND_SOC_DAIFMT_NB_NF |
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500872 SND_SOC_DAIFMT_CBS_CFS
873 );
874 if (ret < 0) {
875 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
876 return ret;
877 }
878
879 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
880 if (ret < 0) {
881 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
882 return ret;
883 }
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600884 }
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530885 return 0;
886}
887
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600888static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530889{
Lars-Peter Clausend0a1b662015-10-18 15:39:30 +0200890 return snd_pcm_hw_constraint_single(substream->runtime,
891 SNDRV_PCM_HW_PARAM_RATE, 48000);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530892}
893
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200894static const struct snd_soc_ops byt_rt5640_aif1_ops = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600895 .startup = byt_rt5640_aif1_startup,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530896};
897
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200898static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600899 .hw_params = byt_rt5640_aif1_hw_params,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530900};
901
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600902static struct snd_soc_dai_link byt_rt5640_dais[] = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530903 [MERR_DPCM_AUDIO] = {
904 .name = "Baytrail Audio Port",
905 .stream_name = "Baytrail Audio",
906 .cpu_dai_name = "media-cpu-dai",
907 .codec_dai_name = "snd-soc-dummy-dai",
908 .codec_name = "snd-soc-dummy",
909 .platform_name = "sst-mfld-platform",
Takashi Iwai6e4cac22017-04-24 14:09:55 +0200910 .nonatomic = true,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530911 .dynamic = 1,
912 .dpcm_playback = 1,
913 .dpcm_capture = 1,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600914 .ops = &byt_rt5640_aif1_ops,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530915 },
Pierre-Louis Bossartd35eb962015-12-17 20:35:45 -0600916 [MERR_DPCM_DEEP_BUFFER] = {
917 .name = "Deep-Buffer Audio Port",
918 .stream_name = "Deep-Buffer Audio",
919 .cpu_dai_name = "deepbuffer-cpu-dai",
920 .codec_dai_name = "snd-soc-dummy-dai",
921 .codec_name = "snd-soc-dummy",
922 .platform_name = "sst-mfld-platform",
Pierre-Louis Bossartd35eb962015-12-17 20:35:45 -0600923 .nonatomic = true,
924 .dynamic = 1,
925 .dpcm_playback = 1,
926 .ops = &byt_rt5640_aif1_ops,
927 },
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530928 /* back ends */
929 {
930 .name = "SSP2-Codec",
Pierre-Louis Bossart149f7752017-10-12 18:38:04 -0500931 .id = 0,
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -0500932 .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530933 .platform_name = "sst-mfld-platform",
934 .no_pcm = 1,
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500935 .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */
Pierre-Louis Bossart7762ef42016-01-04 17:20:29 -0600936 .codec_name = "i2c-10EC5640:00", /* overwritten with HID */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530937 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
938 | SND_SOC_DAIFMT_CBS_CFS,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600939 .be_hw_params_fixup = byt_rt5640_codec_fixup,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530940 .ignore_suspend = 1,
Takashi Iwai6e4cac22017-04-24 14:09:55 +0200941 .nonatomic = true,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530942 .dpcm_playback = 1,
943 .dpcm_capture = 1,
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600944 .init = byt_rt5640_init,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600945 .ops = &byt_rt5640_be_ssp2_ops,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530946 },
947};
948
949/* SoC card */
Hans de Goede77323102018-05-13 09:24:28 +0200950static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
951static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */
952static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
953
954static int byt_rt5640_suspend(struct snd_soc_card *card)
955{
956 struct snd_soc_component *component;
957
958 if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
959 return 0;
960
961 list_for_each_entry(component, &card->component_dev_list, card_list) {
962 if (!strcmp(component->name, byt_rt5640_codec_name)) {
963 dev_dbg(component->dev, "disabling jack detect before suspend\n");
964 snd_soc_component_set_jack(component, NULL, NULL);
965 break;
966 }
967 }
968
969 return 0;
970}
971
972static int byt_rt5640_resume(struct snd_soc_card *card)
973{
974 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
975 struct snd_soc_component *component;
976
977 if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
978 return 0;
979
980 list_for_each_entry(component, &card->component_dev_list, card_list) {
981 if (!strcmp(component->name, byt_rt5640_codec_name)) {
982 dev_dbg(component->dev, "re-enabling jack detect after resume\n");
983 snd_soc_component_set_jack(component, &priv->jack, NULL);
984 break;
985 }
986 }
987
988 return 0;
989}
990
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600991static struct snd_soc_card byt_rt5640_card = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600992 .name = "bytcr-rt5640",
Axel Lin54d86972015-08-21 20:59:21 +0800993 .owner = THIS_MODULE,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600994 .dai_link = byt_rt5640_dais,
995 .num_links = ARRAY_SIZE(byt_rt5640_dais),
996 .dapm_widgets = byt_rt5640_widgets,
997 .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
998 .dapm_routes = byt_rt5640_audio_map,
999 .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001000 .fully_routed = true,
Hans de Goede77323102018-05-13 09:24:28 +02001001 .suspend_pre = byt_rt5640_suspend,
1002 .resume_post = byt_rt5640_resume,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301003};
1004
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001005static bool is_valleyview(void)
1006{
Pierre-Louis Bossartcac17732016-08-16 18:28:21 -05001007 static const struct x86_cpu_id cpu_ids[] = {
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001008 { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
1009 {}
1010 };
1011
1012 if (!x86_match_cpu(cpu_ids))
1013 return false;
1014 return true;
1015}
1016
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001017struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
1018 u64 aif_value; /* 1: AIF1, 2: AIF2 */
1019 u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
1020};
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001021
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001022static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301023{
Hans de Goede6d1bfcc2018-05-13 09:24:33 +02001024 const struct dmi_system_id *dmi_id;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001025 struct byt_rt5640_private *priv;
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001026 struct snd_soc_acpi_mach *mach;
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001027 const char *i2c_name = NULL;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001028 int ret_val = 0;
Pierre-Louis Bossart2193eb92017-10-12 18:38:05 -05001029 int dai_index = 0;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001030 int i;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001031
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -05001032 is_bytcr = false;
Jia-Ju Bai7a3a6322018-04-09 18:47:37 +08001033 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001034 if (!priv)
1035 return -ENOMEM;
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301036
1037 /* register the soc card */
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001038 byt_rt5640_card.dev = &pdev->dev;
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001039 mach = byt_rt5640_card.dev->platform_data;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001040 snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001041
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001042 /* fix index of codec dai */
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001043 for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
1044 if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) {
1045 dai_index = i;
1046 break;
1047 }
1048 }
1049
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001050 /* fixup codec name based on HID */
Andy Shevchenko3a147952018-01-12 23:16:17 +02001051 i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001052 if (i2c_name) {
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001053 snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
1054 "%s%s", "i2c-", i2c_name);
1055
1056 byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name;
1057 }
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301058
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001059 /*
1060 * swap SSP0 if bytcr is detected
1061 * (will be overridden if DMI quirk is detected)
1062 */
1063 if (is_valleyview()) {
1064 struct sst_platform_info *p_info = mach->pdata;
1065 const struct sst_res_info *res_info = p_info->res_info;
1066
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001067 if (res_info->acpi_ipc_irq_index == 0)
1068 is_bytcr = true;
1069 }
1070
1071 if (is_bytcr) {
1072 /*
1073 * Baytrail CR platforms may have CHAN package in BIOS, try
1074 * to find relevant routing quirk based as done on Windows
1075 * platforms. We have to read the information directly from the
1076 * BIOS, at this stage the card is not created and the links
1077 * with the codec driver/pdata are non-existent
1078 */
1079
1080 struct acpi_chan_package chan_package;
1081
1082 /* format specified: 2 64-bit integers */
1083 struct acpi_buffer format = {sizeof("NN"), "NN"};
1084 struct acpi_buffer state = {0, NULL};
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001085 struct snd_soc_acpi_package_context pkg_ctx;
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001086 bool pkg_found = false;
1087
1088 state.length = sizeof(chan_package);
1089 state.pointer = &chan_package;
1090
1091 pkg_ctx.name = "CHAN";
1092 pkg_ctx.length = 2;
1093 pkg_ctx.format = &format;
1094 pkg_ctx.state = &state;
1095 pkg_ctx.data_valid = false;
1096
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001097 pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
1098 &pkg_ctx);
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001099 if (pkg_found) {
1100 if (chan_package.aif_value == 1) {
1101 dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
1102 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
1103 } else if (chan_package.aif_value == 2) {
1104 dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
1105 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1106 } else {
1107 dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
1108 pkg_found = false;
1109 }
1110 }
1111
1112 if (!pkg_found) {
1113 /* no BIOS indications, assume SSP0-AIF2 connection */
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001114 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1115 }
Pierre-Louis Bossartbf462412016-11-12 18:07:46 -06001116
1117 /* change defaults for Baytrail-CR capture */
Hans de Goede96a388fe2018-05-13 09:24:30 +02001118 byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;
Pierre-Louis Bossartbf462412016-11-12 18:07:46 -06001119 } else {
Hans de Goede56ff4402018-05-13 09:24:31 +02001120 byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |
1121 BYT_RT5640_JD_SRC_JD2_IN4N |
1122 BYT_RT5640_OVCD_TH_2000UA |
1123 BYT_RT5640_OVCD_SF_0P75;
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001124 }
1125
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -06001126 /* check quirks before creating card */
Hans de Goede6d1bfcc2018-05-13 09:24:33 +02001127 dmi_id = dmi_first_match(byt_rt5640_quirk_table);
1128 if (dmi_id)
1129 byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;
Takashi Iwai9f2cf732017-04-23 09:22:56 +02001130 if (quirk_override) {
Takashi Iwai0b2c9f82017-04-24 23:34:30 +02001131 dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n",
Takashi Iwai9f2cf732017-04-23 09:22:56 +02001132 (unsigned int)byt_rt5640_quirk, quirk_override);
1133 byt_rt5640_quirk = quirk_override;
1134 }
Hans de Goede6a7c05e2018-05-08 17:35:54 +02001135
1136 /* Must be called before register_card, also see declaration comment. */
1137 ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
1138 if (ret_val)
1139 return ret_val;
1140
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -05001141 log_quirks(&pdev->dev);
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -06001142
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -05001143 if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
1144 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -05001145
1146 /* fixup codec aif name */
1147 snprintf(byt_rt5640_codec_aif_name,
1148 sizeof(byt_rt5640_codec_aif_name),
1149 "%s", "rt5640-aif2");
1150
1151 byt_rt5640_dais[dai_index].codec_dai_name =
1152 byt_rt5640_codec_aif_name;
1153 }
1154
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -05001155 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1156 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
1157
1158 /* fixup cpu dai name name */
1159 snprintf(byt_rt5640_cpu_dai_name,
1160 sizeof(byt_rt5640_cpu_dai_name),
1161 "%s", "ssp0-port");
1162
1163 byt_rt5640_dais[dai_index].cpu_dai_name =
1164 byt_rt5640_cpu_dai_name;
1165 }
1166
Pierre-Louis Bossart7735bce2017-09-08 12:43:52 -05001167 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001168 priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
1169 if (IS_ERR(priv->mclk)) {
Pierre-Louis Bossart4a8b3a62016-12-16 10:55:49 -06001170 ret_val = PTR_ERR(priv->mclk);
1171
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001172 dev_err(&pdev->dev,
Pierre-Louis Bossart4a8b3a62016-12-16 10:55:49 -06001173 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
1174 ret_val);
1175
1176 /*
1177 * Fall back to bit clock usage for -ENOENT (clock not
1178 * available likely due to missing dependencies), bail
1179 * for all other errors, including -EPROBE_DEFER
1180 */
1181 if (ret_val != -ENOENT)
1182 return ret_val;
1183 byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001184 }
1185 }
1186
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001187 ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
1188
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301189 if (ret_val) {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001190 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1191 ret_val);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301192 return ret_val;
1193 }
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001194 platform_set_drvdata(pdev, &byt_rt5640_card);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301195 return ret_val;
1196}
1197
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001198static struct platform_driver snd_byt_rt5640_mc_driver = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301199 .driver = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001200 .name = "bytcr_rt5640",
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301201 },
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001202 .probe = snd_byt_rt5640_mc_probe,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301203};
1204
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001205module_platform_driver(snd_byt_rt5640_mc_driver);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301206
1207MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
1208MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
1209MODULE_LICENSE("GPL v2");
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001210MODULE_ALIAS("platform:bytcr_rt5640");