blob: 601e47c33ba80e557e39af705918d9909ca58842 [file] [log] [blame]
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -06001/*
2 * bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
3 * (derived from bytcr_rt5640.c)
4 *
5 * Copyright (C) 2015 Intel Corp
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
20#include <linux/init.h>
Hans de Goede46058ae2018-03-04 15:35:59 +010021#include <linux/i2c.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060022#include <linux/module.h>
23#include <linux/platform_device.h>
Hans de Goede46058ae2018-03-04 15:35:59 +010024#include <linux/property.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060025#include <linux/acpi.h>
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050026#include <linux/clk.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060027#include <linux/device.h>
28#include <linux/dmi.h>
Hans de Goedecaed9d632018-07-05 00:59:35 +020029#include <linux/input.h>
Hans de Goede5f6fb232018-07-01 20:36:31 +020030#include <linux/gpio/consumer.h>
31#include <linux/gpio/machine.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060032#include <linux/slab.h>
Hans de Goede8a880a22018-03-04 15:36:07 +010033#include <asm/cpu_device_id.h>
Hans de Goedefbea16d2018-07-01 20:36:29 +020034#include <asm/intel-family.h>
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050035#include <asm/platform_sst_audio.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060036#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39#include <sound/jack.h>
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -050040#include <sound/soc-acpi.h>
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -060041#include "../../codecs/rt5651.h"
42#include "../atom/sst-atom-controls.h"
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050043
44enum {
45 BYT_RT5651_DMIC_MAP,
46 BYT_RT5651_IN1_MAP,
Carlo Caioneea261bd2017-11-21 17:15:45 +000047 BYT_RT5651_IN1_IN2_MAP,
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050048};
49
Hans de Goede46058ae2018-03-04 15:35:59 +010050enum {
51 BYT_RT5651_JD_NULL = (RT5651_JD_NULL << 4),
52 BYT_RT5651_JD1_1 = (RT5651_JD1_1 << 4),
53 BYT_RT5651_JD1_2 = (RT5651_JD1_2 << 4),
54 BYT_RT5651_JD2 = (RT5651_JD2 << 4),
55};
56
Hans de Goede8ffaa6a2018-03-04 15:36:02 +010057enum {
58 BYT_RT5651_OVCD_TH_600UA = (6 << 8),
59 BYT_RT5651_OVCD_TH_1500UA = (15 << 8),
60 BYT_RT5651_OVCD_TH_2000UA = (20 << 8),
61};
62
63enum {
64 BYT_RT5651_OVCD_SF_0P5 = (RT5651_OVCD_SF_0P5 << 13),
65 BYT_RT5651_OVCD_SF_0P75 = (RT5651_OVCD_SF_0P75 << 13),
66 BYT_RT5651_OVCD_SF_1P0 = (RT5651_OVCD_SF_1P0 << 13),
67 BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 13),
68};
69
Hans de Goede46058ae2018-03-04 15:35:59 +010070#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0))
71#define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)
Hans de Goede8ffaa6a2018-03-04 15:36:02 +010072#define BYT_RT5651_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)
73#define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)
Hans de Goede46058ae2018-03-04 15:35:59 +010074#define BYT_RT5651_DMIC_EN BIT(16)
75#define BYT_RT5651_MCLK_EN BIT(17)
76#define BYT_RT5651_MCLK_25MHZ BIT(18)
Hans de Goede8a880a22018-03-04 15:36:07 +010077#define BYT_RT5651_SSP2_AIF2 BIT(19) /* default is using AIF1 */
78#define BYT_RT5651_SSP0_AIF1 BIT(20)
79#define BYT_RT5651_SSP0_AIF2 BIT(21)
Hans de Goede8f250e72018-06-24 16:06:33 +020080#define BYT_RT5651_HP_LR_SWAPPED BIT(22)
Hans de Goede46058ae2018-03-04 15:35:59 +010081
Hans de Goedefc7c4602018-06-24 16:06:26 +020082#define BYT_RT5651_DEFAULT_QUIRKS (BYT_RT5651_MCLK_EN | \
83 BYT_RT5651_JD1_1 | \
84 BYT_RT5651_OVCD_TH_2000UA | \
85 BYT_RT5651_OVCD_SF_0P75)
86
Hans de Goede8ffaa6a2018-03-04 15:36:02 +010087/* jack-detect-source + dmic-en + ovcd-th + -sf + terminating empty entry */
88#define MAX_NO_PROPS 5
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050089
90struct byt_rt5651_private {
91 struct clk *mclk;
Hans de Goede5f6fb232018-07-01 20:36:31 +020092 struct gpio_desc *ext_amp_gpio;
Carlo Caioned9f8f9b2017-10-20 12:18:56 +010093 struct snd_soc_jack jack;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050094};
95
Hans de Goede10876d22018-06-24 16:06:27 +020096/* Default: jack-detect on JD1_1, internal mic on in1, headsetmic on in3 */
Hans de Goedefc7c4602018-06-24 16:06:26 +020097static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
Hans de Goedede231472018-06-24 16:06:30 +020098 BYT_RT5651_IN1_MAP;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -050099
100static void log_quirks(struct device *dev)
101{
102 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
103 dev_info(dev, "quirk DMIC_MAP enabled");
104 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
105 dev_info(dev, "quirk IN1_MAP enabled");
Hans de Goede366780d2018-06-24 16:06:28 +0200106 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_IN2_MAP)
107 dev_info(dev, "quirk IN1_IN2_MAP enabled");
Hans de Goede8ffaa6a2018-03-04 15:36:02 +0100108 if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
Hans de Goede46058ae2018-03-04 15:35:59 +0100109 dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
110 BYT_RT5651_JDSRC(byt_rt5651_quirk));
Hans de Goede8ffaa6a2018-03-04 15:36:02 +0100111 dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",
112 BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
113 dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",
114 BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
115 }
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500116 if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
117 dev_info(dev, "quirk DMIC enabled");
118 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
119 dev_info(dev, "quirk MCLK_EN enabled");
120 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
121 dev_info(dev, "quirk MCLK_25MHZ enabled");
Hans de Goede8a880a22018-03-04 15:36:07 +0100122 if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
123 dev_info(dev, "quirk SSP2_AIF2 enabled\n");
124 if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
125 dev_info(dev, "quirk SSP0_AIF1 enabled\n");
126 if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
127 dev_info(dev, "quirk SSP0_AIF2 enabled\n");
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500128}
129
130#define BYT_CODEC_DAI1 "rt5651-aif1"
Hans de Goede8a880a22018-03-04 15:36:07 +0100131#define BYT_CODEC_DAI2 "rt5651-aif2"
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500132
Hans de Goedeaeec6cc2018-03-04 15:36:03 +0100133static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
134 int rate, int bclk_ratio)
135{
136 int clk_id, clk_freq, ret;
137
138 /* Configure the PLL before selecting it */
139 if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
140 clk_id = RT5651_PLL1_S_BCLK1,
141 clk_freq = rate * bclk_ratio;
142 } else {
143 clk_id = RT5651_PLL1_S_MCLK;
144 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
145 clk_freq = 25000000;
146 else
147 clk_freq = 19200000;
148 }
149 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, rate * 512);
150 if (ret < 0) {
Kuninori Morimoto2759ba92018-03-28 01:49:36 +0000151 dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);
Hans de Goedeaeec6cc2018-03-04 15:36:03 +0100152 return ret;
153 }
154
155 ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
156 rate * 512, SND_SOC_CLOCK_IN);
157 if (ret < 0) {
Kuninori Morimoto2759ba92018-03-28 01:49:36 +0000158 dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);
Hans de Goedeaeec6cc2018-03-04 15:36:03 +0100159 return ret;
160 }
161
162 return 0;
163}
164
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500165static int platform_clock_control(struct snd_soc_dapm_widget *w,
166 struct snd_kcontrol *k, int event)
167{
168 struct snd_soc_dapm_context *dapm = w->dapm;
169 struct snd_soc_card *card = dapm->card;
170 struct snd_soc_dai *codec_dai;
171 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
172 int ret;
173
Pierre-Louis Bossartdfb6ec72017-10-12 18:38:03 -0500174 codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
Hans de Goede8a880a22018-03-04 15:36:07 +0100175 if (!codec_dai)
176 codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500177 if (!codec_dai) {
178 dev_err(card->dev,
179 "Codec dai not found; Unable to set platform clock\n");
180 return -EIO;
181 }
182
183 if (SND_SOC_DAPM_EVENT_ON(event)) {
184 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
185 ret = clk_prepare_enable(priv->mclk);
186 if (ret < 0) {
187 dev_err(card->dev,
188 "could not configure MCLK state");
189 return ret;
190 }
191 }
Hans de Goedeaeec6cc2018-03-04 15:36:03 +0100192 ret = byt_rt5651_prepare_and_enable_pll1(codec_dai, 48000, 50);
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500193 } else {
194 /*
195 * Set codec clock source to internal clock before
196 * turning off the platform clock. Codec needs clock
197 * for Jack detection and button press
198 */
199 ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
200 48000 * 512,
201 SND_SOC_CLOCK_IN);
202 if (!ret)
203 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
204 clk_disable_unprepare(priv->mclk);
205 }
206
207 if (ret < 0) {
208 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
209 return ret;
210 }
211
212 return 0;
213}
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600214
Hans de Goede5f6fb232018-07-01 20:36:31 +0200215static int rt5651_ext_amp_power_event(struct snd_soc_dapm_widget *w,
216 struct snd_kcontrol *kcontrol, int event)
217{
218 struct snd_soc_card *card = w->dapm->card;
219 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
220
221 if (SND_SOC_DAPM_EVENT_ON(event))
222 gpiod_set_value_cansleep(priv->ext_amp_gpio, 1);
223 else
224 gpiod_set_value_cansleep(priv->ext_amp_gpio, 0);
225
226 return 0;
227}
228
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600229static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
230 SND_SOC_DAPM_HP("Headphone", NULL),
231 SND_SOC_DAPM_MIC("Headset Mic", NULL),
232 SND_SOC_DAPM_MIC("Internal Mic", NULL),
233 SND_SOC_DAPM_SPK("Speaker", NULL),
Pierre-Louis Bossartea39bdc2018-01-05 13:20:23 -0600234 SND_SOC_DAPM_LINE("Line In", NULL),
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500235 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
236 platform_clock_control, SND_SOC_DAPM_PRE_PMU |
237 SND_SOC_DAPM_POST_PMD),
Hans de Goede5f6fb232018-07-01 20:36:31 +0200238 SND_SOC_DAPM_SUPPLY("Ext Amp Power", SND_SOC_NOPM, 0, 0,
239 rt5651_ext_amp_power_event,
240 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600241};
242
243static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500244 {"Headphone", NULL, "Platform Clock"},
245 {"Headset Mic", NULL, "Platform Clock"},
246 {"Internal Mic", NULL, "Platform Clock"},
247 {"Speaker", NULL, "Platform Clock"},
Hans de Goede5f6fb232018-07-01 20:36:31 +0200248 {"Speaker", NULL, "Ext Amp Power"},
Pierre-Louis Bossartea39bdc2018-01-05 13:20:23 -0600249 {"Line In", NULL, "Platform Clock"},
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500250
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600251 {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600252 {"Headphone", NULL, "HPOL"},
253 {"Headphone", NULL, "HPOR"},
254 {"Speaker", NULL, "LOUTL"},
255 {"Speaker", NULL, "LOUTR"},
Pierre-Louis Bossartea39bdc2018-01-05 13:20:23 -0600256 {"IN2P", NULL, "Line In"},
257 {"IN2N", NULL, "Line In"},
258
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600259};
260
Pierre-Louis Bossart6356c782017-09-08 12:43:53 -0500261static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
262 {"DMIC L1", NULL, "Internal Mic"},
263 {"DMIC R1", NULL, "Internal Mic"},
Hans de Goede37c74012018-06-24 16:06:31 +0200264 {"IN3P", NULL, "Headset Mic"},
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600265};
266
267static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
268 {"Internal Mic", NULL, "micbias1"},
269 {"IN1P", NULL, "Internal Mic"},
Hans de Goedede231472018-06-24 16:06:30 +0200270 {"IN3P", NULL, "Headset Mic"},
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600271};
272
Carlo Caioneea261bd2017-11-21 17:15:45 +0000273static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
274 {"Internal Mic", NULL, "micbias1"},
275 {"IN1P", NULL, "Internal Mic"},
276 {"IN2P", NULL, "Internal Mic"},
277 {"IN3P", NULL, "Headset Mic"},
278};
279
Hans de Goede8a880a22018-03-04 15:36:07 +0100280static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
281 {"ssp0 Tx", NULL, "modem_out"},
282 {"modem_in", NULL, "ssp0 Rx"},
283
284 {"AIF1 Playback", NULL, "ssp0 Tx"},
285 {"ssp0 Rx", NULL, "AIF1 Capture"},
286};
287
288static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
289 {"ssp0 Tx", NULL, "modem_out"},
290 {"modem_in", NULL, "ssp0 Rx"},
291
292 {"AIF2 Playback", NULL, "ssp0 Tx"},
293 {"ssp0 Rx", NULL, "AIF2 Capture"},
294};
295
296static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
297 {"ssp2 Tx", NULL, "codec_out0"},
298 {"ssp2 Tx", NULL, "codec_out1"},
299 {"codec_in0", NULL, "ssp2 Rx"},
300 {"codec_in1", NULL, "ssp2 Rx"},
301
302 {"AIF1 Playback", NULL, "ssp2 Tx"},
303 {"ssp2 Rx", NULL, "AIF1 Capture"},
304};
305
306static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
307 {"ssp2 Tx", NULL, "codec_out0"},
308 {"ssp2 Tx", NULL, "codec_out1"},
309 {"codec_in0", NULL, "ssp2 Rx"},
310 {"codec_in1", NULL, "ssp2 Rx"},
311
312 {"AIF2 Playback", NULL, "ssp2 Tx"},
313 {"ssp2 Rx", NULL, "AIF2 Capture"},
314};
315
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600316static const struct snd_kcontrol_new byt_rt5651_controls[] = {
317 SOC_DAPM_PIN_SWITCH("Headphone"),
318 SOC_DAPM_PIN_SWITCH("Headset Mic"),
319 SOC_DAPM_PIN_SWITCH("Internal Mic"),
320 SOC_DAPM_PIN_SWITCH("Speaker"),
Pierre-Louis Bossartea39bdc2018-01-05 13:20:23 -0600321 SOC_DAPM_PIN_SWITCH("Line In"),
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600322};
323
Carlo Caioned9f8f9b2017-10-20 12:18:56 +0100324static struct snd_soc_jack_pin bytcr_jack_pins[] = {
325 {
326 .pin = "Headphone",
327 .mask = SND_JACK_HEADPHONE,
328 },
329 {
330 .pin = "Headset Mic",
331 .mask = SND_JACK_MICROPHONE,
332 },
333};
334
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600335static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
336 struct snd_pcm_hw_params *params)
337{
338 struct snd_soc_pcm_runtime *rtd = substream->private_data;
339 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Hans de Goede8a880a22018-03-04 15:36:07 +0100340 snd_pcm_format_t format = params_format(params);
Hans de Goedeaeec6cc2018-03-04 15:36:03 +0100341 int rate = params_rate(params);
Hans de Goede8a880a22018-03-04 15:36:07 +0100342 int bclk_ratio;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600343
Hans de Goede8a880a22018-03-04 15:36:07 +0100344 if (format == SNDRV_PCM_FORMAT_S16_LE)
345 bclk_ratio = 32;
346 else
347 bclk_ratio = 50;
348
349 return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate, bclk_ratio);
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600350}
351
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500352static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
353{
354 byt_rt5651_quirk = (unsigned long)id->driver_data;
355 return 1;
356}
357
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600358static const struct dmi_system_id byt_rt5651_quirk_table[] = {
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500359 {
Hans de Goede8f250e72018-06-24 16:06:33 +0200360 /* Chuwi Hi8 Pro (CWI513) */
361 .callback = byt_rt5651_quirk_cb,
362 .matches = {
363 DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
364 DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
365 },
366 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
367 BYT_RT5651_IN1_MAP |
368 BYT_RT5651_HP_LR_SWAPPED),
369 },
370 {
Hans de Goedef026e062018-03-04 15:36:06 +0100371 /* Chuwi Vi8 Plus (CWI519) */
372 .callback = byt_rt5651_quirk_cb,
373 .matches = {
374 DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
375 DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
376 },
Hans de Goedefc7c4602018-06-24 16:06:26 +0200377 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
Hans de Goede8f250e72018-06-24 16:06:33 +0200378 BYT_RT5651_IN1_MAP |
379 BYT_RT5651_HP_LR_SWAPPED),
Hans de Goedef026e062018-03-04 15:36:06 +0100380 },
Hans de Goedef9877eb2018-03-04 15:36:08 +0100381 {
Hans de Goede55d69c02018-06-24 16:06:34 +0200382 /* KIANO SlimNote 14.2 */
383 .callback = byt_rt5651_quirk_cb,
384 .matches = {
385 DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
386 DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
387 },
388 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
389 BYT_RT5651_IN1_IN2_MAP),
390 },
391 {
392 /* Minnowboard Max B3 */
393 .callback = byt_rt5651_quirk_cb,
394 .matches = {
395 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
396 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
397 },
398 .driver_data = (void *)(BYT_RT5651_IN1_MAP),
399 },
400 {
401 /* Minnowboard Turbot */
402 .callback = byt_rt5651_quirk_cb,
403 .matches = {
404 DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
405 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
406 },
407 .driver_data = (void *)(BYT_RT5651_MCLK_EN |
408 BYT_RT5651_IN1_MAP),
409 },
410 {
Hans de Goedef9877eb2018-03-04 15:36:08 +0100411 /* VIOS LTH17 */
412 .callback = byt_rt5651_quirk_cb,
413 .matches = {
414 DMI_MATCH(DMI_SYS_VENDOR, "VIOS"),
415 DMI_MATCH(DMI_PRODUCT_NAME, "LTH17"),
416 },
Hans de Goedefc7c4602018-06-24 16:06:26 +0200417 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
Hans de Goedef9877eb2018-03-04 15:36:08 +0100418 BYT_RT5651_IN1_IN2_MAP),
419 },
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600420 {}
421};
422
Hans de Goede46058ae2018-03-04 15:35:59 +0100423/*
424 * Note this MUST be called before snd_soc_register_card(), so that the props
425 * are in place before the codec component driver's probe function parses them.
426 */
Hans de Goede2c375202018-07-01 20:36:30 +0200427static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
Hans de Goede46058ae2018-03-04 15:35:59 +0100428{
429 struct property_entry props[MAX_NO_PROPS] = {};
Hans de Goede2c375202018-07-01 20:36:30 +0200430 int cnt = 0;
Hans de Goede46058ae2018-03-04 15:35:59 +0100431
432 props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
433 BYT_RT5651_JDSRC(byt_rt5651_quirk));
434
Hans de Goede8ffaa6a2018-03-04 15:36:02 +0100435 props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-threshold-microamp",
436 BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
437
438 props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-scale-factor",
439 BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
440
Hans de Goedec2f26932018-03-04 15:36:00 +0100441 if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
442 props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,dmic-en");
443
Hans de Goede2c375202018-07-01 20:36:30 +0200444 return device_add_properties(i2c_dev, props);
Hans de Goede46058ae2018-03-04 15:35:59 +0100445}
446
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600447static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
448{
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600449 struct snd_soc_card *card = runtime->card;
Kuninori Morimoto17b52012018-01-29 03:44:39 +0000450 struct snd_soc_component *codec = runtime->codec_dai->component;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500451 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600452 const struct snd_soc_dapm_route *custom_map;
453 int num_routes;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500454 int ret;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600455
456 card->dapm.idle_bias_off = true;
457
Hans de Goedec22969d2018-03-04 15:36:10 +0100458 /* Start with RC clk for jack-detect (we disable MCLK below) */
459 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
460 snd_soc_component_update_bits(codec, RT5651_GLB_CLK,
461 RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK);
462
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600463 switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
464 case BYT_RT5651_IN1_MAP:
465 custom_map = byt_rt5651_intmic_in1_map;
466 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
467 break;
Carlo Caioneea261bd2017-11-21 17:15:45 +0000468 case BYT_RT5651_IN1_IN2_MAP:
469 custom_map = byt_rt5651_intmic_in1_in2_map;
470 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
471 break;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600472 default:
Pierre-Louis Bossart6356c782017-09-08 12:43:53 -0500473 custom_map = byt_rt5651_intmic_dmic_map;
474 num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600475 }
Pierre-Louis Bossart6356c782017-09-08 12:43:53 -0500476 ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
477 if (ret)
478 return ret;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600479
Hans de Goede8a880a22018-03-04 15:36:07 +0100480 if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
481 ret = snd_soc_dapm_add_routes(&card->dapm,
482 byt_rt5651_ssp2_aif2_map,
483 ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
484 } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
485 ret = snd_soc_dapm_add_routes(&card->dapm,
486 byt_rt5651_ssp0_aif1_map,
487 ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
488 } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
489 ret = snd_soc_dapm_add_routes(&card->dapm,
490 byt_rt5651_ssp0_aif2_map,
491 ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
492 } else {
493 ret = snd_soc_dapm_add_routes(&card->dapm,
494 byt_rt5651_ssp2_aif1_map,
495 ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
496 }
497 if (ret)
498 return ret;
499
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600500 ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
501 ARRAY_SIZE(byt_rt5651_controls));
502 if (ret) {
503 dev_err(card->dev, "unable to add card controls\n");
504 return ret;
505 }
506 snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
507 snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
508
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500509 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
510 /*
511 * The firmware might enable the clock at
512 * boot (this information may or may not
513 * be reflected in the enable clock register).
514 * To change the rate we must disable the clock
515 * first to cover these cases. Due to common
516 * clock framework restrictions that do not allow
517 * to disable a clock that has not been enabled,
518 * we need to enable the clock first.
519 */
520 ret = clk_prepare_enable(priv->mclk);
521 if (!ret)
522 clk_disable_unprepare(priv->mclk);
523
524 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
525 ret = clk_set_rate(priv->mclk, 25000000);
526 else
527 ret = clk_set_rate(priv->mclk, 19200000);
528
529 if (ret)
530 dev_err(card->dev, "unable to set MCLK rate\n");
531 }
532
Hans de Goedeaed859a2018-03-04 15:36:01 +0100533 if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
534 ret = snd_soc_card_jack_new(runtime->card, "Headset",
Hans de Goedecaed9d632018-07-05 00:59:35 +0200535 SND_JACK_HEADSET | SND_JACK_BTN_0,
536 &priv->jack, bytcr_jack_pins,
537 ARRAY_SIZE(bytcr_jack_pins));
Hans de Goedeaed859a2018-03-04 15:36:01 +0100538 if (ret) {
539 dev_err(runtime->dev, "jack creation failed %d\n", ret);
540 return ret;
541 }
542
Hans de Goedecaed9d632018-07-05 00:59:35 +0200543 snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
544 KEY_PLAYPAUSE);
545
Hans de Goedeaed859a2018-03-04 15:36:01 +0100546 ret = snd_soc_component_set_jack(codec, &priv->jack, NULL);
547 if (ret)
548 return ret;
Carlo Caioned9f8f9b2017-10-20 12:18:56 +0100549 }
550
Hans de Goedeaed859a2018-03-04 15:36:01 +0100551 return 0;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600552}
553
554static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
555 .formats = SNDRV_PCM_FMTBIT_S24_LE,
556 .rate_min = 48000,
557 .rate_max = 48000,
558 .channels_min = 2,
559 .channels_max = 2,
560};
561
562static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
563 struct snd_pcm_hw_params *params)
564{
565 struct snd_interval *rate = hw_param_interval(params,
566 SNDRV_PCM_HW_PARAM_RATE);
567 struct snd_interval *channels = hw_param_interval(params,
568 SNDRV_PCM_HW_PARAM_CHANNELS);
Hans de Goede8a880a22018-03-04 15:36:07 +0100569 int ret, bits;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600570
Hans de Goede8a880a22018-03-04 15:36:07 +0100571 /* The DSP will covert the FE rate to 48k, stereo */
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600572 rate->min = rate->max = 48000;
573 channels->min = channels->max = 2;
574
Hans de Goede8a880a22018-03-04 15:36:07 +0100575 if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
576 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
577 /* set SSP0 to 16-bit */
578 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
579 bits = 16;
580 } else {
581 /* set SSP2 to 24-bit */
582 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
583 bits = 24;
584 }
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600585
586 /*
587 * Default mode for SSP configuration is TDM 4 slot, override config
Hans de Goede8a880a22018-03-04 15:36:07 +0100588 * with explicit setting to I2S 2ch. The word length is set with
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600589 * dai_set_tdm_slot() since there is no other API exposed
590 */
591 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
592 SND_SOC_DAIFMT_I2S |
Pierre-Louis Bossartf12f5c82017-01-26 14:09:29 -0600593 SND_SOC_DAIFMT_NB_NF |
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600594 SND_SOC_DAIFMT_CBS_CFS
595 );
596
597 if (ret < 0) {
598 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
599 return ret;
600 }
601
Hans de Goede8a880a22018-03-04 15:36:07 +0100602 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600603 if (ret < 0) {
604 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
605 return ret;
606 }
607
608 return 0;
609}
610
Takashi Iwai1ebb4d92017-06-08 23:37:22 +0200611static const unsigned int rates_48000[] = {
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600612 48000,
613};
614
Takashi Iwai1ebb4d92017-06-08 23:37:22 +0200615static const struct snd_pcm_hw_constraint_list constraints_48000 = {
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600616 .count = ARRAY_SIZE(rates_48000),
617 .list = rates_48000,
618};
619
620static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
621{
622 return snd_pcm_hw_constraint_list(substream->runtime, 0,
623 SNDRV_PCM_HW_PARAM_RATE,
624 &constraints_48000);
625}
626
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200627static const struct snd_soc_ops byt_rt5651_aif1_ops = {
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600628 .startup = byt_rt5651_aif1_startup,
629};
630
Julia Lawall9b6fdef2016-10-15 16:55:49 +0200631static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600632 .hw_params = byt_rt5651_aif1_hw_params,
633};
634
635static struct snd_soc_dai_link byt_rt5651_dais[] = {
636 [MERR_DPCM_AUDIO] = {
637 .name = "Audio Port",
638 .stream_name = "Audio",
639 .cpu_dai_name = "media-cpu-dai",
640 .codec_dai_name = "snd-soc-dummy-dai",
641 .codec_name = "snd-soc-dummy",
642 .platform_name = "sst-mfld-platform",
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600643 .nonatomic = true,
644 .dynamic = 1,
645 .dpcm_playback = 1,
646 .dpcm_capture = 1,
647 .ops = &byt_rt5651_aif1_ops,
648 },
649 [MERR_DPCM_DEEP_BUFFER] = {
650 .name = "Deep-Buffer Audio Port",
651 .stream_name = "Deep-Buffer Audio",
652 .cpu_dai_name = "deepbuffer-cpu-dai",
653 .codec_dai_name = "snd-soc-dummy-dai",
654 .codec_name = "snd-soc-dummy",
655 .platform_name = "sst-mfld-platform",
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600656 .nonatomic = true,
657 .dynamic = 1,
658 .dpcm_playback = 1,
659 .ops = &byt_rt5651_aif1_ops,
660 },
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600661 /* CODEC<->CODEC link */
662 /* back ends */
663 {
664 .name = "SSP2-Codec",
Pierre-Louis Bossart149f7752017-10-12 18:38:04 -0500665 .id = 0,
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600666 .cpu_dai_name = "ssp2-port",
667 .platform_name = "sst-mfld-platform",
668 .no_pcm = 1,
669 .codec_dai_name = "rt5651-aif1",
670 .codec_name = "i2c-10EC5651:00",
671 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
672 | SND_SOC_DAIFMT_CBS_CFS,
673 .be_hw_params_fixup = byt_rt5651_codec_fixup,
674 .ignore_suspend = 1,
675 .nonatomic = true,
676 .dpcm_playback = 1,
677 .dpcm_capture = 1,
678 .init = byt_rt5651_init,
679 .ops = &byt_rt5651_be_ssp2_ops,
680 },
681};
682
683/* SoC card */
Hans de Goedeb91f4322018-07-05 00:59:34 +0200684static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
685static char byt_rt5651_codec_aif_name[12]; /* = "rt5651-aif[1|2]" */
686static char byt_rt5651_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
687static char byt_rt5651_long_name[40]; /* = "bytcr-rt5651-*-mic[-swapped-hp]" */
688
689static int byt_rt5651_suspend(struct snd_soc_card *card)
690{
691 struct snd_soc_component *component;
692
693 if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
694 return 0;
695
696 list_for_each_entry(component, &card->component_dev_list, card_list) {
697 if (!strcmp(component->name, byt_rt5651_codec_name)) {
698 dev_dbg(component->dev, "disabling jack detect before suspend\n");
699 snd_soc_component_set_jack(component, NULL, NULL);
700 break;
701 }
702 }
703
704 return 0;
705}
706
707static int byt_rt5651_resume(struct snd_soc_card *card)
708{
709 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
710 struct snd_soc_component *component;
711
712 if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
713 return 0;
714
715 list_for_each_entry(component, &card->component_dev_list, card_list) {
716 if (!strcmp(component->name, byt_rt5651_codec_name)) {
717 dev_dbg(component->dev, "re-enabling jack detect after resume\n");
718 snd_soc_component_set_jack(component, &priv->jack, NULL);
719 break;
720 }
721 }
722
723 return 0;
724}
725
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600726static struct snd_soc_card byt_rt5651_card = {
727 .name = "bytcr-rt5651",
728 .owner = THIS_MODULE,
729 .dai_link = byt_rt5651_dais,
730 .num_links = ARRAY_SIZE(byt_rt5651_dais),
731 .dapm_widgets = byt_rt5651_widgets,
732 .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
733 .dapm_routes = byt_rt5651_audio_map,
734 .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
735 .fully_routed = true,
Hans de Goedeb91f4322018-07-05 00:59:34 +0200736 .suspend_pre = byt_rt5651_suspend,
737 .resume_post = byt_rt5651_resume,
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600738};
739
Hans de Goedefbea16d2018-07-01 20:36:29 +0200740static const struct x86_cpu_id baytrail_cpu_ids[] = {
741 { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, /* Valleyview */
742 {}
743};
Hans de Goede8a880a22018-03-04 15:36:07 +0100744
Hans de Goede5f6fb232018-07-01 20:36:31 +0200745static const struct x86_cpu_id cherrytrail_cpu_ids[] = {
746 { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, /* Braswell */
747 {}
748};
749
Hans de Goede0a3badd2018-07-18 22:55:38 +0200750static const struct acpi_gpio_params first_gpio = { 0, 0, false };
751static const struct acpi_gpio_params second_gpio = { 1, 0, false };
Hans de Goede5f6fb232018-07-01 20:36:31 +0200752
Hans de Goede0a3badd2018-07-18 22:55:38 +0200753static const struct acpi_gpio_mapping byt_rt5651_amp_en_first[] = {
754 { "ext-amp-enable-gpios", &first_gpio, 1 },
Hans de Goede5f6fb232018-07-01 20:36:31 +0200755 { },
756};
757
Hans de Goede0a3badd2018-07-18 22:55:38 +0200758static const struct acpi_gpio_mapping byt_rt5651_amp_en_second[] = {
759 { "ext-amp-enable-gpios", &second_gpio, 1 },
760 { },
761};
762
763/*
764 * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources, other
765 * boards may have I2cSerialBusV2, GpioInt, GpioIo instead. We want the
766 * GpioIo one for the ext-amp-enable-gpio and both count for the index in
767 * acpi_gpio_params index. So we have 2 different mappings and the code
768 * below figures out which one to use.
769 */
770struct byt_rt5651_acpi_resource_data {
771 int gpio_count;
772 int gpio_int_idx;
773};
774
775static int snd_byt_rt5651_acpi_resource(struct acpi_resource *ares, void *arg)
776{
777 struct byt_rt5651_acpi_resource_data *data = arg;
778
779 if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
780 return 0;
781
782 if (ares->data.gpio.connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
783 data->gpio_int_idx = data->gpio_count;
784
785 data->gpio_count++;
786 return 0;
787}
788
789static void snd_byt_rt5651_mc_add_amp_en_gpio_mapping(struct device *codec)
790{
791 struct byt_rt5651_acpi_resource_data data = { 0, -1 };
792 LIST_HEAD(resources);
793 int ret;
794
795 ret = acpi_dev_get_resources(ACPI_COMPANION(codec), &resources,
796 snd_byt_rt5651_acpi_resource, &data);
797 if (ret < 0) {
798 dev_warn(codec, "Failed to get ACPI resources, not adding external amplifier GPIO mapping\n");
799 return;
800 }
801
802 /* All info we need is gathered during the walk */
803 acpi_dev_free_resource_list(&resources);
804
805 switch (data.gpio_int_idx) {
806 case 0:
807 devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_second);
808 break;
809 case 1:
810 devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_first);
811 break;
812 default:
813 dev_warn(codec, "Unknown GpioInt index %d, not adding external amplifier GPIO mapping\n",
814 data.gpio_int_idx);
815 }
816}
817
Hans de Goede8a880a22018-03-04 15:36:07 +0100818struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
819 u64 aif_value; /* 1: AIF1, 2: AIF2 */
820 u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
821};
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500822
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600823static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
824{
Hans de Goede8e69cd62018-06-24 16:06:32 +0200825 const char * const mic_name[] = { "dmic", "in1", "in12" };
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500826 struct byt_rt5651_private *priv;
Pierre-Louis Bossart7feb2f72017-10-12 18:49:38 -0500827 struct snd_soc_acpi_mach *mach;
Hans de Goede2c375202018-07-01 20:36:30 +0200828 struct device *codec_dev;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500829 const char *i2c_name = NULL;
Hans de Goede8f250e72018-06-24 16:06:33 +0200830 const char *hp_swapped;
Hans de Goede8a880a22018-03-04 15:36:07 +0100831 bool is_bytcr = false;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600832 int ret_val = 0;
Pierre-Louis Bossart2193eb92017-10-12 18:38:05 -0500833 int dai_index = 0;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500834 int i;
835
Vinod Koulaa5398e2018-04-20 16:14:28 +0530836 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500837 if (!priv)
838 return -ENOMEM;
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -0600839
840 /* register the soc card */
841 byt_rt5651_card.dev = &pdev->dev;
842
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500843 mach = byt_rt5651_card.dev->platform_data;
844 snd_soc_card_set_drvdata(&byt_rt5651_card, priv);
845
846 /* fix index of codec dai */
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500847 for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
848 if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) {
849 dai_index = i;
850 break;
851 }
852 }
853
854 /* fixup codec name based on HID */
Andy Shevchenko3a147952018-01-12 23:16:17 +0200855 i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
Hans de Goedee39cacc2018-03-04 15:35:58 +0100856 if (!i2c_name) {
857 dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
858 return -ENODEV;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500859 }
Hans de Goedee39cacc2018-03-04 15:35:58 +0100860 snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
861 "%s%s", "i2c-", i2c_name);
862 byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500863
Hans de Goede2c375202018-07-01 20:36:30 +0200864 codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
865 byt_rt5651_codec_name);
866 if (!codec_dev)
867 return -EPROBE_DEFER;
868
Hans de Goede8a880a22018-03-04 15:36:07 +0100869 /*
870 * swap SSP0 if bytcr is detected
871 * (will be overridden if DMI quirk is detected)
872 */
Hans de Goedefbea16d2018-07-01 20:36:29 +0200873 if (x86_match_cpu(baytrail_cpu_ids)) {
Hans de Goede8a880a22018-03-04 15:36:07 +0100874 struct sst_platform_info *p_info = mach->pdata;
875 const struct sst_res_info *res_info = p_info->res_info;
876
877 if (res_info->acpi_ipc_irq_index == 0)
878 is_bytcr = true;
879 }
880
881 if (is_bytcr) {
882 /*
883 * Baytrail CR platforms may have CHAN package in BIOS, try
884 * to find relevant routing quirk based as done on Windows
885 * platforms. We have to read the information directly from the
886 * BIOS, at this stage the card is not created and the links
887 * with the codec driver/pdata are non-existent
888 */
889
890 struct acpi_chan_package chan_package;
891
892 /* format specified: 2 64-bit integers */
893 struct acpi_buffer format = {sizeof("NN"), "NN"};
894 struct acpi_buffer state = {0, NULL};
895 struct snd_soc_acpi_package_context pkg_ctx;
896 bool pkg_found = false;
897
898 state.length = sizeof(chan_package);
899 state.pointer = &chan_package;
900
901 pkg_ctx.name = "CHAN";
902 pkg_ctx.length = 2;
903 pkg_ctx.format = &format;
904 pkg_ctx.state = &state;
905 pkg_ctx.data_valid = false;
906
907 pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
908 &pkg_ctx);
909 if (pkg_found) {
910 if (chan_package.aif_value == 1) {
911 dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
912 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
913 } else if (chan_package.aif_value == 2) {
914 dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
915 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
916 } else {
917 dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
918 pkg_found = false;
919 }
920 }
921
922 if (!pkg_found) {
923 /* no BIOS indications, assume SSP0-AIF2 connection */
924 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
925 }
Hans de Goede8a880a22018-03-04 15:36:07 +0100926 }
927
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500928 /* check quirks before creating card */
929 dmi_check_system(byt_rt5651_quirk_table);
Hans de Goede46058ae2018-03-04 15:35:59 +0100930
931 /* Must be called before register_card, also see declaration comment. */
Hans de Goede2c375202018-07-01 20:36:30 +0200932 ret_val = byt_rt5651_add_codec_device_props(codec_dev);
Hans de Goede5f6fb232018-07-01 20:36:31 +0200933 if (ret_val) {
934 put_device(codec_dev);
Hans de Goede46058ae2018-03-04 15:35:59 +0100935 return ret_val;
Hans de Goede5f6fb232018-07-01 20:36:31 +0200936 }
937
938 /* Cherry Trail devices use an external amplifier enable gpio */
939 if (x86_match_cpu(cherrytrail_cpu_ids)) {
Hans de Goede0a3badd2018-07-18 22:55:38 +0200940 snd_byt_rt5651_mc_add_amp_en_gpio_mapping(codec_dev);
Hans de Goede5f6fb232018-07-01 20:36:31 +0200941 priv->ext_amp_gpio = devm_fwnode_get_index_gpiod_from_child(
942 &pdev->dev, "ext-amp-enable", 0,
943 codec_dev->fwnode,
944 GPIOD_OUT_LOW, "speaker-amp");
945 if (IS_ERR(priv->ext_amp_gpio)) {
946 ret_val = PTR_ERR(priv->ext_amp_gpio);
947 switch (ret_val) {
948 case -ENOENT:
949 priv->ext_amp_gpio = NULL;
950 break;
951 default:
952 dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n",
953 ret_val);
954 /* fall through */
955 case -EPROBE_DEFER:
956 put_device(codec_dev);
957 return ret_val;
958 }
959 }
960 }
961
962 put_device(codec_dev);
Hans de Goede46058ae2018-03-04 15:35:59 +0100963
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500964 log_quirks(&pdev->dev);
965
Hans de Goede8a880a22018-03-04 15:36:07 +0100966 if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
967 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
968 /* fixup codec aif name */
969 snprintf(byt_rt5651_codec_aif_name,
970 sizeof(byt_rt5651_codec_aif_name),
971 "%s", "rt5651-aif2");
972
973 byt_rt5651_dais[dai_index].codec_dai_name =
974 byt_rt5651_codec_aif_name;
975 }
976
977 if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
978 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
979 /* fixup cpu dai name name */
980 snprintf(byt_rt5651_cpu_dai_name,
981 sizeof(byt_rt5651_cpu_dai_name),
982 "%s", "ssp0-port");
983
984 byt_rt5651_dais[dai_index].cpu_dai_name =
985 byt_rt5651_cpu_dai_name;
986 }
987
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500988 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
989 priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
990 if (IS_ERR(priv->mclk)) {
Colin Ian Kingde5afce2018-05-02 15:29:45 +0100991 ret_val = PTR_ERR(priv->mclk);
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500992 dev_err(&pdev->dev,
Colin Ian Kingde5afce2018-05-02 15:29:45 +0100993 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
994 ret_val);
Pierre-Louis Bossart02c0a3b2017-10-12 18:37:57 -0500995 /*
996 * Fall back to bit clock usage for -ENOENT (clock not
997 * available likely due to missing dependencies), bail
998 * for all other errors, including -EPROBE_DEFER
999 */
1000 if (ret_val != -ENOENT)
1001 return ret_val;
1002 byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
1003 }
1004 }
1005
Hans de Goede8f250e72018-06-24 16:06:33 +02001006 if (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED)
1007 hp_swapped = "-hp-swapped";
1008 else
1009 hp_swapped = "";
1010
Hans de Goede64484cc2018-05-18 21:35:06 +02001011 snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name),
Hans de Goede8f250e72018-06-24 16:06:33 +02001012 "bytcr-rt5651-%s-mic%s",
1013 mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], hp_swapped);
Hans de Goede64484cc2018-05-18 21:35:06 +02001014 byt_rt5651_card.long_name = byt_rt5651_long_name;
1015
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -06001016 ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
1017
1018 if (ret_val) {
1019 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1020 ret_val);
1021 return ret_val;
1022 }
1023 platform_set_drvdata(pdev, &byt_rt5651_card);
1024 return ret_val;
1025}
1026
1027static struct platform_driver snd_byt_rt5651_mc_driver = {
1028 .driver = {
1029 .name = "bytcr_rt5651",
Pierre-Louis Bossart2bd5bd12016-01-04 17:20:24 -06001030 },
1031 .probe = snd_byt_rt5651_mc_probe,
1032};
1033
1034module_platform_driver(snd_byt_rt5651_mc_driver);
1035
1036MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
1037MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1038MODULE_LICENSE("GPL v2");
1039MODULE_ALIAS("platform:bytcr_rt5651");