public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences
@ 2010-02-24  0:10 Olaya, Margarita
  2010-02-24 10:40 ` Liam Girdwood
  0 siblings, 1 reply; 3+ messages in thread
From: Olaya, Margarita @ 2010-02-24  0:10 UTC (permalink / raw)
  To: alsa-devel@alsa-project.org, linux-omap@vger.kernel.org
  Cc: broonie@opensource.wolfsonmicro.com, lrg@slimlogic.co.uk

From: Misael Lopez Cruz <x0052729@ti.com>

TWL6030 codec device can be powered-up/down through a specific register
writes sequence. These sequences can be used when no gpio line is
provided for AUDPWRON.

When the codec is powered-up in this way, automatic power-down sequence
(triggered by thermal shutdown) is not possible.

Signed-off-by: Misael Lopez Cruz <x0052729@ti.com>
Signed-off-by: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
Signed-off-by: Margarita Olaya Cabrera <magi.olaya@ti.com>
---
 sound/soc/codecs/twl6030.c |  112 ++++++++++++++++++++++++++++++++++++++-----
 sound/soc/codecs/twl6030.h |   16 ++++++
 2 files changed, 115 insertions(+), 13 deletions(-)

diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c
index 8b52aa1..ec838b1 100644
--- a/sound/soc/codecs/twl6030.c
+++ b/sound/soc/codecs/twl6030.c
@@ -244,6 +244,88 @@ static void twl6030_init_vdd_regs(struct snd_soc_codec *codec)
 	}
 }
 
+/* twl6030 codec manual power-up sequence */
+static void twl6030_power_up(struct snd_soc_codec *codec)
+{
+	u8 ncpctl, ldoctl, lppllctl, accctl;
+
+	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
+	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
+	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
+
+	/* enable reference system */
+	ldoctl |= TWL6030_REFENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	mdelay(10);
+	/* enable internal oscillator */
+	ldoctl |= TWL6030_OSCENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(10);
+	/* enable high-side ldo */
+	ldoctl |= TWL6030_HSLDOENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(244);
+	/* enable negative charge pump */
+	ncpctl |= TWL6030_NCPENA | TWL6030_NCPOPEN;
+	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
+	udelay(488);
+	/* enable low-side ldo */
+	ldoctl |= TWL6030_LSLDOENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(244);
+	/* enable low-power pll */
+	lppllctl |= TWL6030_LPLLENA;
+	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+	/* reset state machine */
+	accctl |= TWL6030_RESETSPLIT;
+	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
+	mdelay(5);
+	accctl &= ~TWL6030_RESETSPLIT;
+	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
+	/* disable internal oscillator */
+	ldoctl &= ~TWL6030_OSCENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+}
+
+/* twl6030 codec manual power-down sequence */
+static void twl6030_power_down(struct snd_soc_codec *codec)
+{
+	u8 ncpctl, ldoctl, lppllctl, accctl;
+
+	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
+	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
+	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
+
+	/* enable internal oscillator */
+	ldoctl |= TWL6030_OSCENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(10);
+	/* disable low-power pll */
+	lppllctl &= ~TWL6030_LPLLENA;
+	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+	/* disable low-side ldo */
+	ldoctl &= ~TWL6030_LSLDOENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(244);
+	/* disable negative charge pump */
+	ncpctl &= ~(TWL6030_NCPENA | TWL6030_NCPOPEN);
+	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
+	udelay(488);
+	/* disable high-side ldo */
+	ldoctl &= ~TWL6030_HSLDOENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	udelay(244);
+	/* disable internal oscillator */
+	ldoctl &= ~TWL6030_OSCENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	/* disable reference system */
+	ldoctl &= ~TWL6030_REFENA;
+	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+	mdelay(10);
+}
+
 /*
  * MICATT volume control:
  * from -6 to 0 dB in 6 dB steps
@@ -480,12 +562,15 @@ static int twl6030_set_bias_level(struct snd_soc_codec *codec,
 
 			/* power-up sequence latency */
 			mdelay(16);
-		}
 
-		/* sync registers updated during power-up sequence */
-		twl6030_read(codec, TWL6030_REG_NCPCTL);
-		twl6030_read(codec, TWL6030_REG_LDOCTL);
-		twl6030_read(codec, TWL6030_REG_LPPLLCTL);
+			/* sync registers updated during power-up sequence */
+			twl6030_read(codec, TWL6030_REG_NCPCTL);
+			twl6030_read(codec, TWL6030_REG_LDOCTL);
+			twl6030_read(codec, TWL6030_REG_LPPLLCTL);
+		} else {
+			/* use manual power-up sequence */
+			twl6030_power_up(codec);
+		}
 
 		/* initialize vdd/vss registers with reg_cache */
 		twl6030_init_vdd_regs(codec);
@@ -502,12 +587,16 @@ static int twl6030_set_bias_level(struct snd_soc_codec *codec,
 
 			/* power-down sequence latency */
 			udelay(500);
-		}
 
-		/* sync registers updated during power-down sequence */
-		twl6030_read(codec, TWL6030_REG_NCPCTL);
-		twl6030_read(codec, TWL6030_REG_LDOCTL);
-		twl6030_write_reg_cache(codec, TWL6030_REG_LPPLLCTL, 0x00);
+			/* sync registers updated during power-down sequence */
+			twl6030_read(codec, TWL6030_REG_NCPCTL);
+			twl6030_read(codec, TWL6030_REG_LDOCTL);
+			twl6030_write_reg_cache(codec, TWL6030_REG_LPPLLCTL,
+						0x00);
+		} else {
+			/* use manual power-down sequence */
+			twl6030_power_down(codec);
+		}
 
 		priv->codec_powered = 0;
 		break;
@@ -722,9 +811,6 @@ static int __devinit twl6030_codec_probe(struct platform_device *pdev)
 			goto gpio2_err;
 
 		priv->codec_powered = 0;
-	} else {
-		/* if no gpio is provided, then assume its always on */
-		priv->codec_powered = 1;
 	}
 
 	/* init vio registers */
diff --git a/sound/soc/codecs/twl6030.h b/sound/soc/codecs/twl6030.h
index 7fba60e..81d25f6 100644
--- a/sound/soc/codecs/twl6030.h
+++ b/sound/soc/codecs/twl6030.h
@@ -67,6 +67,18 @@
 #define TWL6030_VIOREGNUM		18
 #define TWL6030_VDDREGNUM		21
 
+/* NCPCTL (0x05) fields */
+
+#define TWL6030_NCPENA			0x01
+#define TWL6030_NCPOPEN			0x40
+
+/* LDOCTL (0x06) fields */
+
+#define TWL6030_LSLDOENA		0x01
+#define TWL6030_HSLDOENA		0x04
+#define TWL6030_REFENA			0x40
+#define TWL6030_OSCENA			0x80
+
 /* HPPLLCTL (0x07) fields */
 
 #define TWL6030_HPLLENA			0x01
@@ -88,6 +100,10 @@
 #define TWL6030_LPLLFIN			0x08
 #define TWL6030_HPLLSEL			0x10
 
+/* ACCCTL (0x2D) fields */
+
+#define TWL6030_RESETSPLIT		0x04
+
 extern struct snd_soc_dai twl6030_dai;
 extern struct snd_soc_codec_device soc_codec_dev_twl6030;
 
-- 
1.6.1.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences
  2010-02-24  0:10 [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences Olaya, Margarita
@ 2010-02-24 10:40 ` Liam Girdwood
  2010-02-24 23:42   ` Olaya, Margarita
  0 siblings, 1 reply; 3+ messages in thread
From: Liam Girdwood @ 2010-02-24 10:40 UTC (permalink / raw)
  To: Olaya, Margarita
  Cc: alsa-devel@alsa-project.org, linux-omap@vger.kernel.org,
	broonie@opensource.wolfsonmicro.com

On Tue, 2010-02-23 at 18:10 -0600, Olaya, Margarita wrote:
> From: Misael Lopez Cruz <x0052729@ti.com>
> 
> TWL6030 codec device can be powered-up/down through a specific register
> writes sequence. These sequences can be used when no gpio line is
> provided for AUDPWRON.
> 
> When the codec is powered-up in this way, automatic power-down sequence
> (triggered by thermal shutdown) is not possible.
> 
> Signed-off-by: Misael Lopez Cruz <x0052729@ti.com>
> Signed-off-by: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
> Signed-off-by: Margarita Olaya Cabrera <magi.olaya@ti.com>
> ---
>  sound/soc/codecs/twl6030.c |  112 ++++++++++++++++++++++++++++++++++++++-----
>  sound/soc/codecs/twl6030.h |   16 ++++++
>  2 files changed, 115 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c
> index 8b52aa1..ec838b1 100644
> --- a/sound/soc/codecs/twl6030.c
> +++ b/sound/soc/codecs/twl6030.c
> @@ -244,6 +244,88 @@ static void twl6030_init_vdd_regs(struct snd_soc_codec *codec)
>  	}
>  }
>  
> +/* twl6030 codec manual power-up sequence */
> +static void twl6030_power_up(struct snd_soc_codec *codec)
> +{
> +	u8 ncpctl, ldoctl, lppllctl, accctl;
> +
> +	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
> +	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
> +	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
> +	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
> +
> +	/* enable reference system */
> +	ldoctl |= TWL6030_REFENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	mdelay(10);
> +	/* enable internal oscillator */
> +	ldoctl |= TWL6030_OSCENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(10);
> +	/* enable high-side ldo */
> +	ldoctl |= TWL6030_HSLDOENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(244);
> +	/* enable negative charge pump */
> +	ncpctl |= TWL6030_NCPENA | TWL6030_NCPOPEN;
> +	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
> +	udelay(488);
> +	/* enable low-side ldo */
> +	ldoctl |= TWL6030_LSLDOENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(244);
> +	/* enable low-power pll */
> +	lppllctl |= TWL6030_LPLLENA;
> +	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
> +	/* reset state machine */
> +	accctl |= TWL6030_RESETSPLIT;
> +	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
> +	mdelay(5);
> +	accctl &= ~TWL6030_RESETSPLIT;
> +	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
> +	/* disable internal oscillator */
> +	ldoctl &= ~TWL6030_OSCENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +}
> +
> +/* twl6030 codec manual power-down sequence */
> +static void twl6030_power_down(struct snd_soc_codec *codec)
> +{
> +	u8 ncpctl, ldoctl, lppllctl, accctl;
> +
> +	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
> +	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
> +	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
> +	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
> +
> +	/* enable internal oscillator */
> +	ldoctl |= TWL6030_OSCENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(10);
> +	/* disable low-power pll */
> +	lppllctl &= ~TWL6030_LPLLENA;
> +	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
> +	/* disable low-side ldo */
> +	ldoctl &= ~TWL6030_LSLDOENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(244);
> +	/* disable negative charge pump */
> +	ncpctl &= ~(TWL6030_NCPENA | TWL6030_NCPOPEN);
> +	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
> +	udelay(488);
> +	/* disable high-side ldo */
> +	ldoctl &= ~TWL6030_HSLDOENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	udelay(244);
> +	/* disable internal oscillator */
> +	ldoctl &= ~TWL6030_OSCENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	/* disable reference system */
> +	ldoctl &= ~TWL6030_REFENA;
> +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> +	mdelay(10);
> +}
> +
>  /*


Some large mdelays here again.

Liam

-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences
  2010-02-24 10:40 ` Liam Girdwood
@ 2010-02-24 23:42   ` Olaya, Margarita
  0 siblings, 0 replies; 3+ messages in thread
From: Olaya, Margarita @ 2010-02-24 23:42 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: alsa-devel@alsa-project.org, linux-omap@vger.kernel.org,
	broonie@opensource.wolfsonmicro.com



> -----Original Message-----
> From: Liam Girdwood [mailto:lrg@slimlogic.co.uk]
> Sent: Wednesday, February 24, 2010 4:41 AM
> To: Olaya, Margarita
> Cc: alsa-devel@alsa-project.org; linux-omap@vger.kernel.org; broonie@opensource.wolfsonmicro.com
> Subject: Re: [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences
> 
> On Tue, 2010-02-23 at 18:10 -0600, Olaya, Margarita wrote:
> > From: Misael Lopez Cruz <x0052729@ti.com>
> >
> > TWL6030 codec device can be powered-up/down through a specific register
> > writes sequence. These sequences can be used when no gpio line is
> > provided for AUDPWRON.
> >
> > When the codec is powered-up in this way, automatic power-down sequence
> > (triggered by thermal shutdown) is not possible.
> >
> > Signed-off-by: Misael Lopez Cruz <x0052729@ti.com>
> > Signed-off-by: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
> > Signed-off-by: Margarita Olaya Cabrera <magi.olaya@ti.com>
> > ---
> >  sound/soc/codecs/twl6030.c |  112 ++++++++++++++++++++++++++++++++++++++-----
> >  sound/soc/codecs/twl6030.h |   16 ++++++
> >  2 files changed, 115 insertions(+), 13 deletions(-)
> >
> > diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c
> > index 8b52aa1..ec838b1 100644
> > --- a/sound/soc/codecs/twl6030.c
> > +++ b/sound/soc/codecs/twl6030.c
> > @@ -244,6 +244,88 @@ static void twl6030_init_vdd_regs(struct snd_soc_codec *codec)
> >  	}
> >  }
> >
> > +/* twl6030 codec manual power-up sequence */
> > +static void twl6030_power_up(struct snd_soc_codec *codec)
> > +{
> > +	u8 ncpctl, ldoctl, lppllctl, accctl;
> > +
> > +	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
> > +	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
> > +	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
> > +	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
> > +
> > +	/* enable reference system */
> > +	ldoctl |= TWL6030_REFENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	mdelay(10);
> > +	/* enable internal oscillator */
> > +	ldoctl |= TWL6030_OSCENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(10);
> > +	/* enable high-side ldo */
> > +	ldoctl |= TWL6030_HSLDOENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(244);
> > +	/* enable negative charge pump */
> > +	ncpctl |= TWL6030_NCPENA | TWL6030_NCPOPEN;
> > +	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
> > +	udelay(488);
> > +	/* enable low-side ldo */
> > +	ldoctl |= TWL6030_LSLDOENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(244);
> > +	/* enable low-power pll */
> > +	lppllctl |= TWL6030_LPLLENA;
> > +	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
> > +	/* reset state machine */
> > +	accctl |= TWL6030_RESETSPLIT;
> > +	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
> > +	mdelay(5);
> > +	accctl &= ~TWL6030_RESETSPLIT;
> > +	twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
> > +	/* disable internal oscillator */
> > +	ldoctl &= ~TWL6030_OSCENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +}
> > +
> > +/* twl6030 codec manual power-down sequence */
> > +static void twl6030_power_down(struct snd_soc_codec *codec)
> > +{
> > +	u8 ncpctl, ldoctl, lppllctl, accctl;
> > +
> > +	ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
> > +	ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
> > +	lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
> > +	accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
> > +
> > +	/* enable internal oscillator */
> > +	ldoctl |= TWL6030_OSCENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(10);
> > +	/* disable low-power pll */
> > +	lppllctl &= ~TWL6030_LPLLENA;
> > +	twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
> > +	/* disable low-side ldo */
> > +	ldoctl &= ~TWL6030_LSLDOENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(244);
> > +	/* disable negative charge pump */
> > +	ncpctl &= ~(TWL6030_NCPENA | TWL6030_NCPOPEN);
> > +	twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
> > +	udelay(488);
> > +	/* disable high-side ldo */
> > +	ldoctl &= ~TWL6030_HSLDOENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	udelay(244);
> > +	/* disable internal oscillator */
> > +	ldoctl &= ~TWL6030_OSCENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	/* disable reference system */
> > +	ldoctl &= ~TWL6030_REFENA;
> > +	twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
> > +	mdelay(10);
> > +}
> > +
> >  /*
> 
> 
> Some large mdelays here again.
> 
> Liam

Ok, I'll verify and change them.

- Margarita
> 
> --
> Freelance Developer, SlimLogic Ltd
> ASoC and Voltage Regulator Maintainer.
> http://www.slimlogic.co.uk


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-02-24 23:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-24  0:10 [PATCHv4 3/7] ASoC: TWL6030: Manual power-up/down sequences Olaya, Margarita
2010-02-24 10:40 ` Liam Girdwood
2010-02-24 23:42   ` Olaya, Margarita

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox