diff options
author | James Morris <jmorris@namei.org> | 2009-03-26 17:28:11 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-03-26 17:28:11 -0400 |
commit | 1987f17d2266e882862528841429b5bf67bc8fe5 (patch) | |
tree | 5c3fbee88018ab7259a18c10e6320e575d0ed679 /sound/soc/pxa/zylonite.c | |
parent | 7198e2eeb44b3fe7cc97f997824002da47a9c644 (diff) | |
parent | 0384e2959127a56d0640505d004d8dd92f9c29f5 (diff) |
Merge branch 'master' into next
Diffstat (limited to 'sound/soc/pxa/zylonite.c')
-rw-r--r-- | sound/soc/pxa/zylonite.c | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd589d3..9a386b4c4ed1 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)); |
@@ -86,40 +96,35 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
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; | 98 | unsigned int pll_out = 0; |
89 | unsigned int acds = 0; | ||
90 | unsigned int wm9713_div = 0; | 99 | unsigned int wm9713_div = 0; |
91 | int ret = 0; | 100 | int ret = 0; |
101 | int rate = params_rate(params); | ||
102 | int width = snd_pcm_format_physical_width(params_format(params)); | ||
92 | 103 | ||
93 | switch (params_rate(params)) { | 104 | /* Only support ratios that we can generate neatly from the AC97 |
105 | * based master clock - in particular, this excludes 44.1kHz. | ||
106 | * In most applications the voice DAC will be used for telephony | ||
107 | * data so multiples of 8kHz will be the common case. | ||
108 | */ | ||
109 | switch (rate) { | ||
94 | case 8000: | 110 | case 8000: |
95 | wm9713_div = 12; | 111 | wm9713_div = 12; |
96 | pll_out = 2048000; | ||
97 | break; | 112 | break; |
98 | case 16000: | 113 | case 16000: |
99 | wm9713_div = 6; | 114 | wm9713_div = 6; |
100 | pll_out = 4096000; | ||
101 | break; | 115 | break; |
102 | case 48000: | 116 | case 48000: |
103 | default: | ||
104 | wm9713_div = 2; | 117 | wm9713_div = 2; |
105 | pll_out = 12288000; | ||
106 | acds = 1; | ||
107 | break; | 118 | break; |
119 | default: | ||
120 | /* Don't support OSS emulation */ | ||
121 | return -EINVAL; | ||
108 | } | 122 | } |
109 | 123 | ||
110 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 124 | /* Add 1 to the width for the leading clock cycle */ |
111 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | 125 | pll_out = rate * (width + 1) * 8; |
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
116 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | 126 | ||
120 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, | 127 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); |
121 | params_channels(params), | ||
122 | params_channels(params)); | ||
123 | if (ret < 0) | 128 | if (ret < 0) |
124 | return ret; | 129 | return ret; |
125 | 130 | ||
@@ -127,19 +132,22 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
127 | if (ret < 0) | 132 | if (ret < 0) |
128 | return ret; | 133 | return ret; |
129 | 134 | ||
130 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); | 135 | if (clk_pout) |
136 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, | ||
137 | WM9713_PCMDIV(wm9713_div)); | ||
138 | else | ||
139 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | ||
140 | WM9713_PCMDIV(wm9713_div)); | ||
131 | if (ret < 0) | 141 | if (ret < 0) |
132 | return ret; | 142 | return ret; |
133 | 143 | ||
134 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); | 144 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
145 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
135 | if (ret < 0) | 146 | if (ret < 0) |
136 | return ret; | 147 | return ret; |
137 | 148 | ||
138 | /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs | 149 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | |
139 | * to be set instead. | 150 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); |
140 | */ | ||
141 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | ||
142 | WM9713_PCMDIV(wm9713_div)); | ||
143 | if (ret < 0) | 151 | if (ret < 0) |
144 | return ret; | 152 | return ret; |
145 | 153 | ||
@@ -173,8 +181,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
173 | }, | 181 | }, |
174 | }; | 182 | }; |
175 | 183 | ||
184 | static int zylonite_probe(struct platform_device *pdev) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | if (clk_pout) { | ||
189 | pout = clk_get(NULL, "CLK_POUT"); | ||
190 | if (IS_ERR(pout)) { | ||
191 | dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", | ||
192 | PTR_ERR(pout)); | ||
193 | return PTR_ERR(pout); | ||
194 | } | ||
195 | |||
196 | ret = clk_enable(pout); | ||
197 | if (ret != 0) { | ||
198 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
199 | ret); | ||
200 | clk_put(pout); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", | ||
205 | clk_get_rate(pout)); | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int zylonite_remove(struct platform_device *pdev) | ||
212 | { | ||
213 | if (clk_pout) { | ||
214 | clk_disable(pout); | ||
215 | clk_put(pout); | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int zylonite_suspend_post(struct platform_device *pdev, | ||
222 | pm_message_t state) | ||
223 | { | ||
224 | if (clk_pout) | ||
225 | clk_disable(pout); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int zylonite_resume_pre(struct platform_device *pdev) | ||
231 | { | ||
232 | int ret = 0; | ||
233 | |||
234 | if (clk_pout) { | ||
235 | ret = clk_enable(pout); | ||
236 | if (ret != 0) | ||
237 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
238 | ret); | ||
239 | } | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
176 | static struct snd_soc_card zylonite = { | 244 | static struct snd_soc_card zylonite = { |
177 | .name = "Zylonite", | 245 | .name = "Zylonite", |
246 | .probe = &zylonite_probe, | ||
247 | .remove = &zylonite_remove, | ||
248 | .suspend_post = &zylonite_suspend_post, | ||
249 | .resume_pre = &zylonite_resume_pre, | ||
178 | .platform = &pxa2xx_soc_platform, | 250 | .platform = &pxa2xx_soc_platform, |
179 | .dai_link = zylonite_dai, | 251 | .dai_link = zylonite_dai, |
180 | .num_links = ARRAY_SIZE(zylonite_dai), | 252 | .num_links = ARRAY_SIZE(zylonite_dai), |