2 * Intel Broxton-P I2S Machine Driver
4 * Copyright (C) 2014-2016, Intel Corporation. All rights reserved.
7 * Intel Skylake I2S Machine driver
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <sound/core.h>
22 #include <sound/pcm.h>
23 #include <sound/soc.h>
24 #include <sound/jack.h>
25 #include <sound/pcm_params.h>
26 #include "../../codecs/hdac_hdmi.h"
27 #include "../../codecs/rt298.h"
29 static struct snd_soc_jack broxton_headset
;
30 /* Headset jack detection DAPM pins */
33 BXT_DPCM_AUDIO_PB
= 0,
35 BXT_DPCM_AUDIO_REF_CP
,
36 BXT_DPCM_AUDIO_DMIC_CP
,
37 BXT_DPCM_AUDIO_HDMI1_PB
,
38 BXT_DPCM_AUDIO_HDMI2_PB
,
39 BXT_DPCM_AUDIO_HDMI3_PB
,
42 static struct snd_soc_jack_pin broxton_headset_pins
[] = {
45 .mask
= SND_JACK_MICROPHONE
,
48 .pin
= "Headphone Jack",
49 .mask
= SND_JACK_HEADPHONE
,
53 static const struct snd_kcontrol_new broxton_controls
[] = {
54 SOC_DAPM_PIN_SWITCH("Speaker"),
55 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
56 SOC_DAPM_PIN_SWITCH("Mic Jack"),
59 static const struct snd_soc_dapm_widget broxton_widgets
[] = {
60 SND_SOC_DAPM_HP("Headphone Jack", NULL
),
61 SND_SOC_DAPM_SPK("Speaker", NULL
),
62 SND_SOC_DAPM_MIC("Mic Jack", NULL
),
63 SND_SOC_DAPM_MIC("DMIC2", NULL
),
64 SND_SOC_DAPM_MIC("SoC DMIC", NULL
),
65 SND_SOC_DAPM_SPK("HDMI1", NULL
),
66 SND_SOC_DAPM_SPK("HDMI2", NULL
),
67 SND_SOC_DAPM_SPK("HDMI3", NULL
),
70 static const struct snd_soc_dapm_route broxton_rt298_map
[] = {
72 {"Speaker", NULL
, "SPOR"},
73 {"Speaker", NULL
, "SPOL"},
75 /* HP jack connectors - unknown if we have jack detect */
76 {"Headphone Jack", NULL
, "HPO Pin"},
79 {"MIC1", NULL
, "Mic Jack"},
82 {"DMIC1 Pin", NULL
, "DMIC2"},
83 {"DMic", NULL
, "SoC DMIC"},
85 {"HDMI1", NULL
, "hif5 Output"},
86 {"HDMI2", NULL
, "hif6 Output"},
87 {"HDMI3", NULL
, "hif7 Output"},
89 /* CODEC BE connections */
90 { "AIF1 Playback", NULL
, "ssp5 Tx"},
91 { "ssp5 Tx", NULL
, "codec0_out"},
92 { "ssp5 Tx", NULL
, "codec1_out"},
94 { "codec0_in", NULL
, "ssp5 Rx" },
95 { "ssp5 Rx", NULL
, "AIF1 Capture" },
97 { "dmic01_hifi", NULL
, "DMIC01 Rx" },
98 { "DMIC01 Rx", NULL
, "Capture" },
100 { "hifi3", NULL
, "iDisp3 Tx"},
101 { "iDisp3 Tx", NULL
, "iDisp3_out"},
102 { "hifi2", NULL
, "iDisp2 Tx"},
103 { "iDisp2 Tx", NULL
, "iDisp2_out"},
104 { "hifi1", NULL
, "iDisp1 Tx"},
105 { "iDisp1 Tx", NULL
, "iDisp1_out"},
109 static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime
*rtd
)
111 struct snd_soc_dapm_context
*dapm
;
112 struct snd_soc_component
*component
= rtd
->cpu_dai
->component
;
114 dapm
= snd_soc_component_get_dapm(component
);
115 snd_soc_dapm_ignore_suspend(dapm
, "Reference Capture");
120 static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime
*rtd
)
122 struct snd_soc_codec
*codec
= rtd
->codec
;
125 ret
= snd_soc_card_jack_new(rtd
->card
, "Headset",
126 SND_JACK_HEADSET
| SND_JACK_BTN_0
,
128 broxton_headset_pins
, ARRAY_SIZE(broxton_headset_pins
));
133 rt298_mic_detect(codec
, &broxton_headset
);
135 snd_soc_dapm_ignore_suspend(&rtd
->card
->dapm
, "SoC DMIC");
140 static int broxton_hdmi_init(struct snd_soc_pcm_runtime
*rtd
)
142 struct snd_soc_dai
*dai
= rtd
->codec_dai
;
144 return hdac_hdmi_jack_init(dai
, BXT_DPCM_AUDIO_HDMI1_PB
+ dai
->id
);
147 static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime
*rtd
,
148 struct snd_pcm_hw_params
*params
)
150 struct snd_interval
*rate
= hw_param_interval(params
,
151 SNDRV_PCM_HW_PARAM_RATE
);
152 struct snd_interval
*channels
= hw_param_interval(params
,
153 SNDRV_PCM_HW_PARAM_CHANNELS
);
154 struct snd_mask
*fmt
= hw_param_mask(params
, SNDRV_PCM_HW_PARAM_FORMAT
);
156 /* The ADSP will covert the FE rate to 48k, stereo */
157 rate
->min
= rate
->max
= 48000;
158 channels
->min
= channels
->max
= 2;
160 /* set SSP5 to 24 bit */
162 snd_mask_set(fmt
, SNDRV_PCM_FORMAT_S24_LE
);
167 static int broxton_rt298_hw_params(struct snd_pcm_substream
*substream
,
168 struct snd_pcm_hw_params
*params
)
170 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
171 struct snd_soc_dai
*codec_dai
= rtd
->codec_dai
;
174 ret
= snd_soc_dai_set_sysclk(codec_dai
, RT298_SCLK_S_PLL
,
175 19200000, SND_SOC_CLOCK_IN
);
177 dev_err(rtd
->dev
, "can't set codec sysclk configuration\n");
184 static const struct snd_soc_ops broxton_rt298_ops
= {
185 .hw_params
= broxton_rt298_hw_params
,
188 static unsigned int rates
[] = {
192 static struct snd_pcm_hw_constraint_list constraints_rates
= {
193 .count
= ARRAY_SIZE(rates
),
198 static int broxton_dmic_fixup(struct snd_soc_pcm_runtime
*rtd
,
199 struct snd_pcm_hw_params
*params
)
201 struct snd_interval
*channels
= hw_param_interval(params
,
202 SNDRV_PCM_HW_PARAM_CHANNELS
);
203 if (params_channels(params
) == 2)
204 channels
->min
= channels
->max
= 2;
206 channels
->min
= channels
->max
= 4;
211 static unsigned int channels_dmic
[] = {
215 static struct snd_pcm_hw_constraint_list constraints_dmic_channels
= {
216 .count
= ARRAY_SIZE(channels_dmic
),
217 .list
= channels_dmic
,
221 static int broxton_dmic_startup(struct snd_pcm_substream
*substream
)
223 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
225 runtime
->hw
.channels_max
= 4;
226 snd_pcm_hw_constraint_list(runtime
, 0, SNDRV_PCM_HW_PARAM_CHANNELS
,
227 &constraints_dmic_channels
);
229 return snd_pcm_hw_constraint_list(substream
->runtime
, 0,
230 SNDRV_PCM_HW_PARAM_RATE
, &constraints_rates
);
233 static const struct snd_soc_ops broxton_dmic_ops
= {
234 .startup
= broxton_dmic_startup
,
237 static unsigned int channels
[] = {
241 static struct snd_pcm_hw_constraint_list constraints_channels
= {
242 .count
= ARRAY_SIZE(channels
),
247 static int bxt_fe_startup(struct snd_pcm_substream
*substream
)
249 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
252 * on this platform for PCM device we support:
257 runtime
->hw
.channels_max
= 2;
258 snd_pcm_hw_constraint_list(runtime
, 0, SNDRV_PCM_HW_PARAM_CHANNELS
,
259 &constraints_channels
);
261 snd_pcm_hw_constraint_list(runtime
, 0,
262 SNDRV_PCM_HW_PARAM_RATE
, &constraints_rates
);
267 static const struct snd_soc_ops broxton_rt286_fe_ops
= {
268 .startup
= bxt_fe_startup
,
271 /* broxton digital audio interface glue - connects codec <--> CPU */
272 static struct snd_soc_dai_link broxton_rt298_dais
[] = {
273 /* Front End DAI links */
274 [BXT_DPCM_AUDIO_PB
] =
276 .name
= "Bxt Audio Port",
277 .stream_name
= "Audio",
278 .cpu_dai_name
= "System Pin",
279 .platform_name
= "0000:00:0e.0",
282 .codec_name
= "snd-soc-dummy",
283 .codec_dai_name
= "snd-soc-dummy-dai",
284 .init
= broxton_rt298_fe_init
,
285 .trigger
= {SND_SOC_DPCM_TRIGGER_POST
, SND_SOC_DPCM_TRIGGER_POST
},
287 .ops
= &broxton_rt286_fe_ops
,
289 [BXT_DPCM_AUDIO_CP
] =
291 .name
= "Bxt Audio Capture Port",
292 .stream_name
= "Audio Record",
293 .cpu_dai_name
= "System Pin",
294 .platform_name
= "0000:00:0e.0",
297 .codec_name
= "snd-soc-dummy",
298 .codec_dai_name
= "snd-soc-dummy-dai",
299 .trigger
= {SND_SOC_DPCM_TRIGGER_POST
, SND_SOC_DPCM_TRIGGER_POST
},
301 .ops
= &broxton_rt286_fe_ops
,
303 [BXT_DPCM_AUDIO_REF_CP
] =
305 .name
= "Bxt Audio Reference cap",
306 .stream_name
= "refcap",
307 .cpu_dai_name
= "Reference Pin",
308 .codec_name
= "snd-soc-dummy",
309 .codec_dai_name
= "snd-soc-dummy-dai",
310 .platform_name
= "0000:00:0e.0",
316 [BXT_DPCM_AUDIO_DMIC_CP
] =
318 .name
= "Bxt Audio DMIC cap",
319 .stream_name
= "dmiccap",
320 .cpu_dai_name
= "DMIC Pin",
321 .codec_name
= "snd-soc-dummy",
322 .codec_dai_name
= "snd-soc-dummy-dai",
323 .platform_name
= "0000:00:0e.0",
328 .ops
= &broxton_dmic_ops
,
330 [BXT_DPCM_AUDIO_HDMI1_PB
] =
332 .name
= "Bxt HDMI Port1",
333 .stream_name
= "Hdmi1",
334 .cpu_dai_name
= "HDMI1 Pin",
335 .codec_name
= "snd-soc-dummy",
336 .codec_dai_name
= "snd-soc-dummy-dai",
337 .platform_name
= "0000:00:0e.0",
343 [BXT_DPCM_AUDIO_HDMI2_PB
] =
345 .name
= "Bxt HDMI Port2",
346 .stream_name
= "Hdmi2",
347 .cpu_dai_name
= "HDMI2 Pin",
348 .codec_name
= "snd-soc-dummy",
349 .codec_dai_name
= "snd-soc-dummy-dai",
350 .platform_name
= "0000:00:0e.0",
356 [BXT_DPCM_AUDIO_HDMI3_PB
] =
358 .name
= "Bxt HDMI Port3",
359 .stream_name
= "Hdmi3",
360 .cpu_dai_name
= "HDMI3 Pin",
361 .codec_name
= "snd-soc-dummy",
362 .codec_dai_name
= "snd-soc-dummy-dai",
363 .platform_name
= "0000:00:0e.0",
369 /* Back End DAI links */
372 .name
= "SSP5-Codec",
374 .cpu_dai_name
= "SSP5 Pin",
375 .platform_name
= "0000:00:0e.0",
377 .codec_name
= "i2c-INT343A:00",
378 .codec_dai_name
= "rt298-aif1",
379 .init
= broxton_rt298_codec_init
,
380 .dai_fmt
= SND_SOC_DAIFMT_DSP_A
| SND_SOC_DAIFMT_NB_NF
|
381 SND_SOC_DAIFMT_CBS_CFS
,
382 .ignore_pmdown_time
= 1,
383 .be_hw_params_fixup
= broxton_ssp5_fixup
,
384 .ops
= &broxton_rt298_ops
,
391 .cpu_dai_name
= "DMIC01 Pin",
392 .codec_name
= "dmic-codec",
393 .codec_dai_name
= "dmic-hifi",
394 .platform_name
= "0000:00:0e.0",
395 .be_hw_params_fixup
= broxton_dmic_fixup
,
403 .cpu_dai_name
= "iDisp1 Pin",
404 .codec_name
= "ehdaudio0D2",
405 .codec_dai_name
= "intel-hdmi-hifi1",
406 .platform_name
= "0000:00:0e.0",
407 .init
= broxton_hdmi_init
,
414 .cpu_dai_name
= "iDisp2 Pin",
415 .codec_name
= "ehdaudio0D2",
416 .codec_dai_name
= "intel-hdmi-hifi2",
417 .platform_name
= "0000:00:0e.0",
418 .init
= broxton_hdmi_init
,
425 .cpu_dai_name
= "iDisp3 Pin",
426 .codec_name
= "ehdaudio0D2",
427 .codec_dai_name
= "intel-hdmi-hifi3",
428 .platform_name
= "0000:00:0e.0",
429 .init
= broxton_hdmi_init
,
435 /* broxton audio machine driver for SPT + RT298S */
436 static struct snd_soc_card broxton_rt298
= {
437 .name
= "broxton-rt298",
438 .owner
= THIS_MODULE
,
439 .dai_link
= broxton_rt298_dais
,
440 .num_links
= ARRAY_SIZE(broxton_rt298_dais
),
441 .controls
= broxton_controls
,
442 .num_controls
= ARRAY_SIZE(broxton_controls
),
443 .dapm_widgets
= broxton_widgets
,
444 .num_dapm_widgets
= ARRAY_SIZE(broxton_widgets
),
445 .dapm_routes
= broxton_rt298_map
,
446 .num_dapm_routes
= ARRAY_SIZE(broxton_rt298_map
),
447 .fully_routed
= true,
450 static int broxton_audio_probe(struct platform_device
*pdev
)
452 broxton_rt298
.dev
= &pdev
->dev
;
454 return devm_snd_soc_register_card(&pdev
->dev
, &broxton_rt298
);
457 static struct platform_driver broxton_audio
= {
458 .probe
= broxton_audio_probe
,
460 .name
= "bxt_alc298s_i2s",
461 .pm
= &snd_soc_pm_ops
,
464 module_platform_driver(broxton_audio
)
466 /* Module information */
467 MODULE_AUTHOR("Ramesh Babu <Ramesh.Babu@intel.com>");
468 MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>");
469 MODULE_DESCRIPTION("Intel SST Audio for Broxton");
470 MODULE_LICENSE("GPL v2");
471 MODULE_ALIAS("platform:bxt_alc298s_i2s");