Skip to content

Commit

Permalink
ASoC: cx20442: add bias control over a platform provided regulator
Browse files Browse the repository at this point in the history
Now that a regulator device for controlling the codec chip reset state
over a platform agnostic regulator API is available on the only board
using this driver so far, extend the driver with a bias control function
which will request virtual power to the codec chip from that virtual
regulator, and will supersede the present implementation existing at the
sound card level.

Thanks to the regulator sharing mechanism, both the old (the sound card)
and the new (the codec) implementations should coexist smoothly until
the sound card file is updated. For this to work as expected, update the
sound card .set_bias_level callback to not touch codec->dapm.bias_level.

While extending the cx20442 structure, drop unused control_type member.

Created against linxu-3.2-rc6, tested on top of patch 1/4 "ARM: OMAP1:
ams-delta: set up a regulator over the modem reset GPIO pin".

Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@ti.com>
  • Loading branch information
Janusz Krzysztofik authored and Liam Girdwood committed Jan 9, 2012
1 parent b425b88 commit f75a8ff
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
48 changes: 46 additions & 2 deletions sound/soc/codecs/cx20442.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>

#include <sound/core.h>
#include <sound/initval.h>
Expand All @@ -25,8 +26,8 @@


struct cx20442_priv {
enum snd_soc_control_type control_type;
void *control_data;
struct regulator *por;
};

#define CX20442_PM 0x0
Expand Down Expand Up @@ -324,16 +325,52 @@ static struct snd_soc_dai_driver cx20442_dai = {
},
};

static int cx20442_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
int err = 0;

switch (level) {
case SND_SOC_BIAS_PREPARE:
if (codec->dapm.bias_level != SND_SOC_BIAS_STANDBY)
break;
if (IS_ERR(cx20442->por))
err = PTR_ERR(cx20442->por);
else
err = regulator_enable(cx20442->por);
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level != SND_SOC_BIAS_PREPARE)
break;
if (IS_ERR(cx20442->por))
err = PTR_ERR(cx20442->por);
else
err = regulator_disable(cx20442->por);
break;
default:
break;
}
if (!err)
codec->dapm.bias_level = level;

return err;
}

static int cx20442_codec_probe(struct snd_soc_codec *codec)
{
struct cx20442_priv *cx20442;

cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
if (cx20442 == NULL)
return -ENOMEM;
snd_soc_codec_set_drvdata(codec, cx20442);

cx20442->por = regulator_get(codec->dev, "POR");
if (IS_ERR(cx20442->por))
dev_warn(codec->dev, "failed to get the regulator");
cx20442->control_data = NULL;

snd_soc_codec_set_drvdata(codec, cx20442);
codec->hw_write = NULL;
codec->card->pop_time = 0;

Expand All @@ -350,6 +387,12 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
tty_hangup(tty);
}

if (!IS_ERR(cx20442->por)) {
/* should be already in STANDBY, hence disabled */
regulator_put(cx20442->por);
}

snd_soc_codec_set_drvdata(codec, NULL);
kfree(cx20442);
return 0;
}
Expand All @@ -359,6 +402,7 @@ static const u8 cx20442_reg;
static struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
.set_bias_level = cx20442_set_bias_level,
.reg_cache_default = &cx20442_reg,
.reg_cache_size = 1,
.reg_word_size = sizeof(u8),
Expand Down
8 changes: 3 additions & 5 deletions sound/soc/omap/ams-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,22 +431,20 @@ static int ams_delta_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
struct snd_soc_codec *codec = card->rtd->codec;

switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
AMS_DELTA_LATCH2_MODEM_NRESET);
break;
case SND_SOC_BIAS_OFF:
if (codec->dapm.bias_level != SND_SOC_BIAS_OFF)
if (card->dapm.bias_level != SND_SOC_BIAS_OFF)
ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
0);
}
codec->dapm.bias_level = level;
card->dapm.bias_level = level;

return 0;
}
Expand Down

0 comments on commit f75a8ff

Please sign in to comment.