diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-16 11:35:52 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-19 11:15:35 -0500 |
commit | 2c782f5981a022f7a238d550af5daa75c8acf382 (patch) | |
tree | 53e44b9e096e31634f45bb1b119bbad9d9d0ef1e /sound/soc/pxa/zylonite.c | |
parent | c42f69bb064333624dcc1452ed109441c3c9e7b4 (diff) |
ASoC: Implement support for CLK_POUT as MCLK on Zylonite
The Zylonite supports switching the MCLK for the WM9713 between the
AC97CLK and CLK_POUT outputs of the PXA processor via switch SW15 on
the board. This patch adds support for configuring the system to use
CLK_POUT.
Unfortunately it is not possible to read the state of SW15 from software
so this feature is controlled by a module option 'clk_pout' which should
be set to a non-zero value to enable the use of CLK_POUT.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/pxa/zylonite.c')
-rw-r--r-- | sound/soc/pxa/zylonite.c | 101 |
1 files changed, 84 insertions, 17 deletions
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd589d3..8541b679f6eb 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
@@ -26,6 +27,17 @@ | |||
26 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
27 | #include "pxa-ssp.h" | 28 | #include "pxa-ssp.h" |
28 | 29 | ||
30 | /* | ||
31 | * There is a physical switch SW15 on the board which changes the MCLK | ||
32 | * for the WM9713 between the standard AC97 master clock and the | ||
33 | * output of the CLK_POUT signal from the PXA. | ||
34 | */ | ||
35 | static int clk_pout; | ||
36 | module_param(clk_pout, int, 0); | ||
37 | MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); | ||
38 | |||
39 | static struct clk *pout; | ||
40 | |||
29 | static struct snd_soc_card zylonite; | 41 | static struct snd_soc_card zylonite; |
30 | 42 | ||
31 | static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { | 43 | static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { |
@@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
61 | 73 | ||
62 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) | 74 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) |
63 | { | 75 | { |
64 | /* Currently we only support use of the AC97 clock here. If | 76 | if (clk_pout) |
65 | * CLK_POUT is selected by SW15 then the clock API will need | 77 | snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); |
66 | * to be used to request and enable it here. | ||
67 | */ | ||
68 | 78 | ||
69 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, | 79 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, |
70 | ARRAY_SIZE(zylonite_dapm_widgets)); | 80 | ARRAY_SIZE(zylonite_dapm_widgets)); |
@@ -85,7 +95,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
85 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
86 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
87 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 97 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
88 | unsigned int pll_out = 0; | ||
89 | unsigned int acds = 0; | 98 | unsigned int acds = 0; |
90 | unsigned int wm9713_div = 0; | 99 | unsigned int wm9713_div = 0; |
91 | int ret = 0; | 100 | int ret = 0; |
@@ -93,16 +102,13 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
93 | switch (params_rate(params)) { | 102 | switch (params_rate(params)) { |
94 | case 8000: | 103 | case 8000: |
95 | wm9713_div = 12; | 104 | wm9713_div = 12; |
96 | pll_out = 2048000; | ||
97 | break; | 105 | break; |
98 | case 16000: | 106 | case 16000: |
99 | wm9713_div = 6; | 107 | wm9713_div = 6; |
100 | pll_out = 4096000; | ||
101 | break; | 108 | break; |
102 | case 48000: | 109 | case 48000: |
103 | default: | 110 | default: |
104 | wm9713_div = 2; | 111 | wm9713_div = 2; |
105 | pll_out = 12288000; | ||
106 | acds = 1; | 112 | acds = 1; |
107 | break; | 113 | break; |
108 | } | 114 | } |
@@ -123,10 +129,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
123 | if (ret < 0) | 129 | if (ret < 0) |
124 | return ret; | 130 | return ret; |
125 | 131 | ||
126 | ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); | ||
127 | if (ret < 0) | ||
128 | return ret; | ||
129 | |||
130 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); | 132 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); |
131 | if (ret < 0) | 133 | if (ret < 0) |
132 | return ret; | 134 | return ret; |
@@ -135,11 +137,12 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
135 | if (ret < 0) | 137 | if (ret < 0) |
136 | return ret; | 138 | return ret; |
137 | 139 | ||
138 | /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs | 140 | if (clk_pout) |
139 | * to be set instead. | 141 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, |
140 | */ | 142 | WM9713_PCMDIV(wm9713_div)); |
141 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | 143 | else |
142 | WM9713_PCMDIV(wm9713_div)); | 144 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, |
145 | WM9713_PCMDIV(wm9713_div)); | ||
143 | if (ret < 0) | 146 | if (ret < 0) |
144 | return ret; | 147 | return ret; |
145 | 148 | ||
@@ -173,8 +176,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
173 | }, | 176 | }, |
174 | }; | 177 | }; |
175 | 178 | ||
179 | static int zylonite_probe(struct platform_device *pdev) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | if (clk_pout) { | ||
184 | pout = clk_get(NULL, "CLK_POUT"); | ||
185 | if (IS_ERR(pout)) { | ||
186 | dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", | ||
187 | PTR_ERR(pout)); | ||
188 | return PTR_ERR(pout); | ||
189 | } | ||
190 | |||
191 | ret = clk_enable(pout); | ||
192 | if (ret != 0) { | ||
193 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
194 | ret); | ||
195 | clk_put(pout); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", | ||
200 | clk_get_rate(pout)); | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int zylonite_remove(struct platform_device *pdev) | ||
207 | { | ||
208 | if (clk_pout) { | ||
209 | clk_disable(pout); | ||
210 | clk_put(pout); | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int zylonite_suspend_post(struct platform_device *pdev, | ||
217 | pm_message_t state) | ||
218 | { | ||
219 | if (clk_pout) | ||
220 | clk_disable(pout); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int zylonite_resume_pre(struct platform_device *pdev) | ||
226 | { | ||
227 | int ret = 0; | ||
228 | |||
229 | if (clk_pout) { | ||
230 | ret = clk_enable(pout); | ||
231 | if (ret != 0) | ||
232 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
233 | ret); | ||
234 | } | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
176 | static struct snd_soc_card zylonite = { | 239 | static struct snd_soc_card zylonite = { |
177 | .name = "Zylonite", | 240 | .name = "Zylonite", |
241 | .probe = &zylonite_probe, | ||
242 | .remove = &zylonite_remove, | ||
243 | .suspend_post = &zylonite_suspend_post, | ||
244 | .resume_pre = &zylonite_resume_pre, | ||
178 | .platform = &pxa2xx_soc_platform, | 245 | .platform = &pxa2xx_soc_platform, |
179 | .dai_link = zylonite_dai, | 246 | .dai_link = zylonite_dai, |
180 | .num_links = ARRAY_SIZE(zylonite_dai), | 247 | .num_links = ARRAY_SIZE(zylonite_dai), |