1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * zylonite.c -- SoC audio for Zylonite
5 * Copyright 2008 Wolfson Microelectronics PLC.
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/device.h>
12 #include <linux/clk.h>
13 #include <linux/i2c.h>
14 #include <sound/core.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/soc.h>
19 #include "../codecs/wm9713.h"
23 * There is a physical switch SW15 on the board which changes the MCLK
24 * for the WM9713 between the standard AC97 master clock and the
25 * output of the CLK_POUT signal from the PXA.
28 module_param(clk_pout
, int, 0);
29 MODULE_PARM_DESC(clk_pout
, "Use CLK_POUT as WM9713 MCLK (SW15 on board).");
31 static struct clk
*pout
;
33 static struct snd_soc_card zylonite
;
35 static const struct snd_soc_dapm_widget zylonite_dapm_widgets
[] = {
36 SND_SOC_DAPM_HP("Headphone", NULL
),
37 SND_SOC_DAPM_MIC("Headset Microphone", NULL
),
38 SND_SOC_DAPM_MIC("Handset Microphone", NULL
),
39 SND_SOC_DAPM_SPK("Multiactor", NULL
),
40 SND_SOC_DAPM_SPK("Headset Earpiece", NULL
),
43 /* Currently supported audio map */
44 static const struct snd_soc_dapm_route audio_map
[] = {
46 /* Headphone output connected to HPL/HPR */
47 { "Headphone", NULL
, "HPL" },
48 { "Headphone", NULL
, "HPR" },
50 /* On-board earpiece */
51 { "Headset Earpiece", NULL
, "OUT3" },
54 { "MIC2A", NULL
, "Mic Bias" },
55 { "Mic Bias", NULL
, "Headset Microphone" },
58 { "MIC1", NULL
, "Mic Bias" },
59 { "Mic Bias", NULL
, "Handset Microphone" },
61 /* Multiactor differentially connected over SPKL/SPKR */
62 { "Multiactor", NULL
, "SPKL" },
63 { "Multiactor", NULL
, "SPKR" },
66 static int zylonite_wm9713_init(struct snd_soc_pcm_runtime
*rtd
)
69 snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd
, 0), 0, 0,
70 clk_get_rate(pout
), 0);
75 static int zylonite_voice_hw_params(struct snd_pcm_substream
*substream
,
76 struct snd_pcm_hw_params
*params
)
78 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
79 struct snd_soc_dai
*codec_dai
= asoc_rtd_to_codec(rtd
, 0);
80 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
81 unsigned int wm9713_div
= 0;
83 int rate
= params_rate(params
);
85 /* Only support ratios that we can generate neatly from the AC97
86 * based master clock - in particular, this excludes 44.1kHz.
87 * In most applications the voice DAC will be used for telephony
88 * data so multiples of 8kHz will be the common case.
101 /* Don't support OSS emulation */
105 ret
= snd_soc_dai_set_sysclk(cpu_dai
, PXA_SSP_CLK_AUDIO
, 0, 1);
110 ret
= snd_soc_dai_set_clkdiv(codec_dai
, WM9713_PCMCLK_PLL_DIV
,
111 WM9713_PCMDIV(wm9713_div
));
113 ret
= snd_soc_dai_set_clkdiv(codec_dai
, WM9713_PCMCLK_DIV
,
114 WM9713_PCMDIV(wm9713_div
));
121 static const struct snd_soc_ops zylonite_voice_ops
= {
122 .hw_params
= zylonite_voice_hw_params
,
125 SND_SOC_DAILINK_DEFS(ac97
,
126 DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")),
127 DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-hifi")),
128 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
130 SND_SOC_DAILINK_DEFS(ac97_aux
,
131 DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")),
132 DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-aux")),
133 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
135 SND_SOC_DAILINK_DEFS(voice
,
136 DAILINK_COMP_ARRAY(COMP_CPU("pxa-ssp-dai.2")),
137 DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-voice")),
138 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
140 static struct snd_soc_dai_link zylonite_dai
[] = {
143 .stream_name
= "AC97 HiFi",
144 .init
= zylonite_wm9713_init
,
145 SND_SOC_DAILINK_REG(ac97
),
149 .stream_name
= "AC97 Aux",
150 SND_SOC_DAILINK_REG(ac97_aux
),
153 .name
= "WM9713 Voice",
154 .stream_name
= "WM9713 Voice",
155 .dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
|
156 SND_SOC_DAIFMT_CBS_CFS
,
157 .ops
= &zylonite_voice_ops
,
158 SND_SOC_DAILINK_REG(voice
),
162 static int zylonite_probe(struct snd_soc_card
*card
)
167 pout
= clk_get(NULL
, "CLK_POUT");
169 dev_err(card
->dev
, "Unable to obtain CLK_POUT: %ld\n",
171 return PTR_ERR(pout
);
174 ret
= clk_enable(pout
);
176 dev_err(card
->dev
, "Unable to enable CLK_POUT: %d\n",
182 dev_dbg(card
->dev
, "MCLK enabled at %luHz\n",
189 static int zylonite_remove(struct snd_soc_card
*card
)
199 static int zylonite_suspend_post(struct snd_soc_card
*card
)
207 static int zylonite_resume_pre(struct snd_soc_card
*card
)
212 ret
= clk_enable(pout
);
214 dev_err(card
->dev
, "Unable to enable CLK_POUT: %d\n",
221 static struct snd_soc_card zylonite
= {
223 .owner
= THIS_MODULE
,
224 .probe
= &zylonite_probe
,
225 .remove
= &zylonite_remove
,
226 .suspend_post
= &zylonite_suspend_post
,
227 .resume_pre
= &zylonite_resume_pre
,
228 .dai_link
= zylonite_dai
,
229 .num_links
= ARRAY_SIZE(zylonite_dai
),
231 .dapm_widgets
= zylonite_dapm_widgets
,
232 .num_dapm_widgets
= ARRAY_SIZE(zylonite_dapm_widgets
),
233 .dapm_routes
= audio_map
,
234 .num_dapm_routes
= ARRAY_SIZE(audio_map
),
237 static struct platform_device
*zylonite_snd_ac97_device
;
239 static int __init
zylonite_init(void)
243 zylonite_snd_ac97_device
= platform_device_alloc("soc-audio", -1);
244 if (!zylonite_snd_ac97_device
)
247 platform_set_drvdata(zylonite_snd_ac97_device
, &zylonite
);
249 ret
= platform_device_add(zylonite_snd_ac97_device
);
251 platform_device_put(zylonite_snd_ac97_device
);
256 static void __exit
zylonite_exit(void)
258 platform_device_unregister(zylonite_snd_ac97_device
);
261 module_init(zylonite_init
);
262 module_exit(zylonite_exit
);
264 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
265 MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
266 MODULE_LICENSE("GPL");