[alsa-devel] [PATCH] ASoC: omap: rx51: Add stereo output support to audio jack
Audio jack in Nokia RX-51/N900 is driven by TPA6130 headphone amplifier. This patch adds support for it and stereo output can be active when "Jack Function" == "TV-OUT" || "Headphone".
As the TPA6130 can output very high volume levels the output is limited with snd_soc_limit_volume. Limiting value is found from Maemo kernel sources.
Signed-off-by: Jarkko Nikula jhnikula@gmail.com Cc: Peter Ujfalusi peter.ujfalusi@nokia.com --- This support could have been implemented earlier but I was targeting to have ASoC cross-device support first. But as there's no DAPM widgets anymore in TPA6130, I don't see any other way to implement this than by registering TPA6130 controls to aic34a with tpa6130a2_add_controls and by using tpa6130a2_stereo_enable.
This is from top of "ASoC: Remove needless inclusion of tlv320aic3x.h from machine drivers" but applies also into lrg's tree. --- sound/soc/omap/Kconfig | 1 + sound/soc/omap/rx51.c | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index a088db6..b592298 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -24,6 +24,7 @@ config SND_OMAP_SOC_RX51 select OMAP_MCBSP select SND_OMAP_SOC_MCBSP select SND_SOC_TLV320AIC3X + select SND_SOC_TPA6130A2 help Say Y if you want to add support for SoC audio on Nokia RX-51 hardware. This is also known as Nokia N900 product. diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 09fb0df..251afbe 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -31,6 +31,7 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <plat/mcbsp.h> +#include "../codecs/tpa6130a2.h"
#include <asm/mach-types.h>
@@ -47,7 +48,8 @@
enum { RX51_JACK_DISABLED, - RX51_JACK_TVOUT, /* tv-out */ + RX51_JACK_TVOUT, /* tv-out with stereo output */ + RX51_JACK_HP, /* headphone: stereo output, no mic */ };
static int rx51_spk_func; @@ -57,6 +59,15 @@ static int rx51_jack_func; static void rx51_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; + int hp = 0, tvout = 0; + + switch (rx51_jack_func) { + case RX51_JACK_TVOUT: + tvout = 1; + case RX51_JACK_HP: + hp = 1; + break; + }
if (rx51_spk_func) snd_soc_dapm_enable_pin(dapm, "Ext Spk"); @@ -66,9 +77,12 @@ static void rx51_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_enable_pin(dapm, "DMic"); else snd_soc_dapm_disable_pin(dapm, "DMic"); + if (hp) + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + else + snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
- gpio_set_value(RX51_TVOUT_SEL_GPIO, - rx51_jack_func == RX51_JACK_TVOUT); + gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
snd_soc_dapm_sync(dapm); } @@ -153,6 +167,19 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
+static int rx51_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_codec *codec = w->dapm->codec; + + if (SND_SOC_DAPM_EVENT_ON(event)) + tpa6130a2_stereo_enable(codec, 1); + else + tpa6130a2_stereo_enable(codec, 0); + + return 0; +} + static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -212,11 +239,14 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL), + SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), };
static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPLOUT"}, {"Ext Spk", NULL, "HPROUT"}, + {"Headphone Jack", NULL, "LLOUT"}, + {"Headphone Jack", NULL, "RLOUT"},
{"DMic Rate 64", NULL, "Mic Bias 2V"}, {"Mic Bias 2V", NULL, "DMic"}, @@ -224,7 +254,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
static const char *spk_function[] = {"Off", "On"}; static const char *input_function[] = {"ADC", "Digital Mic"}; -static const char *jack_function[] = {"Off", "TV-OUT"}; +static const char *jack_function[] = {"Off", "TV-OUT", "Headphone"};
static const struct soc_enum rx51_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), @@ -265,6 +295,11 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) /* Set up RX-51 specific audio path audio_map */ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+ err = tpa6130a2_add_controls(codec); + if (err < 0) + return err; + snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42); + snd_soc_dapm_sync(dapm);
/* AV jack detection */
On Wed, Jan 05, 2011 at 05:46:00PM +0200, Jarkko Nikula wrote:
This support could have been implemented earlier but I was targeting to have ASoC cross-device support first. But as there's no DAPM widgets anymore in TPA6130, I don't see any other way to implement this than by registering TPA6130 controls to aic34a with tpa6130a2_add_controls and by using tpa6130a2_stereo_enable.
Having thought about it for at least a second I think we should have a DAPM context in the cards for all the board-level stuff - does that seem resonable? The patch itself looks good:
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
in the context of the current APIs, though.
On Wed, 5 Jan 2011 15:55:09 +0000 Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Wed, Jan 05, 2011 at 05:46:00PM +0200, Jarkko Nikula wrote:
This support could have been implemented earlier but I was targeting to have ASoC cross-device support first. But as there's no DAPM widgets anymore in TPA6130, I don't see any other way to implement this than by registering TPA6130 controls to aic34a with tpa6130a2_add_controls and by using tpa6130a2_stereo_enable.
Having thought about it for at least a second I think we should have a DAPM context in the cards for all the board-level stuff - does that seem resonable? The patch itself looks good:
I don't know. Probably it would be good if machine widgets are in own context. Like having own debugfs/sysfs directory for them etc.
In this case it would be just enough if the tpa6130 is a codec driver having DAPM widgets. Then machine driver wouldn't need any these exported special tpa6130a2_ functions and soc-dapm could take care of power changes according to audio map and other info.
But as far as I understood there's no any better way to get rid of pops in tpa6130a2.
On Wed, Jan 05, 2011 at 06:29:24PM +0200, Jarkko Nikula wrote:
Mark Brown broonie@opensource.wolfsonmicro.com wrote:
Having thought about it for at least a second I think we should have a DAPM context in the cards for all the board-level stuff - does that seem resonable? The patch itself looks good:
I don't know. Probably it would be good if machine widgets are in own context. Like having own debugfs/sysfs directory for them etc.
Yes, exactly.
In this case it would be just enough if the tpa6130 is a codec driver having DAPM widgets. Then machine driver wouldn't need any these exported special tpa6130a2_ functions and soc-dapm could take care of power changes according to audio map and other info.
But as far as I understood there's no any better way to get rid of pops in tpa6130a2.
As far as I remember from the previous discussion that had been that making it a CODEC driver would be the simplest thing. Peter said in reply to my mail saying this:
| At least with my device I need to add some delay before enabling the amp, so | anyway I need to ahve the DAPM_HP in the machine driver.
but it'd seem that the amp driver could do this just as well, possibly based off platform data?
From: ext Mark Brown [broonie@opensource.wolfsonmicro.com] Sent: Wednesday, January 05, 2011 18:39 To: Jarkko Nikula Cc: alsa-devel@alsa-project.org; Liam Girdwood; Ujfalusi Peter (Nokia-MS/Tampere) Subject: Re: [PATCH] ASoC: omap: rx51: Add stereo output support to audio jack
As far as I remember from the previous discussion that had been that making it a CODEC driver would be the simplest thing. Peter said in reply to my mail saying this:
| At least with my device I need to add some delay before enabling the amp, so | anyway I need to ahve the DAPM_HP in the machine driver.
but it'd seem that the amp driver could do this just as well, possibly based off platform data?
Yes that could be done with platform data (the additional delay after amp enable). The only thing is that the tpa6130a2 driver must have DAPM_HP widget. If we do that, than it would be also useful to have the SOC_DAPM_PIN_SWITCH() defined in the tpa6130a2 driver, which might cause some problems with the rx51 machine driver, as Jarkko handling the pins within that. In rx51, we have several functions on the jack, so SOC_DAPM_PIN_SWITCH() will not going to work there, but in my board, I'm using that. While we are here, I'd also like to customize the DAPM_HP name as well, since I do not want to have TPA6XXXX HP or something visible for user space. Also: Calling dapm_sync from machine driver might cause some locking issues: http://mailman.alsa-project.org/pipermail/alsa-devel/2010-November/033362.ht...
I have another issue with my setup, which needs the exported enable/disable function, which is the playback start, while the codec BIAS is on, since I need to do some tricks to remove some unwanted clicks.
We can add optional DAPM widget to the driver, as I already commented, I have no problems with that, but it has to be really optional.
Peter
participants (3)
-
Jarkko Nikula
-
Mark Brown
-
peter.ujfalusi@nokia.com