diff mbox

[PATCHv2,7/7] ASoC: TWL6030: Power-up seq completion through audio interrupt

Message ID 67059DBF19D7214F9C66BB0EA91BA90E90A391E5@dlee04.ent.ti.com (mailing list archive)
State Awaiting Upstream, archived
Headers show

Commit Message

Lopez Cruz, Misael Sept. 26, 2009, 2:03 a.m. UTC
When the codec is powered-up through external AUDPWRON line it starts
its power-up sequence. The completion of the sequence is signaled
through the audio interrupt, and then codec is operational.

CODEC driver starts a wait_for_completion just after AUDPWRON line
transitions from low to high. It's signaled as complete when servicing
READYINT interrupt.

Signed-off-by: Misael Lopez Cruz <x0052729@ti.com>
---
 sound/soc/codecs/twl6030.c |   46 ++++++++++++++++++++++++++++---------------
 1 files changed, 30 insertions(+), 16 deletions(-)

Comments

Mark Brown Sept. 28, 2009, 1:37 p.m. UTC | #1
On Fri, Sep 25, 2009 at 09:03:45PM -0500, Lopez Cruz, Misael wrote:

> -	0x41, /* TWL6030_INTMR		0x04	*/
> +	0x00, /* TWL6030_INTMR		0x04	*/

I suspect this should've been in the previous patch.

> -			/* power-up sequence latency */
> -			mdelay(16);
> +			/* wait for ready interrupt */
> +			wait_for_completion(&priv->ready_completion);

You should provide a timeout here, otherwise if there's a hardware
problem the driver will hang indefinitately waiting for the IRQ.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c
index 5cf2099..f8bd8ee 100644
--- a/sound/soc/codecs/twl6030.c
+++ b/sound/soc/codecs/twl6030.c
@@ -48,6 +48,7 @@  struct twl6030_data {
 	int codec_powered;
 	unsigned int sysclk;
 	struct work_struct audint_work;
+	struct completion ready_completion;
 };
 
 /*
@@ -58,7 +59,7 @@  static const u8 twl6030_reg[TWL6030_CACHEREGNUM] = {
 	0x4B, /* TWL6030_ASICID (ro)	0x01	*/
 	0x00, /* TWL6030_ASICREV (ro)	0x02	*/
 	0x00, /* TWL6030_INTID		0x03	*/
-	0x41, /* TWL6030_INTMR		0x04	*/
+	0x00, /* TWL6030_INTMR		0x04	*/
 	0x00, /* TWL6030_NCPCTRL	0x05	*/
 	0x00, /* TWL6030_LDOCTL		0x06	*/
 	0x00, /* TWL6030_HPPLLCTL	0x07	*/
@@ -186,6 +187,23 @@  static inline void twl6030_write_reg_cache(struct snd_soc_codec *codec,
 }
 
 /*
+ * read from twl6030 hardware register
+ */
+static int twl6030_read(struct snd_soc_codec *codec,
+			unsigned int reg)
+{
+	u8 value;
+
+	if (reg > TWL6030_CACHEREGNUM)
+		return -EIO;
+
+	twl_i2c_read_u8(TWL6030_MODULE_AUDIO, &value, reg);
+	twl6030_write_reg_cache(codec, reg, value);
+
+	return value;
+}
+
+/*
  * write to the twl6030 register space
  */
 static int twl6030_write(struct snd_soc_codec *codec,
@@ -372,7 +390,8 @@  void twl6030_naudint_work(struct work_struct *work)
 		dev_alert(codec->dev, "vib drivers over current detection\n");
 		break;
 	case TWL6030_READYINT:
-		dev_alert(codec->dev, "codec is ready\n");
+		priv->codec_powered = 1;
+		complete(&priv->ready_completion);
 		break;
 	default:
 		dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
@@ -617,25 +636,21 @@  static int twl6030_set_bias_level(struct snd_soc_codec *codec,
 			/* use AUDPWRON line */
 			gpio_set_value(audpwron_gpio, 1);
 
-			/* power-up sequence latency */
-			mdelay(16);
+			/* wait for ready interrupt */
+			wait_for_completion(&priv->ready_completion);
 
 			/* sync registers updated during power-up sequence */
-			twl6030_write_reg_cache(codec, TWL6030_REG_NCPCTL,
-						0x81);
-			twl6030_write_reg_cache(codec, TWL6030_REG_LDOCTL,
-						0x45);
-			twl6030_write_reg_cache(codec, TWL6030_REG_LPPLLCTL,
-						0x01);
+			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);
+			priv->codec_powered = 1;
 		}
 
 		/* initialize vdd/vss registers with reg_cache */
 		twl6030_init_vdd_regs(codec);
-
-		priv->codec_powered = 1;
 		break;
 	case SND_SOC_BIAS_OFF:
 		if (!priv->codec_powered)
@@ -649,10 +664,8 @@  static int twl6030_set_bias_level(struct snd_soc_codec *codec,
 			udelay(500);
 
 			/* sync registers updated during power-down sequence */
-			twl6030_write_reg_cache(codec, TWL6030_REG_NCPCTL,
-						0x00);
-			twl6030_write_reg_cache(codec, TWL6030_REG_LDOCTL,
-						0x00);
+			twl6030_read(codec, TWL6030_REG_NCPCTL);
+			twl6030_read(codec, TWL6030_REG_LDOCTL);
 			twl6030_write_reg_cache(codec, TWL6030_REG_LPPLLCTL,
 						0x00);
 		} else {
@@ -1061,6 +1074,7 @@  static int __devinit twl6030_codec_probe(struct platform_device *pdev)
 
 	/* audio interrupt */
 	INIT_WORK(&priv->audint_work, twl6030_naudint_work);
+	init_completion(&priv->ready_completion);
 
 	ret = request_irq(naudint_irq,
 			twl6030_naudint_handler,