alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control
@ 2010-09-20  7:39 Jarkko Nikula
  2010-09-20  7:39 ` [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain Jarkko Nikula
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Jarkko Nikula @ 2010-09-20  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown, Liam Girdwood

Hi

I named this set as v2 since aic3x soc-cache conversion was done between v1
and this.

Set goes on top of my previous aic3x one liner:
http://mailman.alsa-project.org/pipermail/alsa-devel/2010-September/031749.html

-- 
Jarkko

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

* [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain
  2010-09-20  7:39 [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control Jarkko Nikula
@ 2010-09-20  7:39 ` Jarkko Nikula
  2010-09-20  9:26   ` Mark Brown
  2010-09-20  7:39 ` [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level Jarkko Nikula
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Jarkko Nikula @ 2010-09-20  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown, Liam Girdwood

It will be easier to keep regulator enable/disable calls in sync when dynamic
regulator management is added if regulator management is moved from
aic3x_i2c_probe/_remove to aic3x_probe/_remove.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
 sound/soc/codecs/tlv320aic3x.c |  100 ++++++++++++++++++++--------------------
 1 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 6190351..c60ead9 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1266,7 +1266,7 @@ static int aic3x_init(struct snd_soc_codec *codec)
 static int aic3x_probe(struct snd_soc_codec *codec)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-	int ret;
+	int ret, i;
 
 	codec->control_data = aic3x->control_data;
 
@@ -1276,6 +1276,35 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
+	if (aic3x->gpio_reset >= 0) {
+		ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
+		if (ret != 0)
+			goto err_gpio;
+		gpio_direction_output(aic3x->gpio_reset, 0);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+		aic3x->supplies[i].supply = aic3x_supply_names[i];
+
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
+				 aic3x->supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+		goto err_get;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
+				    aic3x->supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_enable;
+	}
+
+	if (aic3x->gpio_reset >= 0) {
+		udelay(1);
+		gpio_set_value(aic3x->gpio_reset, 1);
+	}
+
 	aic3x_init(codec);
 
 	if (aic3x->setup) {
@@ -1294,11 +1323,29 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 	aic3x_add_widgets(codec);
 
 	return 0;
+
+err_enable:
+	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+err_get:
+	if (aic3x->gpio_reset >= 0)
+		gpio_free(aic3x->gpio_reset);
+err_gpio:
+	kfree(aic3x);
+	return ret;
 }
 
 static int aic3x_remove(struct snd_soc_codec *codec)
 {
+	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	if (aic3x->gpio_reset >= 0) {
+		gpio_set_value(aic3x->gpio_reset, 0);
+		gpio_free(aic3x->gpio_reset);
+	}
+	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+
 	return 0;
 }
 
@@ -1336,7 +1383,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 {
 	struct aic3x_pdata *pdata = i2c->dev.platform_data;
 	struct aic3x_priv *aic3x;
-	int ret, i;
+	int ret;
 	const struct i2c_device_id *tbl;
 
 	aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
@@ -1356,68 +1403,21 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 		aic3x->gpio_reset = -1;
 	}
 
-	if (aic3x->gpio_reset >= 0) {
-		ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
-		if (ret != 0)
-			goto err_gpio;
-		gpio_direction_output(aic3x->gpio_reset, 0);
-	}
-
 	for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
 		if (!strcmp(tbl->name, id->name))
 			break;
 	}
 	aic3x->model = tbl - aic3x_i2c_id;
 
-	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
-		aic3x->supplies[i].supply = aic3x_supply_names[i];
-
-	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies),
-				 aic3x->supplies);
-	if (ret != 0) {
-		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
-		goto err_get;
-	}
-
-	ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
-				    aic3x->supplies);
-	if (ret != 0) {
-		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_enable;
-	}
-
-	if (aic3x->gpio_reset >= 0) {
-		udelay(1);
-		gpio_set_value(aic3x->gpio_reset, 1);
-	}
-
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_aic3x, &aic3x_dai, 1);
 	if (ret < 0)
-		goto err_enable;
-	return ret;
-
-err_enable:
-	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-err_get:
-	if (aic3x->gpio_reset >= 0)
-		gpio_free(aic3x->gpio_reset);
-err_gpio:
-	kfree(aic3x);
+		kfree(aic3x);
 	return ret;
 }
 
 static int aic3x_i2c_remove(struct i2c_client *client)
 {
-	struct aic3x_priv *aic3x = i2c_get_clientdata(client);
-
-	if (aic3x->gpio_reset >= 0) {
-		gpio_set_value(aic3x->gpio_reset, 0);
-		gpio_free(aic3x->gpio_reset);
-	}
-	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-
 	snd_soc_unregister_codec(&client->dev);
 	kfree(i2c_get_clientdata(client));
 	return 0;
-- 
1.7.1

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

* [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level
  2010-09-20  7:39 [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control Jarkko Nikula
  2010-09-20  7:39 ` [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain Jarkko Nikula
@ 2010-09-20  7:39 ` Jarkko Nikula
  2010-09-20  9:36   ` Mark Brown
  2010-09-20  7:39 ` [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync Jarkko Nikula
  2010-09-20  7:39 ` [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle Jarkko Nikula
  3 siblings, 1 reply; 10+ messages in thread
From: Jarkko Nikula @ 2010-09-20  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown, Liam Girdwood

Now all the regulators are disabled when entering into SND_SOC_BIAS_OFF
and enabled when coming back to SND_SOC_BIAS_STANDBY state. Currently this
runtime control happens only with suspend/resume as this patch does not
change the default idle behavior.

This patch manages all the regulators and reset since it seems that register
sync is needed even if only analog supplies AVDD and DRVDD are disabled.
This was noted when the system was running with idle behavior changed and
IOVDD and DVDD were on.

It is not known are all the registers needed to sync or only some subset of
them. Therefore patch plays safe and does always full shutdown/power-up.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
 sound/soc/codecs/tlv320aic3x.c |   83 +++++++++++++++++++++++++++++++---------
 1 files changed, 65 insertions(+), 18 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index c60ead9..5f8a7c4 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -70,6 +70,7 @@ struct aic3x_priv {
 	unsigned int sysclk;
 	int master;
 	int gpio_reset;
+	int power;
 #define AIC3X_MODEL_3X 0
 #define AIC3X_MODEL_33 1
 #define AIC3X_MODEL_3007 2
@@ -1028,6 +1029,64 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
+static int aic3x_init_3007(struct snd_soc_codec *codec)
+{
+	u8 tmp1, tmp2, *cache = codec->reg_cache;
+
+	/*
+	 * There is no need to cache writes to undocumented page 0xD but
+	 * respective page 0 register cache entries must be preserved
+	 */
+	tmp1 = cache[0xD];
+	tmp2 = cache[0x8];
+	/* Class-D speaker driver init; datasheet p. 46 */
+	snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
+	snd_soc_write(codec, 0xD, 0x0D);
+	snd_soc_write(codec, 0x8, 0x5C);
+	snd_soc_write(codec, 0x8, 0x5D);
+	snd_soc_write(codec, 0x8, 0x5C);
+	snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
+	cache[0xD] = tmp1;
+	cache[0x8] = tmp2;
+
+	return 0;
+}
+
+static int aic3x_set_power(struct snd_soc_codec *codec, int power)
+{
+	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+	int i, ret;
+	u8 *cache = codec->reg_cache;
+
+	if (power) {
+		ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
+					    aic3x->supplies);
+		if (ret)
+			goto out;
+		aic3x->power = 1;
+		if (aic3x->gpio_reset >= 0) {
+			udelay(1);
+			gpio_set_value(aic3x->gpio_reset, 1);
+		}
+
+		/* Sync reg_cache with the hardware */
+		codec->cache_only = 0;
+		for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++)
+			snd_soc_write(codec, i, cache[i]);
+		if (aic3x->model == AIC3X_MODEL_3007)
+			aic3x_init_3007(codec);
+		codec->cache_sync = 0;
+	} else {
+		aic3x->power = 0;
+		if (aic3x->gpio_reset >= 0)
+			gpio_set_value(aic3x->gpio_reset, 0);
+		ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
+					     aic3x->supplies);
+	}
+out:
+	return ret;
+}
+
 static int aic3x_set_bias_level(struct snd_soc_codec *codec,
 				enum snd_soc_bias_level level)
 {
@@ -1047,6 +1106,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
 		}
 		break;
 	case SND_SOC_BIAS_STANDBY:
+		if (!aic3x->power)
+			aic3x_set_power(codec, 1);
 		if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
 		    aic3x->master) {
 			/* disable pll */
@@ -1056,6 +1117,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
 		}
 		break;
 	case SND_SOC_BIAS_OFF:
+		if (aic3x->power)
+			aic3x_set_power(codec, 0);
 		break;
 	}
 	codec->bias_level = level;
@@ -1155,17 +1218,6 @@ static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int aic3x_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u8 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
-		data[0] = i;
-		data[1] = cache[i];
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	return 0;
@@ -1247,13 +1299,7 @@ static int aic3x_init(struct snd_soc_codec *codec)
 	snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
 	if (aic3x->model == AIC3X_MODEL_3007) {
-		/* Class-D speaker driver init; datasheet p. 46 */
-		snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
-		snd_soc_write(codec, 0xD, 0x0D);
-		snd_soc_write(codec, 0x8, 0x5C);
-		snd_soc_write(codec, 0x8, 0x5D);
-		snd_soc_write(codec, 0x8, 0x5C);
-		snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
+		aic3x_init_3007(codec);
 		snd_soc_write(codec, CLASSD_CTRL, 0);
 	}
 
@@ -1299,6 +1345,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
 		goto err_enable;
 	}
+	aic3x->power = 1;
 
 	if (aic3x->gpio_reset >= 0) {
 		udelay(1);
-- 
1.7.1

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

* [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync
  2010-09-20  7:39 [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control Jarkko Nikula
  2010-09-20  7:39 ` [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain Jarkko Nikula
  2010-09-20  7:39 ` [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level Jarkko Nikula
@ 2010-09-20  7:39 ` Jarkko Nikula
  2010-09-20 10:38   ` Mark Brown
  2010-09-20  7:39 ` [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle Jarkko Nikula
  3 siblings, 1 reply; 10+ messages in thread
From: Jarkko Nikula @ 2010-09-20  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown, Liam Girdwood

There is no need to reset the codec and perform cache sync if none of the
supply regulators were not disabled. Patch registers a notifier callback for
each supply and callback then sets a flag to indicate when cache sync is
required.

HW writes are also needless when codec bias is off so cache_only flag is set
independently of actual supply regulators state.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
 sound/soc/codecs/tlv320aic3x.c |   63 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 5f8a7c4..5356946 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -61,9 +61,18 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
 	"DRVDD",	/* ADC Analog and Output Driver Voltage */
 };
 
+struct aic3x_priv;
+
+struct aic3x_disable_nb {
+	struct notifier_block nb;
+	struct aic3x_priv *aic3x;
+};
+
 /* codec private data */
 struct aic3x_priv {
+	struct snd_soc_codec *codec;
 	struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
+	struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
 	enum snd_soc_control_type control_type;
 	struct aic3x_setup_data *setup;
 	void *control_data;
@@ -122,6 +131,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
 {
 	u8 *cache = codec->reg_cache;
 
+	if (codec->cache_only)
+		return -EINVAL;
 	if (reg >= AIC3X_CACHEREGNUM)
 		return -1;
 
@@ -1052,6 +1063,26 @@ static int aic3x_init_3007(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static int aic3x_regulator_event(struct notifier_block *nb,
+				 unsigned long event, void *data)
+{
+	struct aic3x_disable_nb *disable_nb =
+		container_of(nb, struct aic3x_disable_nb, nb);
+	struct aic3x_priv *aic3x = disable_nb->aic3x;
+
+	if (event & REGULATOR_EVENT_DISABLE) {
+		/*
+		 * Put codec to reset and require cache sync as at least one
+		 * of the supplies was disabled
+		 */
+		if (aic3x->gpio_reset >= 0)
+			gpio_set_value(aic3x->gpio_reset, 0);
+		aic3x->codec->cache_sync = 1;
+	}
+
+	return 0;
+}
+
 static int aic3x_set_power(struct snd_soc_codec *codec, int power)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
@@ -1064,6 +1095,13 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
 		if (ret)
 			goto out;
 		aic3x->power = 1;
+		/*
+		 * Reset release and cache sync is necessary only if some
+		 * supply was off or if there were cached writes
+		 */
+		if (!codec->cache_sync)
+			goto out;
+
 		if (aic3x->gpio_reset >= 0) {
 			udelay(1);
 			gpio_set_value(aic3x->gpio_reset, 1);
@@ -1078,8 +1116,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
 		codec->cache_sync = 0;
 	} else {
 		aic3x->power = 0;
-		if (aic3x->gpio_reset >= 0)
-			gpio_set_value(aic3x->gpio_reset, 0);
+		/* HW writes are needless when bias is off */
+		codec->cache_only = 1;
 		ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
 					     aic3x->supplies);
 	}
@@ -1315,6 +1353,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 	int ret, i;
 
 	codec->control_data = aic3x->control_data;
+	aic3x->codec = codec;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
 	if (ret != 0) {
@@ -1338,6 +1377,18 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
 		goto err_get;
 	}
+	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
+		aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
+		aic3x->disable_nb[i].aic3x = aic3x;
+		ret = regulator_register_notifier(aic3x->supplies[i].consumer,
+						  &aic3x->disable_nb[i].nb);
+		if (ret) {
+			dev_err(codec->dev,
+				"Failed to request regulator notifier: %d\n",
+				 ret);
+			goto err_notif;
+		}
+	}
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
 				    aic3x->supplies);
@@ -1372,6 +1423,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 	return 0;
 
 err_enable:
+err_notif:
+	while (i--)
+		regulator_unregister_notifier(aic3x->supplies[i].consumer,
+					      &aic3x->disable_nb[i].nb);
 	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 err_get:
 	if (aic3x->gpio_reset >= 0)
@@ -1384,6 +1439,7 @@ err_gpio:
 static int aic3x_remove(struct snd_soc_codec *codec)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+	int i;
 
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	if (aic3x->gpio_reset >= 0) {
@@ -1391,6 +1447,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
 		gpio_free(aic3x->gpio_reset);
 	}
 	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+		regulator_unregister_notifier(aic3x->supplies[i].consumer,
+					      &aic3x->disable_nb[i].nb);
 	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 
 	return 0;
-- 
1.7.1

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

* [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle
  2010-09-20  7:39 [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control Jarkko Nikula
                   ` (2 preceding siblings ...)
  2010-09-20  7:39 ` [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync Jarkko Nikula
@ 2010-09-20  7:39 ` Jarkko Nikula
  2010-09-20 10:39   ` Mark Brown
  3 siblings, 1 reply; 10+ messages in thread
From: Jarkko Nikula @ 2010-09-20  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown, Liam Girdwood

Now codec hits the SND_SOC_BIAS_OFF also when it is idle. This is also
the default state after probing and codec is left unconfigured and
unpowered by default. Initialization will happen when the bias state changes
and aic3x_set_power does power-up and cache sync.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
 sound/soc/codecs/tlv320aic3x.c |   20 ++------------------
 1 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 5356946..fc68779 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1341,9 +1341,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
 		snd_soc_write(codec, CLASSD_CTRL, 0);
 	}
 
-	/* off, with power on */
-	aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
@@ -1354,6 +1351,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 
 	codec->control_data = aic3x->control_data;
 	aic3x->codec = codec;
+	codec->idle_bias_off = 1;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
 	if (ret != 0) {
@@ -1390,19 +1388,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 		}
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
-				    aic3x->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_enable;
-	}
-	aic3x->power = 1;
-
-	if (aic3x->gpio_reset >= 0) {
-		udelay(1);
-		gpio_set_value(aic3x->gpio_reset, 1);
-	}
-
+	codec->cache_only = 1;
 	aic3x_init(codec);
 
 	if (aic3x->setup) {
@@ -1422,7 +1408,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 
 	return 0;
 
-err_enable:
 err_notif:
 	while (i--)
 		regulator_unregister_notifier(aic3x->supplies[i].consumer,
@@ -1446,7 +1431,6 @@ static int aic3x_remove(struct snd_soc_codec *codec)
 		gpio_set_value(aic3x->gpio_reset, 0);
 		gpio_free(aic3x->gpio_reset);
 	}
-	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
 		regulator_unregister_notifier(aic3x->supplies[i].consumer,
 					      &aic3x->disable_nb[i].nb);
-- 
1.7.1

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

* Re: [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain
  2010-09-20  7:39 ` [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain Jarkko Nikula
@ 2010-09-20  9:26   ` Mark Brown
  2010-09-20 17:41     ` Liam Girdwood
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2010-09-20  9:26 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: alsa-devel, Liam Girdwood

On Mon, Sep 20, 2010 at 10:39:11AM +0300, Jarkko Nikula wrote:
> It will be easier to keep regulator enable/disable calls in sync when dynamic
> regulator management is added if regulator management is moved from
> aic3x_i2c_probe/_remove to aic3x_probe/_remove.
> 
> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>

Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

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

* Re: [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level
  2010-09-20  7:39 ` [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level Jarkko Nikula
@ 2010-09-20  9:36   ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2010-09-20  9:36 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: alsa-devel, Liam Girdwood

On Mon, Sep 20, 2010 at 10:39:12AM +0300, Jarkko Nikula wrote:
> Now all the regulators are disabled when entering into SND_SOC_BIAS_OFF
> and enabled when coming back to SND_SOC_BIAS_STANDBY state. Currently this
> runtime control happens only with suspend/resume as this patch does not
> change the default idle behavior.

Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

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

* Re: [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync
  2010-09-20  7:39 ` [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync Jarkko Nikula
@ 2010-09-20 10:38   ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2010-09-20 10:38 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: alsa-devel, Liam Girdwood

On Mon, Sep 20, 2010 at 10:39:13AM +0300, Jarkko Nikula wrote:
> There is no need to reset the codec and perform cache sync if none of the
> supply regulators were not disabled. Patch registers a notifier callback for
> each supply and callback then sets a flag to indicate when cache sync is
> required.
> 
> HW writes are also needless when codec bias is off so cache_only flag is set
> independently of actual supply regulators state.
> 
> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>

Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

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

* Re: [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle
  2010-09-20  7:39 ` [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle Jarkko Nikula
@ 2010-09-20 10:39   ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2010-09-20 10:39 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: alsa-devel, Liam Girdwood

On Mon, Sep 20, 2010 at 10:39:14AM +0300, Jarkko Nikula wrote:
> Now codec hits the SND_SOC_BIAS_OFF also when it is idle. This is also
> the default state after probing and codec is left unconfigured and
> unpowered by default. Initialization will happen when the bias state changes
> and aic3x_set_power does power-up and cache sync.
> 
> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>

Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

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

* Re: [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain
  2010-09-20  9:26   ` Mark Brown
@ 2010-09-20 17:41     ` Liam Girdwood
  0 siblings, 0 replies; 10+ messages in thread
From: Liam Girdwood @ 2010-09-20 17:41 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel

On Mon, 2010-09-20 at 10:26 +0100, Mark Brown wrote:
> On Mon, Sep 20, 2010 at 10:39:11AM +0300, Jarkko Nikula wrote:
> > It will be easier to keep regulator enable/disable calls in sync when dynamic
> > regulator management is added if regulator management is moved from
> > aic3x_i2c_probe/_remove to aic3x_probe/_remove.
> > 
> > Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
> 
> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

All Applied.

Thanks

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

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

end of thread, other threads:[~2010-09-20 17:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-20  7:39 [PATCHv2 0/4] ASoC: tlv320aic3x: Add dynamic regulator control Jarkko Nikula
2010-09-20  7:39 ` [PATCHv2 1/4] ASoC: tlv320aic3x: Move regulator management from i2c to soc domain Jarkko Nikula
2010-09-20  9:26   ` Mark Brown
2010-09-20 17:41     ` Liam Girdwood
2010-09-20  7:39 ` [PATCHv2 2/4] ASoC: tlv320aic3x: Add runtime regulator control to aic3x_set_bias_level Jarkko Nikula
2010-09-20  9:36   ` Mark Brown
2010-09-20  7:39 ` [PATCHv2 3/4] ASoC: tlv320aic3x: Use regulator notifiers for optimizing the cache sync Jarkko Nikula
2010-09-20 10:38   ` Mark Brown
2010-09-20  7:39 ` [PATCHv2 4/4] ASoC: tlv320aic3x: Let the codec hit SND_SOC_BIAS_OFF when idle Jarkko Nikula
2010-09-20 10:39   ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).