summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/ab5500.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ab5500.c')
-rw-r--r--sound/soc/codecs/ab5500.c63
1 files changed, 43 insertions, 20 deletions
diff --git a/sound/soc/codecs/ab5500.c b/sound/soc/codecs/ab5500.c
index 52c56c13631..1875db4fc77 100644
--- a/sound/soc/codecs/ab5500.c
+++ b/sound/soc/codecs/ab5500.c
@@ -34,8 +34,14 @@
#include <stdarg.h>
#include "ab5500.h"
+/* No of digital interface on the Codec */
+#define NO_CODEC_DAI_IF 2
+
/* codec private data */
struct ab5500_codec_dai_data {
+ bool playback_active;
+ bool capture_active;
+
};
static struct device *ab5500_dev;
@@ -85,8 +91,11 @@ static void mask_set_reg(u8 reg, u8 mask, u8 val)
case AB5500_VIRTUAL_REG3:
if ((diff & (1 << SPKR1_PWR_SHIFT))) {
if ((val & (1 << SPKR1_PWR_SHIFT)) == 0) {
- /* If the new value has PWR_SHIFT disabled, set the
- * PWR_MASK to 0 */
+ /*
+ * If the new value has PWR_SHIFT
+ * disabled, set the
+ * PWR_MASK to 0
+ */
mask_set_reg(SPKR1, SPKRx_PWR_MASK, 0);
}
else {
@@ -109,8 +118,11 @@ static void mask_set_reg(u8 reg, u8 mask, u8 val)
}
if ((diff & (1 << SPKR2_PWR_SHIFT))) {
if ((val & (1 << SPKR2_PWR_SHIFT)) == 0) {
- /* If the new value has PWR_SHIFT disabled, set the
- * PWR_MASK to 0 */
+ /*
+ * If the new value has PWR_SHIFT
+ * disabled, set the
+ * PWR_MASK to 0
+ */
mask_set_reg(SPKR2, SPKRx_PWR_MASK, 0);
}
else {
@@ -374,11 +386,15 @@ static const struct snd_soc_dapm_route intercon[] = {
};
-struct codec_dai_private {
- unsigned active_flags;
-} privates[] = {
- {0},
- {0}
+struct ab5500_codec_dai_data ab5500_codec_privates[NO_CODEC_DAI_IF] = {
+ {
+ .playback_active = false,
+ .capture_active = false,
+ },
+ {
+ .playback_active = false,
+ .capture_active = false,
+ }
};
static const char *enum_rx_input_select[] = {
@@ -882,9 +898,9 @@ static void power_widget_unlocked(enum enum_power onoff, enum enum_widget widget
unsigned long i;
unsigned long *srcs = widget_pm_array[w].source_list;
unsigned long *sinks = widget_pm_array[w].sink_list;
-
- dev_info(ab5500_dev, "%s: processing widget %s.\n",
+ dev_dbg(ab5500_dev, "%s: processing widget %s.\n",
__func__, widget_names[w]);
+
if (onoff == POWER_ON &&
!bitmap_empty(srcs, number_of_widgets) &&
!has_powered_neighbors(srcs)) {
@@ -916,10 +932,9 @@ static void power_widget_unlocked(enum enum_power onoff, enum enum_widget widget
mask_set_reg(widget_pm_array[w].reg,
1 << widget_pm_array[w].shift,
onoff == POWER_ON ? 0xff : 0);
- dev_info(ab5500_dev, "%s: widget %s powered %s.\n",
+ dev_dbg(ab5500_dev, "%s: widget %s powered %s.\n",
__func__, widget_names[w],
onoff == POWER_ON ? "on" : "off");
-
if (onoff == POWER_ON &&
!bitmap_empty(sinks, number_of_widgets) &&
!has_powered_neighbors(sinks) &&
@@ -968,7 +983,7 @@ static void dump_registers(const char *where, ...)
short reg = va_arg(ap, int);
if (reg < 0)
break;
- dev_info(ab5500_dev, "%s from %s> 0x%02X : 0x%02X.\n",
+ dev_dbg(ab5500_dev, "%s from %s> 0x%02X : 0x%02X.\n",
__func__, where, reg, read_reg(reg));
} while (1);
va_end(ap);
@@ -1080,7 +1095,7 @@ static int ab5500_add_widgets(struct snd_soc_codec *codec)
static void power_for_playback(enum enum_power onoff, int ifsel)
{
- dev_info(ab5500_dev, "%s: interface %d power %s.\n", __func__,
+ dev_dbg(ab5500_dev, "%s: interface %d power %s.\n", __func__,
ifsel, onoff == POWER_ON ? "on" : "off");
if (mutex_lock_interruptible(&ab5500_pm_mutex)) {
dev_warn(ab5500_dev,
@@ -1186,14 +1201,19 @@ static int ab5500_pcm_hw_params(struct snd_pcm_substream *substream,
static int ab5500_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- dev_info(ab5500_dev, "%s called.\n", __func__);
-
+ dev_dbg(ab5500_dev, "%s called.\n", __func__);
/* Configure registers for either playback or capture */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
+ !(ab5500_codec_privates[dai->id].playback_active == true)) {
power_for_playback(POWER_ON, dai->id);
- else
+ ab5500_codec_privates[dai->id].playback_active = true;
+ } else if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
+ !(ab5500_codec_privates[dai->id].capture_active == true)) {
power_for_capture(POWER_ON, dai->id);
- dump_registers(__func__, RX1, AUXO1_ADDER, RX2, AUXO2_ADDER, RX1_DPGA, RX2_DPGA, AUXO1, AUXO2, -1);
+ ab5500_codec_privates[dai->id].capture_active = true;
+ }
+ dump_registers(__func__, RX1, AUXO1_ADDER, RX2,
+ AUXO2_ADDER, RX1_DPGA, RX2_DPGA, AUXO1, AUXO2, -1);
return 0;
}
@@ -1204,8 +1224,11 @@ static void ab5500_pcm_shutdown(struct snd_pcm_substream *substream,
dev_info(ab5500_dev, "%s called.\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
power_for_playback(POWER_OFF, dai->id);
+ ab5500_codec_privates[dai->id].playback_active = false;
} else {
power_for_capture(POWER_OFF, dai->id);
+ ab5500_codec_privates[dai->id].capture_active = false;
+
}
if (!dai->playback_active && !dai->capture_active &&
(read_reg(iface) & I2Sx_MODE_MASK) == 0)