diff options
author | Omair M Abdullah <omair.m.abdullah@intel.com> | 2015-10-14 11:41:43 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-19 15:28:48 -0400 |
commit | 624729fd51871bfbddb647764f180126789a29ee (patch) | |
tree | 25809a3a9cc2fa89f6c38a85d28155663f1e29fc | |
parent | 01bb84b5001e4a6221582b163b34e90b3095f451 (diff) |
ASoC: Intel: Skylake - Add Skylake RT286 I2S machine driver
Add the SKL I2S machine driver using Realtek ALC286S codec
in I2S mode.
Signed-off-by: Omair M Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/intel/Kconfig | 13 | ||||
-rw-r--r-- | sound/soc/intel/boards/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/intel/boards/skl_rt286.c | 266 |
3 files changed, 281 insertions, 0 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 664df1f44530..6d67357f2d74 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -140,3 +140,16 @@ config SND_SOC_INTEL_SKYLAKE | |||
140 | select SND_HDA_EXT_CORE | 140 | select SND_HDA_EXT_CORE |
141 | select SND_SOC_TOPOLOGY | 141 | select SND_SOC_TOPOLOGY |
142 | select SND_SOC_INTEL_SST | 142 | select SND_SOC_INTEL_SST |
143 | |||
144 | config SND_SOC_INTEL_SKL_RT286_MACH | ||
145 | tristate "ASoC Audio driver for SKL with RT286 I2S mode" | ||
146 | depends on X86 && ACPI | ||
147 | select SND_SOC_INTEL_SST | ||
148 | select SND_SOC_INTEL_SKYLAKE | ||
149 | select SND_SOC_RT286 | ||
150 | select SND_SOC_DMIC | ||
151 | help | ||
152 | This adds support for ASoC machine driver for Skylake platforms | ||
153 | with RT286 I2S audio codec. | ||
154 | Say Y if you have such a device | ||
155 | If unsure select "N". | ||
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index cb94895c9edb..371c4565cad8 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
@@ -6,6 +6,7 @@ snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o | |||
6 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | 6 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o |
7 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | 7 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o |
8 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o | 8 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o |
9 | snd-soc-skl_rt286-objs := skl_rt286.o | ||
9 | 10 | ||
10 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 11 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
11 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 12 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
@@ -15,3 +16,4 @@ obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o | |||
15 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | 16 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o |
16 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | 17 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o |
17 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o | 18 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o |
19 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o | ||
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c new file mode 100644 index 000000000000..488c98ee1ded --- /dev/null +++ b/sound/soc/intel/boards/skl_rt286.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * Intel Skylake I2S Machine Driver | ||
3 | * | ||
4 | * Copyright (C) 2014-2015, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * Modified from: | ||
7 | * Intel Broadwell Wildcatpoint SST Audio | ||
8 | * | ||
9 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License version | ||
13 | * 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/jack.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include "../../codecs/rt286.h" | ||
29 | |||
30 | static struct snd_soc_jack skylake_headset; | ||
31 | /* Headset jack detection DAPM pins */ | ||
32 | static struct snd_soc_jack_pin skylake_headset_pins[] = { | ||
33 | { | ||
34 | .pin = "Mic Jack", | ||
35 | .mask = SND_JACK_MICROPHONE, | ||
36 | }, | ||
37 | { | ||
38 | .pin = "Headphone Jack", | ||
39 | .mask = SND_JACK_HEADPHONE, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static const struct snd_kcontrol_new skylake_controls[] = { | ||
44 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
45 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
46 | SOC_DAPM_PIN_SWITCH("Mic Jack"), | ||
47 | }; | ||
48 | |||
49 | static const struct snd_soc_dapm_widget skylake_widgets[] = { | ||
50 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
51 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
52 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
53 | SND_SOC_DAPM_MIC("DMIC2", NULL), | ||
54 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | ||
55 | }; | ||
56 | |||
57 | static const struct snd_soc_dapm_route skylake_rt286_map[] = { | ||
58 | /* speaker */ | ||
59 | {"Speaker", NULL, "SPOR"}, | ||
60 | {"Speaker", NULL, "SPOL"}, | ||
61 | |||
62 | /* HP jack connectors - unknown if we have jack deteck */ | ||
63 | {"Headphone Jack", NULL, "HPO Pin"}, | ||
64 | |||
65 | /* other jacks */ | ||
66 | {"MIC1", NULL, "Mic Jack"}, | ||
67 | |||
68 | /* digital mics */ | ||
69 | {"DMIC1 Pin", NULL, "DMIC2"}, | ||
70 | {"DMIC AIF", NULL, "SoC DMIC"}, | ||
71 | |||
72 | /* CODEC BE connections */ | ||
73 | { "AIF1 Playback", NULL, "ssp0 Tx"}, | ||
74 | { "ssp0 Tx", NULL, "codec0_out"}, | ||
75 | { "ssp0 Tx", NULL, "codec1_out"}, | ||
76 | |||
77 | { "codec0_in", NULL, "ssp0 Rx" }, | ||
78 | { "codec1_in", NULL, "ssp0 Rx" }, | ||
79 | { "ssp0 Rx", NULL, "AIF1 Capture" }, | ||
80 | |||
81 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | ||
82 | { "DMIC01 Rx", NULL, "Capture" }, | ||
83 | |||
84 | { "hif1", NULL, "iDisp Tx"}, | ||
85 | { "iDisp Tx", NULL, "iDisp_out"}, | ||
86 | |||
87 | }; | ||
88 | |||
89 | static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
90 | { | ||
91 | struct snd_soc_codec *codec = rtd->codec; | ||
92 | int ret; | ||
93 | |||
94 | ret = snd_soc_card_jack_new(rtd->card, "Headset", | ||
95 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
96 | &skylake_headset, | ||
97 | skylake_headset_pins, ARRAY_SIZE(skylake_headset_pins)); | ||
98 | |||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | rt286_mic_detect(codec, &skylake_headset); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | |||
108 | static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
109 | struct snd_pcm_hw_params *params) | ||
110 | { | ||
111 | struct snd_interval *rate = hw_param_interval(params, | ||
112 | SNDRV_PCM_HW_PARAM_RATE); | ||
113 | struct snd_interval *channels = hw_param_interval(params, | ||
114 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
115 | |||
116 | /* The output is 48KHz, stereo, 16bits */ | ||
117 | rate->min = rate->max = 48000; | ||
118 | channels->min = channels->max = 2; | ||
119 | params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int skylake_rt286_hw_params(struct snd_pcm_substream *substream, | ||
125 | struct snd_pcm_hw_params *params) | ||
126 | { | ||
127 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
128 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
129 | int ret; | ||
130 | |||
131 | ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, | ||
132 | SND_SOC_CLOCK_IN); | ||
133 | if (ret < 0) | ||
134 | dev_err(rtd->dev, "set codec sysclk failed: %d\n", ret); | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static struct snd_soc_ops skylake_rt286_ops = { | ||
140 | .hw_params = skylake_rt286_hw_params, | ||
141 | }; | ||
142 | |||
143 | /* skylake digital audio interface glue - connects codec <--> CPU */ | ||
144 | static struct snd_soc_dai_link skylake_rt286_dais[] = { | ||
145 | /* Front End DAI links */ | ||
146 | { | ||
147 | .name = "Skl Audio Port", | ||
148 | .stream_name = "Audio", | ||
149 | .cpu_dai_name = "System Pin", | ||
150 | .platform_name = "0000:00:1f.3", | ||
151 | .nonatomic = 1, | ||
152 | .dynamic = 1, | ||
153 | .codec_name = "snd-soc-dummy", | ||
154 | .codec_dai_name = "snd-soc-dummy-dai", | ||
155 | .trigger = { | ||
156 | SND_SOC_DPCM_TRIGGER_POST, | ||
157 | SND_SOC_DPCM_TRIGGER_POST | ||
158 | }, | ||
159 | .dpcm_playback = 1, | ||
160 | }, | ||
161 | { | ||
162 | .name = "Skl Audio Capture Port", | ||
163 | .stream_name = "Audio Record", | ||
164 | .cpu_dai_name = "System Pin", | ||
165 | .platform_name = "0000:00:1f.3", | ||
166 | .nonatomic = 1, | ||
167 | .dynamic = 1, | ||
168 | .codec_name = "snd-soc-dummy", | ||
169 | .codec_dai_name = "snd-soc-dummy-dai", | ||
170 | .trigger = { | ||
171 | SND_SOC_DPCM_TRIGGER_POST, | ||
172 | SND_SOC_DPCM_TRIGGER_POST | ||
173 | }, | ||
174 | .dpcm_capture = 1, | ||
175 | }, | ||
176 | { | ||
177 | .name = "Skl Audio Reference cap", | ||
178 | .stream_name = "refcap", | ||
179 | .cpu_dai_name = "Reference Pin", | ||
180 | .codec_name = "snd-soc-dummy", | ||
181 | .codec_dai_name = "snd-soc-dummy-dai", | ||
182 | .platform_name = "0000:00:1f.3", | ||
183 | .init = NULL, | ||
184 | .dpcm_capture = 1, | ||
185 | .ignore_suspend = 1, | ||
186 | .nonatomic = 1, | ||
187 | .dynamic = 1, | ||
188 | }, | ||
189 | |||
190 | /* Back End DAI links */ | ||
191 | { | ||
192 | /* SSP0 - Codec */ | ||
193 | .name = "SSP0-Codec", | ||
194 | .be_id = 0, | ||
195 | .cpu_dai_name = "SSP0 Pin", | ||
196 | .platform_name = "0000:00:1f.3", | ||
197 | .no_pcm = 1, | ||
198 | .codec_name = "i2c-INT343A:00", | ||
199 | .codec_dai_name = "rt286-aif1", | ||
200 | .init = skylake_rt286_codec_init, | ||
201 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
202 | SND_SOC_DAIFMT_NB_NF | | ||
203 | SND_SOC_DAIFMT_CBS_CFS, | ||
204 | .ignore_suspend = 1, | ||
205 | .ignore_pmdown_time = 1, | ||
206 | .be_hw_params_fixup = skylake_ssp0_fixup, | ||
207 | .ops = &skylake_rt286_ops, | ||
208 | .dpcm_playback = 1, | ||
209 | .dpcm_capture = 1, | ||
210 | }, | ||
211 | { | ||
212 | .name = "dmic01", | ||
213 | .be_id = 1, | ||
214 | .cpu_dai_name = "DMIC01 Pin", | ||
215 | .codec_name = "dmic-codec", | ||
216 | .codec_dai_name = "dmic-hifi", | ||
217 | .platform_name = "0000:00:1f.3", | ||
218 | .ignore_suspend = 1, | ||
219 | .dpcm_capture = 1, | ||
220 | .no_pcm = 1, | ||
221 | }, | ||
222 | }; | ||
223 | |||
224 | /* skylake audio machine driver for SPT + RT286S */ | ||
225 | static struct snd_soc_card skylake_rt286 = { | ||
226 | .name = "skylake-rt286", | ||
227 | .owner = THIS_MODULE, | ||
228 | .dai_link = skylake_rt286_dais, | ||
229 | .num_links = ARRAY_SIZE(skylake_rt286_dais), | ||
230 | .controls = skylake_controls, | ||
231 | .num_controls = ARRAY_SIZE(skylake_controls), | ||
232 | .dapm_widgets = skylake_widgets, | ||
233 | .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), | ||
234 | .dapm_routes = skylake_rt286_map, | ||
235 | .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map), | ||
236 | .fully_routed = true, | ||
237 | }; | ||
238 | |||
239 | static int skylake_audio_probe(struct platform_device *pdev) | ||
240 | { | ||
241 | skylake_rt286.dev = &pdev->dev; | ||
242 | |||
243 | return snd_soc_register_card(&skylake_rt286); | ||
244 | } | ||
245 | |||
246 | static int skylake_audio_remove(struct platform_device *pdev) | ||
247 | { | ||
248 | snd_soc_unregister_card(&skylake_rt286); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static struct platform_driver skylake_audio = { | ||
253 | .probe = skylake_audio_probe, | ||
254 | .remove = skylake_audio_remove, | ||
255 | .driver = { | ||
256 | .name = "skl_alc286s_i2s", | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | module_platform_driver(skylake_audio) | ||
261 | |||
262 | /* Module information */ | ||
263 | MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>"); | ||
264 | MODULE_DESCRIPTION("Intel SST Audio for Skylake"); | ||
265 | MODULE_LICENSE("GPL v2"); | ||
266 | MODULE_ALIAS("platform:skl_alc286s_i2s"); | ||