aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung/bells.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-02 10:47:44 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-14 22:29:38 -0400
commitb138707874729473bed70561c88566821156d6a6 (patch)
treebd5251a91ce59801bdb6143eaa389c4d5631e7f7 /sound/soc/samsung/bells.c
parentffaa839b11a72a327bf758dd428181937395421e (diff)
ASoC: bells: Provide additional parameterisation
Not all CODEC devices have three audio interfaces and the clock rates which support these things vary. Support this by using driver data to supply the clock rates and by only completing the parts of system setup which are required for the system. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/samsung/bells.c')
-rw-r--r--sound/soc/samsung/bells.c122
1 files changed, 75 insertions, 47 deletions
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 293d2d9dfc12..588bb635b1de 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -18,15 +18,6 @@
18#include "../codecs/wm5102.h" 18#include "../codecs/wm5102.h"
19#include "../codecs/wm9081.h" 19#include "../codecs/wm9081.h"
20 20
21/*
22 * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
23 * to allow all the DSP functionality to be enabled if desired.
24 */
25#define SYSCLK_RATE (44100 * 1024)
26
27/* 48kHz based clocks for the ASYNC domain */
28#define ASYNCCLK_RATE (48000 * 512)
29
30/* BCLK2 is fixed at this currently */ 21/* BCLK2 is fixed at this currently */
31#define BCLK2_RATE (64 * 8000) 22#define BCLK2_RATE (64 * 8000)
32 23
@@ -44,12 +35,28 @@
44#define DAI_CODEC_CP 2 35#define DAI_CODEC_CP 2
45#define DAI_CODEC_SUB 3 36#define DAI_CODEC_SUB 3
46 37
38struct bells_drvdata {
39 int sysclk_rate;
40 int asyncclk_rate;
41};
42
43static struct bells_drvdata wm5102_drvdata = {
44 .sysclk_rate = 45158400,
45 .asyncclk_rate = 49152000,
46};
47
48static struct bells_drvdata wm5110_drvdata = {
49 .sysclk_rate = 135475200,
50 .asyncclk_rate = 147456000,
51};
52
47static int bells_set_bias_level(struct snd_soc_card *card, 53static int bells_set_bias_level(struct snd_soc_card *card,
48 struct snd_soc_dapm_context *dapm, 54 struct snd_soc_dapm_context *dapm,
49 enum snd_soc_bias_level level) 55 enum snd_soc_bias_level level)
50{ 56{
51 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai; 57 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
52 struct snd_soc_codec *codec = codec_dai->codec; 58 struct snd_soc_codec *codec = codec_dai->codec;
59 struct bells_drvdata *bells = card->drvdata;
53 int ret; 60 int ret;
54 61
55 if (dapm->dev != codec_dai->dev) 62 if (dapm->dev != codec_dai->dev)
@@ -57,18 +64,21 @@ static int bells_set_bias_level(struct snd_soc_card *card,
57 64
58 switch (level) { 65 switch (level) {
59 case SND_SOC_BIAS_PREPARE: 66 case SND_SOC_BIAS_PREPARE:
60 if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { 67 if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
61 ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 68 break;
62 ARIZONA_FLL_SRC_MCLK1,
63 MCLK_RATE,
64 SYSCLK_RATE);
65 if (ret < 0)
66 pr_err("Failed to start FLL: %d\n", ret);
67 69
70 ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
71 ARIZONA_FLL_SRC_MCLK1,
72 MCLK_RATE,
73 bells->sysclk_rate);
74 if (ret < 0)
75 pr_err("Failed to start FLL: %d\n", ret);
76
77 if (bells->asyncclk_rate) {
68 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 78 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
69 ARIZONA_FLL_SRC_AIF2BCLK, 79 ARIZONA_FLL_SRC_AIF2BCLK,
70 BCLK2_RATE, 80 BCLK2_RATE,
71 ASYNCCLK_RATE); 81 bells->asyncclk_rate);
72 if (ret < 0) 82 if (ret < 0)
73 pr_err("Failed to start FLL: %d\n", ret); 83 pr_err("Failed to start FLL: %d\n", ret);
74 } 84 }
@@ -87,6 +97,7 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
87{ 97{
88 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai; 98 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
89 struct snd_soc_codec *codec = codec_dai->codec; 99 struct snd_soc_codec *codec = codec_dai->codec;
100 struct bells_drvdata *bells = card->drvdata;
90 int ret; 101 int ret;
91 102
92 if (dapm->dev != codec_dai->dev) 103 if (dapm->dev != codec_dai->dev)
@@ -100,10 +111,13 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
100 return ret; 111 return ret;
101 } 112 }
102 113
103 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); 114 if (bells->asyncclk_rate) {
104 if (ret < 0) { 115 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
105 pr_err("Failed to stop FLL: %d\n", ret); 116 0, 0, 0);
106 return ret; 117 if (ret < 0) {
118 pr_err("Failed to stop FLL: %d\n", ret);
119 return ret;
120 }
107 } 121 }
108 break; 122 break;
109 123
@@ -118,14 +132,24 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
118 132
119static int bells_late_probe(struct snd_soc_card *card) 133static int bells_late_probe(struct snd_soc_card *card)
120{ 134{
135 struct bells_drvdata *bells = card->drvdata;
121 struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec; 136 struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
122 struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec; 137 struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
123 struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai; 138 struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
124 struct snd_soc_dai *aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai; 139 struct snd_soc_dai *aif2_dai;
125 struct snd_soc_dai *aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai; 140 struct snd_soc_dai *aif3_dai;
126 struct snd_soc_dai *wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai; 141 struct snd_soc_dai *wm9081_dai;
127 int ret; 142 int ret;
128 143
144 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
145 ARIZONA_CLK_SRC_FLL1,
146 bells->sysclk_rate,
147 SND_SOC_CLOCK_IN);
148 if (ret != 0) {
149 dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
150 return ret;
151 }
152
129 ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0); 153 ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
130 if (ret != 0) { 154 if (ret != 0) {
131 dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret); 155 dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
@@ -133,43 +157,43 @@ static int bells_late_probe(struct snd_soc_card *card)
133 } 157 }
134 158
135 ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); 159 ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
136 if (ret != 0) { 160 if (ret != 0)
137 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); 161 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
138 return ret;
139 }
140 162
141 ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); 163 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
142 if (ret != 0) { 164 SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
143 dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); 165 if (ret != 0)
144 return ret; 166 dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
145 }
146 167
147 ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); 168 if (card->num_rtd == DAI_CODEC_CP)
148 if (ret != 0) { 169 return 0;
149 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
150 return ret;
151 }
152 170
153 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, 171 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
154 ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, 172 ARIZONA_CLK_SRC_FLL2,
173 bells->asyncclk_rate,
155 SND_SOC_CLOCK_IN); 174 SND_SOC_CLOCK_IN);
156 if (ret != 0) { 175 if (ret != 0) {
157 dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); 176 dev_err(codec->dev, "Failed to set ASYNCCLK: %d\n", ret);
158 return ret; 177 return ret;
159 } 178 }
160 179
161 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, 180 aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
162 SYS_MCLK_RATE, SND_SOC_CLOCK_OUT); 181
182 ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
163 if (ret != 0) { 183 if (ret != 0) {
164 dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); 184 dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
165 return ret; 185 return ret;
166 } 186 }
167 187
168 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, 188 if (card->num_rtd == DAI_CODEC_SUB)
169 ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, 189 return 0;
170 SND_SOC_CLOCK_IN); 190
191 aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
192 wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
193
194 ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
171 if (ret != 0) { 195 if (ret != 0) {
172 dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); 196 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
173 return ret; 197 return ret;
174 } 198 }
175 199
@@ -318,6 +342,8 @@ static struct snd_soc_card bells_cards[] = {
318 342
319 .set_bias_level = bells_set_bias_level, 343 .set_bias_level = bells_set_bias_level,
320 .set_bias_level_post = bells_set_bias_level_post, 344 .set_bias_level_post = bells_set_bias_level_post,
345
346 .drvdata = &wm5102_drvdata,
321 }, 347 },
322 { 348 {
323 .name = "Bells WM5110", 349 .name = "Bells WM5110",
@@ -334,6 +360,8 @@ static struct snd_soc_card bells_cards[] = {
334 360
335 .set_bias_level = bells_set_bias_level, 361 .set_bias_level = bells_set_bias_level,
336 .set_bias_level_post = bells_set_bias_level_post, 362 .set_bias_level_post = bells_set_bias_level_post,
363
364 .drvdata = &wm5110_drvdata,
337 }, 365 },
338}; 366};
339 367