blob: 33065ba294a93b3a69f6bf814443483e6e26cc4f [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 = {
Hans de Goedebcf441a2018-05-28 22:26:49 +0200424 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 },
432 {
433 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500434 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
435 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600436 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500437 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
Hans de Goede77323102018-05-13 09:24:28 +0200438 BYT_RT5640_JD_SRC_JD2_IN4N |
439 BYT_RT5640_OVCD_TH_2000UA |
440 BYT_RT5640_OVCD_SF_0P75 |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500441 BYT_RT5640_MCLK_EN),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600442 },
443 {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600444 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500445 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
446 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
447 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500448 .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),
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500453 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200454 { /* 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 },
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500466 {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500467 .matches = {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200468 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
469 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
470 },
471 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP),
472 },
473 {
Hans de Goede3c0d0112018-05-13 09:24:32 +0200474 .matches = {
Hans de Goede6748fb72018-05-13 09:24:27 +0200475 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500476 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600477 },
Hans de Goede6748fb72018-05-13 09:24:27 +0200478 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
Hans de Goede77323102018-05-13 09:24:28 +0200479 BYT_RT5640_JD_SRC_JD2_IN4N |
480 BYT_RT5640_OVCD_TH_2000UA |
481 BYT_RT5640_OVCD_SF_0P75 |
Hans de Goede6748fb72018-05-13 09:24:27 +0200482 BYT_RT5640_MONO_SPEAKER |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500483 BYT_RT5640_MCLK_EN),
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600484 },
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600485 {
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600486 .matches = {
Pierre-Louis Bossart73442e32016-08-12 16:27:44 -0500487 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
488 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600489 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500490 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
491 BYT_RT5640_MCLK_EN),
Jorge Fernandez Monteagudo55fc2052016-01-04 17:20:30 -0600492 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200493 { /* HP Pavilion x2 10-n000nd */
494 .matches = {
495 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
496 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
497 },
498 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
499 BYT_RT5640_JD_SRC_JD2_IN4N |
500 BYT_RT5640_OVCD_TH_1500UA |
501 BYT_RT5640_OVCD_SF_0P75 |
502 BYT_RT5640_SSP0_AIF1 |
503 BYT_RT5640_MCLK_EN),
504 },
505 { /* HP Stream 7 */
506 .matches = {
507 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
508 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),
509 },
510 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
511 BYT_RT5640_MONO_SPEAKER |
512 BYT_RT5640_JD_NOT_INV |
513 BYT_RT5640_SSP0_AIF1 |
514 BYT_RT5640_MCLK_EN),
515 },
516 { /* I.T.Works TW891 */
517 .matches = {
518 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
519 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
520 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
521 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
522 },
523 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
524 BYT_RT5640_MONO_SPEAKER |
525 BYT_RT5640_SSP0_AIF1 |
526 BYT_RT5640_MCLK_EN),
527 },
528 { /* Lamina I8270 / T701BR.SE */
529 .matches = {
530 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),
531 DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),
532 },
533 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
534 BYT_RT5640_MONO_SPEAKER |
535 BYT_RT5640_JD_NOT_INV |
536 BYT_RT5640_SSP0_AIF1 |
537 BYT_RT5640_MCLK_EN),
538 },
539 { /* MSI S100 tablet */
540 .matches = {
541 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
542 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),
543 },
544 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
545 BYT_RT5640_JD_SRC_JD2_IN4N |
546 BYT_RT5640_OVCD_TH_2000UA |
547 BYT_RT5640_OVCD_SF_0P75 |
548 BYT_RT5640_MONO_SPEAKER |
549 BYT_RT5640_DIFF_MIC |
550 BYT_RT5640_MCLK_EN),
551 },
552 { /* Pipo W4 */
553 .matches = {
554 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
555 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
556 /* The above are too generic, also match BIOS info */
557 DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),
558 },
559 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
560 BYT_RT5640_MONO_SPEAKER |
561 BYT_RT5640_SSP0_AIF1 |
562 BYT_RT5640_MCLK_EN),
563 },
564 { /* Point of View Mobii TAB-P800W (V2.0) */
565 .matches = {
566 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
567 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
568 /* The above are too generic, also match BIOS info */
569 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
570 DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),
571 },
572 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
573 BYT_RT5640_JD_SRC_JD2_IN4N |
574 BYT_RT5640_OVCD_TH_2000UA |
575 BYT_RT5640_OVCD_SF_0P75 |
576 BYT_RT5640_MONO_SPEAKER |
577 BYT_RT5640_DIFF_MIC |
578 BYT_RT5640_SSP0_AIF2 |
579 BYT_RT5640_MCLK_EN),
580 },
581 { /* Point of View Mobii TAB-P800W (V2.1) */
582 .matches = {
583 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
584 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
585 /* The above are too generic, also match BIOS info */
586 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
587 DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),
588 },
589 .driver_data = (void *)(BYT_RT5640_IN1_MAP |
590 BYT_RT5640_JD_SRC_JD2_IN4N |
591 BYT_RT5640_OVCD_TH_2000UA |
592 BYT_RT5640_OVCD_SF_0P75 |
593 BYT_RT5640_MONO_SPEAKER |
594 BYT_RT5640_DIFF_MIC |
595 BYT_RT5640_SSP0_AIF2 |
596 BYT_RT5640_MCLK_EN),
597 },
Irina Tirdea0565e772016-08-12 16:27:58 -0500598 {
Irina Tirdea0565e772016-08-12 16:27:58 -0500599 .matches = {
Pierre-Louis Bossartec1c90e2016-08-12 16:27:59 -0500600 DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
601 DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
602 },
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500603 .driver_data = (void *)(BYT_RT5640_IN3_MAP |
604 BYT_RT5640_MCLK_EN |
605 BYT_RT5640_SSP0_AIF1),
Pierre-Louis Bossartec1c90e2016-08-12 16:27:59 -0500606 },
Hans de Goedeec8e8412018-05-13 09:24:34 +0200607 { /* Toshiba Satellite Click Mini L9W-B */
608 .matches = {
609 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
610 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),
611 },
612 .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
613 BYT_RT5640_JD_SRC_JD2_IN4N |
614 BYT_RT5640_OVCD_TH_1500UA |
615 BYT_RT5640_OVCD_SF_0P75 |
616 BYT_RT5640_SSP0_AIF1 |
617 BYT_RT5640_MCLK_EN),
618 },
Hans de Goede3c0d0112018-05-13 09:24:32 +0200619 { /* Catch-all for generic Insyde tablets, must be last */
youling25757180042017-01-04 15:44:53 -0600620 .matches = {
621 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
622 },
Hans de Goede96a388fe2018-05-13 09:24:30 +0200623 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500624 BYT_RT5640_MCLK_EN |
625 BYT_RT5640_SSP0_AIF1),
youling25757180042017-01-04 15:44:53 -0600626
627 },
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600628 {}
629};
630
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200631/*
632 * Note this MUST be called before snd_soc_register_card(), so that the props
633 * are in place before the codec component driver's probe function parses them.
634 */
635static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
636{
637 struct property_entry props[MAX_NO_PROPS] = {};
638 struct device *i2c_dev;
639 int ret, cnt = 0;
640
641 i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
642 if (!i2c_dev)
643 return -EPROBE_DEFER;
644
645 switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
Hans de Goedea3ad2912018-05-13 09:24:26 +0200646 case BYT_RT5640_DMIC1_MAP:
647 props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",
648 RT5640_DMIC1_DATA_PIN_IN1P);
649 break;
650 case BYT_RT5640_DMIC2_MAP:
651 props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",
652 RT5640_DMIC2_DATA_PIN_IN1N);
653 break;
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200654 case BYT_RT5640_IN1_MAP:
655 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
656 props[cnt++] =
657 PROPERTY_ENTRY_BOOL("realtek,in1-differential");
658 break;
659 case BYT_RT5640_IN3_MAP:
660 if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
661 props[cnt++] =
662 PROPERTY_ENTRY_BOOL("realtek,in3-differential");
663 break;
664 }
665
Hans de Goede77323102018-05-13 09:24:28 +0200666 if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
667 props[cnt++] = PROPERTY_ENTRY_U32(
668 "realtek,jack-detect-source",
669 BYT_RT5640_JDSRC(byt_rt5640_quirk));
670
671 props[cnt++] = PROPERTY_ENTRY_U32(
672 "realtek,over-current-threshold-microamp",
673 BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);
674
675 props[cnt++] = PROPERTY_ENTRY_U32(
676 "realtek,over-current-scale-factor",
677 BYT_RT5640_OVCD_SF(byt_rt5640_quirk));
678 }
679
680 if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
681 props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
682
Hans de Goede6a7c05e2018-05-08 17:35:54 +0200683 ret = device_add_properties(i2c_dev, props);
684 put_device(i2c_dev);
685
686 return ret;
687}
688
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600689static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
690{
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600691 struct snd_soc_card *card = runtime->card;
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500692 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
Kuninori Morimotod5a41b52018-01-29 03:42:46 +0000693 struct snd_soc_component *component = runtime->codec_dai->component;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500694 const struct snd_soc_dapm_route *custom_map;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600695 int num_routes;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500696 int ret;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600697
698 card->dapm.idle_bias_off = true;
699
Hans de Goede77323102018-05-13 09:24:28 +0200700 /* Start with RC clk for jack-detect (we disable MCLK below) */
701 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
702 snd_soc_component_update_bits(component, RT5640_GLB_CLK,
703 RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);
704
Kuninori Morimotod5a41b52018-01-29 03:42:46 +0000705 rt5640_sel_asrc_clk_src(component,
Pierre-Louis Bossart0ec66e2d2016-01-04 17:20:27 -0600706 RT5640_DA_STEREO_FILTER |
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500707 RT5640_DA_MONO_L_FILTER |
708 RT5640_DA_MONO_R_FILTER |
709 RT5640_AD_STEREO_FILTER |
710 RT5640_AD_MONO_L_FILTER |
711 RT5640_AD_MONO_R_FILTER,
Pierre-Louis Bossart0ec66e2d2016-01-04 17:20:27 -0600712 RT5640_CLK_SEL_ASRC);
713
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600714 ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
715 ARRAY_SIZE(byt_rt5640_controls));
716 if (ret) {
717 dev_err(card->dev, "unable to add card controls\n");
718 return ret;
719 }
720
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600721 switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
722 case BYT_RT5640_IN1_MAP:
723 custom_map = byt_rt5640_intmic_in1_map;
724 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
725 break;
Pierre-Louis Bossart59e8b652016-08-12 16:27:54 -0500726 case BYT_RT5640_IN3_MAP:
727 custom_map = byt_rt5640_intmic_in3_map;
728 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
729 break;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600730 case BYT_RT5640_DMIC2_MAP:
731 custom_map = byt_rt5640_intmic_dmic2_map;
732 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
733 break;
734 default:
735 custom_map = byt_rt5640_intmic_dmic1_map;
736 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
737 }
738
739 ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
740 if (ret)
741 return ret;
742
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500743 if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
744 ret = snd_soc_dapm_add_routes(&card->dapm,
745 byt_rt5640_ssp2_aif2_map,
746 ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -0500747 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
748 ret = snd_soc_dapm_add_routes(&card->dapm,
749 byt_rt5640_ssp0_aif1_map,
750 ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));
751 } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
752 ret = snd_soc_dapm_add_routes(&card->dapm,
753 byt_rt5640_ssp0_aif2_map,
754 ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500755 } else {
756 ret = snd_soc_dapm_add_routes(&card->dapm,
757 byt_rt5640_ssp2_aif1_map,
758 ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
759 }
760 if (ret)
761 return ret;
762
Pierre-Louis Bossart68817cd2016-08-12 16:27:45 -0500763 if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
764 ret = snd_soc_dapm_add_routes(&card->dapm,
765 byt_rt5640_mono_spk_map,
766 ARRAY_SIZE(byt_rt5640_mono_spk_map));
767 } else {
768 ret = snd_soc_dapm_add_routes(&card->dapm,
769 byt_rt5640_stereo_spk_map,
770 ARRAY_SIZE(byt_rt5640_stereo_spk_map));
771 }
772 if (ret)
773 return ret;
774
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600775 snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
776 snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
777
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -0500778 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500779 /*
780 * The firmware might enable the clock at
781 * boot (this information may or may not
782 * be reflected in the enable clock register).
783 * To change the rate we must disable the clock
784 * first to cover these cases. Due to common
785 * clock framework restrictions that do not allow
786 * to disable a clock that has not been enabled,
787 * we need to enable the clock first.
788 */
789 ret = clk_prepare_enable(priv->mclk);
790 if (!ret)
791 clk_disable_unprepare(priv->mclk);
792
793 if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
794 ret = clk_set_rate(priv->mclk, 25000000);
795 else
796 ret = clk_set_rate(priv->mclk, 19200000);
797
Hans de Goede77323102018-05-13 09:24:28 +0200798 if (ret) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500799 dev_err(card->dev, "unable to set MCLK rate\n");
Hans de Goede77323102018-05-13 09:24:28 +0200800 return ret;
801 }
Irina Tirdeadf1a2772016-08-12 16:27:57 -0500802 }
803
Hans de Goede77323102018-05-13 09:24:28 +0200804 if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
805 ret = snd_soc_card_jack_new(card, "Headset",
806 SND_JACK_HEADSET | SND_JACK_BTN_0,
807 &priv->jack, rt5640_pins,
808 ARRAY_SIZE(rt5640_pins));
809 if (ret) {
810 dev_err(card->dev, "Jack creation failed %d\n", ret);
811 return ret;
812 }
813 snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
814 KEY_PLAYPAUSE);
815 snd_soc_component_set_jack(component, &priv->jack, NULL);
816 }
817
818 return 0;
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600819}
820
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600821static const struct snd_soc_pcm_stream byt_rt5640_dai_params = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530822 .formats = SNDRV_PCM_FMTBIT_S24_LE,
823 .rate_min = 48000,
824 .rate_max = 48000,
825 .channels_min = 2,
826 .channels_max = 2,
827};
828
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600829static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530830 struct snd_pcm_hw_params *params)
831{
832 struct snd_interval *rate = hw_param_interval(params,
833 SNDRV_PCM_HW_PARAM_RATE);
834 struct snd_interval *channels = hw_param_interval(params,
835 SNDRV_PCM_HW_PARAM_CHANNELS);
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600836 int ret;
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530837
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500838 /* The DSP will covert the FE rate to 48k, stereo */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530839 rate->min = rate->max = 48000;
840 channels->min = channels->max = 2;
841
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500842 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
843 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600844
Pierre-Louis Bossart8f98307d2016-08-16 18:28:22 -0500845 /* set SSP0 to 16-bit */
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500846 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
847
848 /*
849 * Default mode for SSP configuration is TDM 4 slot, override config
850 * with explicit setting to I2S 2ch 16-bit. The word length is set with
851 * dai_set_tdm_slot() since there is no other API exposed
852 */
853 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
854 SND_SOC_DAIFMT_I2S |
Pierre-Louis Bossartf12f5c82017-01-26 14:09:29 -0600855 SND_SOC_DAIFMT_NB_NF |
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500856 SND_SOC_DAIFMT_CBS_CFS
857 );
858 if (ret < 0) {
859 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
860 return ret;
861 }
862
863 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16);
864 if (ret < 0) {
865 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
866 return ret;
867 }
868
869 } else {
870
871 /* set SSP2 to 24-bit */
872 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
873
874 /*
875 * Default mode for SSP configuration is TDM 4 slot, override config
876 * with explicit setting to I2S 2ch 24-bit. The word length is set with
877 * dai_set_tdm_slot() since there is no other API exposed
878 */
879 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
880 SND_SOC_DAIFMT_I2S |
Pierre-Louis Bossartf12f5c82017-01-26 14:09:29 -0600881 SND_SOC_DAIFMT_NB_NF |
Pierre-Louis Bossart038a50e2016-08-12 16:27:52 -0500882 SND_SOC_DAIFMT_CBS_CFS
883 );
884 if (ret < 0) {
885 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
886 return ret;
887 }
888
889 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
890 if (ret < 0) {
891 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
892 return ret;
893 }
Sebastien Guiriec3f27ded2015-12-17 20:35:39 -0600894 }
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530895 return 0;
896}
897
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600898static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530899{
Lars-Peter Clausend0a1b662015-10-18 15:39:30 +0200900 return snd_pcm_hw_constraint_single(substream->runtime,
901 SNDRV_PCM_HW_PARAM_RATE, 48000);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530902}
903
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200904static const struct snd_soc_ops byt_rt5640_aif1_ops = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600905 .startup = byt_rt5640_aif1_startup,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530906};
907
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200908static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600909 .hw_params = byt_rt5640_aif1_hw_params,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530910};
911
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600912static struct snd_soc_dai_link byt_rt5640_dais[] = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530913 [MERR_DPCM_AUDIO] = {
914 .name = "Baytrail Audio Port",
915 .stream_name = "Baytrail Audio",
916 .cpu_dai_name = "media-cpu-dai",
917 .codec_dai_name = "snd-soc-dummy-dai",
918 .codec_name = "snd-soc-dummy",
919 .platform_name = "sst-mfld-platform",
Takashi Iwai6e4cac22017-04-24 14:09:55 +0200920 .nonatomic = true,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530921 .dynamic = 1,
922 .dpcm_playback = 1,
923 .dpcm_capture = 1,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600924 .ops = &byt_rt5640_aif1_ops,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530925 },
Pierre-Louis Bossartd35eb962015-12-17 20:35:45 -0600926 [MERR_DPCM_DEEP_BUFFER] = {
927 .name = "Deep-Buffer Audio Port",
928 .stream_name = "Deep-Buffer Audio",
929 .cpu_dai_name = "deepbuffer-cpu-dai",
930 .codec_dai_name = "snd-soc-dummy-dai",
931 .codec_name = "snd-soc-dummy",
932 .platform_name = "sst-mfld-platform",
Pierre-Louis Bossartd35eb962015-12-17 20:35:45 -0600933 .nonatomic = true,
934 .dynamic = 1,
935 .dpcm_playback = 1,
936 .ops = &byt_rt5640_aif1_ops,
937 },
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530938 /* back ends */
939 {
940 .name = "SSP2-Codec",
Pierre-Louis Bossart149f7752017-10-12 18:38:04 -0500941 .id = 0,
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -0500942 .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530943 .platform_name = "sst-mfld-platform",
944 .no_pcm = 1,
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -0500945 .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */
Pierre-Louis Bossart7762ef42016-01-04 17:20:29 -0600946 .codec_name = "i2c-10EC5640:00", /* overwritten with HID */
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530947 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
948 | SND_SOC_DAIFMT_CBS_CFS,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600949 .be_hw_params_fixup = byt_rt5640_codec_fixup,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530950 .ignore_suspend = 1,
Takashi Iwai6e4cac22017-04-24 14:09:55 +0200951 .nonatomic = true,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530952 .dpcm_playback = 1,
953 .dpcm_capture = 1,
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -0600954 .init = byt_rt5640_init,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -0600955 .ops = &byt_rt5640_be_ssp2_ops,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +0530956 },
957};
958
959/* SoC card */
Hans de Goede77323102018-05-13 09:24:28 +0200960static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
961static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */
962static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
Hans de Goede063422c2018-05-13 09:24:35 +0200963static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
Hans de Goede77323102018-05-13 09:24:28 +0200964
965static int byt_rt5640_suspend(struct snd_soc_card *card)
966{
967 struct snd_soc_component *component;
968
969 if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
970 return 0;
971
972 list_for_each_entry(component, &card->component_dev_list, card_list) {
973 if (!strcmp(component->name, byt_rt5640_codec_name)) {
974 dev_dbg(component->dev, "disabling jack detect before suspend\n");
975 snd_soc_component_set_jack(component, NULL, NULL);
976 break;
977 }
978 }
979
980 return 0;
981}
982
983static int byt_rt5640_resume(struct snd_soc_card *card)
984{
985 struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
986 struct snd_soc_component *component;
987
988 if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
989 return 0;
990
991 list_for_each_entry(component, &card->component_dev_list, card_list) {
992 if (!strcmp(component->name, byt_rt5640_codec_name)) {
993 dev_dbg(component->dev, "re-enabling jack detect after resume\n");
994 snd_soc_component_set_jack(component, &priv->jack, NULL);
995 break;
996 }
997 }
998
999 return 0;
1000}
1001
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001002static struct snd_soc_card byt_rt5640_card = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001003 .name = "bytcr-rt5640",
Axel Lin54d86972015-08-21 20:59:21 +08001004 .owner = THIS_MODULE,
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001005 .dai_link = byt_rt5640_dais,
1006 .num_links = ARRAY_SIZE(byt_rt5640_dais),
1007 .dapm_widgets = byt_rt5640_widgets,
1008 .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
1009 .dapm_routes = byt_rt5640_audio_map,
1010 .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001011 .fully_routed = true,
Hans de Goede77323102018-05-13 09:24:28 +02001012 .suspend_pre = byt_rt5640_suspend,
1013 .resume_post = byt_rt5640_resume,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301014};
1015
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001016static bool is_valleyview(void)
1017{
Pierre-Louis Bossartcac17732016-08-16 18:28:21 -05001018 static const struct x86_cpu_id cpu_ids[] = {
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001019 { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
1020 {}
1021 };
1022
1023 if (!x86_match_cpu(cpu_ids))
1024 return false;
1025 return true;
1026}
1027
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001028struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
1029 u64 aif_value; /* 1: AIF1, 2: AIF2 */
1030 u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
1031};
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001032
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001033static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301034{
Hans de Goede063422c2018-05-13 09:24:35 +02001035 const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" };
Hans de Goede6d1bfcc2018-05-13 09:24:33 +02001036 const struct dmi_system_id *dmi_id;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001037 struct byt_rt5640_private *priv;
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001038 struct snd_soc_acpi_mach *mach;
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001039 const char *i2c_name = NULL;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001040 int ret_val = 0;
Pierre-Louis Bossart2193eb92017-10-12 18:38:05 -05001041 int dai_index = 0;
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001042 int i;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001043
Pierre-Louis Bossartcb67d762017-04-24 16:34:33 -05001044 is_bytcr = false;
Jia-Ju Bai7a3a6322018-04-09 18:47:37 +08001045 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001046 if (!priv)
1047 return -ENOMEM;
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301048
1049 /* register the soc card */
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001050 byt_rt5640_card.dev = &pdev->dev;
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001051 mach = byt_rt5640_card.dev->platform_data;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001052 snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001053
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001054 /* fix index of codec dai */
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001055 for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
1056 if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) {
1057 dai_index = i;
1058 break;
1059 }
1060 }
1061
Pierre-Louis Bossartcaf94ed2016-01-04 17:20:28 -06001062 /* fixup codec name based on HID */
Andy Shevchenko3a147952018-01-12 23:16:17 +02001063 i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
Pierre-Louis Bossart17b52732017-10-12 18:37:58 -05001064 if (i2c_name) {
Pierre-Louis Bossarta232b962016-03-03 21:36:38 -06001065 snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
1066 "%s%s", "i2c-", i2c_name);
1067
1068 byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name;
1069 }
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301070
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001071 /*
1072 * swap SSP0 if bytcr is detected
1073 * (will be overridden if DMI quirk is detected)
1074 */
1075 if (is_valleyview()) {
1076 struct sst_platform_info *p_info = mach->pdata;
1077 const struct sst_res_info *res_info = p_info->res_info;
1078
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001079 if (res_info->acpi_ipc_irq_index == 0)
1080 is_bytcr = true;
1081 }
1082
1083 if (is_bytcr) {
1084 /*
1085 * Baytrail CR platforms may have CHAN package in BIOS, try
1086 * to find relevant routing quirk based as done on Windows
1087 * platforms. We have to read the information directly from the
1088 * BIOS, at this stage the card is not created and the links
1089 * with the codec driver/pdata are non-existent
1090 */
1091
1092 struct acpi_chan_package chan_package;
1093
1094 /* format specified: 2 64-bit integers */
1095 struct acpi_buffer format = {sizeof("NN"), "NN"};
1096 struct acpi_buffer state = {0, NULL};
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001097 struct snd_soc_acpi_package_context pkg_ctx;
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001098 bool pkg_found = false;
1099
1100 state.length = sizeof(chan_package);
1101 state.pointer = &chan_package;
1102
1103 pkg_ctx.name = "CHAN";
1104 pkg_ctx.length = 2;
1105 pkg_ctx.format = &format;
1106 pkg_ctx.state = &state;
1107 pkg_ctx.data_valid = false;
1108
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -05001109 pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
1110 &pkg_ctx);
Pierre-Louis Bossart64e84302016-11-12 18:07:45 -06001111 if (pkg_found) {
1112 if (chan_package.aif_value == 1) {
1113 dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
1114 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
1115 } else if (chan_package.aif_value == 2) {
1116 dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
1117 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1118 } else {
1119 dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
1120 pkg_found = false;
1121 }
1122 }
1123
1124 if (!pkg_found) {
1125 /* no BIOS indications, assume SSP0-AIF2 connection */
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001126 byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1127 }
Pierre-Louis Bossartbf462412016-11-12 18:07:46 -06001128
1129 /* change defaults for Baytrail-CR capture */
Hans de Goede96a388fe2018-05-13 09:24:30 +02001130 byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;
Pierre-Louis Bossartbf462412016-11-12 18:07:46 -06001131 } else {
Hans de Goede56ff4402018-05-13 09:24:31 +02001132 byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |
1133 BYT_RT5640_JD_SRC_JD2_IN4N |
1134 BYT_RT5640_OVCD_TH_2000UA |
1135 BYT_RT5640_OVCD_SF_0P75;
Pierre-Louis Bossarte214f5e2016-08-12 16:27:53 -05001136 }
1137
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -06001138 /* check quirks before creating card */
Hans de Goede6d1bfcc2018-05-13 09:24:33 +02001139 dmi_id = dmi_first_match(byt_rt5640_quirk_table);
1140 if (dmi_id)
1141 byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;
Takashi Iwai9f2cf732017-04-23 09:22:56 +02001142 if (quirk_override) {
Takashi Iwai0b2c9f82017-04-24 23:34:30 +02001143 dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n",
Takashi Iwai9f2cf732017-04-23 09:22:56 +02001144 (unsigned int)byt_rt5640_quirk, quirk_override);
1145 byt_rt5640_quirk = quirk_override;
1146 }
Hans de Goede6a7c05e2018-05-08 17:35:54 +02001147
1148 /* Must be called before register_card, also see declaration comment. */
1149 ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
1150 if (ret_val)
1151 return ret_val;
1152
Pierre-Louis Bossartd7e60d52016-08-12 16:28:00 -05001153 log_quirks(&pdev->dev);
Pierre-Louis Bossartab738e42016-03-03 21:36:37 -06001154
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -05001155 if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
1156 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
Pierre-Louis Bossart89b89072016-08-12 16:27:50 -05001157
1158 /* fixup codec aif name */
1159 snprintf(byt_rt5640_codec_aif_name,
1160 sizeof(byt_rt5640_codec_aif_name),
1161 "%s", "rt5640-aif2");
1162
1163 byt_rt5640_dais[dai_index].codec_dai_name =
1164 byt_rt5640_codec_aif_name;
1165 }
1166
Pierre-Louis Bossartf47088d2016-08-12 16:27:51 -05001167 if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1168 (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
1169
1170 /* fixup cpu dai name name */
1171 snprintf(byt_rt5640_cpu_dai_name,
1172 sizeof(byt_rt5640_cpu_dai_name),
1173 "%s", "ssp0-port");
1174
1175 byt_rt5640_dais[dai_index].cpu_dai_name =
1176 byt_rt5640_cpu_dai_name;
1177 }
1178
Pierre-Louis Bossart7735bce2017-09-08 12:43:52 -05001179 if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001180 priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
1181 if (IS_ERR(priv->mclk)) {
Pierre-Louis Bossart4a8b3a62016-12-16 10:55:49 -06001182 ret_val = PTR_ERR(priv->mclk);
1183
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001184 dev_err(&pdev->dev,
Pierre-Louis Bossart4a8b3a62016-12-16 10:55:49 -06001185 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
1186 ret_val);
1187
1188 /*
1189 * Fall back to bit clock usage for -ENOENT (clock not
1190 * available likely due to missing dependencies), bail
1191 * for all other errors, including -EPROBE_DEFER
1192 */
1193 if (ret_val != -ENOENT)
1194 return ret_val;
1195 byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
Irina Tirdeadf1a2772016-08-12 16:27:57 -05001196 }
1197 }
1198
Hans de Goede063422c2018-05-13 09:24:35 +02001199 snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
1200 "bytcr-rt5640-%s-spk-%s-mic",
1201 (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ?
1202 "mono" : "stereo",
1203 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
1204 byt_rt5640_card.long_name = byt_rt5640_long_name;
1205
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001206 ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
1207
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301208 if (ret_val) {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001209 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1210 ret_val);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301211 return ret_val;
1212 }
Pierre-Louis Bossart9fd57472015-12-17 20:35:42 -06001213 platform_set_drvdata(pdev, &byt_rt5640_card);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301214 return ret_val;
1215}
1216
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001217static struct platform_driver snd_byt_rt5640_mc_driver = {
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301218 .driver = {
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001219 .name = "bytcr_rt5640",
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301220 },
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001221 .probe = snd_byt_rt5640_mc_probe,
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301222};
1223
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001224module_platform_driver(snd_byt_rt5640_mc_driver);
Subhransu S. Prusty996cc842014-11-19 15:13:27 +05301225
1226MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
1227MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
1228MODULE_LICENSE("GPL v2");
Pierre-Louis Bossarta2d55632015-12-17 20:35:41 -06001229MODULE_ALIAS("platform:bytcr_rt5640");