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>
This commit is contained in:
parent
471f488583
commit
1023dbd90c
2 changed files with 78 additions and 2 deletions
|
@ -143,6 +143,71 @@
|
||||||
#define ADSP2_RAM_RDY_SHIFT 0
|
#define ADSP2_RAM_RDY_SHIFT 0
|
||||||
#define ADSP2_RAM_RDY_WIDTH 1
|
#define ADSP2_RAM_RDY_WIDTH 1
|
||||||
|
|
||||||
|
#define WM_ADSP_NUM_FW 3
|
||||||
|
|
||||||
|
static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
|
||||||
|
"MBC/VSS", "Tx", "Rx ANC"
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *file;
|
||||||
|
} wm_adsp_fw[WM_ADSP_NUM_FW] = {
|
||||||
|
{ .file = "mbc-vss" },
|
||||||
|
{ .file = "tx" },
|
||||||
|
{ .file = "rx-anc" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||||
|
struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
ucontrol->value.integer.value[0] = adsp[e->shift_l].fw;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||||
|
struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (adsp[e->shift_l].running)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
adsp->fw = ucontrol->value.integer.value[0];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct soc_enum wm_adsp_fw_enum[] = {
|
||||||
|
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||||
|
SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||||
|
SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||||
|
SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
|
||||||
|
SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
|
||||||
|
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||||
|
SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
|
||||||
|
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||||
|
SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
|
||||||
|
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||||
|
SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
|
||||||
|
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
|
||||||
|
|
||||||
static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
|
static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
|
||||||
int type)
|
int type)
|
||||||
|
@ -197,7 +262,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
|
snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
|
||||||
|
wm_adsp_fw[dsp->fw].file);
|
||||||
file[PAGE_SIZE - 1] = '\0';
|
file[PAGE_SIZE - 1] = '\0';
|
||||||
|
|
||||||
ret = request_firmware(&firmware, file, dsp->dev);
|
ret = request_firmware(&firmware, file, dsp->dev);
|
||||||
|
@ -596,7 +662,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
|
snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
|
||||||
|
wm_adsp_fw[dsp->fw].file);
|
||||||
file[PAGE_SIZE - 1] = '\0';
|
file[PAGE_SIZE - 1] = '\0';
|
||||||
|
|
||||||
ret = request_firmware(&firmware, file, dsp->dev);
|
ret = request_firmware(&firmware, file, dsp->dev);
|
||||||
|
@ -886,9 +953,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
||||||
ADSP2_CORE_ENA | ADSP2_START);
|
ADSP2_CORE_ENA | ADSP2_START);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
dsp->running = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SND_SOC_DAPM_PRE_PMD:
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
dsp->running = false;
|
||||||
|
|
||||||
regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
|
regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
|
||||||
ADSP2_SYS_ENA | ADSP2_CORE_ENA |
|
ADSP2_SYS_ENA | ADSP2_CORE_ENA |
|
||||||
ADSP2_START, 0);
|
ADSP2_START, 0);
|
||||||
|
|
|
@ -46,6 +46,9 @@ struct wm_adsp {
|
||||||
const struct wm_adsp_region *mem;
|
const struct wm_adsp_region *mem;
|
||||||
int num_mems;
|
int num_mems;
|
||||||
|
|
||||||
|
int fw;
|
||||||
|
bool running;
|
||||||
|
|
||||||
struct regulator *dvfs;
|
struct regulator *dvfs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +62,8 @@ struct wm_adsp {
|
||||||
.shift = num, .event = wm_adsp2_event, \
|
.shift = num, .event = wm_adsp2_event, \
|
||||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
|
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
|
||||||
|
|
||||||
|
extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
|
||||||
|
|
||||||
int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
|
int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
|
||||||
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event);
|
struct snd_kcontrol *kcontrol, int event);
|
||||||
|
|
Loading…
Reference in a new issue