diff mbox

[2/3] ASoC: twl4030: allow voice port to be connected externally.

Message ID 20141108003803.6561.57464.stgit@notabene.brown
State Needs Review / ACK, archived
Headers show

Checks

Context Check Description
robh/checkpatch warning total: 1 errors, 0 warnings, 0 lines checked
robh/patch-applied success

Commit Message

NeilBrown Nov. 8, 2014, 12:38 a.m. UTC
If voice port on twl4030 is not connected to a McBSP (or similar)
then we cannot configure the format the way we normally do for a DAI.

In this case, allow the platform data/devicetree to specify a format
which is put into effect when the 'voice' mode is selected.

If there is a voice connection, then we keep the twl side tri-stated
when not being driven.  This allows for the device to also be
connected to a McBSP if desired.

This is needed if the 'voice' port directly connects to a mobile-phone
module.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../devicetree/bindings/mfd/twl4030-audio.txt      |    7 ++++
 include/linux/i2c/twl.h                            |    3 ++
 sound/soc/codecs/twl4030.c                         |   34 +++++++++++++++++++-
 3 files changed, 42 insertions(+), 2 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Mark Brown Nov. 8, 2014, 9:26 a.m. UTC | #1
On Sat, Nov 08, 2014 at 11:38:03AM +1100, NeilBrown wrote:

> If voice port on twl4030 is not connected to a McBSP (or similar)
> then we cannot configure the format the way we normally do for a DAI.

Yes we can, you need to represent the DAI link to whatever else the
device is connected to in the driver like we do anything else - and in
any case this isn't a device specific issue so we shouldn't be doing
something driver specific to solve it.  Look at something like speyside.
NeilBrown Nov. 9, 2014, 11:25 p.m. UTC | #2
On Sat, 8 Nov 2014 09:26:22 +0000 Mark Brown <broonie@kernel.org> wrote:

> On Sat, Nov 08, 2014 at 11:38:03AM +1100, NeilBrown wrote:
> 
> > If voice port on twl4030 is not connected to a McBSP (or similar)
> > then we cannot configure the format the way we normally do for a DAI.
> 
> Yes we can, you need to represent the DAI link to whatever else the
> device is connected to in the driver like we do anything else - and in
> any case this isn't a device specific issue so we shouldn't be doing
> something driver specific to solve it.  Look at something like speyside.

Hi Mark,
 thanks for the reply ... I might need a little bit more help though.

I had a look at sound/soc/samsung/speyside.c, but I'm not entirely sure what
I'm looking for.
Presumably this is an audio processor not unlike the audio module in the
twl4030.

I see that there are 3 dai-links:
  CPU-DSP
  DSP-CODEC
  Baseband

Presumably "Baseband" is similar, in purpose at least, to the "voice"
interface on the twl4030.

Each dai-link has a "cpu_dai_name" and a "codec_dai_name", even though it
appears that only "CPU-DSP" is connected to the CPU.  Maybe that naming is
the source of some of my confusion.

"Baseband" declares
                .cpu_dai_name = "wm8996-aif2",
so wm8996 is something with 2 audio interfaces, (aif), and this is the second
one?  Maybe the  wm8996 is the audio module, so what is the "speyside"?

http://opensource.wolfsonmicro.com/content/speyside-audio

says it is a "reference platform".  Does that mean it is a board with a bunch
of chips soldered onto it?  If it were a board it should be described by a
dts file, not by a pile of C code (I thought), so I must be wrong about that.


In my case, I have a board with a GSM module and the twl4030 module.  Each
has an audio interface and these are connected.  I assume that I need to
express this connection in the dts file.
The GSM module doesn't currently appear in the dts file as it is usb-attached.
However I've been thinking that we will need to add it so we can express
power-on controls (twiddling some GPIOs).  So let's suppose we have the GSM
module in the dts file (child of a USB interface) and the twl4030 as well
(beneath an i2c interface).

The twl4030 needs to know the master/polarity of the clk/frm lines.  The GSM
module declares that these are.  So presumably we need some sort of linkage.
Ahhhh... I found Documentation/devicetree/bindings/sound/simple-card.txt

So I need to make the "voice" port on the twl4030 look like a "cpu" end of a
dai-link, and create a "codec" end in the GSM module, and use "sound-dai" to
point from the twl4030 to the GSM module.
Then I use frame-master, bitclock-master, bitclock-inversion, frame-inversion
for the settings I need.

I suspect I can make that work.

Am I on the right track?

Thanks,
NeilBrown
H. Nikolaus Schaller Nov. 10, 2014, 6:46 a.m. UTC | #3
Am 10.11.2014 um 00:25 schrieb NeilBrown <neilb@suse.de>:

> On Sat, 8 Nov 2014 09:26:22 +0000 Mark Brown <broonie@kernel.org> wrote:
> 
>> On Sat, Nov 08, 2014 at 11:38:03AM +1100, NeilBrown wrote:
>> 
>>> If voice port on twl4030 is not connected to a McBSP (or similar)
>>> then we cannot configure the format the way we normally do for a DAI.
>> 
>> Yes we can, you need to represent the DAI link to whatever else the
>> device is connected to in the driver like we do anything else - and in
>> any case this isn't a device specific issue so we shouldn't be doing
>> something driver specific to solve it.  Look at something like speyside.
> 
> Hi Mark,
> thanks for the reply ... I might need a little bit more help though.
> 
> I had a look at sound/soc/samsung/speyside.c, but I'm not entirely sure what
> I'm looking for.
> Presumably this is an audio processor not unlike the audio module in the
> twl4030.
> 
> I see that there are 3 dai-links:
>  CPU-DSP
>  DSP-CODEC
>  Baseband
> 
> Presumably "Baseband" is similar, in purpose at least, to the "voice"
> interface on the twl4030.
> 
> Each dai-link has a "cpu_dai_name" and a "codec_dai_name", even though it
> appears that only "CPU-DSP" is connected to the CPU.  Maybe that naming is
> the source of some of my confusion.
> 
> "Baseband" declares
>                .cpu_dai_name = "wm8996-aif2",
> so wm8996 is something with 2 audio interfaces, (aif), and this is the second
> one?  Maybe the  wm8996 is the audio module, so what is the "speyside"?
> 
> http://opensource.wolfsonmicro.com/content/speyside-audio
> 
> says it is a "reference platform".  Does that mean it is a board with a bunch
> of chips soldered onto it?  If it were a board it should be described by a
> dts file, not by a pile of C code (I thought), so I must be wrong about that.
> 
> 
> In my case, I have a board with a GSM module and the twl4030 module.  Each
> has an audio interface and these are connected.  I assume that I need to
> express this connection in the dts file.
> The GSM module doesn't currently appear in the dts file as it is usb-attached.
> However I've been thinking that we will need to add it so we can express
> power-on controls (twiddling some GPIOs).  So let's suppose we have the GSM
> module in the dts file (child of a USB interface)

It is a quite complex connection pattern and I am not sure if the modem is really
a logical child of the USB interface. Powering up/down the USB interface has nothing
to do with the modem power. Rather, it continues to operate if USB is suspended
and the modem notifies USB that it has become active.

The connections on this GTA04 board are:

Modem USB <—> CPU USB
Modem PCM <—> TWL4030 Voice <—> OMAP3 McBSP4 (yes, it is a 3-way connection)
Modem Power control <—> 1 or 2 GPIOs (depending on board variant)

The reason for the 3-way connection is that user space can chose if the GSM
voice is routed directly to the TWL codec (low latency, independent of CPU) or
goes through the CPU (e.g. for DTAM or voice scrambling by software) and
then through the other PCM link between the CPU and the TWL.

This is why I would make the McBSP4 a separate sound card.

And, this is why it needs some control and tri-state of the TWL4030 and OMAP3
McBSP4 since only one can provide a digital PCM stream to the modem.

One more thing to consider for a general solution is that there are modem modules
that communicate data through UART or SPI - but otherwise have a similar connection
for digital audio. So forcing the power control driver to be a subnode of USB doesn’t
appear general enough to me.

Finally, this connection pattern is not specific to this modem (OPTION GTM601) on this
GTA04 board. We plan to use a Gemalto PHS8  in the Pyra-Handheld and the Neo900
devices - but the general connection pattern as defined above remains the same.

So my proposal is to have a specific wwan-power driver for this type of modems.
And power control can and should be kept separately from USB (except the case
where only 1 GPIO exists and USB must be tapped to detect the modem power
state). You can find work in progress for this approach here:

<http://git.goldelico.com/?p=gta04-kernel.git;a=blob;f=drivers/misc/wwan-on-off.c;h=e13f47dbd734d14f4e38ea9cf622982dc3550212;hb=154bcd388a8f5bcc7fcf0e57e93b6388daa16980>

> and the twl4030 as well
> (beneath an i2c interface).
> 
> The twl4030 needs to know the master/polarity of the clk/frm lines.  The GSM
> module declares that these are.  So presumably we need some sort of linkage.
> Ahhhh... I found Documentation/devicetree/bindings/sound/simple-card.txt
> 
> So I need to make the "voice" port on the twl4030 look like a "cpu" end of a
> dai-link, and create a "codec" end in the GSM module, and use "sound-dai" to
> point from the twl4030 to the GSM module.

What I wonder a little is that we have all these dai-links working since your 3.7
kernel for GTA04. Is it necessary to re-invent a solution or should we just make
the solution device tree compatible?

> Then I use frame-master, bitclock-master, bitclock-inversion, frame-inversion
> for the settings I need.
> 
> I suspect I can make that work.
> 
> Am I on the right track?
> 
> Thanks,
> NeilBrown
> _______________________________________________
> Gta04-owner mailing list
> Gta04-owner@goldelico.com
> http://lists.goldelico.com/mailman/listinfo.cgi/gta04-owner

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Nov. 10, 2014, 12:11 p.m. UTC | #4
On Mon, Nov 10, 2014 at 10:25:51AM +1100, NeilBrown wrote:

> says it is a "reference platform".  Does that mean it is a board with a bunch
> of chips soldered onto it?  If it were a board it should be described by a
> dts file, not by a pile of C code (I thought), so I must be wrong about that.

No, like I say please see previous discussion ad nauseum about this.

> The twl4030 needs to know the master/polarity of the clk/frm lines.  The GSM
> module declares that these are.  So presumably we need some sort of linkage.
> Ahhhh... I found Documentation/devicetree/bindings/sound/simple-card.txt

Or just write a machine driver.  simple-card is one such machine driver
but it's not going to be suitable for non-trivial systems.  Possibly
your system is simple enough, possibly it isn't - I don't know anything
about it really.  Regardless of how you do this it shouldn't have
individual devices needing to open code configuration for links, it's
something essentially every device is going to need to do and forcing
the DT to configure the same thing twice for a link isn't a good idea
either.
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mfd/twl4030-audio.txt b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
index 414d2ae0adf6..f133cd9db6aa 100644
--- a/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
+++ b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
@@ -19,6 +19,13 @@  Audio functionality:
 -ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the
 		      valid values.
 
+Voice functionality:
+- ti,voice_fmt:  The separate 'voice' interface is connected to a
+		 separate device such as a GSM modem.  This field
+		 sets the format expected by that device (who masters
+		 the clock/FRM and what their polarity is).
+
+
 Vibra functionality
 - ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if
 		   missing or it is 0, the vibra functionality is disabled.
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 8cfb50f38529..0a59acd597b7 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -688,6 +688,9 @@  struct twl4030_codec_data {
 	unsigned int offset_cncl_path;
 	unsigned int hs_extmute:1;
 	int hs_extmute_gpio;
+	unsigned int voice_fmt;	/* If != 0, gives format for external
+				 * voice connection.
+				 */
 };
 
 struct twl4030_vibra_data {
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index c873f5887486..39b6d24377e5 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -221,6 +221,9 @@  static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata,
 	if (!of_property_read_u32(node, "ti,hs_extmute", &value))
 		pdata->hs_extmute = value;
 
+	if (of_property_read_u32(node, "ti,voice_fmt", &value) == 0)
+		pdata->voice_fmt = value;
+
 	pdata->hs_extmute_gpio = of_get_named_gpio(node,
 						   "ti,hs_extmute_gpio", 0);
 	if (gpio_is_valid(pdata->hs_extmute_gpio))
@@ -249,6 +252,8 @@  static struct twl4030_codec_data *twl4030_get_pdata(struct snd_soc_codec *codec)
 	return pdata;
 }
 
+static int twl4030_voice_set_codec_fmt(struct snd_soc_codec *codec,
+				       unsigned int fmt);
 static void twl4030_init_chip(struct snd_soc_codec *codec)
 {
 	struct twl4030_codec_data *pdata;
@@ -338,6 +343,16 @@  static void twl4030_init_chip(struct snd_soc_codec *codec)
 		 ((byte & TWL4030_CNCL_OFFSET_START) ==
 		  TWL4030_CNCL_OFFSET_START));
 
+	if (twl4030->pdata->voice_fmt) {
+		/* Configure voice format but keep interface
+		 * tri-state until enabled */
+		twl4030_voice_set_codec_fmt(codec,
+					    twl4030->pdata->voice_fmt);
+		twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+				 TWL4030_VIF_TRI_EN,
+				 TWL4030_REG_VOICE_IF);
+	}
+
 	twl4030_codec_enable(codec, 0);
 }
 
@@ -969,6 +984,15 @@  static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
 			"operation mode cannot be changed on-the-fly\n");
 		return -EBUSY;
 	}
+	if (twl4030->pdata->voice_fmt) {
+		/* There is no SND interface to voice, we need to control
+		 * it here.
+		 */
+		/* If 'val' then voice is disabled, so tri-state it as well */
+		snd_soc_update_bits(codec, TWL4030_REG_VOICE_IF,
+				    TWL4030_VIF_TRI_EN,
+				    val ? 0xff : 0);
+	}
 
 	return snd_soc_put_enum_double(kcontrol, ucontrol);
 }
@@ -2038,10 +2062,9 @@  static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int twl4030_voice_set_codec_fmt(struct snd_soc_codec *codec,
 				     unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 	u8 old_format, format;
 
@@ -2090,6 +2113,13 @@  static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
+static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	return twl4030_voice_set_codec_fmt(codec, fmt);
+}
+
 static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
 	struct snd_soc_codec *codec = dai->codec;