diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-02 10:47:44 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-14 22:29:38 -0400 |
commit | b138707874729473bed70561c88566821156d6a6 (patch) | |
tree | bd5251a91ce59801bdb6143eaa389c4d5631e7f7 /sound/soc/samsung/bells.c | |
parent | ffaa839b11a72a327bf758dd428181937395421e (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.c | 122 |
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 | ||
38 | struct bells_drvdata { | ||
39 | int sysclk_rate; | ||
40 | int asyncclk_rate; | ||
41 | }; | ||
42 | |||
43 | static struct bells_drvdata wm5102_drvdata = { | ||
44 | .sysclk_rate = 45158400, | ||
45 | .asyncclk_rate = 49152000, | ||
46 | }; | ||
47 | |||
48 | static struct bells_drvdata wm5110_drvdata = { | ||
49 | .sysclk_rate = 135475200, | ||
50 | .asyncclk_rate = 147456000, | ||
51 | }; | ||
52 | |||
47 | static int bells_set_bias_level(struct snd_soc_card *card, | 53 | static 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 | ||
119 | static int bells_late_probe(struct snd_soc_card *card) | 133 | static 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 | ||