[alsa-devel] [PATCH v9 0/2] sun4i-codec: Add Line-In, FM-In, Mic 2, Capture Source, Differential Line-In
This patch adds support for some mixer controls: - Line-In - FM-In - Mic 2 - Capture Source - Differential Line-In
v9 changes compared to v8 are: - added Line Differential Capture Switch. - split Capture Source into Left Capture Select, Right Capture Select. - added Line Capture Volume. - rename "sun4i_codec_widgets" to "sun4i_codec_controls" for consistency with the struct field it's used in. - rename "Line-In" to "Line". - rename "Power Amplifier Playback Volume" to "Headphone Playback Volume".
v8 changes compared to v7 are: - fixed the routes for line and mic capturing.
v7 changes compared to v6 are: - preparation for different A20, A10 controls is now in an extra patch. - all register definitions are now at the top. - sun7i-specific things (A20-specific things) are now less grouped-together. - rename "Power Amplifier Volume" to "Power Amplifier Playback Volume".
v6 changes compared to v5 are: - Mic preamplifier special cases for A20 and A10 now are now not icky: There are two different _widget arrays and the probe() function now selects the right one to pass to snd_soc_register_codec() unmodified. - sun7i-specific things (A20-specific things) are now grouped together.
v5 changes compared to v4 are: - Mic preamplifier controls have more common names now. - Mic preamplifier scale has a 0 dB entry as well now, as documented in the A20 user manual. - Mic preamplifier has special cases for A20 and A10 now. - Gain controls have "Gain" in the name now.
v4 changes compared to v3 are: - names of the input are not uppercase anymore. - bit index constants are now named as in the A20 user manual v1.4. - added Mic1-In, Mac2-In. - added Mic1 and Mic2 Pre-Amplifiers.
v3 changes compared to v2 are: - added DAPM routes.
v2 changes compared to v1 are: - moved Line-In and FM-In playback switches to their respective sun4i_codec_*_mixer_controls.
v1 changes: - added linein, fmin output volumes and switches.
Danny Milosavljevic (2): ASoC: sun4i-codec: Distinguish sun4i from sun7i Add mixer controls: Line-In, FM-In, Mic 2, Capture Source, Differential Line-In.
sound/soc/sunxi/sun4i-codec.c | 278 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 259 insertions(+), 19 deletions(-)
This distinguishes sun4i from sun7i. It is necessary because they use different registers for the audio mixer. --- sound/soc/sunxi/sun4i-codec.c | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 0e19c50..30f4ea2 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -96,8 +96,9 @@ /* Other various ADC registers */ #define SUN4I_CODEC_DAC_TXCNT (0x30) #define SUN4I_CODEC_ADC_RXCNT (0x34) -#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c) + +#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
struct sun4i_codec { struct device *dev; @@ -509,10 +510,17 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute =
static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
-static const struct snd_kcontrol_new sun4i_codec_widgets[] = { - SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL, - SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0, - sun4i_codec_pa_volume_scale), +#define SUN4I_COMMON_CODEC_CONTROLS \ + SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,\ + SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,\ + sun4i_codec_pa_volume_scale) + +static const struct snd_kcontrol_new sun4i_codec_controls[] = { + SUN4I_COMMON_CODEC_CONTROLS, +}; + +static const struct snd_kcontrol_new sun7i_codec_controls[] = { + SUN4I_COMMON_CODEC_CONTROLS, };
static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = { @@ -629,8 +637,18 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = { - .controls = sun4i_codec_widgets, - .num_controls = ARRAY_SIZE(sun4i_codec_widgets), + .controls = sun4i_codec_controls, + .num_controls = ARRAY_SIZE(sun4i_codec_controls), + .dapm_widgets = sun4i_codec_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), + .dapm_routes = sun4i_codec_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), + }, +}; +static struct snd_soc_codec_driver sun7i_codec_codec = { + .component_driver = { + .controls = sun7i_codec_controls, + .num_controls = ARRAY_SIZE(sun7i_codec_controls), .dapm_widgets = sun4i_codec_codec_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), .dapm_routes = sun4i_codec_codec_dapm_routes, @@ -682,7 +700,7 @@ static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = SUN4I_CODEC_AC_MIC_PHONE_CAL, + .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL, };
static const struct of_device_id sun4i_codec_of_match[] = { @@ -760,6 +778,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) { struct snd_soc_card *card; struct sun4i_codec *scodec; + struct snd_soc_codec_driver *codec; struct resource *res; void __iomem *base; int ret; @@ -822,7 +841,12 @@ static int sun4i_codec_probe(struct platform_device *pdev) scodec->capture_dma_data.maxburst = 4; scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec, + if (of_device_is_compatible(pdev->dev.of_node, + "allwinner,sun7i-a20-codec")) + codec = &sun7i_codec_codec; + else + codec = &sun4i_codec_codec; + ret = snd_soc_register_codec(&pdev->dev, codec, &sun4i_codec_dai, 1); if (ret) { dev_err(&pdev->dev, "Failed to register our codec\n");
On Tue, Aug 30, 2016 at 1:44 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
This distinguishes sun4i from sun7i. It is necessary because they use different registers for the audio mixer.
sound/soc/sunxi/sun4i-codec.c | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 0e19c50..30f4ea2 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -96,8 +96,9 @@ /* Other various ADC registers */ #define SUN4I_CODEC_DAC_TXCNT (0x30) #define SUN4I_CODEC_ADC_RXCNT (0x34) -#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
struct sun4i_codec { struct device *dev; @@ -509,10 +510,17 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute =
static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
-static const struct snd_kcontrol_new sun4i_codec_widgets[] = {
SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
sun4i_codec_pa_volume_scale),
+#define SUN4I_COMMON_CODEC_CONTROLS \
SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,\
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,\
sun4i_codec_pa_volume_scale)
This is slightly worrying. It will get messy as you add more widgets.
+static const struct snd_kcontrol_new sun4i_codec_controls[] = {
SUN4I_COMMON_CODEC_CONTROLS,
+};
+static const struct snd_kcontrol_new sun7i_codec_controls[] = {
SUN4I_COMMON_CODEC_CONTROLS,
};
static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = { @@ -629,8 +637,18 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = {
.controls = sun4i_codec_widgets,
.num_controls = ARRAY_SIZE(sun4i_codec_widgets),
.controls = sun4i_codec_controls,
.num_controls = ARRAY_SIZE(sun4i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
},
+}; +static struct snd_soc_codec_driver sun7i_codec_codec = {
.component_driver = {
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls), .dapm_widgets = sun4i_codec_codec_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), .dapm_routes = sun4i_codec_codec_dapm_routes,
@@ -682,7 +700,7 @@ static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32,
.max_register = SUN4I_CODEC_AC_MIC_PHONE_CAL,
.max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
};
On sun4i the registers only go as far as SUN4I_CODEC_ADC_RXCNT. Could you add a separate regmap_config as well?
static const struct of_device_id sun4i_codec_of_match[] = { @@ -760,6 +778,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) { struct snd_soc_card *card; struct sun4i_codec *scodec;
struct snd_soc_codec_driver *codec; struct resource *res; void __iomem *base; int ret;
@@ -822,7 +841,12 @@ static int sun4i_codec_probe(struct platform_device *pdev) scodec->capture_dma_data.maxburst = 4; scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
if (of_device_is_compatible(pdev->dev.of_node,
"allwinner,sun7i-a20-codec"))
codec = &sun7i_codec_codec;
else
codec = &sun4i_codec_codec;
ret = snd_soc_register_codec(&pdev->dev, codec,
This will get reworked into something like in
https://github.com/wens/linux/commit/54a58e3087fb67572ca416256bc000e08b16348...
I haven't gotten around to posting this series yet though.
ChenYu
&sun4i_codec_dai, 1); if (ret) { dev_err(&pdev->dev, "Failed to register our codec\n");
Hi Danny,
On Tue, Aug 30, 2016 at 07:44:02AM +0200, Danny Milosavljevic wrote:
This distinguishes sun4i from sun7i. It is necessary because they use different registers for the audio mixer.
Your Signed-off-by is missing
sound/soc/sunxi/sun4i-codec.c | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 0e19c50..30f4ea2 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -96,8 +96,9 @@ /* Other various ADC registers */ #define SUN4I_CODEC_DAC_TXCNT (0x30) #define SUN4I_CODEC_ADC_RXCNT (0x34) -#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
That will need at least some mention in the commit log.
struct sun4i_codec { struct device *dev; @@ -509,10 +510,17 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute =
static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
-static const struct snd_kcontrol_new sun4i_codec_widgets[] = {
- SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
sun4i_codec_pa_volume_scale),
+#define SUN4I_COMMON_CODEC_CONTROLS \
- SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,\
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,\
sun4i_codec_pa_volume_scale)
+static const struct snd_kcontrol_new sun4i_codec_controls[] = {
- SUN4I_COMMON_CODEC_CONTROLS,
+};
+static const struct snd_kcontrol_new sun7i_codec_controls[] = {
- SUN4I_COMMON_CODEC_CONTROLS,
};
static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = { @@ -629,8 +637,18 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = {
.controls = sun4i_codec_widgets,
.num_controls = ARRAY_SIZE(sun4i_codec_widgets),
.controls = sun4i_codec_controls,
.num_controls = ARRAY_SIZE(sun4i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
- },
+};
You need a new line here.
+static struct snd_soc_codec_driver sun7i_codec_codec = {
- .component_driver = {
.controls = sun7i_codec_controls,
.dapm_widgets = sun4i_codec_codec_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), .dapm_routes = sun4i_codec_codec_dapm_routes,.num_controls = ARRAY_SIZE(sun7i_codec_controls),
@@ -682,7 +700,7 @@ static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32,
- .max_register = SUN4I_CODEC_AC_MIC_PHONE_CAL,
- .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
};
static const struct of_device_id sun4i_codec_of_match[] = { @@ -760,6 +778,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) { struct snd_soc_card *card; struct sun4i_codec *scodec;
- struct snd_soc_codec_driver *codec; struct resource *res; void __iomem *base; int ret;
@@ -822,7 +841,12 @@ static int sun4i_codec_probe(struct platform_device *pdev) scodec->capture_dma_data.maxburst = 4; scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
- if (of_device_is_compatible(pdev->dev.of_node,
"allwinner,sun7i-a20-codec"))
codec = &sun7i_codec_codec;
- else
codec = &sun4i_codec_codec;
It would be better to add a structure assiocated to the data field of of_device_id. That way, you'll also be able to have any quirks without adding more checks (such as a different regmap config, like Chen-Yu suggested).
Thanks! Maxime
Hi Maxime,
On Wed, 31 Aug 2016 19:46:23 +0200 Maxime Ripard maxime.ripard@free-electrons.com wrote:
-#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
That will need at least some mention in the commit log.
Hm? It's now called like it is called in the user manual. Also, the macro SUN4I_CODEC_AC_SYS_VERI was unused before anyway.
What should I write in the commit log?
It would be better to add a structure assiocated to the data field of of_device_id. That way, you'll also be able to have any quirks without adding more checks (such as a different regmap config, like Chen-Yu suggested).
Yeah, I did that now; seems to work.
Cheers, Danny
Hi Danny,
On Wed, Aug 31, 2016 at 10:14:02PM +0200, Danny Milosavljevic wrote:
Hi Maxime,
On Wed, 31 Aug 2016 19:46:23 +0200 Maxime Ripard maxime.ripard@free-electrons.com wrote:
-#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
That will need at least some mention in the commit log.
Hm? It's now called like it is called in the user manual. Also, the macro SUN4I_CODEC_AC_SYS_VERI was unused before anyway.
What should I write in the commit log?
For example, that the current code was wrong and those registers are not present on the A10.
That way, you justify both the renaming, and the max_register change in the regmap.
Maxime
Note: Mic1 Capture Volume is in a different register on A20 than on A10. Note: Mic2 Capture Volume is in a different register on A20 than on A10. --- sound/soc/sunxi/sun4i-codec.c | 256 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 236 insertions(+), 20 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 30f4ea2..f510e6d 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -59,9 +59,20 @@ #define SUN4I_CODEC_DAC_ACTL_DACAENR (31) #define SUN4I_CODEC_DAC_ACTL_DACAENL (30) #define SUN4I_CODEC_DAC_ACTL_MIXEN (29) +#define SUN4I_CODEC_DAC_ACTL_LNG (26) +#define SUN4I_CODEC_DAC_ACTL_FMG (23) +#define SUN4I_CODEC_DAC_ACTL_MICG (20) +#define SUN4I_CODEC_DAC_ACTL_LLNS (19) +#define SUN4I_CODEC_DAC_ACTL_RLNS (18) +#define SUN4I_CODEC_DAC_ACTL_LFMS (17) +#define SUN4I_CODEC_DAC_ACTL_RFMS (16) #define SUN4I_CODEC_DAC_ACTL_LDACLMIXS (15) #define SUN4I_CODEC_DAC_ACTL_RDACRMIXS (14) #define SUN4I_CODEC_DAC_ACTL_LDACRMIXS (13) +#define SUN4I_CODEC_DAC_ACTL_MIC1LS (12) +#define SUN4I_CODEC_DAC_ACTL_MIC1RS (11) +#define SUN4I_CODEC_DAC_ACTL_MIC2LS (10) +#define SUN4I_CODEC_DAC_ACTL_MIC2RS (9) #define SUN4I_CODEC_DAC_ACTL_DACPAS (8) #define SUN4I_CODEC_DAC_ACTL_MIXPAS (7) #define SUN4I_CODEC_DAC_ACTL_PA_MUTE (6) @@ -87,8 +98,12 @@ #define SUN4I_CODEC_ADC_ACTL_PREG1EN (29) #define SUN4I_CODEC_ADC_ACTL_PREG2EN (28) #define SUN4I_CODEC_ADC_ACTL_VMICEN (27) -#define SUN4I_CODEC_ADC_ACTL_VADCG (20) +#define SUN4I_CODEC_ADC_ACTL_PREG1 (25) +#define SUN4I_CODEC_ADC_ACTL_PREG2 (23) +#define SUN4I_CODEC_ADC_ACTL_ADCG (20) #define SUN4I_CODEC_ADC_ACTL_ADCIS (17) +#define SUN4I_CODEC_ADC_ACTL_LNRDF (16) +#define SUN4I_CODEC_ADC_ACTL_LNPREG (13) #define SUN4I_CODEC_ADC_ACTL_PA_EN (4) #define SUN4I_CODEC_ADC_ACTL_DDE (3) #define SUN4I_CODEC_ADC_DEBUG (0x2c) @@ -100,6 +115,9 @@ #define SUN7I_CODEC_AC_DAC_CAL (0x38) #define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1 (29) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2 (26) + struct sun4i_codec { struct device *dev; struct regmap *regmap; @@ -509,23 +527,142 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute = SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1); +static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_loopback_gain_scale, + -150, + 150, + 0); +static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_preamp_gain_scale, + -1200, + 300, + 0); +static DECLARE_TLV_DB_SCALE(sun4i_codec_fmin_loopback_gain_scale, + -450, + 150, + 0); +static DECLARE_TLV_DB_SCALE(sun4i_codec_micin_loopback_gain_scale, + -450, + 150, + 0); +static DECLARE_TLV_DB_RANGE(sun4i_codec_micin_preamp_gain_scale, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 7, TLV_DB_SCALE_ITEM(3500, 300, 0)); +static DECLARE_TLV_DB_SCALE(sun4i_codec_adc_gain_scale, -450, 150, 0); +static DECLARE_TLV_DB_RANGE(sun7i_codec_micin_preamp_gain_scale, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0) +); + +static const char * const sun4i_codec_capture_source[] = { + "Line", + "FM", + "Mic1", + "Mic2", + "Mic1,Mic2", + "Mic1+Mic2", + "Output Mixer", + "Line,Mic1", +}; +static SOC_ENUM_SINGLE_DECL(sun4i_codec_enum_capture_source, + SUN4I_CODEC_ADC_ACTL, + SUN4I_CODEC_ADC_ACTL_ADCIS, + sun4i_codec_capture_source); + +static const struct snd_kcontrol_new sun4i_codec_capture_source_controls = + SOC_DAPM_ENUM("Capture Source", sun4i_codec_enum_capture_source); + +static const char * const sun4i_codec_difflinein_capture_source[] = { + "Non-Differential", + "Differential", +}; +static SOC_ENUM_SINGLE_DECL(sun4i_codec_enum_difflinein_capture_source, + SUN4I_CODEC_ADC_ACTL, + SUN4I_CODEC_ADC_ACTL_ADCIS, + sun4i_codec_difflinein_capture_source); + +static const struct snd_kcontrol_new sun4i_codec_difflinein_capture_source_controls = + SOC_DAPM_ENUM("Differential Line Capture Switch", + sun4i_codec_enum_difflinein_capture_source);
#define SUN4I_COMMON_CODEC_CONTROLS \ - SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,\ - SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,\ - sun4i_codec_pa_volume_scale) + SOC_SINGLE_TLV("Headphone Playback Volume", SUN4I_CODEC_DAC_ACTL,\ + SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0, \ + sun4i_codec_pa_volume_scale), \ + /* Line, FM, Mic1, Mic2 */ \ + SOC_SINGLE_TLV("Line Playback Volume", \ + SUN4I_CODEC_DAC_ACTL, \ + SUN4I_CODEC_DAC_ACTL_LNG, \ + 1, \ + 0, \ + sun4i_codec_linein_loopback_gain_scale), \ + SOC_SINGLE_TLV("FM Playback Volume", \ + SUN4I_CODEC_DAC_ACTL, \ + SUN4I_CODEC_DAC_ACTL_FMG, \ + 3, \ + 0, \ + sun4i_codec_fmin_loopback_gain_scale), \ + SOC_SINGLE_TLV("Mic Playback Volume", \ + SUN4I_CODEC_DAC_ACTL, \ + SUN4I_CODEC_DAC_ACTL_MICG, \ + 7, \ + 0, \ + sun4i_codec_micin_loopback_gain_scale), \ + /* ADC */ \ + SOC_SINGLE_TLV("Capture Volume", \ + SUN4I_CODEC_ADC_ACTL, \ + SUN4I_CODEC_ADC_ACTL_ADCG, \ + 4, \ + 0, \ + sun4i_codec_adc_gain_scale), \ + SOC_SINGLE_TLV("Line Capture Volume", \ + SUN4I_CODEC_ADC_ACTL, \ + SUN4I_CODEC_ADC_ACTL_LNPREG, \ + 7, \ + 0, \ + sun4i_codec_linein_preamp_gain_scale)
static const struct snd_kcontrol_new sun4i_codec_controls[] = { SUN4I_COMMON_CODEC_CONTROLS, + SOC_SINGLE_TLV("Mic1 Capture Volume", + SUN4I_CODEC_ADC_ACTL, + SUN4I_CODEC_ADC_ACTL_PREG1, + 3, + 0, + sun4i_codec_micin_preamp_gain_scale), + SOC_SINGLE_TLV("Mic2 Capture Volume", + SUN4I_CODEC_ADC_ACTL, + SUN4I_CODEC_ADC_ACTL_PREG2, + 3, + 0, + sun4i_codec_micin_preamp_gain_scale), };
static const struct snd_kcontrol_new sun7i_codec_controls[] = { SUN4I_COMMON_CODEC_CONTROLS, + SOC_SINGLE_TLV("Mic1 Capture Volume", + SUN7I_CODEC_AC_MIC_PHONE_CAL, + SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1, + 7, + 0, + sun7i_codec_micin_preamp_gain_scale), + SOC_SINGLE_TLV("Mic2 Capture Volume", + SUN7I_CODEC_AC_MIC_PHONE_CAL, + SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2, + 7, + 0, + sun7i_codec_micin_preamp_gain_scale), };
static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = { SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_LDACLMIXS, 1, 0), + SOC_DAPM_SINGLE("Left Line Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_LLNS, 1, 0), + SOC_DAPM_SINGLE("Left FM Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_LFMS, 1, 0), + SOC_DAPM_SINGLE("Mic1 Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_MIC1LS, 1, 0), + SOC_DAPM_SINGLE("Mic2 Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_MIC2LS, 1, 0), };
static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = { @@ -533,6 +670,14 @@ static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = { SUN4I_CODEC_DAC_ACTL_RDACRMIXS, 1, 0), SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_LDACRMIXS, 1, 0), + SOC_DAPM_SINGLE("Right Line Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_RLNS, 1, 0), + SOC_DAPM_SINGLE("Right FM Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_RFMS, 1, 0), + SOC_DAPM_SINGLE("Mic1 Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_MIC1RS, 1, 0), + SOC_DAPM_SINGLE("Mic2 Playback Switch", SUN4I_CODEC_DAC_ACTL, + SUN4I_CODEC_DAC_ACTL_MIC2RS, 1, 0), };
static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = { @@ -565,6 +710,16 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_DACAENR, 0),
+ /* MUX */ + SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, + &sun4i_codec_capture_source_controls), + SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, + &sun4i_codec_capture_source_controls), + SND_SOC_DAPM_MUX("Differential Line Capture Switch", SND_SOC_NOPM, + 0, + 0, + &sun4i_codec_difflinein_capture_source_controls), + /* Mixers */ SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, sun4i_codec_left_mixer_controls, @@ -584,6 +739,8 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { /* Mic Pre-Amplifiers */ SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL, SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC2 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL, + SUN4I_CODEC_ADC_ACTL_PREG2EN, 0, NULL, 0),
/* Power Amplifier */ SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL, @@ -593,8 +750,15 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0, &sun4i_codec_pa_mute),
+ /* Inputs */ SND_SOC_DAPM_INPUT("Mic1"), + SND_SOC_DAPM_INPUT("Mic2"), + SND_SOC_DAPM_INPUT("Line Right"), + SND_SOC_DAPM_INPUT("Line Left"), + SND_SOC_DAPM_INPUT("FM Right"), + SND_SOC_DAPM_INPUT("FM Left"),
+ /* Outputs */ SND_SOC_DAPM_OUTPUT("HP Right"), SND_SOC_DAPM_OUTPUT("HP Left"), }; @@ -608,14 +772,22 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { { "Right ADC", NULL, "ADC" }, { "Right DAC", NULL, "DAC" },
+ /* Left Mixer Routes */ + { "Left Mixer", NULL, "Mixer Enable" }, + { "Left Mixer", "Left DAC Playback Switch", "Left DAC" }, + { "Left Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" }, + { "Left Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" }, + { "Left Mixer", "Left Line Playback Switch", "Line Left" }, + { "Left Mixer", "Left FM Playback Switch", "FM Left" }, + /* Right Mixer Routes */ { "Right Mixer", NULL, "Mixer Enable" }, { "Right Mixer", "Left DAC Playback Switch", "Left DAC" }, { "Right Mixer", "Right DAC Playback Switch", "Right DAC" }, - - /* Left Mixer Routes */ - { "Left Mixer", NULL, "Mixer Enable" }, - { "Left Mixer", "Left DAC Playback Switch", "Left DAC" }, + { "Right Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" }, + { "Right Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" }, + { "Right Mixer", "Right Line Playback Switch", "Line Right" }, + { "Right Mixer", "Right FM Playback Switch", "FM Right" },
/* Power Amplifier Routes */ { "Power Amplifier", "Mixer Playback Switch", "Left Mixer" }, @@ -633,26 +805,70 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { { "Right ADC", NULL, "MIC1 Pre-Amplifier" }, { "MIC1 Pre-Amplifier", NULL, "Mic1"}, { "Mic1", NULL, "VMIC" }, + /* see also Left Mixer Routes, Right Mixer Routes */ + + /* Mic2 Routes */ + { "Left ADC", NULL, "MIC2 Pre-Amplifier" }, + { "Right ADC", NULL, "MIC2 Pre-Amplifier" }, + { "MIC2 Pre-Amplifier", NULL, "Mic2"}, + { "Mic2", NULL, "VMIC" }, + /* see also Left Mixer Routes, Right Mixer Routes */ + + /* Line, FM Routes */ + /* see also Left Mixer Routes, Right Mixer Routes */ + + /* LNRDF Routes */ + { "Differential Line Capture Switch", "Differential", "Line Left" }, + { "Differential Line Capture Switch", "Differential", "Line Right" }, + /*{ "Differential Line Capture Switch", "Non-Differential", "Line X" }, implicit */ + + /* Left ADC Input Routes */ + { "Left Capture Select", "Line", "Line Left" }, + { "Left Capture Select", "Line", "Differential Line Capture Switch" }, + { "Left Capture Select", "FM", "FM Left" }, + { "Left Capture Select", "Mic1", "MIC1 Pre-Amplifier" }, + { "Left Capture Select", "Mic2", "MIC2 Pre-Amplifier" }, + { "Left Capture Select", "Mic1,Mic2", "MIC1 Pre-Amplifier" }, + { "Left Capture Select", "Mic1+Mic2", "MIC1 Pre-Amplifier" }, + { "Left Capture Select", "Mic1+Mic2", "MIC2 Pre-Amplifier" }, + { "Left Capture Select", "Output Mixer", "Left Mixer" }, + { "Left Capture Select", "Line,Mic1", "Line Left" }, + { "Left Capture Select", "Line,Mic1", "Differential Line Capture Switch" }, + { "Left ADC", NULL, "Left Capture Select" }, + + /* Right ADC Input Routes */ + { "Right Capture Select", "Line", "Line Right" }, + { "Right Capture Select", "Line", "Differential Line Capture Switch" }, + { "Right Capture Select", "FM", "FM Right" }, + { "Right Capture Select", "Mic1", "MIC1 Pre-Amplifier" }, + { "Right Capture Select", "Mic2", "MIC2 Pre-Amplifier" }, + { "Right Capture Select", "Mic1,Mic2", "MIC2 Pre-Amplifier" }, + { "Right Capture Select", "Mic1+Mic2", "MIC2 Pre-Amplifier" }, + { "Right Capture Select", "Mic1+Mic2", "MIC1 Pre-Amplifier" }, + { "Right Capture Select", "Output Mixer", "Right Mixer" }, + { "Right Capture Select", "Line,Mic1", "MIC1 Pre-Amplifier" }, + { "Right ADC", NULL, "Right Capture Select" }, };
static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = { - .controls = sun4i_codec_controls, - .num_controls = ARRAY_SIZE(sun4i_codec_controls), - .dapm_widgets = sun4i_codec_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), - .dapm_routes = sun4i_codec_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), + .controls = sun4i_codec_controls, + .num_controls = ARRAY_SIZE(sun4i_codec_controls), + .dapm_widgets = sun4i_codec_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), + .dapm_routes = sun4i_codec_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), }, }; + static struct snd_soc_codec_driver sun7i_codec_codec = { .component_driver = { - .controls = sun7i_codec_controls, - .num_controls = ARRAY_SIZE(sun7i_codec_controls), - .dapm_widgets = sun4i_codec_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), - .dapm_routes = sun4i_codec_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), + .controls = sun7i_codec_controls, + .num_controls = ARRAY_SIZE(sun7i_codec_controls), + .dapm_widgets = sun4i_codec_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), + .dapm_routes = sun4i_codec_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), }, };
Hi,
On Tue, Aug 30, 2016 at 1:44 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
Note: Mic1 Capture Volume is in a different register on A20 than on A10. Note: Mic2 Capture Volume is in a different register on A20 than on A10.
The subject would be better saying "Add support for Line-In, FM-In, Mic 2 and Capture Source paths". You are not just adding mixer controls, but DAPM widgets and routes as well.
A general description and any quirks of the hardware would be nice, such as the capture source has a mux and not a mixer, in addition to what you mentioned.
sound/soc/sunxi/sun4i-codec.c | 256 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 236 insertions(+), 20 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 30f4ea2..f510e6d 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -59,9 +59,20 @@ #define SUN4I_CODEC_DAC_ACTL_DACAENR (31) #define SUN4I_CODEC_DAC_ACTL_DACAENL (30) #define SUN4I_CODEC_DAC_ACTL_MIXEN (29) +#define SUN4I_CODEC_DAC_ACTL_LNG (26) +#define SUN4I_CODEC_DAC_ACTL_FMG (23) +#define SUN4I_CODEC_DAC_ACTL_MICG (20) +#define SUN4I_CODEC_DAC_ACTL_LLNS (19) +#define SUN4I_CODEC_DAC_ACTL_RLNS (18) +#define SUN4I_CODEC_DAC_ACTL_LFMS (17) +#define SUN4I_CODEC_DAC_ACTL_RFMS (16) #define SUN4I_CODEC_DAC_ACTL_LDACLMIXS (15) #define SUN4I_CODEC_DAC_ACTL_RDACRMIXS (14) #define SUN4I_CODEC_DAC_ACTL_LDACRMIXS (13) +#define SUN4I_CODEC_DAC_ACTL_MIC1LS (12) +#define SUN4I_CODEC_DAC_ACTL_MIC1RS (11) +#define SUN4I_CODEC_DAC_ACTL_MIC2LS (10) +#define SUN4I_CODEC_DAC_ACTL_MIC2RS (9) #define SUN4I_CODEC_DAC_ACTL_DACPAS (8) #define SUN4I_CODEC_DAC_ACTL_MIXPAS (7) #define SUN4I_CODEC_DAC_ACTL_PA_MUTE (6) @@ -87,8 +98,12 @@ #define SUN4I_CODEC_ADC_ACTL_PREG1EN (29) #define SUN4I_CODEC_ADC_ACTL_PREG2EN (28) #define SUN4I_CODEC_ADC_ACTL_VMICEN (27) -#define SUN4I_CODEC_ADC_ACTL_VADCG (20) +#define SUN4I_CODEC_ADC_ACTL_PREG1 (25) +#define SUN4I_CODEC_ADC_ACTL_PREG2 (23) +#define SUN4I_CODEC_ADC_ACTL_ADCG (20) #define SUN4I_CODEC_ADC_ACTL_ADCIS (17) +#define SUN4I_CODEC_ADC_ACTL_LNRDF (16) +#define SUN4I_CODEC_ADC_ACTL_LNPREG (13) #define SUN4I_CODEC_ADC_ACTL_PA_EN (4) #define SUN4I_CODEC_ADC_ACTL_DDE (3) #define SUN4I_CODEC_ADC_DEBUG (0x2c) @@ -100,6 +115,9 @@ #define SUN7I_CODEC_AC_DAC_CAL (0x38) #define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c)
+#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1 (29) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2 (26)
struct sun4i_codec { struct device *dev; struct regmap *regmap; @@ -509,23 +527,142 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute = SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1); +static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_loopback_gain_scale,
X_playback_gain_scale, matching the control names later.
-150,
150,
0);
+static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_preamp_gain_scale,
-1200,
300,
0);
+static DECLARE_TLV_DB_SCALE(sun4i_codec_fmin_loopback_gain_scale,
-450,
150,
0);
+static DECLARE_TLV_DB_SCALE(sun4i_codec_micin_loopback_gain_scale,
-450,
150,
0);
Please merge the above 2. Also can they be const? Same for all the other TLV structures.
+static DECLARE_TLV_DB_RANGE(sun4i_codec_micin_preamp_gain_scale,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 7, TLV_DB_SCALE_ITEM(3500, 300, 0));
+static DECLARE_TLV_DB_SCALE(sun4i_codec_adc_gain_scale, -450, 150, 0); +static DECLARE_TLV_DB_RANGE(sun7i_codec_micin_preamp_gain_scale,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0)
+);
+static const char * const sun4i_codec_capture_source[] = {
"Line",
"FM",
"Mic1",
"Mic2",
"Mic1,Mic2",
"Mic1+Mic2",
"Output Mixer",
Given there's only one mixer in the system, you can drop the "Output".
"Line,Mic1",
+}; +static SOC_ENUM_SINGLE_DECL(sun4i_codec_enum_capture_source,
SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_ADCIS,
sun4i_codec_capture_source);
+static const struct snd_kcontrol_new sun4i_codec_capture_source_controls =
SOC_DAPM_ENUM("Capture Source", sun4i_codec_enum_capture_source);
+static const char * const sun4i_codec_difflinein_capture_source[] = {
"Non-Differential",
"Differential",
How about "Stereo"? And possibly "Mono Differential"? or just "Mono". A differential input can be used single-ended by grounding one side.
+}; +static SOC_ENUM_SINGLE_DECL(sun4i_codec_enum_difflinein_capture_source,
SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_ADCIS,
sun4i_codec_difflinein_capture_source);
+static const struct snd_kcontrol_new sun4i_codec_difflinein_capture_source_controls =
SOC_DAPM_ENUM("Differential Line Capture Switch",
sun4i_codec_enum_difflinein_capture_source);
#define SUN4I_COMMON_CODEC_CONTROLS \
SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,\
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,\
sun4i_codec_pa_volume_scale)
SOC_SINGLE_TLV("Headphone Playback Volume", SUN4I_CODEC_DAC_ACTL,\
SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0, \
sun4i_codec_pa_volume_scale), \
/* Line, FM, Mic1, Mic2 */ \
SOC_SINGLE_TLV("Line Playback Volume", \
SUN4I_CODEC_DAC_ACTL, \
SUN4I_CODEC_DAC_ACTL_LNG, \
1, \
0, \
sun4i_codec_linein_loopback_gain_scale), \
SOC_SINGLE_TLV("FM Playback Volume", \
SUN4I_CODEC_DAC_ACTL, \
SUN4I_CODEC_DAC_ACTL_FMG, \
3, \
0, \
sun4i_codec_fmin_loopback_gain_scale), \
SOC_SINGLE_TLV("Mic Playback Volume", \
SUN4I_CODEC_DAC_ACTL, \
SUN4I_CODEC_DAC_ACTL_MICG, \
7, \
0, \
sun4i_codec_micin_loopback_gain_scale), \
/* ADC */ \
SOC_SINGLE_TLV("Capture Volume", \
SUN4I_CODEC_ADC_ACTL, \
SUN4I_CODEC_ADC_ACTL_ADCG, \
4, \
0, \
sun4i_codec_adc_gain_scale), \
SOC_SINGLE_TLV("Line Capture Volume", \
SUN4I_CODEC_ADC_ACTL, \
SUN4I_CODEC_ADC_ACTL_LNPREG, \
7, \
0, \
sun4i_codec_linein_preamp_gain_scale)
Nope. This is a pre-gain or boost. It affects both playback and capture. "Line Boost Volume" would be better.
static const struct snd_kcontrol_new sun4i_codec_controls[] = { SUN4I_COMMON_CODEC_CONTROLS,
SOC_SINGLE_TLV("Mic1 Capture Volume",
SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_PREG1,
3,
0,
sun4i_codec_micin_preamp_gain_scale),
SOC_SINGLE_TLV("Mic2 Capture Volume",
SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_PREG2,
3,
0,
sun4i_codec_micin_preamp_gain_scale),
};
static const struct snd_kcontrol_new sun7i_codec_controls[] = { SUN4I_COMMON_CODEC_CONTROLS,
SOC_SINGLE_TLV("Mic1 Capture Volume",
SUN7I_CODEC_AC_MIC_PHONE_CAL,
SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1,
7,
0,
sun7i_codec_micin_preamp_gain_scale),
SOC_SINGLE_TLV("Mic2 Capture Volume",
SUN7I_CODEC_AC_MIC_PHONE_CAL,
SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2,
7,
0,
sun7i_codec_micin_preamp_gain_scale),
Same for the Mic pre-amp gain controls.
};
static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = { SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_LDACLMIXS, 1, 0),
SOC_DAPM_SINGLE("Left Line Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_LLNS, 1, 0),
SOC_DAPM_SINGLE("Left FM Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_LFMS, 1, 0),
SOC_DAPM_SINGLE("Mic1 Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_MIC1LS, 1, 0),
SOC_DAPM_SINGLE("Mic2 Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_MIC2LS, 1, 0),
};
static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = { @@ -533,6 +670,14 @@ static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = { SUN4I_CODEC_DAC_ACTL_RDACRMIXS, 1, 0), SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_LDACRMIXS, 1, 0),
SOC_DAPM_SINGLE("Right Line Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_RLNS, 1, 0),
SOC_DAPM_SINGLE("Right FM Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_RFMS, 1, 0),
SOC_DAPM_SINGLE("Mic1 Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_MIC1RS, 1, 0),
SOC_DAPM_SINGLE("Mic2 Playback Switch", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_MIC2RS, 1, 0),
I have a few patches that introduce SOC_DAPM_DOUBLE, so you can share a control between left/right channels. IMHO it makes the userspace mixer less confusing.
};
static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = { @@ -565,6 +710,16 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_DACAENR, 0),
/* MUX */
SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Differential Line Capture Switch", SND_SOC_NOPM,
0,
0,
&sun4i_codec_difflinein_capture_source_controls),
The proper function suffix is "Route", not "Select".
/* Mixers */ SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, sun4i_codec_left_mixer_controls,
@@ -584,6 +739,8 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { /* Mic Pre-Amplifiers */ SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL, SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0),
SND_SOC_DAPM_PGA("MIC2 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_PREG2EN, 0, NULL, 0), /* Power Amplifier */ SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL,
@@ -593,8 +750,15 @@ static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0, &sun4i_codec_pa_mute),
/* Inputs */ SND_SOC_DAPM_INPUT("Mic1"),
SND_SOC_DAPM_INPUT("Mic2"),
How about SND_SOC_DAPM_MIC? And what about microphone bias?
SND_SOC_DAPM_INPUT("Line Right"),
SND_SOC_DAPM_INPUT("Line Left"),
SND_SOC_DAPM_INPUT("FM Right"),
SND_SOC_DAPM_INPUT("FM Left"),
Why the left/right channels? You aren't doing anything special for them. You could just have one Line and one FM, and have routes to left/right mixers.
/* Outputs */ SND_SOC_DAPM_OUTPUT("HP Right"), SND_SOC_DAPM_OUTPUT("HP Left"),
}; @@ -608,14 +772,22 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { { "Right ADC", NULL, "ADC" }, { "Right DAC", NULL, "DAC" },
/* Left Mixer Routes */
{ "Left Mixer", NULL, "Mixer Enable" },
{ "Left Mixer", "Left DAC Playback Switch", "Left DAC" },
{ "Left Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
{ "Left Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
{ "Left Mixer", "Left Line Playback Switch", "Line Left" },
{ "Left Mixer", "Left FM Playback Switch", "FM Left" },
/* Right Mixer Routes */ { "Right Mixer", NULL, "Mixer Enable" }, { "Right Mixer", "Left DAC Playback Switch", "Left DAC" }, { "Right Mixer", "Right DAC Playback Switch", "Right DAC" },
/* Left Mixer Routes */
{ "Left Mixer", NULL, "Mixer Enable" },
{ "Left Mixer", "Left DAC Playback Switch", "Left DAC" },
{ "Right Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
{ "Right Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
{ "Right Mixer", "Right Line Playback Switch", "Line Right" },
{ "Right Mixer", "Right FM Playback Switch", "FM Right" }, /* Power Amplifier Routes */ { "Power Amplifier", "Mixer Playback Switch", "Left Mixer" },
@@ -633,26 +805,70 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { { "Right ADC", NULL, "MIC1 Pre-Amplifier" }, { "MIC1 Pre-Amplifier", NULL, "Mic1"}, { "Mic1", NULL, "VMIC" },
/* see also Left Mixer Routes, Right Mixer Routes */
/* Mic2 Routes */
{ "Left ADC", NULL, "MIC2 Pre-Amplifier" },
{ "Right ADC", NULL, "MIC2 Pre-Amplifier" },
{ "MIC2 Pre-Amplifier", NULL, "Mic2"},
{ "Mic2", NULL, "VMIC" },
/* see also Left Mixer Routes, Right Mixer Routes */
/* Line, FM Routes */
/* see also Left Mixer Routes, Right Mixer Routes */
/* LNRDF Routes */
{ "Differential Line Capture Switch", "Differential", "Line Left" },
{ "Differential Line Capture Switch", "Differential", "Line Right" },
/*{ "Differential Line Capture Switch", "Non-Differential", "Line X" }, implicit */
/* Left ADC Input Routes */
{ "Left Capture Select", "Line", "Line Left" },
{ "Left Capture Select", "Line", "Differential Line Capture Switch" },
{ "Left Capture Select", "FM", "FM Left" },
{ "Left Capture Select", "Mic1", "MIC1 Pre-Amplifier" },
{ "Left Capture Select", "Mic2", "MIC2 Pre-Amplifier" },
{ "Left Capture Select", "Mic1,Mic2", "MIC1 Pre-Amplifier" },
{ "Left Capture Select", "Mic1+Mic2", "MIC1 Pre-Amplifier" },
{ "Left Capture Select", "Mic1+Mic2", "MIC2 Pre-Amplifier" },
{ "Left Capture Select", "Output Mixer", "Left Mixer" },
{ "Left Capture Select", "Line,Mic1", "Line Left" },
{ "Left Capture Select", "Line,Mic1", "Differential Line Capture Switch" },
{ "Left ADC", NULL, "Left Capture Select" },
/* Right ADC Input Routes */
{ "Right Capture Select", "Line", "Line Right" },
{ "Right Capture Select", "Line", "Differential Line Capture Switch" },
{ "Right Capture Select", "FM", "FM Right" },
{ "Right Capture Select", "Mic1", "MIC1 Pre-Amplifier" },
{ "Right Capture Select", "Mic2", "MIC2 Pre-Amplifier" },
{ "Right Capture Select", "Mic1,Mic2", "MIC2 Pre-Amplifier" },
{ "Right Capture Select", "Mic1+Mic2", "MIC2 Pre-Amplifier" },
{ "Right Capture Select", "Mic1+Mic2", "MIC1 Pre-Amplifier" },
{ "Right Capture Select", "Output Mixer", "Right Mixer" },
{ "Right Capture Select", "Line,Mic1", "MIC1 Pre-Amplifier" },
{ "Right ADC", NULL, "Right Capture Select" },
};
static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = {
.controls = sun4i_codec_controls,
.num_controls = ARRAY_SIZE(sun4i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
.controls = sun4i_codec_controls,
.num_controls = ARRAY_SIZE(sun4i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), },
};
static struct snd_soc_codec_driver sun7i_codec_codec = { .component_driver = {
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
You should put these changes in the first patch.
Note that I haven't checked the register offsets.
Regards ChenYu
},
};
Hi Chen-Yu,
+static const char * const sun4i_codec_difflinein_capture_source[] = {
"Non-Differential",
"Differential",
How about "Stereo"? And possibly "Mono Differential"? or just "Mono".
A differential input can be used single-ended by grounding one side.
Yes, but that's interpretation of what it's going to be used for. The hardware either subtracts or not, nothing more. That said, I'll change it to "Stereo" and "Mono Differential".
SOC_SINGLE_TLV("Line Capture Volume", \
SUN4I_CODEC_ADC_ACTL, \
SUN4I_CODEC_ADC_ACTL_LNPREG, \
7, \
0, \
sun4i_codec_linein_preamp_gain_scale)
Nope. This is a pre-gain or boost. It affects both playback and capture. "Line Boost Volume" would be better.
According to Documentation/sound/alsa/ControlNames.txt that is not a valid name. Also alsa-lib does special things depending on the control name so we are not free to choose here. If it were me freely choosing the names then half the control names in this module would change.
Same for the Mic pre-amp gain controls.
Likewise. I can see that it's confusing... but what should we do?
I have a few patches that introduce SOC_DAPM_DOUBLE, so you can share a control between left/right channels. IMHO it makes the userspace mixer less confusing.
I agree. It would be nice to use this in the future when it's merged. Will you post it?
/* MUX */
SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Differential Line Capture Switch", SND_SOC_NOPM,
0,
0,
&sun4i_codec_difflinein_capture_source_controls),
The proper function suffix is "Route", not "Select".
Indeed. Also for "Differential Line Capture Switch" except for the enum, I suppose.
/* Inputs */ SND_SOC_DAPM_INPUT("Mic1"),
SND_SOC_DAPM_INPUT("Mic2"),
How about SND_SOC_DAPM_MIC?
What does it do differently? Seems to use different callback and all. Is it worth changing an extensively tested patch because of it?
And what about microphone bias?
The User Manual mentions microphone bias exactly once - in the summary.
Searching for just "bias", there's AC_ADDA_BIAS_CTRL "for DAC/ADC performance tuning" and AC_DAC_CAL BIASCALI. Is it one of those? How does it work?
SND_SOC_DAPM_INPUT("Line Right"),
SND_SOC_DAPM_INPUT("Line Left"),
SND_SOC_DAPM_INPUT("FM Right"),
SND_SOC_DAPM_INPUT("FM Left"),
Why the left/right channels?
Because they exist in hardware. Also Mic1 and Mic2 are listed as well, so for symmetry.
You aren't doing anything special for them. You could just have one Line and one FM, and have routes to left/right mixers.
static struct snd_soc_codec_driver sun7i_codec_codec = { .component_driver = {
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
You should put these changes in the first patch.
Indeed.
Cheers, Danny
On Wed, Aug 31, 2016 at 3:17 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
Hi Chen-Yu,
+static const char * const sun4i_codec_difflinein_capture_source[] = {
"Non-Differential",
"Differential",
How about "Stereo"? And possibly "Mono Differential"? or just "Mono".
A differential input can be used single-ended by grounding one side.
Yes, but that's interpretation of what it's going to be used for. The hardware either subtracts or not, nothing more. That said, I'll change it to "Stereo" and "Mono Differential".
SOC_SINGLE_TLV("Line Capture Volume", \
SUN4I_CODEC_ADC_ACTL, \
SUN4I_CODEC_ADC_ACTL_LNPREG, \
7, \
0, \
sun4i_codec_linein_preamp_gain_scale)
Nope. This is a pre-gain or boost. It affects both playback and capture. "Line Boost Volume" would be better.
According to Documentation/sound/alsa/ControlNames.txt that is not a valid name. Also alsa-lib does special things depending on the control name so we are not free to choose here. If it were me freely choosing the names then half the control names in this module would change.
I saw some other drivers use "Boost Volume". Also, alsa-lib looks for suffices, such as "Volume", "Playback Volume", "Switch", etc..
"Boost" is not part of any special name treatment. Though if you want to follow ControlNames.txt closely, I would suggest "X Pre-Amp", which would really be the source.
Same for the Mic pre-amp gain controls.
Likewise. I can see that it's confusing... but what should we do?
I have a few patches that introduce SOC_DAPM_DOUBLE, so you can share a control between left/right channels. IMHO it makes the userspace mixer less confusing.
I agree. It would be nice to use this in the future when it's merged. Will you post it?
I will, probably as part of the A31 codec series. If you really like it I can post it first, and we both can base our patches on it.
As you mentioned ControlNames.txt, I need to revisit the A31 control names.
/* MUX */
SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
&sun4i_codec_capture_source_controls),
SND_SOC_DAPM_MUX("Differential Line Capture Switch", SND_SOC_NOPM,
0,
0,
&sun4i_codec_difflinein_capture_source_controls),
The proper function suffix is "Route", not "Select".
Indeed. Also for "Differential Line Capture Switch" except for the enum, I suppose.
IIRC alsa-lib checks if it's an enum first, so it would appear as the right type of control anyway. I'm not sure though.
/* Inputs */ SND_SOC_DAPM_INPUT("Mic1"),
SND_SOC_DAPM_INPUT("Mic2"),
How about SND_SOC_DAPM_MIC?
What does it do differently? Seems to use different callback and all. Is it worth changing an extensively tested patch because of it?
Seems that you can tie an extra event handler to it, and it is treated as an endpoint on a fully routed card. Neither is the case here, so it really makes no difference. Lets keep it as INPUT for now.
Ref: On a fully routed card, INPUT/OUTPUT widgets are not endpoints. You need to route Mic/Headphone/Speaker/Line widgets to/from them for the whole path to work.
I might need to rethink my approach as well.
And what about microphone bias?
The User Manual mentions microphone bias exactly once - in the summary.
Searching for just "bias", there's AC_ADDA_BIAS_CTRL "for DAC/ADC performance tuning" and AC_DAC_CAL BIASCALI. Is it one of those? How does it work?
As I mentioned in my other reply, you did everything right in this patch. Sorry for the noise.
SND_SOC_DAPM_INPUT("Line Right"),
SND_SOC_DAPM_INPUT("Line Left"),
SND_SOC_DAPM_INPUT("FM Right"),
SND_SOC_DAPM_INPUT("FM Left"),
Why the left/right channels?
Because they exist in hardware. Also Mic1 and Mic2 are listed as well, so for symmetry.
You aren't doing anything special for them. You could just have one Line and one FM, and have routes to left/right mixers.
static struct snd_soc_codec_driver sun7i_codec_codec = { .component_driver = {
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
.controls = sun7i_codec_controls,
.num_controls = ARRAY_SIZE(sun7i_codec_controls),
.dapm_widgets = sun4i_codec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
.dapm_routes = sun4i_codec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
You should put these changes in the first patch.
Indeed.
Cheers, Danny
Regards ChenYu
And what about microphone bias?
Would this be OK?
static int sun4i_codec_handle_mic_bias_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); if (SND_SOC_DAPM_EVENT_ON(event)) regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL, BIT(SUN4I_CODEC_ADC_ACTL_VMICEN), BIT(SUN4I_CODEC_ADC_ACTL_VMICEN)); else regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL, BIT(SUN4I_CODEC_ADC_ACTL_VMICEN), 0); }
static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { ... SND_SOC_DAPM_MIC("Mic1", sun4i_codec_handle_mic_bias_event), SND_SOC_DAPM_MIC("Mic2", sun4i_codec_handle_mic_bias_event),
Do I then remove
SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL, SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
completely? What about the routes?
On Wed, Aug 31, 2016 at 3:40 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
And what about microphone bias?
Would this be OK?
static int sun4i_codec_handle_mic_bias_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); if (SND_SOC_DAPM_EVENT_ON(event)) regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL, BIT(SUN4I_CODEC_ADC_ACTL_VMICEN), BIT(SUN4I_CODEC_ADC_ACTL_VMICEN)); else regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL, BIT(SUN4I_CODEC_ADC_ACTL_VMICEN), 0); }
static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = { ... SND_SOC_DAPM_MIC("Mic1", sun4i_codec_handle_mic_bias_event), SND_SOC_DAPM_MIC("Mic2", sun4i_codec_handle_mic_bias_event),
Do I then remove
SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL, SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
completely? What about the routes?
My apologies. I didn't notice that VMIC was already in the driver. In that your original patch did everything right.
ChenYu
Hi Chen-Yu,
My apologies. I didn't notice that VMIC was already in the driver. In that your original patch did everything right.
Don't worry about it :)
But I have a question:
If I replace DAPM_INPUT by DAPM_MIC it wants a callback that is supposed to fiddle with the bias. Do I provide one? If so, will it conflict with the supply?
Or do I leave it as DAPM_INPUT ?
On Wed, Aug 31, 2016 at 3:49 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
Hi Chen-Yu,
My apologies. I didn't notice that VMIC was already in the driver. In that your original patch did everything right.
Don't worry about it :)
But I have a question:
If I replace DAPM_INPUT by DAPM_MIC it wants a callback that is supposed to fiddle with the bias. Do I provide one? If so, will it conflict with the supply?
Or do I leave it as DAPM_INPUT ?
I think leaving it as DAPM_INPUT will do. Also, if you use DAPM_MIC or any other widget type that takes a callback, the callback can be NULL.
I took a quick look at other drivers. The codecs only use non-endpoint types, like INPUT/OUTPUT. It's up to the card to provide endpoints (HP/SPEAKER/LINE/MIC) and route them to the codec INPUT/OUTPUTs.
Regards ChenYu
Hi Chen-Yu,
I have a few patches that introduce SOC_DAPM_DOUBLE, so you can share a control between left/right channels. IMHO it makes the userspace mixer less confusing.
I definitely agree that cutting down on the number of sliders would be good. I do a double-take every time I open alsamixer - and I *added* these sun4i widgets :)
It would be good if your patch series was queued and I could use SOC_DAPM_DOUBLE in a future version of my patch.
Can you post it?
Since it changes user space-visible API whether I group the widgets or not we have to be careful about it. So far my patch has not been merged which is good for API stability I guess.
I wondered about why there's a SOC_DOUBLE_TLV but no SOC_DAPM_DOUBLE before, so it's good to know there's no deep reason.
That said, I'd have to remove the distinction between Left Mixer and Right Mixer then. Right now it does distinguish.
Removing the distinction would remove noteworthy routes like
{ "Right Mixer", "Left DAC Playback Switch", "Left DAC" },
(not a typo). Would that be OK?
Well, let's see how it will work out.
In the mean time I added the second regmap and the quirks and will post another patch series for comments.
Cheers, Danny
On Thu, Sep 1, 2016 at 6:56 PM, Danny Milosavljevic dannym@scratchpost.org wrote:
Hi Chen-Yu,
I have a few patches that introduce SOC_DAPM_DOUBLE, so you can share a control between left/right channels. IMHO it makes the userspace mixer less confusing.
I definitely agree that cutting down on the number of sliders would be good. I do a double-take every time I open alsamixer - and I *added* these sun4i widgets :)
It would be good if your patch series was queued and I could use SOC_DAPM_DOUBLE in a future version of my patch.
Can you post it?
I'll try to make some time.
Since it changes user space-visible API whether I group the widgets or not we have to be careful about it. So far my patch has not been merged which is good for API stability I guess.
I wondered about why there's a SOC_DOUBLE_TLV but no SOC_DAPM_DOUBLE before, so it's good to know there's no deep reason.
AFAIU DAPM can't handle multiple channels. SOC_DAPM_ENUM_DOUBLE being the exception, as for enums both channels are controlled together, so you don't run into the problem of having to figure out which channel to connect or disconnect.
That said, I'd have to remove the distinction between Left Mixer and Right Mixer then. Right now it does distinguish.
Removing the distinction would remove noteworthy routes like
{ "Right Mixer", "Left DAC Playback Switch", "Left DAC" },
(not a typo). Would that be OK?
The SOC_DAPM_DOUBLE controls are to be shared between the left/right widgets.
See: https://github.com/wens/linux/commit/ea8ce9e865635595c73bc8f7eecd711d7500f8b...
sun6i_codec_mixer_controls is shared by the "Left Mixer" and "Right Mixer" widgets. (Not shown in the patch.)
So you would still have:
{ "Left Mixer", "DAC Playback Switch", "Left DAC" }, { "Right Mixer", "DAC Playback Switch", "Right DAC" },
This is what the DAPM diagram looks like on my A31:
The routes are not exported to userspace, not counting debugfs. Only the controls are.
Hope this explains things.
Regards ChenYu
Well, let's see how it will work out.
In the mean time I added the second regmap and the quirks and will post another patch series for comments.
Cheers, Danny
-- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
participants (3)
-
Chen-Yu Tsai
-
Danny Milosavljevic
-
Maxime Ripard