diff mbox

[v5,1/4] ASoC: tlv320aic32x4: Support for master clock

Message ID 1392631460-32002-2-git-send-email-mpa@pengutronix.de (mailing list archive)
State Changes Requested
Headers show

Commit Message

Markus Pargmann Feb. 17, 2014, 10:04 a.m. UTC
Add support for a master clock passed through DT. The master clock of
the codec is only active when the codec is in use.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 .../devicetree/bindings/sound/tlv320aic32x4.txt    |  4 ++++
 sound/soc/codecs/tlv320aic32x4.c                   | 23 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)

Comments

Mark Brown Feb. 18, 2014, 1:23 a.m. UTC | #1
On Mon, Feb 17, 2014 at 11:04:17AM +0100, Markus Pargmann wrote:

>  Optional properties:
>   - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
> + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
> +   See clock/clock-bindings.txt for information about the detailed format.

Looking at the code the clock isn't physically optional, why not make it
mandatory?  There's only one mainline user, it looks like it should be
straightforward to update with a fixed clock.

> +	aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk");
> +	if (IS_ERR(aic32x4->mclk))
> +		dev_info(&i2c->dev, "No mclk found, continuing without clock\n");

This is going to break with deferred probe, we need to handle that at
least.
Markus Pargmann Feb. 18, 2014, 8:46 p.m. UTC | #2
Hi,

On Tue, Feb 18, 2014 at 10:23:29AM +0900, Mark Brown wrote:
> On Mon, Feb 17, 2014 at 11:04:17AM +0100, Markus Pargmann wrote:
> 
> >  Optional properties:
> >   - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
> > + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
> > +   See clock/clock-bindings.txt for information about the detailed format.
> 
> Looking at the code the clock isn't physically optional, why not make it
> mandatory?  There's only one mainline user, it looks like it should be
> straightforward to update with a fixed clock.

The masterclock is physically optional. There are several modes to use
this codec without master clock. The PLL can use different clock inputs,
BCLK, MCLK, etc. and even the PLL is not necessary. Instead BCLK and so
on can be used as direct codec clock input. However, most of this is not
supported by the driver yet and I can't test these cases.

> 
> > +	aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk");
> > +	if (IS_ERR(aic32x4->mclk))
> > +		dev_info(&i2c->dev, "No mclk found, continuing without clock\n");
> 
> This is going to break with deferred probe, we need to handle that at
> least.

Yes, I fixed this.

Thanks,

Markus
Mark Brown Feb. 19, 2014, 3:54 a.m. UTC | #3
On Tue, Feb 18, 2014 at 09:46:46PM +0100, Markus Pargmann wrote:
> On Tue, Feb 18, 2014 at 10:23:29AM +0900, Mark Brown wrote:

> > Looking at the code the clock isn't physically optional, why not make it
> > mandatory?  There's only one mainline user, it looks like it should be
> > straightforward to update with a fixed clock.

> The masterclock is physically optional. There are several modes to use
> this codec without master clock. The PLL can use different clock inputs,
> BCLK, MCLK, etc. and even the PLL is not necessary. Instead BCLK and so
> on can be used as direct codec clock input. However, most of this is not
> supported by the driver yet and I can't test these cases.

Are any of these modes supported by the driver yet?  If there's modes
that don't use MCLK supported then I'd expect them to only enable MCLK
if it's actively being used in the current configuration (triggered via
set_sysclk()).
Markus Pargmann Feb. 20, 2014, 11:37 a.m. UTC | #4
Hi,

On Wed, Feb 19, 2014 at 12:54:06PM +0900, Mark Brown wrote:
> On Tue, Feb 18, 2014 at 09:46:46PM +0100, Markus Pargmann wrote:
> > On Tue, Feb 18, 2014 at 10:23:29AM +0900, Mark Brown wrote:
> 
> > > Looking at the code the clock isn't physically optional, why not make it
> > > mandatory?  There's only one mainline user, it looks like it should be
> > > straightforward to update with a fixed clock.
> 
> > The masterclock is physically optional. There are several modes to use
> > this codec without master clock. The PLL can use different clock inputs,
> > BCLK, MCLK, etc. and even the PLL is not necessary. Instead BCLK and so
> > on can be used as direct codec clock input. However, most of this is not
> > supported by the driver yet and I can't test these cases.
> 
> Are any of these modes supported by the driver yet?  If there's modes
> that don't use MCLK supported then I'd expect them to only enable MCLK
> if it's actively being used in the current configuration (triggered via
> set_sysclk()).

It seems none of these modes are supported yet. aic32x4_hw_params setups
the clock tree relying on a master clock to be used for the PLL.
Otherwise hw_params fails. So currently mclk is not optional for the
driver. But it is still optional for the real hardware.

What do you think about declaring the mclk as optional property in the
DT bindings documentation but to handle it as a required clock in the
driver?

Thanks,

Markus
Mark Brown Feb. 20, 2014, 11:47 a.m. UTC | #5
On Thu, Feb 20, 2014 at 12:37:49PM +0100, Markus Pargmann wrote:

> It seems none of these modes are supported yet. aic32x4_hw_params setups
> the clock tree relying on a master clock to be used for the PLL.
> Otherwise hw_params fails. So currently mclk is not optional for the
> driver. But it is still optional for the real hardware.

> What do you think about declaring the mclk as optional property in the
> DT bindings documentation but to handle it as a required clock in the
> driver?

That's fine, makes sense.
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
index db05510..352be7b 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
@@ -8,6 +8,8 @@  Required properties:
 
 Optional properties:
  - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
+ - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
+   See clock/clock-bindings.txt for information about the detailed format.
 
 
 Example:
@@ -15,4 +17,6 @@  Example:
 codec: tlv320aic32x4@18 {
 	compatible = "ti,tlv320aic32x4";
 	reg = <0x18>;
+	clocks = <&clks 201>;
+	clock-names = "mclk";
 };
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 1dd50e4..d96cb7c 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -33,6 +33,7 @@ 
 #include <linux/i2c.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <sound/tlv320aic32x4.h>
 #include <sound/core.h>
@@ -67,6 +68,7 @@  struct aic32x4_priv {
 	u32 micpga_routing;
 	bool swapdacs;
 	int rstn_gpio;
+	struct clk *mclk;
 };
 
 /* 0dB min, 0.5dB steps */
@@ -487,8 +489,21 @@  static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
 static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
+		/* Switch on master clock */
+		if (!IS_ERR(aic32x4->mclk)) {
+			int ret;
+
+			ret = clk_prepare_enable(aic32x4->mclk);
+			if (ret) {
+				dev_err(codec->dev, "Failed to enable master clock\n");
+				return ret;
+			}
+		}
+
 		/* Switch on PLL */
 		snd_soc_update_bits(codec, AIC32X4_PLLPR,
 				    AIC32X4_PLLEN, AIC32X4_PLLEN);
@@ -539,6 +554,10 @@  static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 		/* Switch off BCLK_N Divider */
 		snd_soc_update_bits(codec, AIC32X4_BCLKN,
 				    AIC32X4_BCLKEN, 0);
+
+		/* Switch off master clock */
+		if (!IS_ERR(aic32x4->mclk))
+			clk_disable_unprepare(aic32x4->mclk);
 		break;
 	case SND_SOC_BIAS_OFF:
 		break;
@@ -717,6 +736,10 @@  static int aic32x4_i2c_probe(struct i2c_client *i2c,
 		aic32x4->rstn_gpio = -1;
 	}
 
+	aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk");
+	if (IS_ERR(aic32x4->mclk))
+		dev_info(&i2c->dev, "No mclk found, continuing without clock\n");
+
 	if (gpio_is_valid(aic32x4->rstn_gpio)) {
 		ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
 				GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");