* [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec
@ 2010-04-30 11:59 Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 1/4] ASoC: tlv320dac33: Optimize power up, and restore Peter Ujfalusi
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Peter Ujfalusi @ 2010-04-30 11:59 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lrg
Hello,
Changes since v1:
- patch 1: Removed extra register writes
- patch 4:
- Let core to bring the codec to BIAS_OFF (set idle_bias_off)
- dac33_set_bias_level only takes care of power and minimum initialization
- PRE_DAPM widget event is replacing the dac33_pcm_pointer call to take
care of the initialization needed before _every_ playback.
There are few scenarios, which has to be taken care::
1. Analog bypass caused BIAS_OFF -> BIAS_ON
We need to power on the codec, and do the chip init, but we does not
need to execute the playback related configuration
2. Playback caused BIAS_OFF -> BIAS_ON
We need to power on the codec, and do the chip init, and also we need
to execute the playback related configuration.
3. Playback start, while Analog bypass is on (BIAS_ON -> BIAS_ON)
We need to execute the playback related configuration. The codec is
already on.
4. Analog bypass enable, while playback (BIAS_ON -> BIAS_ON)
Nothing need to be done.
5. Playback start withing soc power down timeout (BIAS_ON -> BIAS_ON)
We need to execute the playback related configuration. The codec is
still on.
Since the power up, and the codec init is optimized, the added overhead
in stream start is minimal.
Withing this patch, the hard_power function is now only doing what it
supposed to: only handle the powers, and GPIO reset line.
The codec initialization and state restore has been moved out.
---
Peter Ujfalusi (4):
ASoC: tlv320dac33: Optimize power up, and restore
ASoC: tlv320dac33: Revised module loading, and DAC33 ID read
ASoC: tlv320dac33: Manage a pointer for snd_pcm_substream in private
structure
ASoC: tlv320dac33: Support for turning off the codec
sound/soc/codecs/tlv320dac33.c | 235 ++++++++++++++++++++++------------------
1 files changed, 129 insertions(+), 106 deletions(-)
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHv2 1/4] ASoC: tlv320dac33: Optimize power up, and restore
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
@ 2010-04-30 11:59 ` Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 2/4] ASoC: tlv320dac33: Revised module loading, and DAC33 ID read Peter Ujfalusi
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Peter Ujfalusi @ 2010-04-30 11:59 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lrg
On power up we only need to initialize the codec, and
restore only registers, which are not in either in DAPM
nor in the playback start sequence.
These are mostly gain related registers.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
---
sound/soc/codecs/tlv320dac33.c | 106 +++++++++++++++-------------------------
1 files changed, 39 insertions(+), 67 deletions(-)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 54b2a05..329a97f 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -284,45 +284,49 @@ static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg,
return ret;
}
-static void dac33_restore_regs(struct snd_soc_codec *codec)
+static void dac33_init_chip(struct snd_soc_codec *codec)
{
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
- u8 *cache = codec->reg_cache;
- u8 data[2];
- int i, ret;
- if (!dac33->chip_power)
+ if (unlikely(!dac33->chip_power))
return;
- for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) {
- data[0] = i;
- data[1] = cache[i];
- /* Skip the read only registers */
- if ((i >= DAC33_INT_OSC_STATUS &&
- i <= DAC33_INT_OSC_FREQ_RAT_READ_B) ||
- (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) ||
- i == DAC33_DAC_STATUS_FLAGS ||
- i == DAC33_SRC_EST_REF_CLK_RATIO_A ||
- i == DAC33_SRC_EST_REF_CLK_RATIO_B)
- continue;
- ret = codec->hw_write(codec->control_data, data, 2);
- if (ret != 2)
- dev_err(codec->dev, "Write failed (%d)\n", ret);
- }
- for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) {
- data[0] = i;
- data[1] = cache[i];
- ret = codec->hw_write(codec->control_data, data, 2);
- if (ret != 2)
- dev_err(codec->dev, "Write failed (%d)\n", ret);
- }
- for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) {
- data[0] = i;
- data[1] = cache[i];
- ret = codec->hw_write(codec->control_data, data, 2);
- if (ret != 2)
- dev_err(codec->dev, "Write failed (%d)\n", ret);
- }
+ /* 44-46: DAC Control Registers */
+ /* A : DAC sample rate Fsref/1.5 */
+ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0));
+ /* B : DAC src=normal, not muted */
+ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
+ DAC33_DACSRCL_LEFT);
+ /* C : (defaults) */
+ dac33_write(codec, DAC33_DAC_CTRL_C, 0x00);
+
+ /* 64-65 : L&R DAC power control
+ Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/
+ dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
+ dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
+
+ /* 73 : volume soft stepping control,
+ clock source = internal osc (?) */
+ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
+
+ /* 66 : LOP/LOM Modes */
+ dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff);
+
+ /* 68 : LOM inverted from LOP */
+ dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2));
+
+ dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
+
+ /* Restore only selected registers (gains mostly) */
+ dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL,
+ dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL));
+ dac33_write(codec, DAC33_RDAC_DIG_VOL_CTRL,
+ dac33_read_reg_cache(codec, DAC33_RDAC_DIG_VOL_CTRL));
+
+ dac33_write(codec, DAC33_LINEL_TO_LLO_VOL,
+ dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL));
+ dac33_write(codec, DAC33_LINER_TO_RLO_VOL,
+ dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL));
}
static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
@@ -358,8 +362,7 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power)
dac33->chip_power = 1;
- /* Restore registers */
- dac33_restore_regs(codec);
+ dac33_init_chip(codec);
dac33_soft_power(codec, 1);
} else {
@@ -1269,35 +1272,6 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-static void dac33_init_chip(struct snd_soc_codec *codec)
-{
- /* 44-46: DAC Control Registers */
- /* A : DAC sample rate Fsref/1.5 */
- dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0));
- /* B : DAC src=normal, not muted */
- dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
- DAC33_DACSRCL_LEFT);
- /* C : (defaults) */
- dac33_write(codec, DAC33_DAC_CTRL_C, 0x00);
-
- /* 64-65 : L&R DAC power control
- Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/
- dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
- dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
-
- /* 73 : volume soft stepping control,
- clock source = internal osc (?) */
- dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
-
- /* 66 : LOP/LOM Modes */
- dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff);
-
- /* 68 : LOM inverted from LOP */
- dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2));
-
- dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
-}
-
static int dac33_soc_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1313,8 +1287,6 @@ static int dac33_soc_probe(struct platform_device *pdev)
/* Power up the codec */
dac33_hard_power(codec, 1);
- /* Set default configuration */
- dac33_init_chip(codec);
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 2/4] ASoC: tlv320dac33: Revised module loading, and DAC33 ID read
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 1/4] ASoC: tlv320dac33: Optimize power up, and restore Peter Ujfalusi
@ 2010-04-30 11:59 ` Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 3/4] ASoC: tlv320dac33: Manage a pointer for snd_pcm_substream in private structure Peter Ujfalusi
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Peter Ujfalusi @ 2010-04-30 11:59 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lrg
Optimize the way how tlv320dac33 is powered uppon module and
soc initialization.
Also read the DAC33 ID registers, and update the reg_cache
to reflect it.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
---
sound/soc/codecs/tlv320dac33.c | 37 ++++++++++++++++++-------------------
1 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 329a97f..9944721 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -329,6 +329,15 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL));
}
+static inline void dac33_read_id(struct snd_soc_codec *codec)
+{
+ u8 reg;
+
+ dac33_read(codec, DAC33_DEVICE_ID_MSB, ®);
+ dac33_read(codec, DAC33_DEVICE_ID_LSB, ®);
+ dac33_read(codec, DAC33_DEVICE_REV_ID, ®);
+}
+
static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
{
u8 reg;
@@ -1285,9 +1294,6 @@ static int dac33_soc_probe(struct platform_device *pdev)
socdev->card->codec = codec;
dac33 = snd_soc_codec_get_drvdata(codec);
- /* Power up the codec */
- dac33_hard_power(codec, 1);
-
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
@@ -1307,9 +1313,6 @@ static int dac33_soc_probe(struct platform_device *pdev)
/* power on device */
dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- /* Bias level configuration has enabled regulator an extra time */
- regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies);
-
return 0;
pcm_err:
@@ -1459,8 +1462,6 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
goto error_gpio;
}
gpio_direction_output(dac33->power_gpio, 0);
- } else {
- dac33->chip_power = 1;
}
/* Check if the IRQ number is valid and request it */
@@ -1498,12 +1499,14 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
goto err_get;
}
- ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies),
- dac33->supplies);
+ /* Read the tlv320dac33 ID registers */
+ ret = dac33_hard_power(codec, 1);
if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_enable;
+ dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
+ goto error_codec;
}
+ dac33_read_id(codec);
+ dac33_hard_power(codec, 0);
ret = snd_soc_register_codec(codec);
if (ret != 0) {
@@ -1518,14 +1521,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
goto error_codec;
}
- /* Shut down the codec for now */
- dac33_hard_power(codec, 0);
-
return ret;
error_codec:
- regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies);
-err_enable:
regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
err_get:
if (dac33->irq >= 0) {
@@ -1549,14 +1547,15 @@ static int __devexit dac33_i2c_remove(struct i2c_client *client)
struct tlv320dac33_priv *dac33;
dac33 = i2c_get_clientdata(client);
- dac33_hard_power(&dac33->codec, 0);
+
+ if (unlikely(dac33->chip_power))
+ dac33_hard_power(&dac33->codec, 0);
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
if (dac33->irq >= 0)
free_irq(dac33->irq, &dac33->codec);
- regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies);
regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
destroy_workqueue(dac33->dac33_wq);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 3/4] ASoC: tlv320dac33: Manage a pointer for snd_pcm_substream in private structure
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 1/4] ASoC: tlv320dac33: Optimize power up, and restore Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 2/4] ASoC: tlv320dac33: Revised module loading, and DAC33 ID read Peter Ujfalusi
@ 2010-04-30 11:59 ` Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 4/4] ASoC: tlv320dac33: Support for turning off the codec Peter Ujfalusi
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Peter Ujfalusi @ 2010-04-30 11:59 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lrg
As a preparation for supporting codec to be turned off,
when we are in BIAS_STANDBY.
The substream must be easily available in other places than
pcm_* callbacks.
Manage a pointer in _startup, and _shutdown for this.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
---
sound/soc/codecs/tlv320dac33.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 9944721..50d1522 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -91,6 +91,7 @@ struct tlv320dac33_priv {
struct work_struct work;
struct snd_soc_codec codec;
struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
+ struct snd_pcm_substream *substream;
int power_gpio;
int chip_power;
int irq;
@@ -720,6 +721,31 @@ static void dac33_oscwait(struct snd_soc_codec *codec)
"internal oscillator calibration failed\n");
}
+static int dac33_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
+
+ /* Stream started, save the substream pointer */
+ dac33->substream = substream;
+
+ return 0;
+}
+
+static void dac33_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
+
+ dac33->substream = NULL;
+}
+
static int dac33_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -1367,6 +1393,8 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
static struct snd_soc_dai_ops dac33_dai_ops = {
+ .startup = dac33_startup,
+ .shutdown = dac33_shutdown,
.hw_params = dac33_hw_params,
.prepare = dac33_pcm_prepare,
.trigger = dac33_pcm_trigger,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 4/4] ASoC: tlv320dac33: Support for turning off the codec
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
` (2 preceding siblings ...)
2010-04-30 11:59 ` [PATCHv2 3/4] ASoC: tlv320dac33: Manage a pointer for snd_pcm_substream in private structure Peter Ujfalusi
@ 2010-04-30 11:59 ` Peter Ujfalusi
2010-04-30 12:50 ` [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Mark Brown
2010-05-03 12:19 ` Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Peter Ujfalusi @ 2010-04-30 11:59 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lrg
Let the codec to hit OFF instead of STANDBY, when there is no activity.
When the codec is off, than the associated regulator can be also turned
off (if the number of users on the regulator is 0).
After initialization, the codec remains in power off, it is only turned
on for reading the ID registers (also testing the regulators).
The codec power is enabled, when the codec is moving from BIAS_OFF
to BIAS_STANDBY.
The codec is turned off, when it hits BIAS_OFF.
There are few scenarios, which has to be taken care::
1. Analog bypass caused BIAS_OFF -> BIAS_ON
We need to power on the codec, and do the chip init, but we does not
need to execute the playback related configuration
2. Playback caused BIAS_OFF -> BIAS_ON
We need to power on the codec, and do the chip init, and also we need
to execute the playback related configuration.
3. Playback start, while Analog bypass is on (BIAS_ON -> BIAS_ON)
We need to execute the playback related configuration. The codec is
already on.
4. Analog bypass enable, while playback (BIAS_ON -> BIAS_ON)
Nothing need to be done.
5. Playback start withing soc power down timeout (BIAS_ON -> BIAS_ON)
We need to execute the playback related configuration. The codec is
still on.
Since the power up, and the codec init is optimized, the added overhead
in stream start is minimal.
Withing this patch, the hard_power function is now only doing what it
supposed to: only handle the powers, and GPIO reset line.
The codec initialization and state restore has been moved out.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
---
sound/soc/codecs/tlv320dac33.c | 66 +++++++++++++++++++++++++++-------------
1 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 50d1522..68b7ccb 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -61,6 +61,8 @@
#define US_TO_SAMPLES(rate, us) \
(rate / (1000000 / us))
+static void dac33_calculate_times(struct snd_pcm_substream *substream);
+static int dac33_prepare_chip(struct snd_pcm_substream *substream);
static struct snd_soc_codec *tlv320dac33_codec;
@@ -355,9 +357,17 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
static int dac33_hard_power(struct snd_soc_codec *codec, int power)
{
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
- int ret;
+ int ret = 0;
mutex_lock(&dac33->mutex);
+
+ /* Safety check */
+ if (unlikely(power == dac33->chip_power)) {
+ dev_warn(codec->dev, "Trying to set the same power state: %s\n",
+ power ? "ON" : "OFF");
+ goto exit;
+ }
+
if (power) {
ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies),
dac33->supplies);
@@ -371,10 +381,6 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power)
gpio_set_value(dac33->power_gpio, 1);
dac33->chip_power = 1;
-
- dac33_init_chip(codec);
-
- dac33_soft_power(codec, 1);
} else {
dac33_soft_power(codec, 0);
if (dac33->power_gpio >= 0)
@@ -396,6 +402,22 @@ exit:
return ret;
}
+static int playback_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (likely(dac33->substream)) {
+ dac33_calculate_times(dac33->substream);
+ dac33_prepare_chip(dac33->substream);
+ }
+ break;
+ }
+ return 0;
+}
+
static int dac33_get_nsample(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -525,6 +547,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power",
DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
+
+ SND_SOC_DAPM_PRE("Prepare Playback", playback_event),
};
static const struct snd_soc_dapm_route audio_map[] = {
@@ -567,18 +591,18 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Coming from OFF, switch on the codec */
ret = dac33_hard_power(codec, 1);
if (ret != 0)
return ret;
- }
- dac33_soft_power(codec, 0);
+ dac33_init_chip(codec);
+ }
break;
case SND_SOC_BIAS_OFF:
ret = dac33_hard_power(codec, 0);
if (ret != 0)
return ret;
-
break;
}
codec->bias_level = level;
@@ -829,6 +853,16 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
}
mutex_lock(&dac33->mutex);
+
+ if (!dac33->chip_power) {
+ /*
+ * Chip is not powered yet.
+ * Do the init in the dac33_set_bias_level later.
+ */
+ mutex_unlock(&dac33->mutex);
+ return 0;
+ }
+
dac33_soft_power(codec, 0);
dac33_soft_power(codec, 1);
@@ -1035,15 +1069,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
}
-static int dac33_pcm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- dac33_calculate_times(substream);
- dac33_prepare_chip(substream);
-
- return 0;
-}
-
static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
@@ -1336,9 +1361,6 @@ static int dac33_soc_probe(struct platform_device *pdev)
dac33_add_widgets(codec);
- /* power on device */
- dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
pcm_err:
@@ -1375,6 +1397,8 @@ static int dac33_soc_resume(struct platform_device *pdev)
struct snd_soc_codec *codec = socdev->card->codec;
dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+ dac33_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
dac33_set_bias_level(codec, codec->suspend_bias_level);
return 0;
@@ -1396,7 +1420,6 @@ static struct snd_soc_dai_ops dac33_dai_ops = {
.startup = dac33_startup,
.shutdown = dac33_shutdown,
.hw_params = dac33_hw_params,
- .prepare = dac33_pcm_prepare,
.trigger = dac33_pcm_trigger,
.delay = dac33_dai_delay,
.set_sysclk = dac33_set_dai_sysclk,
@@ -1450,6 +1473,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
codec->hw_write = (hw_write_t) i2c_master_send;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = dac33_set_bias_level;
+ codec->idle_bias_off = 1;
codec->dai = &dac33_dai;
codec->num_dai = 1;
codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
` (3 preceding siblings ...)
2010-04-30 11:59 ` [PATCHv2 4/4] ASoC: tlv320dac33: Support for turning off the codec Peter Ujfalusi
@ 2010-04-30 12:50 ` Mark Brown
2010-05-03 12:19 ` Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2010-04-30 12:50 UTC (permalink / raw)
To: Peter Ujfalusi; +Cc: alsa-devel, lrg
On Fri, Apr 30, 2010 at 02:59:32PM +0300, Peter Ujfalusi wrote:
> Changes since v1:
> - patch 1: Removed extra register writes
> - patch 4:
> - Let core to bring the codec to BIAS_OFF (set idle_bias_off)
> - dac33_set_bias_level only takes care of power and minimum initialization
> - PRE_DAPM widget event is replacing the dac33_pcm_pointer call to take
> care of the initialization needed before _every_ playback.
These all look fine to me
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
` (4 preceding siblings ...)
2010-04-30 12:50 ` [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Mark Brown
@ 2010-05-03 12:19 ` Liam Girdwood
5 siblings, 0 replies; 7+ messages in thread
From: Liam Girdwood @ 2010-05-03 12:19 UTC (permalink / raw)
To: Peter Ujfalusi; +Cc: alsa-devel, broonie
On Fri, 2010-04-30 at 14:59 +0300, Peter Ujfalusi wrote:
> Hello,
>
> Changes since v1:
> - patch 1: Removed extra register writes
> - patch 4:
> - Let core to bring the codec to BIAS_OFF (set idle_bias_off)
> - dac33_set_bias_level only takes care of power and minimum initialization
> - PRE_DAPM widget event is replacing the dac33_pcm_pointer call to take
> care of the initialization needed before _every_ playback.
>
> There are few scenarios, which has to be taken care::
> 1. Analog bypass caused BIAS_OFF -> BIAS_ON
> We need to power on the codec, and do the chip init, but we does not
> need to execute the playback related configuration
> 2. Playback caused BIAS_OFF -> BIAS_ON
> We need to power on the codec, and do the chip init, and also we need
> to execute the playback related configuration.
> 3. Playback start, while Analog bypass is on (BIAS_ON -> BIAS_ON)
> We need to execute the playback related configuration. The codec is
> already on.
> 4. Analog bypass enable, while playback (BIAS_ON -> BIAS_ON)
> Nothing need to be done.
> 5. Playback start withing soc power down timeout (BIAS_ON -> BIAS_ON)
> We need to execute the playback related configuration. The codec is
> still on.
>
> Since the power up, and the codec init is optimized, the added overhead
> in stream start is minimal.
>
> Withing this patch, the hard_power function is now only doing what it
> supposed to: only handle the powers, and GPIO reset line.
> The codec initialization and state restore has been moved out.
>
Applied.
Thanks !
Liam
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2010-05-03 12:19 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-30 11:59 [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 1/4] ASoC: tlv320dac33: Optimize power up, and restore Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 2/4] ASoC: tlv320dac33: Revised module loading, and DAC33 ID read Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 3/4] ASoC: tlv320dac33: Manage a pointer for snd_pcm_substream in private structure Peter Ujfalusi
2010-04-30 11:59 ` [PATCHv2 4/4] ASoC: tlv320dac33: Support for turning off the codec Peter Ujfalusi
2010-04-30 12:50 ` [PATCHv2 0/4] ASoC: tlv320dac33: Support for turning off codec Mark Brown
2010-05-03 12:19 ` Liam Girdwood
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.