treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174
[linux-2.6-block.git] / sound / soc / intel / boards / skl_rt286.c
CommitLineData
1802d0be 1// SPDX-License-Identifier: GPL-2.0-only
624729fd
OA
2/*
3 * Intel Skylake I2S Machine Driver
4 *
5 * Copyright (C) 2014-2015, Intel Corporation. All rights reserved.
6 *
7 * Modified from:
8 * Intel Broadwell Wildcatpoint SST Audio
9 *
10 * Copyright (C) 2013, Intel Corporation. All rights reserved.
624729fd
OA
11 */
12
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/soc.h>
18#include <sound/jack.h>
19#include <sound/pcm_params.h>
20#include "../../codecs/rt286.h"
23905cd1 21#include "../../codecs/hdac_hdmi.h"
624729fd
OA
22
23static struct snd_soc_jack skylake_headset;
f3af3592 24static struct snd_soc_jack skylake_hdmi[3];
23905cd1 25
1a10612f
SP
26struct skl_hdmi_pcm {
27 struct list_head head;
28 struct snd_soc_dai *codec_dai;
29 int device;
30};
31
32struct skl_rt286_private {
33 struct list_head hdmi_pcm_list;
34};
35
23905cd1
JK
36enum {
37 SKL_DPCM_AUDIO_PB = 0,
1f0f8bde 38 SKL_DPCM_AUDIO_DB_PB,
23905cd1
JK
39 SKL_DPCM_AUDIO_CP,
40 SKL_DPCM_AUDIO_REF_CP,
41 SKL_DPCM_AUDIO_DMIC_CP,
42 SKL_DPCM_AUDIO_HDMI1_PB,
43 SKL_DPCM_AUDIO_HDMI2_PB,
44 SKL_DPCM_AUDIO_HDMI3_PB,
45};
46
624729fd
OA
47/* Headset jack detection DAPM pins */
48static struct snd_soc_jack_pin skylake_headset_pins[] = {
49 {
50 .pin = "Mic Jack",
51 .mask = SND_JACK_MICROPHONE,
52 },
53 {
54 .pin = "Headphone Jack",
55 .mask = SND_JACK_HEADPHONE,
56 },
57};
58
59static const struct snd_kcontrol_new skylake_controls[] = {
60 SOC_DAPM_PIN_SWITCH("Speaker"),
61 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
62 SOC_DAPM_PIN_SWITCH("Mic Jack"),
63};
64
65static const struct snd_soc_dapm_widget skylake_widgets[] = {
66 SND_SOC_DAPM_HP("Headphone Jack", NULL),
67 SND_SOC_DAPM_SPK("Speaker", NULL),
68 SND_SOC_DAPM_MIC("Mic Jack", NULL),
69 SND_SOC_DAPM_MIC("DMIC2", NULL),
70 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
23905cd1
JK
71 SND_SOC_DAPM_SPK("HDMI1", NULL),
72 SND_SOC_DAPM_SPK("HDMI2", NULL),
73 SND_SOC_DAPM_SPK("HDMI3", NULL),
624729fd
OA
74};
75
76static const struct snd_soc_dapm_route skylake_rt286_map[] = {
77 /* speaker */
78 {"Speaker", NULL, "SPOR"},
79 {"Speaker", NULL, "SPOL"},
80
81 /* HP jack connectors - unknown if we have jack deteck */
82 {"Headphone Jack", NULL, "HPO Pin"},
83
84 /* other jacks */
85 {"MIC1", NULL, "Mic Jack"},
86
87 /* digital mics */
88 {"DMIC1 Pin", NULL, "DMIC2"},
820f339f 89 {"DMic", NULL, "SoC DMIC"},
624729fd
OA
90
91 /* CODEC BE connections */
92 { "AIF1 Playback", NULL, "ssp0 Tx"},
93 { "ssp0 Tx", NULL, "codec0_out"},
94 { "ssp0 Tx", NULL, "codec1_out"},
95
96 { "codec0_in", NULL, "ssp0 Rx" },
97 { "codec1_in", NULL, "ssp0 Rx" },
98 { "ssp0 Rx", NULL, "AIF1 Capture" },
99
100 { "dmic01_hifi", NULL, "DMIC01 Rx" },
820f339f 101 { "DMIC01 Rx", NULL, "DMIC AIF" },
624729fd 102
23905cd1
JK
103 { "hifi3", NULL, "iDisp3 Tx"},
104 { "iDisp3 Tx", NULL, "iDisp3_out"},
105 { "hifi2", NULL, "iDisp2 Tx"},
106 { "iDisp2 Tx", NULL, "iDisp2_out"},
107 { "hifi1", NULL, "iDisp1 Tx"},
108 { "iDisp1 Tx", NULL, "iDisp1_out"},
624729fd
OA
109
110};
111
9ec2053b
PD
112static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd)
113{
114 struct snd_soc_dapm_context *dapm;
115 struct snd_soc_component *component = rtd->cpu_dai->component;
116
117 dapm = snd_soc_component_get_dapm(component);
118 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
119
120 return 0;
121}
122
624729fd
OA
123static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
124{
45101122 125 struct snd_soc_component *component = rtd->codec_dai->component;
624729fd
OA
126 int ret;
127
128 ret = snd_soc_card_jack_new(rtd->card, "Headset",
129 SND_JACK_HEADSET | SND_JACK_BTN_0,
130 &skylake_headset,
131 skylake_headset_pins, ARRAY_SIZE(skylake_headset_pins));
132
133 if (ret)
134 return ret;
135
45101122 136 rt286_mic_detect(component, &skylake_headset);
624729fd 137
9ec2053b 138 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
9ec2053b 139
624729fd
OA
140 return 0;
141}
142
23905cd1
JK
143static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
144{
1a10612f 145 struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card);
23905cd1 146 struct snd_soc_dai *dai = rtd->codec_dai;
1a10612f
SP
147 struct skl_hdmi_pcm *pcm;
148
149 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
150 if (!pcm)
151 return -ENOMEM;
23905cd1 152
1a10612f
SP
153 pcm->device = SKL_DPCM_AUDIO_HDMI1_PB + dai->id;
154 pcm->codec_dai = dai;
155
156 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
157
158 return 0;
23905cd1
JK
159}
160
617647ae 161static const unsigned int rates[] = {
5eab6ab9
VK
162 48000,
163};
164
617647ae 165static const struct snd_pcm_hw_constraint_list constraints_rates = {
5eab6ab9
VK
166 .count = ARRAY_SIZE(rates),
167 .list = rates,
168 .mask = 0,
169};
170
617647ae 171static const unsigned int channels[] = {
5eab6ab9
VK
172 2,
173};
174
617647ae 175static const struct snd_pcm_hw_constraint_list constraints_channels = {
5eab6ab9
VK
176 .count = ARRAY_SIZE(channels),
177 .list = channels,
178 .mask = 0,
179};
180
181static int skl_fe_startup(struct snd_pcm_substream *substream)
182{
183 struct snd_pcm_runtime *runtime = substream->runtime;
184
185 /*
186 * on this platform for PCM device we support,
187 * 48Khz
188 * stereo
189 * 16 bit audio
190 */
191
192 runtime->hw.channels_max = 2;
193 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
194 &constraints_channels);
195
196 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
197 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
198
199 snd_pcm_hw_constraint_list(runtime, 0,
200 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
201
202 return 0;
203}
204
205static const struct snd_soc_ops skylake_rt286_fe_ops = {
206 .startup = skl_fe_startup,
207};
624729fd
OA
208
209static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
210 struct snd_pcm_hw_params *params)
211{
212 struct snd_interval *rate = hw_param_interval(params,
213 SNDRV_PCM_HW_PARAM_RATE);
214 struct snd_interval *channels = hw_param_interval(params,
215 SNDRV_PCM_HW_PARAM_CHANNELS);
677165f7 216 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
624729fd
OA
217
218 /* The output is 48KHz, stereo, 16bits */
219 rate->min = rate->max = 48000;
220 channels->min = channels->max = 2;
624729fd 221
677165f7
JK
222 /* set SSP0 to 24 bit */
223 snd_mask_none(fmt);
b5453e8c 224 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
624729fd
OA
225 return 0;
226}
227
228static int skylake_rt286_hw_params(struct snd_pcm_substream *substream,
229 struct snd_pcm_hw_params *params)
230{
231 struct snd_soc_pcm_runtime *rtd = substream->private_data;
232 struct snd_soc_dai *codec_dai = rtd->codec_dai;
233 int ret;
234
235 ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
236 SND_SOC_CLOCK_IN);
237 if (ret < 0)
238 dev_err(rtd->dev, "set codec sysclk failed: %d\n", ret);
239
240 return ret;
241}
242
9b6fdef6 243static const struct snd_soc_ops skylake_rt286_ops = {
624729fd
OA
244 .hw_params = skylake_rt286_hw_params,
245};
246
4386b767
JK
247static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
248 struct snd_pcm_hw_params *params)
249{
250 struct snd_interval *channels = hw_param_interval(params,
251 SNDRV_PCM_HW_PARAM_CHANNELS);
6e3ffa00
JK
252 if (params_channels(params) == 2)
253 channels->min = channels->max = 2;
254 else
255 channels->min = channels->max = 4;
4386b767
JK
256
257 return 0;
258}
259
617647ae 260static const unsigned int channels_dmic[] = {
4386b767
JK
261 2, 4,
262};
263
617647ae 264static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
4386b767
JK
265 .count = ARRAY_SIZE(channels_dmic),
266 .list = channels_dmic,
267 .mask = 0,
268};
269
270static int skylake_dmic_startup(struct snd_pcm_substream *substream)
271{
272 struct snd_pcm_runtime *runtime = substream->runtime;
273
274 runtime->hw.channels_max = 4;
275 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
276 &constraints_dmic_channels);
277
278 return snd_pcm_hw_constraint_list(substream->runtime, 0,
279 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
280}
281
9b6fdef6 282static const struct snd_soc_ops skylake_dmic_ops = {
4386b767
JK
283 .startup = skylake_dmic_startup,
284};
285
624729fd
OA
286/* skylake digital audio interface glue - connects codec <--> CPU */
287static struct snd_soc_dai_link skylake_rt286_dais[] = {
288 /* Front End DAI links */
23905cd1 289 [SKL_DPCM_AUDIO_PB] = {
624729fd
OA
290 .name = "Skl Audio Port",
291 .stream_name = "Audio",
292 .cpu_dai_name = "System Pin",
293 .platform_name = "0000:00:1f.3",
294 .nonatomic = 1,
295 .dynamic = 1,
296 .codec_name = "snd-soc-dummy",
297 .codec_dai_name = "snd-soc-dummy-dai",
9ec2053b 298 .init = skylake_rt286_fe_init,
624729fd
OA
299 .trigger = {
300 SND_SOC_DPCM_TRIGGER_POST,
301 SND_SOC_DPCM_TRIGGER_POST
302 },
303 .dpcm_playback = 1,
5eab6ab9 304 .ops = &skylake_rt286_fe_ops,
624729fd 305 },
1f0f8bde
SP
306 [SKL_DPCM_AUDIO_DB_PB] = {
307 .name = "Skl Deepbuffer Port",
308 .stream_name = "Deep Buffer Audio",
309 .cpu_dai_name = "Deepbuffer Pin",
310 .platform_name = "0000:00:1f.3",
311 .nonatomic = 1,
312 .dynamic = 1,
313 .codec_name = "snd-soc-dummy",
314 .codec_dai_name = "snd-soc-dummy-dai",
315 .trigger = {
316 SND_SOC_DPCM_TRIGGER_POST,
317 SND_SOC_DPCM_TRIGGER_POST
318 },
319 .dpcm_playback = 1,
320 .ops = &skylake_rt286_fe_ops,
321
322 },
23905cd1 323 [SKL_DPCM_AUDIO_CP] = {
624729fd
OA
324 .name = "Skl Audio Capture Port",
325 .stream_name = "Audio Record",
326 .cpu_dai_name = "System Pin",
327 .platform_name = "0000:00:1f.3",
328 .nonatomic = 1,
329 .dynamic = 1,
330 .codec_name = "snd-soc-dummy",
331 .codec_dai_name = "snd-soc-dummy-dai",
332 .trigger = {
333 SND_SOC_DPCM_TRIGGER_POST,
334 SND_SOC_DPCM_TRIGGER_POST
335 },
336 .dpcm_capture = 1,
5eab6ab9 337 .ops = &skylake_rt286_fe_ops,
624729fd 338 },
23905cd1 339 [SKL_DPCM_AUDIO_REF_CP] = {
624729fd
OA
340 .name = "Skl Audio Reference cap",
341 .stream_name = "refcap",
342 .cpu_dai_name = "Reference Pin",
343 .codec_name = "snd-soc-dummy",
344 .codec_dai_name = "snd-soc-dummy-dai",
345 .platform_name = "0000:00:1f.3",
346 .init = NULL,
347 .dpcm_capture = 1,
624729fd
OA
348 .nonatomic = 1,
349 .dynamic = 1,
350 },
23905cd1 351 [SKL_DPCM_AUDIO_DMIC_CP] = {
4386b767
JK
352 .name = "Skl Audio DMIC cap",
353 .stream_name = "dmiccap",
354 .cpu_dai_name = "DMIC Pin",
355 .codec_name = "snd-soc-dummy",
356 .codec_dai_name = "snd-soc-dummy-dai",
357 .platform_name = "0000:00:1f.3",
358 .init = NULL,
359 .dpcm_capture = 1,
4386b767
JK
360 .nonatomic = 1,
361 .dynamic = 1,
362 .ops = &skylake_dmic_ops,
363 },
23905cd1
JK
364 [SKL_DPCM_AUDIO_HDMI1_PB] = {
365 .name = "Skl HDMI Port1",
366 .stream_name = "Hdmi1",
367 .cpu_dai_name = "HDMI1 Pin",
368 .codec_name = "snd-soc-dummy",
369 .codec_dai_name = "snd-soc-dummy-dai",
370 .platform_name = "0000:00:1f.3",
371 .dpcm_playback = 1,
372 .init = NULL,
373 .nonatomic = 1,
374 .dynamic = 1,
375 },
376 [SKL_DPCM_AUDIO_HDMI2_PB] = {
377 .name = "Skl HDMI Port2",
378 .stream_name = "Hdmi2",
379 .cpu_dai_name = "HDMI2 Pin",
380 .codec_name = "snd-soc-dummy",
381 .codec_dai_name = "snd-soc-dummy-dai",
382 .platform_name = "0000:00:1f.3",
383 .dpcm_playback = 1,
384 .init = NULL,
385 .nonatomic = 1,
386 .dynamic = 1,
387 },
388 [SKL_DPCM_AUDIO_HDMI3_PB] = {
389 .name = "Skl HDMI Port3",
390 .stream_name = "Hdmi3",
391 .cpu_dai_name = "HDMI3 Pin",
392 .codec_name = "snd-soc-dummy",
393 .codec_dai_name = "snd-soc-dummy-dai",
394 .platform_name = "0000:00:1f.3",
395 .dpcm_playback = 1,
396 .init = NULL,
397 .nonatomic = 1,
398 .dynamic = 1,
399 },
624729fd
OA
400
401 /* Back End DAI links */
402 {
403 /* SSP0 - Codec */
404 .name = "SSP0-Codec",
2f0ad491 405 .id = 0,
624729fd
OA
406 .cpu_dai_name = "SSP0 Pin",
407 .platform_name = "0000:00:1f.3",
408 .no_pcm = 1,
409 .codec_name = "i2c-INT343A:00",
410 .codec_dai_name = "rt286-aif1",
411 .init = skylake_rt286_codec_init,
412 .dai_fmt = SND_SOC_DAIFMT_I2S |
413 SND_SOC_DAIFMT_NB_NF |
414 SND_SOC_DAIFMT_CBS_CFS,
624729fd
OA
415 .ignore_pmdown_time = 1,
416 .be_hw_params_fixup = skylake_ssp0_fixup,
417 .ops = &skylake_rt286_ops,
418 .dpcm_playback = 1,
419 .dpcm_capture = 1,
420 },
421 {
422 .name = "dmic01",
2f0ad491 423 .id = 1,
624729fd
OA
424 .cpu_dai_name = "DMIC01 Pin",
425 .codec_name = "dmic-codec",
426 .codec_dai_name = "dmic-hifi",
427 .platform_name = "0000:00:1f.3",
4386b767 428 .be_hw_params_fixup = skylake_dmic_fixup,
624729fd
OA
429 .ignore_suspend = 1,
430 .dpcm_capture = 1,
431 .no_pcm = 1,
432 },
23905cd1
JK
433 {
434 .name = "iDisp1",
2f0ad491 435 .id = 2,
23905cd1
JK
436 .cpu_dai_name = "iDisp1 Pin",
437 .codec_name = "ehdaudio0D2",
438 .codec_dai_name = "intel-hdmi-hifi1",
439 .platform_name = "0000:00:1f.3",
440 .init = skylake_hdmi_init,
441 .dpcm_playback = 1,
442 .no_pcm = 1,
443 },
444 {
445 .name = "iDisp2",
2f0ad491 446 .id = 3,
23905cd1
JK
447 .cpu_dai_name = "iDisp2 Pin",
448 .codec_name = "ehdaudio0D2",
449 .codec_dai_name = "intel-hdmi-hifi2",
450 .platform_name = "0000:00:1f.3",
451 .init = skylake_hdmi_init,
452 .dpcm_playback = 1,
453 .no_pcm = 1,
454 },
455 {
456 .name = "iDisp3",
2f0ad491 457 .id = 4,
23905cd1
JK
458 .cpu_dai_name = "iDisp3 Pin",
459 .codec_name = "ehdaudio0D2",
460 .codec_dai_name = "intel-hdmi-hifi3",
461 .platform_name = "0000:00:1f.3",
462 .init = skylake_hdmi_init,
463 .dpcm_playback = 1,
464 .no_pcm = 1,
465 },
624729fd
OA
466};
467
f3af3592 468#define NAME_SIZE 32
1a10612f
SP
469static int skylake_card_late_probe(struct snd_soc_card *card)
470{
471 struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card);
472 struct skl_hdmi_pcm *pcm;
45101122 473 struct snd_soc_component *component = NULL;
f3af3592
JK
474 int err, i = 0;
475 char jack_name[NAME_SIZE];
1a10612f
SP
476
477 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
45101122 478 component = pcm->codec_dai->component;
f3af3592
JK
479 snprintf(jack_name, sizeof(jack_name),
480 "HDMI/DP, pcm=%d Jack", pcm->device);
481 err = snd_soc_card_jack_new(card, jack_name,
482 SND_JACK_AVOUT, &skylake_hdmi[i],
483 NULL, 0);
484
485 if (err)
486 return err;
487
488 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
489 &skylake_hdmi[i]);
1a10612f
SP
490 if (err < 0)
491 return err;
f3af3592
JK
492
493 i++;
1a10612f
SP
494 }
495
45101122 496 if (!component)
64f8620d
JK
497 return -EINVAL;
498
45101122 499 return hdac_hdmi_jack_port_init(component, &card->dapm);
1a10612f
SP
500}
501
624729fd
OA
502/* skylake audio machine driver for SPT + RT286S */
503static struct snd_soc_card skylake_rt286 = {
504 .name = "skylake-rt286",
505 .owner = THIS_MODULE,
506 .dai_link = skylake_rt286_dais,
507 .num_links = ARRAY_SIZE(skylake_rt286_dais),
508 .controls = skylake_controls,
509 .num_controls = ARRAY_SIZE(skylake_controls),
510 .dapm_widgets = skylake_widgets,
511 .num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
512 .dapm_routes = skylake_rt286_map,
513 .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map),
514 .fully_routed = true,
1a10612f 515 .late_probe = skylake_card_late_probe,
624729fd
OA
516};
517
518static int skylake_audio_probe(struct platform_device *pdev)
519{
1a10612f
SP
520 struct skl_rt286_private *ctx;
521
a6b09837 522 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1a10612f
SP
523 if (!ctx)
524 return -ENOMEM;
525
526 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
527
624729fd 528 skylake_rt286.dev = &pdev->dev;
1a10612f 529 snd_soc_card_set_drvdata(&skylake_rt286, ctx);
624729fd 530
4901aa06 531 return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286);
624729fd
OA
532}
533
894a16db
VK
534static const struct platform_device_id skl_board_ids[] = {
535 { .name = "skl_alc286s_i2s" },
536 { .name = "kbl_alc286s_i2s" },
537 { }
538};
539
624729fd
OA
540static struct platform_driver skylake_audio = {
541 .probe = skylake_audio_probe,
624729fd
OA
542 .driver = {
543 .name = "skl_alc286s_i2s",
314038e4 544 .pm = &snd_soc_pm_ops,
624729fd 545 },
894a16db
VK
546 .id_table = skl_board_ids,
547
624729fd
OA
548};
549
550module_platform_driver(skylake_audio)
551
552/* Module information */
553MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>");
554MODULE_DESCRIPTION("Intel SST Audio for Skylake");
555MODULE_LICENSE("GPL v2");
556MODULE_ALIAS("platform:skl_alc286s_i2s");
894a16db 557MODULE_ALIAS("platform:kbl_alc286s_i2s");