aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2016-01-21 12:53:02 -0500
committerMark Brown <broonie@kernel.org>2016-01-28 18:31:46 -0500
commitd82d767f0e61da5f1f872d40358904eb316af264 (patch)
tree89287959ea9947cf5dbf7b72f3fba7460d724f10
parent7ce4283ca405d459c186960ed39d41ec0e6fb2bf (diff)
ASoC: wm_adsp: Move setting of DSP speed into CODEC specific code
The ADSP code should be agnostic of which CODEC it runs upon, currently there is only one remaining part of the implementation that doesn't follow this. When the DSP is booted on ADSP2 we read ARIZONA_SYSTEM_CLOCK_1 and use that to set the initial speed for the DSP clock. This patch factors that out into CODEC specific code, leaving the ADSP code entirely CODEC agnostic. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/cs47l24.c23
-rw-r--r--sound/soc/codecs/wm5102.c6
-rw-r--r--sound/soc/codecs/wm5110.c27
-rw-r--r--sound/soc/codecs/wm_adsp.c40
-rw-r--r--sound/soc/codecs/wm_adsp.h8
5 files changed, 65 insertions, 39 deletions
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index dc5ae7f7a1bd..9dc77a4da35d 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = {
57 cs47l24_dsp3_regions, 57 cs47l24_dsp3_regions,
58}; 58};
59 59
60static int cs47l24_adsp_power_ev(struct snd_soc_dapm_widget *w,
61 struct snd_kcontrol *kcontrol, int event)
62{
63 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
64 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
65 unsigned int v;
66 int ret;
67
68 ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
69 if (ret != 0) {
70 dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
71 return ret;
72 }
73
74 v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
75
76 return wm_adsp2_early_event(w, kcontrol, event, v);
77}
78
60static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); 79static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
61static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); 80static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
62static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); 81static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0);
@@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
405SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, 424SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
406 NULL, 0), 425 NULL, 0),
407 426
408WM_ADSP2("DSP2", 1), 427WM_ADSP2("DSP2", 1, cs47l24_adsp_power_ev),
409WM_ADSP2("DSP3", 2), 428WM_ADSP2("DSP3", 2, cs47l24_adsp_power_ev),
410 429
411SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, 430SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
412 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), 431 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 64637d1cf4e5..7c0860df3204 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
619{ 619{
620 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 620 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
621 struct arizona *arizona = dev_get_drvdata(codec->dev->parent); 621 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
622 unsigned int v; 622 unsigned int v = 0;
623 int ret; 623 int ret;
624 624
625 switch (event) { 625 switch (event) {
@@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
654 break; 654 break;
655 } 655 }
656 656
657 return wm_adsp2_early_event(w, kcontrol, event); 657 return wm_adsp2_early_event(w, kcontrol, event, v);
658} 658}
659 659
660static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, 660static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
@@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
1408ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), 1408ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
1409ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), 1409ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
1410 1410
1411WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev), 1411WM_ADSP2("DSP1", 0, wm5102_adsp_power_ev),
1412 1412
1413SND_SOC_DAPM_OUTPUT("HPOUT1L"), 1413SND_SOC_DAPM_OUTPUT("HPOUT1L"),
1414SND_SOC_DAPM_OUTPUT("HPOUT1R"), 1414SND_SOC_DAPM_OUTPUT("HPOUT1R"),
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 83760b72aa03..b47bc4418e30 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
191 return 0; 191 return 0;
192} 192}
193 193
194static int wm5110_adsp_power_ev(struct snd_soc_dapm_widget *w,
195 struct snd_kcontrol *kcontrol, int event)
196{
197 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
198 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
199 unsigned int v;
200 int ret;
201
202 ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
203 if (ret != 0) {
204 dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
205 return ret;
206 }
207
208 v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
209
210 return wm_adsp2_early_event(w, kcontrol, event, v);
211}
212
194static const struct reg_sequence wm5110_no_dre_left_enable[] = { 213static const struct reg_sequence wm5110_no_dre_left_enable[] = {
195 { 0x3024, 0xE410 }, 214 { 0x3024, 0xE410 },
196 { 0x3025, 0x0056 }, 215 { 0x3025, 0x0056 },
@@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
1179SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, 1198SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
1180 NULL, 0), 1199 NULL, 0),
1181 1200
1182WM_ADSP2("DSP1", 0), 1201WM_ADSP2("DSP1", 0, wm5110_adsp_power_ev),
1183WM_ADSP2("DSP2", 1), 1202WM_ADSP2("DSP2", 1, wm5110_adsp_power_ev),
1184WM_ADSP2("DSP3", 2), 1203WM_ADSP2("DSP3", 2, wm5110_adsp_power_ev),
1185WM_ADSP2("DSP4", 3), 1204WM_ADSP2("DSP4", 3, wm5110_adsp_power_ev),
1186 1205
1187SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, 1206SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
1188 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), 1207 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index a81f568a9660..76ab52d2c670 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -32,9 +32,6 @@
32#include <sound/initval.h> 32#include <sound/initval.h>
33#include <sound/tlv.h> 33#include <sound/tlv.h>
34 34
35#include <linux/mfd/arizona/registers.h>
36
37#include "arizona.h"
38#include "wm_adsp.h" 35#include "wm_adsp.h"
39 36
40#define adsp_crit(_dsp, fmt, ...) \ 37#define adsp_crit(_dsp, fmt, ...) \
@@ -2146,30 +2143,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
2146 struct wm_adsp, 2143 struct wm_adsp,
2147 boot_work); 2144 boot_work);
2148 int ret; 2145 int ret;
2149 unsigned int val;
2150 2146
2151 mutex_lock(&dsp->pwr_lock); 2147 mutex_lock(&dsp->pwr_lock);
2152 2148
2153 /*
2154 * For simplicity set the DSP clock rate to be the
2155 * SYSCLK rate rather than making it configurable.
2156 */
2157 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
2158 if (ret != 0) {
2159 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
2160 goto err_mutex;
2161 }
2162 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
2163 >> ARIZONA_SYSCLK_FREQ_SHIFT;
2164
2165 ret = regmap_update_bits_async(dsp->regmap,
2166 dsp->base + ADSP2_CLOCKING,
2167 ADSP2_CLK_SEL_MASK, val);
2168 if (ret != 0) {
2169 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2170 goto err_mutex;
2171 }
2172
2173 ret = wm_adsp2_ena(dsp); 2149 ret = wm_adsp2_ena(dsp);
2174 if (ret != 0) 2150 if (ret != 0)
2175 goto err_mutex; 2151 goto err_mutex;
@@ -2209,8 +2185,21 @@ err_mutex:
2209 mutex_unlock(&dsp->pwr_lock); 2185 mutex_unlock(&dsp->pwr_lock);
2210} 2186}
2211 2187
2188static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
2189{
2190 int ret;
2191
2192 ret = regmap_update_bits_async(dsp->regmap,
2193 dsp->base + ADSP2_CLOCKING,
2194 ADSP2_CLK_SEL_MASK,
2195 freq << ADSP2_CLK_SEL_SHIFT);
2196 if (ret != 0)
2197 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2198}
2199
2212int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 2200int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
2213 struct snd_kcontrol *kcontrol, int event) 2201 struct snd_kcontrol *kcontrol, int event,
2202 unsigned int freq)
2214{ 2203{
2215 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 2204 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2216 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 2205 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
@@ -2220,6 +2209,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
2220 2209
2221 switch (event) { 2210 switch (event) {
2222 case SND_SOC_DAPM_PRE_PMU: 2211 case SND_SOC_DAPM_PRE_PMU:
2212 wm_adsp2_set_dspclk(dsp, freq);
2223 queue_work(system_unbound_wq, &dsp->boot_work); 2213 queue_work(system_unbound_wq, &dsp->boot_work);
2224 break; 2214 break;
2225 default: 2215 default:
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 1a928ec54741..b61cb57e600f 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -80,7 +80,7 @@ struct wm_adsp {
80 SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ 80 SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
81 wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) 81 wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
82 82
83#define WM_ADSP2_E(wname, num, event_fn) \ 83#define WM_ADSP2(wname, num, event_fn) \
84{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ 84{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
85 .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ 85 .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
86 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ 86 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
@@ -88,9 +88,6 @@ struct wm_adsp {
88 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ 88 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
89 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } 89 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
90 90
91#define WM_ADSP2(wname, num) \
92 WM_ADSP2_E(wname, num, wm_adsp2_early_event)
93
94extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; 91extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
95 92
96int wm_adsp1_init(struct wm_adsp *dsp); 93int wm_adsp1_init(struct wm_adsp *dsp);
@@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
100int wm_adsp1_event(struct snd_soc_dapm_widget *w, 97int wm_adsp1_event(struct snd_soc_dapm_widget *w,
101 struct snd_kcontrol *kcontrol, int event); 98 struct snd_kcontrol *kcontrol, int event);
102int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 99int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
103 struct snd_kcontrol *kcontrol, int event); 100 struct snd_kcontrol *kcontrol, int event,
101 unsigned int freq);
104int wm_adsp2_event(struct snd_soc_dapm_widget *w, 102int wm_adsp2_event(struct snd_soc_dapm_widget *w,
105 struct snd_kcontrol *kcontrol, int event); 103 struct snd_kcontrol *kcontrol, int event);
106 104