aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/ab3550.c3
-rw-r--r--sound/soc/codecs/ab5500.c63
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c6
-rw-r--r--sound/soc/ux500/ux500_pcm.c8
4 files changed, 55 insertions, 25 deletions
diff --git a/sound/soc/codecs/ab3550.c b/sound/soc/codecs/ab3550.c
index c2251c6b7d6..4a15ab64d32 100644
--- a/sound/soc/codecs/ab3550.c
+++ b/sound/soc/codecs/ab3550.c
@@ -680,9 +680,9 @@ static void power_widget_unlocked(enum enum_power onoff,
unsigned long i;
unsigned long *srcs = widget_pm_array[w].source_list;
unsigned long *sinks = widget_pm_array[w].sink_list;
-
dev_dbg(ab3550_dev, "%s: processing widget %s.\n",
__func__, widget_names[w]);
+
if (onoff == POWER_ON &&
!bitmap_empty(srcs, number_of_widgets) &&
!has_powered_neighbors(srcs)) {
@@ -877,6 +877,7 @@ static void power_for_playback(enum enum_power onoff, int ifsel)
{
dev_dbg(ab3550_dev, "%s: interface %d power %s.\n", __func__,
ifsel, onoff == POWER_ON ? "on" : "off");
+
if (mutex_lock_interruptible(&ab3550_pm_mutex)) {
dev_warn(ab3550_dev,
"%s: Signal received while waiting on the PM mutex.\n",
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)
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 4558ea61f72..53f3982343b 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -536,10 +536,12 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
/* If already configured -> not errors reported */
if (mode_playback) {
- if (drvdata->configured & PLAYBACK_CONFIGURED)
+ if ((drvdata->configured & PLAYBACK_CONFIGURED) &&
+ (drvdata->playback_active))
goto cleanup;
} else {
- if (drvdata->configured & CAPTURE_CONFIGURED)
+ if ((drvdata->configured & CAPTURE_CONFIGURED) &&
+ (drvdata->capture_active))
goto cleanup;
}
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index a0fa9723e4c..ee953f1b5e5 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -242,7 +242,6 @@ static int ux500_pcm_hw_free(struct snd_pcm_substream *substream)
static int ux500_pcm_prepare(struct snd_pcm_substream *substream)
{
pr_debug("%s: Enter\n", __func__);
-
return 0;
}
@@ -258,6 +257,12 @@ static int ux500_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ pr_debug("%s: START/PAUSE-RELEASE\n", __func__);
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN) {
+ pr_debug("XRUN occurred\n");
+ return 0;
+ }
+
private->no_of_underruns = 0;
private->offset = 0;
ret = ux500_msp_dai_i2s_configure_sg(runtime->dma_addr,
@@ -305,7 +310,6 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
-
pr_debug("%s: Enter.\n", __func__);
return dma_mmap_coherent(