[alsa-devel] [PATCH 1/2] ASoC: Add input and output AIF widgets
Currently DAPM interfaces with the audio streams to and from the processor at the DAC and ADC widgets. As the digital capabilities of parts increases this is becoming a less and less able to meet the needs of parts.
To meet the needs of these devices create new widgets interfacing with the TDM bus but not integrated into any other functionality. Audio can then be routed to and from these widgets using existing routing widgets.
A slot number is provided in the definition but this is currently not used yet. This is intended to support devices which can use more than one TDM slot on a single interface.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- include/sound/soc-dapm.h | 8 ++++++ sound/soc/soc-dapm.c | 58 ++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 35814ce..3388405 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -137,6 +137,12 @@ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
/* stream domain */ +#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ +{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ + .reg = wreg, .shift = wshift, .invert = winvert } +#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ +{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ + .reg = wreg, .shift = wshift, .invert = winvert } #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ .shift = wshift, .invert = winvert} @@ -312,6 +318,8 @@ enum snd_soc_dapm_type { snd_soc_dapm_pre, /* machine specific pre widget - exec first */ snd_soc_dapm_post, /* machine specific post widget - exec last */ snd_soc_dapm_supply, /* power/clock supply */ + snd_soc_dapm_aif_in, /* audio interface input */ + snd_soc_dapm_aif_out, /* audio interface output */ };
/* diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8846131..a225e5a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -55,17 +55,19 @@ static int dapm_up_seq[] = { [snd_soc_dapm_pre] = 0, [snd_soc_dapm_supply] = 1, [snd_soc_dapm_micbias] = 2, - [snd_soc_dapm_mic] = 3, - [snd_soc_dapm_mux] = 4, - [snd_soc_dapm_value_mux] = 4, - [snd_soc_dapm_dac] = 5, - [snd_soc_dapm_mixer] = 6, - [snd_soc_dapm_mixer_named_ctl] = 6, - [snd_soc_dapm_pga] = 7, - [snd_soc_dapm_adc] = 8, - [snd_soc_dapm_hp] = 9, - [snd_soc_dapm_spk] = 9, - [snd_soc_dapm_post] = 10, + [snd_soc_dapm_aif_in] = 3, + [snd_soc_dapm_aif_out] = 3, + [snd_soc_dapm_mic] = 4, + [snd_soc_dapm_mux] = 5, + [snd_soc_dapm_value_mux] = 5, + [snd_soc_dapm_dac] = 6, + [snd_soc_dapm_mixer] = 7, + [snd_soc_dapm_mixer_named_ctl] = 7, + [snd_soc_dapm_pga] = 8, + [snd_soc_dapm_adc] = 9, + [snd_soc_dapm_hp] = 10, + [snd_soc_dapm_spk] = 10, + [snd_soc_dapm_post] = 11, };
static int dapm_down_seq[] = { @@ -81,8 +83,10 @@ static int dapm_down_seq[] = { [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, [snd_soc_dapm_value_mux] = 9, - [snd_soc_dapm_supply] = 10, - [snd_soc_dapm_post] = 11, + [snd_soc_dapm_aif_in] = 10, + [snd_soc_dapm_aif_out] = 10, + [snd_soc_dapm_supply] = 11, + [snd_soc_dapm_post] = 12, };
static void pop_wait(u32 pop_time) @@ -224,6 +228,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_micbias: case snd_soc_dapm_vmid: case snd_soc_dapm_supply: + case snd_soc_dapm_aif_in: + case snd_soc_dapm_aif_out: p->connect = 1; break; /* does effect routing - dynamically connected */ @@ -497,8 +503,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) if (widget->id == snd_soc_dapm_supply) return 0;
- if (widget->id == snd_soc_dapm_adc && widget->active) - return 1; + switch (widget->id) { + case snd_soc_dapm_adc: + case snd_soc_dapm_aif_out: + if (widget->active) + return 1; + default: + break; + }
if (widget->connected) { /* connected pin ? */ @@ -537,8 +549,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) return 0;
/* active stream ? */ - if (widget->id == snd_soc_dapm_dac && widget->active) - return 1; + switch (widget->id) { + case snd_soc_dapm_dac: + case snd_soc_dapm_aif_in: + if (widget->active) + return 1; + default: + break; + }
if (widget->connected) { /* connected pin ? */ @@ -1052,6 +1070,8 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: case snd_soc_dapm_supply: + case snd_soc_dapm_aif_in: + case snd_soc_dapm_aif_out: if (w->name) { in = is_connected_input_ep(w); dapm_clear_walk(w->codec); @@ -1342,6 +1362,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, case snd_soc_dapm_pre: case snd_soc_dapm_post: case snd_soc_dapm_supply: + case snd_soc_dapm_aif_in: + case snd_soc_dapm_aif_out: list_add(&path->list, &codec->dapm_paths); list_add(&path->list_sink, &wsink->sources); list_add(&path->list_source, &wsource->sinks); @@ -1444,9 +1466,11 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) dapm_new_mux(codec, w); break; case snd_soc_dapm_adc: + case snd_soc_dapm_aif_out: w->power_check = dapm_adc_check_power; break; case snd_soc_dapm_dac: + case snd_soc_dapm_aif_in: w->power_check = dapm_dac_check_power; break; case snd_soc_dapm_pga:
The WM8993 provides digital sidetone paths and also allows each channel on the audio interface to be routed separtately to the DACs and ADCs.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/wm8993.c | 88 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index cd15669..ff9b63b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -846,18 +846,76 @@ SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0), SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), };
+static const char *aif_text[] = { + "Left", "Right" +}; + +static const struct soc_enum aifoutl_enum = + SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); + +static const struct snd_kcontrol_new aifoutl_mux = + SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); + +static const struct soc_enum aifoutr_enum = + SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); + +static const struct snd_kcontrol_new aifoutr_mux = + SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); + +static const struct soc_enum aifinl_enum = + SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); + +static const struct snd_kcontrol_new aifinl_mux = + SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); + +static const struct soc_enum aifinr_enum = + SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); + +static const struct snd_kcontrol_new aifinr_mux = + SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); + +static const char *sidetone_text[] = { + "None", "Left", "Right" +}; + +static const struct soc_enum sidetonel_enum = + SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); + +static const struct snd_kcontrol_new sidetonel_mux = + SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); + +static const struct soc_enum sidetoner_enum = + SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); + +static const struct snd_kcontrol_new sidetoner_mux = + SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); + static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
+SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), +SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), + +SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), +SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), + +SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0), -SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0), +SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0), -SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0), +SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), +SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), + +SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux), +SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux), + +SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0), +SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0),
SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), @@ -875,10 +933,32 @@ static const struct snd_soc_dapm_route routes[] = { { "ADCR", NULL, "CLK_SYS" }, { "ADCR", NULL, "CLK_DSP" },
+ { "AIFOUTL Mux", "Left", "ADCL" }, + { "AIFOUTL Mux", "Right", "ADCR" }, + { "AIFOUTR Mux", "Left", "ADCL" }, + { "AIFOUTR Mux", "Right", "ADCR" }, + + { "AIFOUTL", NULL, "AIFOUTL Mux" }, + { "AIFOUTR", NULL, "AIFOUTR Mux" }, + + { "DACL Mux", "Left", "AIFINL" }, + { "DACL Mux", "Right", "AIFINR" }, + { "DACR Mux", "Left", "AIFINL" }, + { "DACR Mux", "Right", "AIFINR" }, + + { "DACL Sidetone", "Left", "ADCL" }, + { "DACL Sidetone", "Right", "ADCR" }, + { "DACR Sidetone", "Left", "ADCL" }, + { "DACR Sidetone", "Right", "ADCR" }, + { "DACL", NULL, "CLK_SYS" }, { "DACL", NULL, "CLK_DSP" }, + { "DACL", NULL, "DACL Mux" }, + { "DACL", NULL, "DACL Sidetone" }, { "DACR", NULL, "CLK_SYS" }, { "DACR", NULL, "CLK_DSP" }, + { "DACR", NULL, "DACR Mux" }, + { "DACR", NULL, "DACR Sidetone" },
{ "Left Output Mixer", "DAC Switch", "DACL" },
participants (1)
-
Mark Brown