aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_adsp.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-11 17:58:28 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-12 13:36:07 -0500
commit1023dbd90c1e3e87921198939917c1f50b4b6af7 (patch)
tree12d090ba617480996cd2eb997aeefb7a454804c1 /sound/soc/codecs/wm_adsp.c
parent471f488583c62e4daca7d24fc7c937a39de7d95f (diff)
ASoC: wm_adsp: Add basic firmware selection support
There are many firmwares available for ADSP devices. Add basic support for selecting between them, including a couple of feature sets in the set of available firmware to start off with. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r--sound/soc/codecs/wm_adsp.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 5015ff287c39..1f8e8e2a1a6a 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -143,6 +143,71 @@
143#define ADSP2_RAM_RDY_SHIFT 0 143#define ADSP2_RAM_RDY_SHIFT 0
144#define ADSP2_RAM_RDY_WIDTH 1 144#define ADSP2_RAM_RDY_WIDTH 1
145 145
146#define WM_ADSP_NUM_FW 3
147
148static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
149 "MBC/VSS", "Tx", "Rx ANC"
150};
151
152static struct {
153 const char *file;
154} wm_adsp_fw[WM_ADSP_NUM_FW] = {
155 { .file = "mbc-vss" },
156 { .file = "tx" },
157 { .file = "rx-anc" },
158};
159
160static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
162{
163 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
164 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
165 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
166
167 ucontrol->value.integer.value[0] = adsp[e->shift_l].fw;
168
169 return 0;
170}
171
172static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
173 struct snd_ctl_elem_value *ucontrol)
174{
175 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
176 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
177 struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
178
179 if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw)
180 return 0;
181
182 if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
183 return -EINVAL;
184
185 if (adsp[e->shift_l].running)
186 return -EBUSY;
187
188 adsp->fw = ucontrol->value.integer.value[0];
189
190 return 0;
191}
192
193static const struct soc_enum wm_adsp_fw_enum[] = {
194 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
195 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
196 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
197 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
198};
199
200const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
201 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
202 wm_adsp_fw_get, wm_adsp_fw_put),
203 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
204 wm_adsp_fw_get, wm_adsp_fw_put),
205 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
206 wm_adsp_fw_get, wm_adsp_fw_put),
207 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
208 wm_adsp_fw_get, wm_adsp_fw_put),
209};
210EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
146 211
147static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 212static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
148 int type) 213 int type)
@@ -197,7 +262,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
197 if (file == NULL) 262 if (file == NULL)
198 return -ENOMEM; 263 return -ENOMEM;
199 264
200 snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num); 265 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
266 wm_adsp_fw[dsp->fw].file);
201 file[PAGE_SIZE - 1] = '\0'; 267 file[PAGE_SIZE - 1] = '\0';
202 268
203 ret = request_firmware(&firmware, file, dsp->dev); 269 ret = request_firmware(&firmware, file, dsp->dev);
@@ -596,7 +662,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
596 if (file == NULL) 662 if (file == NULL)
597 return -ENOMEM; 663 return -ENOMEM;
598 664
599 snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num); 665 snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
666 wm_adsp_fw[dsp->fw].file);
600 file[PAGE_SIZE - 1] = '\0'; 667 file[PAGE_SIZE - 1] = '\0';
601 668
602 ret = request_firmware(&firmware, file, dsp->dev); 669 ret = request_firmware(&firmware, file, dsp->dev);
@@ -886,9 +953,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
886 ADSP2_CORE_ENA | ADSP2_START); 953 ADSP2_CORE_ENA | ADSP2_START);
887 if (ret != 0) 954 if (ret != 0)
888 goto err; 955 goto err;
956
957 dsp->running = true;
889 break; 958 break;
890 959
891 case SND_SOC_DAPM_PRE_PMD: 960 case SND_SOC_DAPM_PRE_PMD:
961 dsp->running = false;
962
892 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 963 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
893 ADSP2_SYS_ENA | ADSP2_CORE_ENA | 964 ADSP2_SYS_ENA | ADSP2_CORE_ENA |
894 ADSP2_START, 0); 965 ADSP2_START, 0);