aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/zylonite.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-16 11:35:52 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-19 11:15:35 -0500
commit2c782f5981a022f7a238d550af5daa75c8acf382 (patch)
tree53e44b9e096e31634f45bb1b119bbad9d9d0ef1e /sound/soc/pxa/zylonite.c
parentc42f69bb064333624dcc1452ed109441c3c9e7b4 (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.c101
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 */
35static int clk_pout;
36module_param(clk_pout, int, 0);
37MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board).");
38
39static struct clk *pout;
40
29static struct snd_soc_card zylonite; 41static struct snd_soc_card zylonite;
30 42
31static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { 43static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
@@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
61 73
62static int zylonite_wm9713_init(struct snd_soc_codec *codec) 74static 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
179static 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
206static 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
216static 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
225static 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
176static struct snd_soc_card zylonite = { 239static 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),