diff options
author | Hui Wang <hui.wang@canonical.com> | 2018-12-13 08:02:16 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-12-13 09:37:35 -0500 |
commit | 8625db9416923b2941ef68776f55062555f7ce65 (patch) | |
tree | 427dba34f2881e070e38f2e46fcb135e8749fee6 /sound | |
parent | 8fe8915b6c0b5298fa547be21957b3860c39c46e (diff) |
ASoC: Intel: kbl_rt5660: Add a new machine driver for kbl with rt5660
The new Dell IoT platform uses kabylake + alc3277 codec, and alc3277
shares the driver with the codec rt5660, here we generate a new
machine driver based on kbl_da7219_max98357a.
The audio design on this IoT platform is as below:
- Intel kabylake platform
- connect the codec ALC3277 via SSP0
- line-out and line-in with Micbias jacks
- line-out mute control and jack detection of line-out and line-in
- two HDMI ports with audio capability
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/intel/boards/Kconfig | 10 | ||||
-rw-r--r-- | sound/soc/intel/boards/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/intel/boards/kbl_rt5660.c | 543 | ||||
-rw-r--r-- | sound/soc/intel/common/soc-acpi-intel-kbl-match.c | 10 |
4 files changed, 565 insertions, 0 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index b177db2a0dbb..3839d6205fcf 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig | |||
@@ -293,6 +293,16 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH | |||
293 | Say Y if you have such a device. | 293 | Say Y if you have such a device. |
294 | If unsure select "N". | 294 | If unsure select "N". |
295 | 295 | ||
296 | config SND_SOC_INTEL_KBL_RT5660_MACH | ||
297 | tristate "KBL with RT5660 in I2S Mode" | ||
298 | depends on MFD_INTEL_LPSS && I2C && ACPI | ||
299 | select SND_SOC_RT5660 | ||
300 | select SND_SOC_HDAC_HDMI | ||
301 | help | ||
302 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
303 | create an alsa sound card for RT5660 I2S audio codec. | ||
304 | Say Y if you have such a device. | ||
305 | |||
296 | config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH | 306 | config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH |
297 | tristate "GLK with RT5682 and MAX98357A in I2S Mode" | 307 | tristate "GLK with RT5682 and MAX98357A in I2S Mode" |
298 | depends on MFD_INTEL_LPSS && I2C && ACPI | 308 | depends on MFD_INTEL_LPSS && I2C && ACPI |
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 5381e27df9cc..bf072ea299b7 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
@@ -20,6 +20,7 @@ snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o | |||
20 | snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o | 20 | snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o |
21 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o | 21 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o |
22 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o | 22 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o |
23 | snd-soc-kbl_rt5660-objs := kbl_rt5660.o | ||
23 | snd-soc-skl_rt286-objs := skl_rt286.o | 24 | snd-soc-skl_rt286-objs := skl_rt286.o |
24 | snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o | 25 | snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o |
25 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o | 26 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o |
@@ -46,6 +47,7 @@ obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH) += snd-soc-kbl_da7219_max9 | |||
46 | obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH) += snd-soc-kbl_da7219_max98927.o | 47 | obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH) += snd-soc-kbl_da7219_max98927.o |
47 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o | 48 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o |
48 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o | 49 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o |
50 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH) += snd-soc-kbl_rt5660.o | ||
49 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o | 51 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o |
50 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o | 52 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o |
51 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o | 53 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o |
diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c new file mode 100644 index 000000000000..3255e0029276 --- /dev/null +++ b/sound/soc/intel/boards/kbl_rt5660.c | |||
@@ -0,0 +1,543 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright(c) 2018-19 Canonical Corporation. | ||
3 | |||
4 | /* | ||
5 | * Intel Kabylake I2S Machine Driver with RT5660 Codec | ||
6 | * | ||
7 | * Modified from: | ||
8 | * Intel Kabylake I2S Machine driver supporting MAXIM98357a and | ||
9 | * DA7219 codecs | ||
10 | * Also referred to: | ||
11 | * Intel Broadwell I2S Machine driver supporting RT5677 codec | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/gpio/consumer.h> | ||
17 | #include <linux/acpi.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/jack.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | #include <sound/soc.h> | ||
23 | |||
24 | #include "../../codecs/hdac_hdmi.h" | ||
25 | #include "../../codecs/rt5660.h" | ||
26 | |||
27 | #define KBL_RT5660_CODEC_DAI "rt5660-aif1" | ||
28 | #define DUAL_CHANNEL 2 | ||
29 | |||
30 | static struct snd_soc_card *kabylake_audio_card; | ||
31 | static struct snd_soc_jack skylake_hdmi[3]; | ||
32 | static struct snd_soc_jack lineout_jack; | ||
33 | static struct snd_soc_jack mic_jack; | ||
34 | |||
35 | struct kbl_hdmi_pcm { | ||
36 | struct list_head head; | ||
37 | struct snd_soc_dai *codec_dai; | ||
38 | int device; | ||
39 | }; | ||
40 | |||
41 | struct kbl_codec_private { | ||
42 | struct gpio_desc *gpio_lo_mute; | ||
43 | struct list_head hdmi_pcm_list; | ||
44 | }; | ||
45 | |||
46 | enum { | ||
47 | KBL_DPCM_AUDIO_PB = 0, | ||
48 | KBL_DPCM_AUDIO_CP, | ||
49 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
50 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
51 | KBL_DPCM_AUDIO_HDMI3_PB, | ||
52 | }; | ||
53 | |||
54 | #define GPIO_LINEOUT_MUTE_INDEX 0 | ||
55 | #define GPIO_LINEOUT_DET_INDEX 3 | ||
56 | #define GPIO_LINEIN_DET_INDEX 4 | ||
57 | |||
58 | static const struct acpi_gpio_params lineout_mute_gpio = { GPIO_LINEOUT_MUTE_INDEX, 0, true }; | ||
59 | static const struct acpi_gpio_params lineout_det_gpio = { GPIO_LINEOUT_DET_INDEX, 0, false }; | ||
60 | static const struct acpi_gpio_params mic_det_gpio = { GPIO_LINEIN_DET_INDEX, 0, false }; | ||
61 | |||
62 | |||
63 | static const struct acpi_gpio_mapping acpi_rt5660_gpios[] = { | ||
64 | { "lineout-mute-gpios", &lineout_mute_gpio, 1 }, | ||
65 | { "lineout-det-gpios", &lineout_det_gpio, 1 }, | ||
66 | { "mic-det-gpios", &mic_det_gpio, 1 }, | ||
67 | { NULL }, | ||
68 | }; | ||
69 | |||
70 | static struct snd_soc_jack_pin lineout_jack_pin = { | ||
71 | .pin = "Line Out", | ||
72 | .mask = SND_JACK_LINEOUT, | ||
73 | }; | ||
74 | |||
75 | static struct snd_soc_jack_pin mic_jack_pin = { | ||
76 | .pin = "Line In", | ||
77 | .mask = SND_JACK_MICROPHONE, | ||
78 | }; | ||
79 | |||
80 | static struct snd_soc_jack_gpio lineout_jack_gpio = { | ||
81 | .name = "lineout-det", | ||
82 | .report = SND_JACK_LINEOUT, | ||
83 | .debounce_time = 200, | ||
84 | }; | ||
85 | |||
86 | static struct snd_soc_jack_gpio mic_jack_gpio = { | ||
87 | .name = "mic-det", | ||
88 | .report = SND_JACK_MICROPHONE, | ||
89 | .debounce_time = 200, | ||
90 | }; | ||
91 | |||
92 | static int kabylake_5660_event_lineout(struct snd_soc_dapm_widget *w, | ||
93 | struct snd_kcontrol *k, int event) | ||
94 | { | ||
95 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
96 | struct kbl_codec_private *priv = snd_soc_card_get_drvdata(dapm->card); | ||
97 | |||
98 | gpiod_set_value_cansleep(priv->gpio_lo_mute, | ||
99 | !(SND_SOC_DAPM_EVENT_ON(event))); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static const struct snd_kcontrol_new kabylake_rt5660_controls[] = { | ||
105 | SOC_DAPM_PIN_SWITCH("Line In"), | ||
106 | SOC_DAPM_PIN_SWITCH("Line Out"), | ||
107 | }; | ||
108 | |||
109 | static const struct snd_soc_dapm_widget kabylake_rt5660_widgets[] = { | ||
110 | SND_SOC_DAPM_MIC("Line In", NULL), | ||
111 | SND_SOC_DAPM_LINE("Line Out", kabylake_5660_event_lineout), | ||
112 | }; | ||
113 | |||
114 | static const struct snd_soc_dapm_route kabylake_rt5660_map[] = { | ||
115 | /* other jacks */ | ||
116 | {"IN1P", NULL, "Line In"}, | ||
117 | {"IN2P", NULL, "Line In"}, | ||
118 | {"Line Out", NULL, "LOUTR"}, | ||
119 | {"Line Out", NULL, "LOUTL"}, | ||
120 | |||
121 | /* CODEC BE connections */ | ||
122 | { "AIF1 Playback", NULL, "ssp0 Tx"}, | ||
123 | { "ssp0 Tx", NULL, "codec0_out"}, | ||
124 | |||
125 | { "codec0_in", NULL, "ssp0 Rx" }, | ||
126 | { "ssp0 Rx", NULL, "AIF1 Capture" }, | ||
127 | |||
128 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
129 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
130 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
131 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
132 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
133 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
134 | }; | ||
135 | |||
136 | static int kabylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
137 | struct snd_pcm_hw_params *params) | ||
138 | { | ||
139 | struct snd_interval *rate = hw_param_interval(params, | ||
140 | SNDRV_PCM_HW_PARAM_RATE); | ||
141 | struct snd_interval *channels = hw_param_interval(params, | ||
142 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
143 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
144 | |||
145 | /* The ADSP will convert the FE rate to 48k, stereo */ | ||
146 | rate->min = rate->max = 48000; | ||
147 | channels->min = channels->max = DUAL_CHANNEL; | ||
148 | |||
149 | /* set SSP0 to 24 bit */ | ||
150 | snd_mask_none(fmt); | ||
151 | snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
157 | { | ||
158 | int ret; | ||
159 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
160 | struct snd_soc_component *component = rtd->codec_dai->component; | ||
161 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); | ||
162 | |||
163 | ret = devm_acpi_dev_add_driver_gpios(component->dev, acpi_rt5660_gpios); | ||
164 | if (ret) | ||
165 | dev_warn(component->dev, "Failed to add driver gpios\n"); | ||
166 | |||
167 | /* Request rt5660 GPIO for lineout mute control, return if fails */ | ||
168 | ctx->gpio_lo_mute = devm_gpiod_get(component->dev, "lineout-mute", | ||
169 | GPIOD_OUT_HIGH); | ||
170 | if (IS_ERR(ctx->gpio_lo_mute)) { | ||
171 | dev_err(component->dev, "Can't find GPIO_MUTE# gpio\n"); | ||
172 | return PTR_ERR(ctx->gpio_lo_mute); | ||
173 | } | ||
174 | |||
175 | /* Create and initialize headphone jack, this jack is not mandatory, don't return if fails */ | ||
176 | ret = snd_soc_card_jack_new(rtd->card, "Lineout Jack", | ||
177 | SND_JACK_LINEOUT, &lineout_jack, | ||
178 | &lineout_jack_pin, 1); | ||
179 | if (ret) | ||
180 | dev_warn(component->dev, "Can't create Lineout jack\n"); | ||
181 | else { | ||
182 | lineout_jack_gpio.gpiod_dev = component->dev; | ||
183 | ret = snd_soc_jack_add_gpios(&lineout_jack, 1, | ||
184 | &lineout_jack_gpio); | ||
185 | if (ret) | ||
186 | dev_warn(component->dev, "Can't add Lineout jack gpio\n"); | ||
187 | } | ||
188 | |||
189 | /* Create and initialize mic jack, this jack is not mandatory, don't return if fails */ | ||
190 | ret = snd_soc_card_jack_new(rtd->card, "Mic Jack", | ||
191 | SND_JACK_MICROPHONE, &mic_jack, | ||
192 | &mic_jack_pin, 1); | ||
193 | if (ret) | ||
194 | dev_warn(component->dev, "Can't create mic jack\n"); | ||
195 | else { | ||
196 | mic_jack_gpio.gpiod_dev = component->dev; | ||
197 | ret = snd_soc_jack_add_gpios(&mic_jack, 1, &mic_jack_gpio); | ||
198 | if (ret) | ||
199 | dev_warn(component->dev, "Can't add mic jack gpio\n"); | ||
200 | } | ||
201 | |||
202 | /* Here we enable some dapms in advance to reduce the pop noise for recording via line-in */ | ||
203 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); | ||
204 | snd_soc_dapm_force_enable_pin(dapm, "BST1"); | ||
205 | snd_soc_dapm_force_enable_pin(dapm, "BST2"); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) | ||
211 | { | ||
212 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
213 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
214 | struct kbl_hdmi_pcm *pcm; | ||
215 | |||
216 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
217 | if (!pcm) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | pcm->device = device; | ||
221 | pcm->codec_dai = dai; | ||
222 | |||
223 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
229 | { | ||
230 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); | ||
231 | } | ||
232 | |||
233 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
234 | { | ||
235 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); | ||
236 | } | ||
237 | |||
238 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) | ||
239 | { | ||
240 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); | ||
241 | } | ||
242 | |||
243 | static int kabylake_rt5660_hw_params(struct snd_pcm_substream *substream, | ||
244 | struct snd_pcm_hw_params *params) | ||
245 | { | ||
246 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
247 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
248 | int ret; | ||
249 | |||
250 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
251 | RT5660_SCLK_S_PLL1, params_rate(params) * 512, | ||
252 | SND_SOC_CLOCK_IN); | ||
253 | if (ret < 0) { | ||
254 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | ret = snd_soc_dai_set_pll(codec_dai, 0, | ||
259 | RT5660_PLL1_S_BCLK, | ||
260 | params_rate(params) * 50, | ||
261 | params_rate(params) * 512); | ||
262 | if (ret < 0) | ||
263 | dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static struct snd_soc_ops kabylake_rt5660_ops = { | ||
269 | .hw_params = kabylake_rt5660_hw_params, | ||
270 | }; | ||
271 | |||
272 | static const unsigned int rates[] = { | ||
273 | 48000, | ||
274 | }; | ||
275 | |||
276 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | ||
277 | .count = ARRAY_SIZE(rates), | ||
278 | .list = rates, | ||
279 | .mask = 0, | ||
280 | }; | ||
281 | |||
282 | static const unsigned int channels[] = { | ||
283 | DUAL_CHANNEL, | ||
284 | }; | ||
285 | |||
286 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | ||
287 | .count = ARRAY_SIZE(channels), | ||
288 | .list = channels, | ||
289 | .mask = 0, | ||
290 | }; | ||
291 | |||
292 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
293 | { | ||
294 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
295 | |||
296 | /* | ||
297 | * On this platform for PCM device we support, | ||
298 | * 48Khz | ||
299 | * stereo | ||
300 | * 16 bit audio | ||
301 | */ | ||
302 | |||
303 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
304 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
305 | &constraints_channels); | ||
306 | |||
307 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
308 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
309 | |||
310 | snd_pcm_hw_constraint_list(runtime, 0, | ||
311 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static const struct snd_soc_ops kabylake_rt5660_fe_ops = { | ||
317 | .startup = kbl_fe_startup, | ||
318 | }; | ||
319 | |||
320 | /* kabylake digital audio interface glue - connects rt5660 codec <--> CPU */ | ||
321 | static struct snd_soc_dai_link kabylake_rt5660_dais[] = { | ||
322 | /* Front End DAI links */ | ||
323 | [KBL_DPCM_AUDIO_PB] = { | ||
324 | .name = "Kbl Audio Port", | ||
325 | .stream_name = "Audio", | ||
326 | .cpu_dai_name = "System Pin", | ||
327 | .platform_name = "0000:00:1f.3", | ||
328 | .dynamic = 1, | ||
329 | .codec_name = "snd-soc-dummy", | ||
330 | .codec_dai_name = "snd-soc-dummy-dai", | ||
331 | .nonatomic = 1, | ||
332 | .trigger = { | ||
333 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
334 | .dpcm_playback = 1, | ||
335 | .ops = &kabylake_rt5660_fe_ops, | ||
336 | }, | ||
337 | [KBL_DPCM_AUDIO_CP] = { | ||
338 | .name = "Kbl Audio Capture Port", | ||
339 | .stream_name = "Audio Record", | ||
340 | .cpu_dai_name = "System Pin", | ||
341 | .platform_name = "0000:00:1f.3", | ||
342 | .dynamic = 1, | ||
343 | .codec_name = "snd-soc-dummy", | ||
344 | .codec_dai_name = "snd-soc-dummy-dai", | ||
345 | .nonatomic = 1, | ||
346 | .trigger = { | ||
347 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
348 | .dpcm_capture = 1, | ||
349 | .ops = &kabylake_rt5660_fe_ops, | ||
350 | }, | ||
351 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
352 | .name = "Kbl HDMI Port1", | ||
353 | .stream_name = "Hdmi1", | ||
354 | .cpu_dai_name = "HDMI1 Pin", | ||
355 | .codec_name = "snd-soc-dummy", | ||
356 | .codec_dai_name = "snd-soc-dummy-dai", | ||
357 | .platform_name = "0000:00:1f.3", | ||
358 | .dpcm_playback = 1, | ||
359 | .init = NULL, | ||
360 | .trigger = { | ||
361 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
362 | .nonatomic = 1, | ||
363 | .dynamic = 1, | ||
364 | }, | ||
365 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
366 | .name = "Kbl HDMI Port2", | ||
367 | .stream_name = "Hdmi2", | ||
368 | .cpu_dai_name = "HDMI2 Pin", | ||
369 | .codec_name = "snd-soc-dummy", | ||
370 | .codec_dai_name = "snd-soc-dummy-dai", | ||
371 | .platform_name = "0000:00:1f.3", | ||
372 | .dpcm_playback = 1, | ||
373 | .init = NULL, | ||
374 | .trigger = { | ||
375 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
376 | .nonatomic = 1, | ||
377 | .dynamic = 1, | ||
378 | }, | ||
379 | [KBL_DPCM_AUDIO_HDMI3_PB] = { | ||
380 | .name = "Kbl HDMI Port3", | ||
381 | .stream_name = "Hdmi3", | ||
382 | .cpu_dai_name = "HDMI3 Pin", | ||
383 | .codec_name = "snd-soc-dummy", | ||
384 | .codec_dai_name = "snd-soc-dummy-dai", | ||
385 | .platform_name = "0000:00:1f.3", | ||
386 | .trigger = { | ||
387 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
388 | .dpcm_playback = 1, | ||
389 | .init = NULL, | ||
390 | .nonatomic = 1, | ||
391 | .dynamic = 1, | ||
392 | }, | ||
393 | |||
394 | /* Back End DAI links */ | ||
395 | { | ||
396 | /* SSP0 - Codec */ | ||
397 | .name = "SSP0-Codec", | ||
398 | .id = 0, | ||
399 | .cpu_dai_name = "SSP0 Pin", | ||
400 | .platform_name = "0000:00:1f.3", | ||
401 | .no_pcm = 1, | ||
402 | .codec_name = "i2c-10EC3277:00", | ||
403 | .codec_dai_name = KBL_RT5660_CODEC_DAI, | ||
404 | .init = kabylake_rt5660_codec_init, | ||
405 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
406 | SND_SOC_DAIFMT_NB_NF | | ||
407 | SND_SOC_DAIFMT_CBS_CFS, | ||
408 | .ignore_pmdown_time = 1, | ||
409 | .be_hw_params_fixup = kabylake_ssp0_fixup, | ||
410 | .ops = &kabylake_rt5660_ops, | ||
411 | .dpcm_playback = 1, | ||
412 | .dpcm_capture = 1, | ||
413 | }, | ||
414 | { | ||
415 | .name = "iDisp1", | ||
416 | .id = 1, | ||
417 | .cpu_dai_name = "iDisp1 Pin", | ||
418 | .codec_name = "ehdaudio0D2", | ||
419 | .codec_dai_name = "intel-hdmi-hifi1", | ||
420 | .platform_name = "0000:00:1f.3", | ||
421 | .dpcm_playback = 1, | ||
422 | .init = kabylake_hdmi1_init, | ||
423 | .no_pcm = 1, | ||
424 | }, | ||
425 | { | ||
426 | .name = "iDisp2", | ||
427 | .id = 2, | ||
428 | .cpu_dai_name = "iDisp2 Pin", | ||
429 | .codec_name = "ehdaudio0D2", | ||
430 | .codec_dai_name = "intel-hdmi-hifi2", | ||
431 | .platform_name = "0000:00:1f.3", | ||
432 | .init = kabylake_hdmi2_init, | ||
433 | .dpcm_playback = 1, | ||
434 | .no_pcm = 1, | ||
435 | }, | ||
436 | { | ||
437 | .name = "iDisp3", | ||
438 | .id = 3, | ||
439 | .cpu_dai_name = "iDisp3 Pin", | ||
440 | .codec_name = "ehdaudio0D2", | ||
441 | .codec_dai_name = "intel-hdmi-hifi3", | ||
442 | .platform_name = "0000:00:1f.3", | ||
443 | .init = kabylake_hdmi3_init, | ||
444 | .dpcm_playback = 1, | ||
445 | .no_pcm = 1, | ||
446 | }, | ||
447 | }; | ||
448 | |||
449 | |||
450 | #define NAME_SIZE 32 | ||
451 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
452 | { | ||
453 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); | ||
454 | struct kbl_hdmi_pcm *pcm; | ||
455 | struct snd_soc_component *component = NULL; | ||
456 | int err, i = 0; | ||
457 | char jack_name[NAME_SIZE]; | ||
458 | |||
459 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
460 | component = pcm->codec_dai->component; | ||
461 | snprintf(jack_name, sizeof(jack_name), | ||
462 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
463 | err = snd_soc_card_jack_new(card, jack_name, | ||
464 | SND_JACK_AVOUT, &skylake_hdmi[i], | ||
465 | NULL, 0); | ||
466 | |||
467 | if (err) | ||
468 | return err; | ||
469 | |||
470 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
471 | &skylake_hdmi[i]); | ||
472 | if (err < 0) | ||
473 | return err; | ||
474 | |||
475 | i++; | ||
476 | |||
477 | } | ||
478 | |||
479 | if (!component) | ||
480 | return -EINVAL; | ||
481 | |||
482 | return hdac_hdmi_jack_port_init(component, &card->dapm); | ||
483 | } | ||
484 | |||
485 | /* kabylake audio machine driver for rt5660 */ | ||
486 | static struct snd_soc_card kabylake_audio_card_rt5660 = { | ||
487 | .name = "kblrt5660", | ||
488 | .owner = THIS_MODULE, | ||
489 | .dai_link = kabylake_rt5660_dais, | ||
490 | .num_links = ARRAY_SIZE(kabylake_rt5660_dais), | ||
491 | .controls = kabylake_rt5660_controls, | ||
492 | .num_controls = ARRAY_SIZE(kabylake_rt5660_controls), | ||
493 | .dapm_widgets = kabylake_rt5660_widgets, | ||
494 | .num_dapm_widgets = ARRAY_SIZE(kabylake_rt5660_widgets), | ||
495 | .dapm_routes = kabylake_rt5660_map, | ||
496 | .num_dapm_routes = ARRAY_SIZE(kabylake_rt5660_map), | ||
497 | .fully_routed = true, | ||
498 | .late_probe = kabylake_card_late_probe, | ||
499 | }; | ||
500 | |||
501 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
502 | { | ||
503 | struct kbl_codec_private *ctx; | ||
504 | |||
505 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | ||
506 | if (!ctx) | ||
507 | return -ENOMEM; | ||
508 | |||
509 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
510 | |||
511 | kabylake_audio_card = | ||
512 | (struct snd_soc_card *)pdev->id_entry->driver_data; | ||
513 | |||
514 | kabylake_audio_card->dev = &pdev->dev; | ||
515 | snd_soc_card_set_drvdata(kabylake_audio_card, ctx); | ||
516 | return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); | ||
517 | } | ||
518 | |||
519 | static const struct platform_device_id kbl_board_ids[] = { | ||
520 | { | ||
521 | .name = "kbl_rt5660", | ||
522 | .driver_data = | ||
523 | (kernel_ulong_t)&kabylake_audio_card_rt5660, | ||
524 | }, | ||
525 | { } | ||
526 | }; | ||
527 | |||
528 | static struct platform_driver kabylake_audio = { | ||
529 | .probe = kabylake_audio_probe, | ||
530 | .driver = { | ||
531 | .name = "kbl_rt5660", | ||
532 | .pm = &snd_soc_pm_ops, | ||
533 | }, | ||
534 | .id_table = kbl_board_ids, | ||
535 | }; | ||
536 | |||
537 | module_platform_driver(kabylake_audio) | ||
538 | |||
539 | /* Module information */ | ||
540 | MODULE_DESCRIPTION("Audio Machine driver-RT5660 in I2S mode"); | ||
541 | MODULE_AUTHOR("Hui Wang <hui.wang@canonical.com>"); | ||
542 | MODULE_LICENSE("GPL v2"); | ||
543 | MODULE_ALIAS("platform:kbl_rt5660"); | ||
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index a317b7790fce..e6fa6f470526 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c | |||
@@ -96,6 +96,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { | |||
96 | .quirk_data = &kbl_7219_98927_codecs, | 96 | .quirk_data = &kbl_7219_98927_codecs, |
97 | .pdata = &skl_dmic_data | 97 | .pdata = &skl_dmic_data |
98 | }, | 98 | }, |
99 | { | ||
100 | .id = "10EC5660", | ||
101 | .drv_name = "kbl_rt5660", | ||
102 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
103 | }, | ||
104 | { | ||
105 | .id = "10EC3277", | ||
106 | .drv_name = "kbl_rt5660", | ||
107 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
108 | }, | ||
99 | {}, | 109 | {}, |
100 | }; | 110 | }; |
101 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines); | 111 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines); |