1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/init.h>
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/acpi.h>
24#include <linux/clk.h>
25#include <linux/device.h>
26#include <linux/dmi.h>
27#include <linux/slab.h>
28#include <asm/platform_sst_audio.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/jack.h>
33#include <sound/soc-acpi.h>
34#include "../../codecs/rt5651.h"
35#include "../atom/sst-atom-controls.h"
36
37enum {
38 BYT_RT5651_DMIC_MAP,
39 BYT_RT5651_IN1_MAP,
40 BYT_RT5651_IN2_MAP,
41 BYT_RT5651_IN1_IN2_MAP,
42 BYT_RT5651_IN3_MAP,
43};
44
45#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(7, 0))
46#define BYT_RT5651_DMIC_EN BIT(16)
47#define BYT_RT5651_MCLK_EN BIT(17)
48#define BYT_RT5651_MCLK_25MHZ BIT(18)
49
50struct byt_rt5651_private {
51 struct clk *mclk;
52 struct snd_soc_jack jack;
53};
54
55static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
56 BYT_RT5651_DMIC_EN |
57 BYT_RT5651_MCLK_EN;
58
59static void log_quirks(struct device *dev)
60{
61 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
62 dev_info(dev, "quirk DMIC_MAP enabled");
63 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
64 dev_info(dev, "quirk IN1_MAP enabled");
65 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
66 dev_info(dev, "quirk IN2_MAP enabled");
67 if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
68 dev_info(dev, "quirk IN3_MAP enabled");
69 if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
70 dev_info(dev, "quirk DMIC enabled");
71 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
72 dev_info(dev, "quirk MCLK_EN enabled");
73 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
74 dev_info(dev, "quirk MCLK_25MHZ enabled");
75}
76
77#define BYT_CODEC_DAI1 "rt5651-aif1"
78
79static int platform_clock_control(struct snd_soc_dapm_widget *w,
80 struct snd_kcontrol *k, int event)
81{
82 struct snd_soc_dapm_context *dapm = w->dapm;
83 struct snd_soc_card *card = dapm->card;
84 struct snd_soc_dai *codec_dai;
85 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
86 int ret;
87
88 codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
89 if (!codec_dai) {
90 dev_err(card->dev,
91 "Codec dai not found; Unable to set platform clock\n");
92 return -EIO;
93 }
94
95 if (SND_SOC_DAPM_EVENT_ON(event)) {
96 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
97 ret = clk_prepare_enable(priv->mclk);
98 if (ret < 0) {
99 dev_err(card->dev,
100 "could not configure MCLK state");
101 return ret;
102 }
103 }
104 ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
105 48000 * 512,
106 SND_SOC_CLOCK_IN);
107 } else {
108
109
110
111
112
113 ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
114 48000 * 512,
115 SND_SOC_CLOCK_IN);
116 if (!ret)
117 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
118 clk_disable_unprepare(priv->mclk);
119 }
120
121 if (ret < 0) {
122 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
123 return ret;
124 }
125
126 return 0;
127}
128
129static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
130 SND_SOC_DAPM_HP("Headphone", NULL),
131 SND_SOC_DAPM_MIC("Headset Mic", NULL),
132 SND_SOC_DAPM_MIC("Internal Mic", NULL),
133 SND_SOC_DAPM_SPK("Speaker", NULL),
134 SND_SOC_DAPM_LINE("Line In", NULL),
135 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
136 platform_clock_control, SND_SOC_DAPM_PRE_PMU |
137 SND_SOC_DAPM_POST_PMD),
138
139};
140
141static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
142 {"Headphone", NULL, "Platform Clock"},
143 {"Headset Mic", NULL, "Platform Clock"},
144 {"Internal Mic", NULL, "Platform Clock"},
145 {"Speaker", NULL, "Platform Clock"},
146 {"Line In", NULL, "Platform Clock"},
147
148 {"AIF1 Playback", NULL, "ssp2 Tx"},
149 {"ssp2 Tx", NULL, "codec_out0"},
150 {"ssp2 Tx", NULL, "codec_out1"},
151 {"codec_in0", NULL, "ssp2 Rx"},
152 {"codec_in1", NULL, "ssp2 Rx"},
153 {"ssp2 Rx", NULL, "AIF1 Capture"},
154
155 {"Headset Mic", NULL, "micbias1"},
156 {"Headphone", NULL, "HPOL"},
157 {"Headphone", NULL, "HPOR"},
158 {"Speaker", NULL, "LOUTL"},
159 {"Speaker", NULL, "LOUTR"},
160 {"IN2P", NULL, "Line In"},
161 {"IN2N", NULL, "Line In"},
162
163};
164
165static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
166 {"IN2P", NULL, "Headset Mic"},
167 {"DMIC L1", NULL, "Internal Mic"},
168 {"DMIC R1", NULL, "Internal Mic"},
169};
170
171static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
172 {"Internal Mic", NULL, "micbias1"},
173 {"IN2P", NULL, "Headset Mic"},
174 {"IN1P", NULL, "Internal Mic"},
175};
176
177static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
178 {"Internal Mic", NULL, "micbias1"},
179 {"IN1P", NULL, "Headset Mic"},
180 {"IN2P", NULL, "Internal Mic"},
181};
182
183static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
184 {"Internal Mic", NULL, "micbias1"},
185 {"IN1P", NULL, "Internal Mic"},
186 {"IN2P", NULL, "Internal Mic"},
187 {"IN3P", NULL, "Headset Mic"},
188};
189
190static const struct snd_soc_dapm_route byt_rt5651_intmic_in3_map[] = {
191 {"Internal Mic", NULL, "micbias1"},
192 {"IN3P", NULL, "Headset Mic"},
193 {"IN1P", NULL, "Internal Mic"},
194};
195
196static const struct snd_kcontrol_new byt_rt5651_controls[] = {
197 SOC_DAPM_PIN_SWITCH("Headphone"),
198 SOC_DAPM_PIN_SWITCH("Headset Mic"),
199 SOC_DAPM_PIN_SWITCH("Internal Mic"),
200 SOC_DAPM_PIN_SWITCH("Speaker"),
201 SOC_DAPM_PIN_SWITCH("Line In"),
202};
203
204static struct snd_soc_jack_pin bytcr_jack_pins[] = {
205 {
206 .pin = "Headphone",
207 .mask = SND_JACK_HEADPHONE,
208 },
209 {
210 .pin = "Headset Mic",
211 .mask = SND_JACK_MICROPHONE,
212 },
213};
214
215static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
216 struct snd_pcm_hw_params *params)
217{
218 struct snd_soc_pcm_runtime *rtd = substream->private_data;
219 struct snd_soc_dai *codec_dai = rtd->codec_dai;
220 int ret;
221
222 snd_soc_dai_set_bclk_ratio(codec_dai, 50);
223
224 ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
225 params_rate(params) * 512,
226 SND_SOC_CLOCK_IN);
227 if (ret < 0) {
228 dev_err(rtd->dev, "can't set codec clock %d\n", ret);
229 return ret;
230 }
231
232 if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
233
234 ret = snd_soc_dai_set_pll(codec_dai, 0,
235 RT5651_PLL1_S_BCLK1,
236 params_rate(params) * 50,
237 params_rate(params) * 512);
238 } else {
239 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
240 ret = snd_soc_dai_set_pll(codec_dai, 0,
241 RT5651_PLL1_S_MCLK,
242 25000000,
243 params_rate(params) * 512);
244 } else {
245 ret = snd_soc_dai_set_pll(codec_dai, 0,
246 RT5651_PLL1_S_MCLK,
247 19200000,
248 params_rate(params) * 512);
249 }
250 }
251
252 if (ret < 0) {
253 dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
254 return ret;
255 }
256
257 return 0;
258}
259
260static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
261{
262 byt_rt5651_quirk = (unsigned long)id->driver_data;
263 return 1;
264}
265
266static const struct dmi_system_id byt_rt5651_quirk_table[] = {
267 {
268 .callback = byt_rt5651_quirk_cb,
269 .matches = {
270 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
271 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
272 },
273 .driver_data = (void *)(BYT_RT5651_IN3_MAP),
274 },
275 {
276 .callback = byt_rt5651_quirk_cb,
277 .matches = {
278 DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
279 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
280 },
281 .driver_data = (void *)(BYT_RT5651_MCLK_EN |
282 BYT_RT5651_IN3_MAP),
283 },
284 {
285 .callback = byt_rt5651_quirk_cb,
286 .matches = {
287 DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
288 DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
289 },
290 .driver_data = (void *)(BYT_RT5651_MCLK_EN |
291 BYT_RT5651_IN1_IN2_MAP),
292 },
293 {}
294};
295
296static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
297{
298 struct snd_soc_card *card = runtime->card;
299 struct snd_soc_codec *codec = runtime->codec;
300 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
301 const struct snd_soc_dapm_route *custom_map;
302 int num_routes;
303 int ret;
304
305 card->dapm.idle_bias_off = true;
306
307 switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
308 case BYT_RT5651_IN1_MAP:
309 custom_map = byt_rt5651_intmic_in1_map;
310 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
311 break;
312 case BYT_RT5651_IN2_MAP:
313 custom_map = byt_rt5651_intmic_in2_map;
314 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
315 break;
316 case BYT_RT5651_IN1_IN2_MAP:
317 custom_map = byt_rt5651_intmic_in1_in2_map;
318 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
319 break;
320 case BYT_RT5651_IN3_MAP:
321 custom_map = byt_rt5651_intmic_in3_map;
322 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in3_map);
323 break;
324 default:
325 custom_map = byt_rt5651_intmic_dmic_map;
326 num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
327 }
328 ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
329 if (ret)
330 return ret;
331
332 ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
333 ARRAY_SIZE(byt_rt5651_controls));
334 if (ret) {
335 dev_err(card->dev, "unable to add card controls\n");
336 return ret;
337 }
338 snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
339 snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
340
341 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
342
343
344
345
346
347
348
349
350
351
352 ret = clk_prepare_enable(priv->mclk);
353 if (!ret)
354 clk_disable_unprepare(priv->mclk);
355
356 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
357 ret = clk_set_rate(priv->mclk, 25000000);
358 else
359 ret = clk_set_rate(priv->mclk, 19200000);
360
361 if (ret)
362 dev_err(card->dev, "unable to set MCLK rate\n");
363 }
364
365 ret = snd_soc_card_jack_new(runtime->card, "Headset",
366 SND_JACK_HEADSET, &priv->jack,
367 bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins));
368 if (ret) {
369 dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
370 return ret;
371 }
372
373 rt5651_set_jack_detect(codec, &priv->jack);
374
375 return ret;
376}
377
378static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
379 .formats = SNDRV_PCM_FMTBIT_S24_LE,
380 .rate_min = 48000,
381 .rate_max = 48000,
382 .channels_min = 2,
383 .channels_max = 2,
384};
385
386static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
387 struct snd_pcm_hw_params *params)
388{
389 struct snd_interval *rate = hw_param_interval(params,
390 SNDRV_PCM_HW_PARAM_RATE);
391 struct snd_interval *channels = hw_param_interval(params,
392 SNDRV_PCM_HW_PARAM_CHANNELS);
393 int ret;
394
395
396 rate->min = rate->max = 48000;
397 channels->min = channels->max = 2;
398
399
400 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
401
402
403
404
405
406
407 ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
408 SND_SOC_DAIFMT_I2S |
409 SND_SOC_DAIFMT_NB_NF |
410 SND_SOC_DAIFMT_CBS_CFS
411 );
412
413 if (ret < 0) {
414 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
415 return ret;
416 }
417
418 ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
419 if (ret < 0) {
420 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
421 return ret;
422 }
423
424 return 0;
425}
426
427static const unsigned int rates_48000[] = {
428 48000,
429};
430
431static const struct snd_pcm_hw_constraint_list constraints_48000 = {
432 .count = ARRAY_SIZE(rates_48000),
433 .list = rates_48000,
434};
435
436static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
437{
438 return snd_pcm_hw_constraint_list(substream->runtime, 0,
439 SNDRV_PCM_HW_PARAM_RATE,
440 &constraints_48000);
441}
442
443static const struct snd_soc_ops byt_rt5651_aif1_ops = {
444 .startup = byt_rt5651_aif1_startup,
445};
446
447static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
448 .hw_params = byt_rt5651_aif1_hw_params,
449};
450
451static struct snd_soc_dai_link byt_rt5651_dais[] = {
452 [MERR_DPCM_AUDIO] = {
453 .name = "Audio Port",
454 .stream_name = "Audio",
455 .cpu_dai_name = "media-cpu-dai",
456 .codec_dai_name = "snd-soc-dummy-dai",
457 .codec_name = "snd-soc-dummy",
458 .platform_name = "sst-mfld-platform",
459 .nonatomic = true,
460 .dynamic = 1,
461 .dpcm_playback = 1,
462 .dpcm_capture = 1,
463 .ops = &byt_rt5651_aif1_ops,
464 },
465 [MERR_DPCM_DEEP_BUFFER] = {
466 .name = "Deep-Buffer Audio Port",
467 .stream_name = "Deep-Buffer Audio",
468 .cpu_dai_name = "deepbuffer-cpu-dai",
469 .codec_dai_name = "snd-soc-dummy-dai",
470 .codec_name = "snd-soc-dummy",
471 .platform_name = "sst-mfld-platform",
472 .nonatomic = true,
473 .dynamic = 1,
474 .dpcm_playback = 1,
475 .ops = &byt_rt5651_aif1_ops,
476 },
477
478
479 {
480 .name = "SSP2-Codec",
481 .id = 0,
482 .cpu_dai_name = "ssp2-port",
483 .platform_name = "sst-mfld-platform",
484 .no_pcm = 1,
485 .codec_dai_name = "rt5651-aif1",
486 .codec_name = "i2c-10EC5651:00",
487 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
488 | SND_SOC_DAIFMT_CBS_CFS,
489 .be_hw_params_fixup = byt_rt5651_codec_fixup,
490 .ignore_suspend = 1,
491 .nonatomic = true,
492 .dpcm_playback = 1,
493 .dpcm_capture = 1,
494 .init = byt_rt5651_init,
495 .ops = &byt_rt5651_be_ssp2_ops,
496 },
497};
498
499
500static struct snd_soc_card byt_rt5651_card = {
501 .name = "bytcr-rt5651",
502 .owner = THIS_MODULE,
503 .dai_link = byt_rt5651_dais,
504 .num_links = ARRAY_SIZE(byt_rt5651_dais),
505 .dapm_widgets = byt_rt5651_widgets,
506 .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
507 .dapm_routes = byt_rt5651_audio_map,
508 .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
509 .fully_routed = true,
510};
511
512static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
513
514static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
515{
516 struct byt_rt5651_private *priv;
517 struct snd_soc_acpi_mach *mach;
518 const char *i2c_name = NULL;
519 int ret_val = 0;
520 int dai_index = 0;
521 int i;
522
523 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
524 if (!priv)
525 return -ENOMEM;
526
527
528 byt_rt5651_card.dev = &pdev->dev;
529
530 mach = byt_rt5651_card.dev->platform_data;
531 snd_soc_card_set_drvdata(&byt_rt5651_card, priv);
532
533
534 for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
535 if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) {
536 dai_index = i;
537 break;
538 }
539 }
540
541
542 i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
543 if (i2c_name) {
544 snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
545 "%s%s", "i2c-", i2c_name);
546
547 byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
548 }
549
550
551 dmi_check_system(byt_rt5651_quirk_table);
552 log_quirks(&pdev->dev);
553
554 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
555 priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
556 if (IS_ERR(priv->mclk)) {
557 dev_err(&pdev->dev,
558 "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
559 PTR_ERR(priv->mclk));
560
561
562
563
564
565 if (ret_val != -ENOENT)
566 return ret_val;
567 byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
568 }
569 }
570
571 ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
572
573 if (ret_val) {
574 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
575 ret_val);
576 return ret_val;
577 }
578 platform_set_drvdata(pdev, &byt_rt5651_card);
579 return ret_val;
580}
581
582static struct platform_driver snd_byt_rt5651_mc_driver = {
583 .driver = {
584 .name = "bytcr_rt5651",
585 },
586 .probe = snd_byt_rt5651_mc_probe,
587};
588
589module_platform_driver(snd_byt_rt5651_mc_driver);
590
591MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
592MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
593MODULE_LICENSE("GPL v2");
594MODULE_ALIAS("platform:bytcr_rt5651");
595