Skip to content

Commit

Permalink
ASoC: wm_adsp: Add basic firmware selection support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Brown committed Jan 12, 2013
1 parent 471f488 commit 1023dbd
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
75 changes: 73 additions & 2 deletions sound/soc/codecs/wm_adsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,71 @@
#define ADSP2_RAM_RDY_SHIFT 0
#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,
int type)
Expand Down Expand Up @@ -197,7 +262,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
if (file == NULL)
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';

ret = request_firmware(&firmware, file, dsp->dev);
Expand Down Expand Up @@ -596,7 +662,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
if (file == NULL)
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';

ret = request_firmware(&firmware, file, dsp->dev);
Expand Down Expand Up @@ -886,9 +953,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
ADSP2_CORE_ENA | ADSP2_START);
if (ret != 0)
goto err;

dsp->running = true;
break;

case SND_SOC_DAPM_PRE_PMD:
dsp->running = false;

regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
ADSP2_SYS_ENA | ADSP2_CORE_ENA |
ADSP2_START, 0);
Expand Down
5 changes: 5 additions & 0 deletions sound/soc/codecs/wm_adsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ struct wm_adsp {
const struct wm_adsp_region *mem;
int num_mems;

int fw;
bool running;

struct regulator *dvfs;
};

Expand All @@ -59,6 +62,8 @@ struct wm_adsp {
.shift = num, .event = wm_adsp2_event, \
.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_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
Expand Down

0 comments on commit 1023dbd

Please sign in to comment.