aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorOla Lilja <elilola@steludxu2785.(none)>2011-04-27 16:07:50 +0200
committerJonas ABERG <jonas.aberg@stericsson.com>2011-04-28 14:52:32 +0200
commitcca519d4e671d063997762827266119b242271f3 (patch)
treeb2f76511357a68e42e8ad5f1c781bad696a086d2 /sound
parent8c47a81fd5ae01ccb4f7a2a5cd808e3dff873490 (diff)
Ux500 ASoC: Move enabling of regulators
Regulators is no longer enabled during machine-driver init, but rather done before playback, and disabled after playback is finished. Change-Id: I5f6bfc3dd60b139ce4e786160104e4daaa4040fc Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21788 Reviewed-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/ab8500_audio.c76
-rw-r--r--sound/soc/codecs/ab8500_audio.h5
-rw-r--r--sound/soc/ux500/ux500_ab8500.c204
3 files changed, 165 insertions, 120 deletions
diff --git a/sound/soc/codecs/ab8500_audio.c b/sound/soc/codecs/ab8500_audio.c
index 5191328142d..b84a6bd389f 100644
--- a/sound/soc/codecs/ab8500_audio.c
+++ b/sound/soc/codecs/ab8500_audio.c
@@ -174,7 +174,6 @@ static struct clk *clk_ptr_audioclk;
static struct clk *clk_ptr_sysclk;
static DEFINE_MUTEX(power_lock);
static int ab8500_power_count;
-static bool ab8500_vibra_on;
/* Reads an arbitrary register from the ab8500 chip.
*/
@@ -1619,6 +1618,28 @@ static int ab8500_codec_set_bit_delay_if1(struct snd_soc_codec *codec, unsigned
return 0;
}
+/* Configures audio macrocell into the AB8500 Chip */
+static void ab8500_codec_configure_audio_macrocell(struct snd_soc_codec *codec)
+{
+ int data;
+
+ data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG);
+ data &= ~CLK_32K_OUT2_DISABLE;
+ ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data);
+ data |= INACTIVE_RESET_AUDIO;
+ ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data);
+
+ data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK,
+ AB8500_SYSULPCLK_CTRL1_REG);
+ data |= ENABLE_AUDIO_CLK_TO_AUDIO_BLK;
+ ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK,
+ AB8500_SYSULPCLK_CTRL1_REG, data);
+
+ data = ab8500_codec_read_reg(codec, AB8500_MISC, AB8500_GPIO_DIR4_REG);
+ data |= GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | GPIO31_DIR_OUTPUT;
+ ab8500_codec_write_reg(codec, AB8500_MISC, AB8500_GPIO_DIR4_REG, data);
+}
+
static int ab8500_codec_power_control_inc(struct snd_soc_codec *codec)
{
int ret;
@@ -1679,30 +1700,27 @@ static void ab8500_codec_power_control_dec(struct snd_soc_codec *codec)
void ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
unsigned char speed_left_neg,
unsigned char speed_right_pos,
- unsigned char speed_right_neg)
+ unsigned char speed_right_neg,
+ bool power_change)
{
unsigned int clear_mask, set_mask;
- bool ab8500_vibra_on_new;
+ bool vibra_on;
if (ab8500_codec == NULL) {
pr_err("%s: ERROR: AB8500 ASoC-driver not yet probed!\n", __func__);
return;
}
- ab8500_vibra_on_new = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg;
- if (!ab8500_vibra_on_new) {
- pr_debug("%s: PWM-vibra off.\n", __func__);
- clear_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2);
- ab8500_codec_update_reg_audio(ab8500_codec, REG_ANACONF4, clear_mask, 0x00);
- ab8500_vibra_on = false;
- ab8500_codec_power_control_dec(ab8500_codec);
- return;
- }
-
- if (!ab8500_vibra_on) {
- pr_debug("%s: PWM-vibra on.\n", __func__);
- ab8500_vibra_on = true;
- ab8500_codec_power_control_inc(ab8500_codec);
+ if (power_change) {
+ vibra_on = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg;
+ if (vibra_on) {
+ ab8500_codec_power_control_inc(ab8500_codec);
+ } else {
+ clear_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2);
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_ANACONF4, clear_mask, 0x00);
+ ab8500_codec_power_control_dec(ab8500_codec);
+ return;
+ }
}
pr_debug("%s: PWM-vibra (%d, %d, %d, %d).\n",
@@ -1858,7 +1876,6 @@ static int ab8500_codec_pcm_startup(struct snd_pcm_substream *substream,
{
pr_debug("%s Enter.\n", __func__);
-
return 0;
}
@@ -2184,28 +2201,6 @@ struct snd_soc_dai_driver ab8500_codec_dai[] = {
}
};
-/* Configures audio macrocell into the AB8500 Chip */
-static void ab8500_codec_configure_audio_macrocell(struct snd_soc_codec *codec)
-{
- int data;
-
- data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG);
- data &= ~CLK_32K_OUT2_DISABLE;
- ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data);
- data |= INACTIVE_RESET_AUDIO;
- ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data);
-
- data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK,
- AB8500_SYSULPCLK_CTRL1_REG);
- data |= ENABLE_AUDIO_CLK_TO_AUDIO_BLK;
- ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK,
- AB8500_SYSULPCLK_CTRL1_REG, data);
-
- data = ab8500_codec_read_reg(codec, AB8500_MISC, AB8500_GPIO_DIR4_REG);
- data |= GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | GPIO31_DIR_OUTPUT;
- ab8500_codec_write_reg(codec, AB8500_MISC, AB8500_GPIO_DIR4_REG, data);
-}
-
static int ab8500_codec_probe(struct snd_soc_codec *codec)
{
int i, ret;
@@ -2233,7 +2228,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
}
ab8500_codec = codec;
- ab8500_vibra_on = false;
ab8500_power_count = 0;
clk_ptr_sysclk = clk_get(codec->dev, "sysclk");
diff --git a/sound/soc/codecs/ab8500_audio.h b/sound/soc/codecs/ab8500_audio.h
index 3bdb141bb76..8f66801eaf0 100644
--- a/sound/soc/codecs/ab8500_audio.h
+++ b/sound/soc/codecs/ab8500_audio.h
@@ -23,6 +23,11 @@ extern struct snd_soc_dai_driver ab8500_codec_dai[];
extern struct snd_soc_codec_driver soc_codec_dev_ab8500;
/* Extended interface for codec-driver */
+void ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
+ unsigned char speed_left_neg,
+ unsigned char speed_right_pos,
+ unsigned char speed_right_neg,
+ bool power_change);
int ab8500_audio_set_word_length(struct snd_soc_dai *dai, unsigned int wl);
int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai, unsigned int delay);
int ab8500_audio_setup_if1(struct snd_soc_codec *codec,
diff --git a/sound/soc/ux500/ux500_ab8500.c b/sound/soc/ux500/ux500_ab8500.c
index f1ef75fcba0..4ffac884635 100644
--- a/sound/soc/ux500/ux500_ab8500.c
+++ b/sound/soc/ux500/ux500_ab8500.c
@@ -55,15 +55,59 @@ static struct regulator_bulk_data ab8500_regus[4] = {
{ .supply = "v-amic2" }
};
+static int enable_regulator(const char *name)
+{
+ int i, status;
+
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i) {
+ if (strcmp(name, ab8500_regus[i].supply) != 0)
+ continue;
+
+ status = regulator_enable(ab8500_regus[i].consumer);
+ if (status != 0) {
+ pr_err("%s: Failure with regulator %s (%d)\n",
+ __func__, name, status);
+ return status;
+ };
+
+ pr_debug("%s: Enabled regulator %s.\n", __func__, name);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void disable_regulator(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i) {
+ if (strcmp(name, ab8500_regus[i].supply) == 0) {
+ regulator_disable(ab8500_regus[i].consumer);
+ pr_debug("%s: Disabled regulator %s.\n", __func__, name);
+ return;
+ }
+ }
+}
+
int ux500_ab8500_startup(struct snd_pcm_substream *substream)
{
+ int i;
+ int status = 0;
+
pr_info("%s: Enter\n", __func__);
- return 0;
+ /* Enable regulators */
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
+ status += enable_regulator(ab8500_regus[i].supply);
+
+ return status;
}
void ux500_ab8500_shutdown(struct snd_pcm_substream *substream)
{
+ int i;
+
pr_info("%s: Enter\n", __func__);
/* Reset slots configuration to default(s) */
@@ -71,6 +115,10 @@ void ux500_ab8500_shutdown(struct snd_pcm_substream *substream)
tx_slots = DEF_TX_SLOTS;
else
rx_slots = DEF_RX_SLOTS;
+
+ /* Disable regulators */
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
+ disable_regulator(ab8500_regus[i].supply);
}
int ux500_ab8500_hw_params(struct snd_pcm_substream *substream,
@@ -184,11 +232,50 @@ int ux500_ab8500_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int create_jack(struct snd_soc_codec *codec)
+{
+ return snd_soc_jack_new(codec,
+ "AB8500 Hs Status",
+ SND_JACK_HEADPHONE |
+ SND_JACK_MICROPHONE |
+ SND_JACK_HEADSET |
+ SND_JACK_LINEOUT |
+ SND_JACK_MECHANICAL |
+ SND_JACK_VIDEOOUT,
+ &jack);
+}
+
+void ux500_ab8500_jack_report(int value)
+{
+ if (jack.jack)
+ snd_soc_jack_report(&jack, value, 0xFF);
+}
+EXPORT_SYMBOL_GPL(ux500_ab8500_jack_report);
+
+
+int ux500_ab8500_machine_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int status;
+
+ pr_info("%s Enter.\n", __func__);
+
+ /* TODO: Add required DAPM routes to control regulators on demand */
+
+ status = create_jack(codec);
+ if (status < 0) {
+ pr_err("%s: Failed to create Jack (%d).\n", __func__, status);
+ return status;
+ }
+
+ return 0;
+}
+
static int create_regulators(void)
{
int i, status = 0;
- pr_info("%s: Enter.\n", __func__);
+ pr_debug("%s: Enter.\n", __func__);
for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
ab8500_regus[i].consumer = NULL;
@@ -219,84 +306,50 @@ err_get:
return status;
}
-static int enable_regulator(const char *name)
-{
- int i, status;
-
- for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i) {
- if (strcmp(name, ab8500_regus[i].supply) != 0)
- continue;
-
- status = regulator_enable(ab8500_regus[i].consumer);
+static bool vibra_on;
- if (status != 0) {
- pr_err("%s: Failure with regulator %s (%d)\n",
- __func__, name, status);
- return status;
- } else {
- pr_info("%s: Enabled regulator %s.\n",
- __func__, name);
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-static void disable_regulator(const char *name)
+void ux500_ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
+ unsigned char speed_left_neg,
+ unsigned char speed_right_pos,
+ unsigned char speed_right_neg)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i) {
- if (strcmp(name, ab8500_regus[i].supply) == 0) {
- regulator_disable(ab8500_regus[i].consumer);
- return;
- }
+ int i, ret;
+ bool vibra_on_new;
+ bool power_change = false;
+
+ vibra_on_new = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg;
+ if ((!vibra_on_new) && (vibra_on)) {
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
+ disable_regulator(ab8500_regus[i].supply);
+
+ pr_debug("%s: PWM-vibra off.\n", __func__);
+ vibra_on = false;
+ power_change = true;
}
-}
-
-static int create_jack(struct snd_soc_codec *codec)
-{
- return snd_soc_jack_new(codec,
- "AB8500 Hs Status",
- SND_JACK_HEADPHONE |
- SND_JACK_MICROPHONE |
- SND_JACK_HEADSET |
- SND_JACK_LINEOUT |
- SND_JACK_MECHANICAL |
- SND_JACK_VIDEOOUT,
- &jack);
-}
-
-void ux500_ab8500_jack_report(int value)
-{
- if (jack.jack)
- snd_soc_jack_report(&jack, value, 0xFF);
-}
-EXPORT_SYMBOL_GPL(ux500_ab8500_jack_report);
-
-int ux500_ab8500_machine_codec_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- int status;
-
- pr_info("%s Enter.\n", __func__);
-
- /* TODO: Add required DAPM routes to control regulators on demand */
-
- status = create_jack(codec);
- if (status < 0) {
- pr_err("%s: Failed to create Jack (%d).\n", __func__, status);
- return status;
+ if ((vibra_on_new) && (!vibra_on)) {
+ ret = 0;
+ for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
+ ret += enable_regulator(ab8500_regus[i].supply);
+ if (ret < 0)
+ pr_err("%s: ERROR: Unable to enable regulators (ret = %d)!\n",
+ __func__,
+ ret);
+
+ pr_debug("%s: PWM-vibra on.\n", __func__);
+ vibra_on = true;
+ power_change = true;
}
- return 0;
+ ab8500_audio_pwm_vibra(speed_left_pos,
+ speed_left_neg,
+ speed_right_pos,
+ speed_right_neg,
+ power_change);
}
int ux500_ab8500_soc_machine_drv_init(void)
{
- int i;
int status = 0;
pr_info("%s: Enter.\n", __func__);
@@ -308,22 +361,15 @@ int ux500_ab8500_soc_machine_drv_init(void)
return status;
}
- /* TODO: Enable only regulators really needed at this point.. */
- for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
- status += enable_regulator(ab8500_regus[i].supply);
+ vibra_on = false;
- return status;
+ return 0;
}
void ux500_ab8500_soc_machine_drv_cleanup(void)
{
- int i;
-
pr_info("%s: Enter.\n", __func__);
- /* Roll out all the regulators */
- for (i = 0; i < ARRAY_SIZE(ab8500_regus); ++i)
- disable_regulator(ab8500_regus[i].supply);
regulator_bulk_free(ARRAY_SIZE(ab8500_regus), ab8500_regus);
}