summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManjunath G Kondaiah <manjugk@ti.com>2011-01-17 12:26:26 +0530
committerManjunath G Kondaiah <manjugk@ti.com>2011-01-17 12:26:26 +0530
commit48f5ebdb916aabcaf03d8887386a95156b222163 (patch)
tree0968a1e7f2e958e376123d508b80262569b117f9
parent186ec7763ba80b43ea5867958cf7eabb6c7244b5 (diff)
parente9354f603d68280d2e5af9597d5ad30b9b587139 (diff)
Merge branch 'audio-for-24.11P6' of git://dev.omapzoom.org/pub/scm/misael/kernel-audio into L24.11
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/codecs/twl6040.c8
-rw-r--r--sound/soc/omap/abe/abe_seq.c2
-rw-r--r--sound/soc/omap/omap-abe-dsp.c148
-rw-r--r--sound/soc/omap/omap-abe.c4
-rw-r--r--sound/soc/omap/omap-dmic.c1
-rw-r--r--sound/soc/omap/omap-hdmi.c101
-rw-r--r--sound/soc/omap/omap-mcbsp.c2
-rw-r--r--sound/soc/omap/omap-mcpdm.c31
-rw-r--r--sound/soc/omap/sdp4430.c18
-rw-r--r--sound/soc/soc-core.c1
-rw-r--r--sound/soc/soc-dapm.c2
12 files changed, 244 insertions, 75 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6361f05f936b..f7535152bff9 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -628,6 +628,7 @@ struct snd_soc_card {
struct list_head list;
struct mutex mutex;
+ struct mutex dapm_mutex;
bool instantiated;
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 7a239a27897d..d482b41e80cb 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -238,7 +238,7 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
unsigned int reg)
{
- u8 value;
+ u8 value = 0;
if (reg >= TWL6040_CACHEREGNUM)
return -EIO;
@@ -720,7 +720,7 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
struct twl6040_jack_data *jack = &priv->hs_jack;
int report = 0;
- u8 intid;
+ u8 intid = 0;
twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
@@ -1188,7 +1188,7 @@ static int twl6040_power_up_completion(struct snd_soc_codec *codec,
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int time_left;
- u8 intid;
+ u8 intid = 0;
time_left = wait_for_completion_timeout(&priv->ready,
msecs_to_jiffies(144));
@@ -1617,7 +1617,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
struct twl6040_data *priv;
int audpwron, naudint;
int ret = 0;
- u8 icrev, intmr = TWL6040_ALLINT_MSK;
+ u8 icrev = 0, intmr = TWL6040_ALLINT_MSK;
priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
if (priv == NULL)
diff --git a/sound/soc/omap/abe/abe_seq.c b/sound/soc/omap/abe/abe_seq.c
index 48ce31a38b7a..9707a7329dbe 100644
--- a/sound/soc/omap/abe/abe_seq.c
+++ b/sound/soc/omap/abe/abe_seq.c
@@ -177,7 +177,7 @@ void abe_call_subroutine(u32 idx, u32 p1, u32 p2, u32 p3, u32 p4)
abe_subroutine3 f3;
abe_subroutine4 f4;
u32 *params;
- if (idx > MAXNBSUBROUTINE)
+ if (idx >= MAXNBSUBROUTINE)
return;
switch (idx) {
/* call the subroutines defined at compilation time
diff --git a/sound/soc/omap/omap-abe-dsp.c b/sound/soc/omap/omap-abe-dsp.c
index 1dda164fe44f..171c7ec75885 100644
--- a/sound/soc/omap/omap-abe-dsp.c
+++ b/sound/soc/omap/omap-abe-dsp.c
@@ -116,8 +116,8 @@ static const struct snd_pcm_hardware omap_abe_hardware = {
SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE,
- .period_bytes_min = 24 * 1024,
- .period_bytes_max = 48 * 1024,
+ .period_bytes_min = 4 * 1024,
+ .period_bytes_max = 24 * 1024,
.periods_min = 2,
.periods_max = 2,
.buffer_bytes_max = 24 * 1024 * 2,
@@ -874,59 +874,65 @@ static int abe_get_equalizer(struct snd_kcontrol *kcontrol,
return 0;
}
-static int abe_put_equalizer(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void abe_dsp_set_equalizer(unsigned int id, unsigned int profile)
{
/* TODO: do not use abe global structure to assign pdev */
struct platform_device *pdev = abe->pdev;
- struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
- u16 val = ucontrol->value.enumerated.item[0];
abe_equ_t equ_params;
- switch (eqc->reg) {
+ switch (id) {
case EQ1:
equ_params.equ_length = NBDL1COEFFS;
- memcpy(equ_params.coef.type1, dl1_equ_coeffs[val],
- sizeof(dl1_equ_coeffs[val]));
- abe->dl1_equ_profile = val;
+ memcpy(equ_params.coef.type1, dl1_equ_coeffs[profile],
+ sizeof(dl1_equ_coeffs[profile]));
+ abe->dl1_equ_profile = profile;
break;
case EQ2L:
equ_params.equ_length = NBDL2COEFFS;
- memcpy(equ_params.coef.type1, dl20_equ_coeffs[val],
- sizeof(dl20_equ_coeffs[val]));
- abe->dl20_equ_profile = val;
+ memcpy(equ_params.coef.type1, dl20_equ_coeffs[profile],
+ sizeof(dl20_equ_coeffs[profile]));
+ abe->dl20_equ_profile = profile;
break;
case EQ2R:
equ_params.equ_length = NBDL2COEFFS;
- memcpy(equ_params.coef.type1, dl21_equ_coeffs[val],
- sizeof(dl21_equ_coeffs[val]));
- abe->dl21_equ_profile = val;
+ memcpy(equ_params.coef.type1, dl21_equ_coeffs[profile],
+ sizeof(dl21_equ_coeffs[profile]));
+ abe->dl21_equ_profile = profile;
break;
case EQAMIC:
equ_params.equ_length = NBAMICCOEFFS;
- memcpy(equ_params.coef.type1, amic_equ_coeffs[val],
- sizeof(amic_equ_coeffs[val]));
- abe->amic_equ_profile = val;
+ memcpy(equ_params.coef.type1, amic_equ_coeffs[profile],
+ sizeof(amic_equ_coeffs[profile]));
+ abe->amic_equ_profile = profile;
break;
case EQDMIC:
equ_params.equ_length = NBDMICCOEFFS;
- memcpy(equ_params.coef.type1, dmic_equ_coeffs[val],
- sizeof(dmic_equ_coeffs[val]));
- abe->dmic_equ_profile = val;
+ memcpy(equ_params.coef.type1, dmic_equ_coeffs[profile],
+ sizeof(dmic_equ_coeffs[profile]));
+ abe->dmic_equ_profile = profile;
break;
case EQSDT:
equ_params.equ_length = NBSDTCOEFFS;
- memcpy(equ_params.coef.type1, sdt_equ_coeffs[val],
- sizeof(sdt_equ_coeffs[val]));
- abe->sdt_equ_profile = val;
+ memcpy(equ_params.coef.type1, sdt_equ_coeffs[profile],
+ sizeof(sdt_equ_coeffs[profile]));
+ abe->sdt_equ_profile = profile;
break;
default:
- break;
+ return;
}
pm_runtime_get_sync(&pdev->dev);
- abe_write_equalizer(eqc->reg, &equ_params);
+ abe_write_equalizer(id, &equ_params);
pm_runtime_put_sync(&pdev->dev);
+}
+
+static int abe_put_equalizer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
+ u16 val = ucontrol->value.enumerated.item[0];
+
+ abe_dsp_set_equalizer(eqc->reg, val);
return 1;
}
@@ -1697,8 +1703,12 @@ static int aess_set_opp_mode(void)
break;
}
} else if (abe->opp < opp) {
- /* Increase OPP mode - no need of OPP25% */
+ /* Increase OPP mode */
switch (opp) {
+ case 25:
+ omap_device_set_rate(&pdev->dev, &pdev->dev, 49000000);
+ abe_set_opp_processing(ABE_OPP25);
+ break;
case 50:
omap_device_set_rate(&pdev->dev, &pdev->dev, 98300000);
abe_set_opp_processing(ABE_OPP50);
@@ -2024,6 +2034,7 @@ static int aess_open(struct snd_pcm_substream *substream)
struct snd_soc_dai *dai = rtd->cpu_dai;
/* TODO: do not use abe global structure to assign pdev */
struct platform_device *pdev = abe->pdev;
+ int ret = 0;
mutex_lock(&abe->mutex);
@@ -2040,30 +2051,38 @@ static int aess_open(struct snd_pcm_substream *substream)
break;
case ABE_FRONTEND_DAI_LP_MEDIA:
snd_soc_set_runtime_hwparams(substream, &omap_abe_hardware);
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1024);
break;
default:
break;
}
mutex_unlock(&abe->mutex);
- return 0;
+ return ret;
}
static int abe_ping_pong_init(struct snd_pcm_hw_params *params,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
abe_data_format_t format;
+ size_t period_size;
u32 dst;
/*Storing substream pointer for irq*/
abe->psubs = substream;
format.f = params_rate(params);
- format.samp_format = STEREO_16_16;
+ if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
+ format.samp_format = STEREO_MSB;
+ else
+ format.samp_format = STEREO_16_16;
if (format.f == 44100)
abe_write_event_generator(EVENT_44100);
+ period_size = params_period_bytes(params);
+
/*Adding ping pong buffer subroutine*/
abe_add_subroutine(&abe_irq_pingpong_player_id,
(abe_subroutine2) abe_irq_pingpong_subroutine,
@@ -2072,17 +2091,16 @@ static int abe_ping_pong_init(struct snd_pcm_hw_params *params,
/* Connect a Ping-Pong cache-flush protocol to MM_DL port */
abe_connect_irq_ping_pong_port(MM_DL_PORT, &format,
abe_irq_pingpong_player_id,
- N_SAMPLES_BYTES, &dst,
+ period_size, &dst,
PING_PONG_WITH_MCU_IRQ);
/* Memory mapping for hw params */
- runtime->dma_area = abe->io_base + ABE_DMEM_BASE_OFFSET_MPU +
- ABE_VM_AESS_OFFSET + dst;
+ runtime->dma_area = abe->io_base + ABE_DMEM_BASE_OFFSET_MPU + dst;
runtime->dma_addr = 0;
- runtime->dma_bytes = N_SAMPLES_BYTES * 2;
+ runtime->dma_bytes = period_size * 2;
/* Need to set the first buffer in order to get interrupt */
- abe_set_ping_pong_buffer(MM_DL_PORT, N_SAMPLES_BYTES);
+ abe_set_ping_pong_buffer(MM_DL_PORT, period_size);
return 0;
}
@@ -2233,6 +2251,36 @@ static int aess_suspend(struct device *dev)
pdev = to_platform_device(dev);
pdata = pdev->dev.platform_data;
+ pm_runtime_get_sync(&pdev->dev);
+
+ if (abe->active && abe_check_activity()) {
+ dev_dbg(&pdev->dev, "Suspend in a middle of ABE activity!\n");
+ goto no_suspend;
+ }
+
+ /* TODO: Find a better way to save/retore gains after dor OFF mode */
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+
+no_suspend:
+ pm_runtime_put_sync(&pdev->dev);
+
+ /*
+ * force setting OPP after suspend/resume to ensure
+ * ABE freq/volt are set to proper values
+ */
+ abe->opp = 0;
+
if (pdata->get_context_loss_count)
abe->loss_count = pdata->get_context_loss_count(dev);
@@ -2254,17 +2302,43 @@ static int aess_resume(struct device *dev)
pm_runtime_get_sync(&pdev->dev);
+ if (abe->active && abe_check_activity()) {
+ dev_dbg(&pdev->dev, "Resume in a middle of ABE activity!\n");
+ goto no_resume;
+ }
+
if (loss_count != abe->loss_count)
abe_reload_fw();
+ /* TODO: Find a better way to save/retore gains after dor OFF mode */
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL2);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_dsp_set_equalizer(EQ1, abe->dl1_equ_profile);
+ abe_dsp_set_equalizer(EQ2L, abe->dl20_equ_profile);
+ abe_dsp_set_equalizer(EQ2R, abe->dl21_equ_profile);
+ abe_dsp_set_equalizer(EQAMIC, abe->amic_equ_profile);
+ abe_dsp_set_equalizer(EQDMIC, abe->dmic_equ_profile);
+ abe_dsp_set_equalizer(EQSDT, abe->sdt_equ_profile);
+
+no_resume:
pm_runtime_put_sync(&pdev->dev);
return 0;
}
#else
-#define aess_runtime_suspend NULL
-#define aess_runtime_resume NULL
+#define aess_suspend NULL
+#define aess_resume NULL
#endif
static const struct dev_pm_ops aess_pm_ops = {
diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c
index c2c12edfa05c..a310df64851d 100644
--- a/sound/soc/omap/omap-abe.c
+++ b/sound/soc/omap/omap-abe.c
@@ -1281,10 +1281,10 @@ static void mute_fe_port(struct snd_pcm_substream *substream, int stream)
switch(rtd->cpu_dai->id) {
case ABE_FRONTEND_DAI_MEDIA:
+ case ABE_FRONTEND_DAI_LP_MEDIA:
if (abe_data.be_active[OMAP_ABE_DAI_PDM_DL2][SNDRV_PCM_STREAM_PLAYBACK]) {
abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
}
- case ABE_FRONTEND_DAI_LP_MEDIA:
if (abe_data.be_active[OMAP_ABE_DAI_PDM_DL1][SNDRV_PCM_STREAM_PLAYBACK]) {
abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
}
@@ -1323,10 +1323,10 @@ static void unmute_fe_port(struct snd_pcm_substream *substream, int stream)
switch(rtd->cpu_dai->id) {
case ABE_FRONTEND_DAI_MEDIA:
+ case ABE_FRONTEND_DAI_LP_MEDIA:
if (abe_data.be_active[OMAP_ABE_DAI_PDM_DL2][SNDRV_PCM_STREAM_PLAYBACK]) {
abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
}
- case ABE_FRONTEND_DAI_LP_MEDIA:
if (abe_data.be_active[OMAP_ABE_DAI_PDM_DL1][SNDRV_PCM_STREAM_PLAYBACK]) {
abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
}
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 8429e2209e71..5617d1d88e3c 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -581,6 +581,7 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dmic);
dmic->dev = &pdev->dev;
dmic->link = &omap_dmic_link;
+ dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
spin_lock_init(&dmic->lock);
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 0df153870edb..4933617d86aa 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -30,19 +30,26 @@
#include <sound/initval.h>
#include <sound/soc.h>
-#include <plat/control.h>
#include <plat/dma.h>
#include "omap-pcm.h"
#include "omap-hdmi.h"
#define CONFIG_HDMI_NO_IP_MODULE
-#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_48000)
+#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-/* Currently, we support only 16b samples at HDMI */
-#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+/* Support for 16 and 24 bits */
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
-#ifdef CONFIG_HDMI_NO_IP_MODULE
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
#include <plat/hdmi_lib.h>
+
+struct omap_hdmi_data {
+ struct hdmi_notifier notifier;
+};
+
+struct omap_hdmi_data hdmi_data;
#else
struct hdmi_ip_driver hdmi_audio_core;
#endif
@@ -54,11 +61,27 @@ static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
.sync_mode = OMAP_DMA_SYNC_PACKET,
};
+#ifdef CONFIG_HDMI_NO_IP_MODULE
+static void hdmi_hpd_notifier(int state, void *data)
+{
+ struct snd_pcm_substream *substream = data;
+
+ if (!state && substream)
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+}
+#endif
+
static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
int err = 0;
-#ifdef CONFIG_HDMI_NO_IP_MODULE
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
+ struct hdmi_notifier *notifier = &hdmi_data.notifier;
+
+ notifier->hpd_notifier = hdmi_hpd_notifier;
+ notifier->private_data = substream;
+ hdmi_add_notifier(notifier);
+
err = hdmi_w1_wrapper_enable(HDMI_WP);
#else
if (hdmi_audio_core.module_loaded)
@@ -72,8 +95,13 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
-#ifdef CONFIG_HDMI_NO_IP_MODULE
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
+ struct hdmi_notifier *notifier = &hdmi_data.notifier;
+
hdmi_w1_wrapper_disable(HDMI_WP);
+
+ hdmi_remove_notifier(notifier);
+ notifier->private_data = NULL;
#else
if (hdmi_audio_core.module_loaded)
hdmi_audio_core.wrapper_disable(HDMI_WP);
@@ -92,7 +120,7 @@ static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-#ifdef CONFIG_HDMI_NO_IP_MODULE
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
err = hdmi_w1_start_audio_transfer(HDMI_WP);
#else
if (hdmi_audio_core.module_loaded)
@@ -106,7 +134,7 @@ static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-#ifdef CONFIG_HDMI_NO_IP_MODULE
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
err = hdmi_w1_stop_audio_transfer(HDMI_WP);
#else
if (hdmi_audio_core.module_loaded)
@@ -131,13 +159,59 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FORMAT_S32_LE:
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
+ err = hdmi_configure_audio_sample_size(HDMI_SAMPLE_16BITS);
+#else
+ if (hdmi_audio_core.module_loaded)
+ err = hdmi_audio_core.config_sample_size(HDMI_WP,
+ HDMI_SAMPLE_16BITS);
+ else
+ printk(KERN_WARNING "Warning: hdmi_core.ko is "
+ "not enabled");
+#endif
+ omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
+ err = hdmi_configure_audio_sample_size(HDMI_SAMPLE_24BITS);
+#else
+ if (hdmi_audio_core.module_loaded)
+ err = hdmi_audio_core.config_sample_size(HDMI_WP,
+ HDMI_SAMPLE_24BITS);
+ else
+ printk(KERN_WARNING "Warning: hdmi_core.ko is "
+ "not enabled");
+#endif
omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
break;
-
default:
err = -EINVAL;
}
+ if (err < 0)
+ return err;
+
+#if defined(CONFIG_HDMI_NO_IP) || defined(CONFIG_HDMI_NO_IP_MODULE)
+ err = hdmi_configure_audio_channels(params_channels(params),
+ HDMI_CEA_CODE_00);
+ if (err < 0)
+ return err;
+ err = hdmi_configure_audio_sample_rate(params_rate(params));
+ if (err < 0)
+ return err;
+ err = hdmi_configure_audio();
+ if (err < 0)
+ return err;
+#else
+ err = hdmi_audio_core.config_audio_channels(HDMI_WP,
+ params_channels(params), HDMI_CEA_CODE_00);
+ if (err < 0)
+ return err;
+ err = hdmi_audio_core.config_audio_sample_rate(HDMI_WP,
+ params_rate(params));
+ if (err < 0)
+ return err;
+#endif
+
omap_hdmi_dai_dma_params.packet_size = 0x20;
snd_soc_dai_set_dma_data(dai, substream,
@@ -196,7 +270,7 @@ static void __exit hdmi_dai_exit(void)
}
module_exit(hdmi_dai_exit);
-#ifndef CONFIG_HDMI_NO_IP_MODULE
+#if !defined(CONFIG_HDMI_NO_IP) && !defined(CONFIG_HDMI_NO_IP_MODULE)
/* stub */
int audio_stub_lib_init(void)
@@ -225,6 +299,9 @@ void hdmi_audio_core_stub_init(void)
hdmi_audio_core.set_wait_pwr = NULL;
hdmi_audio_core.set_wait_srst = NULL;
hdmi_audio_core.read_edid = NULL;
+ hdmi_audio_core.config_audio_sample_rate = NULL;
+ hdmi_audio_core.config_sample_size = NULL;
+ hdmi_audio_core.config_audio_channels = NULL;
hdmi_audio_core.ip_init = audio_stub_lib_init;
hdmi_audio_core.ip_exit = audio_stub_lib_exit;
hdmi_audio_core.module_loaded = 0;
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 1eb2c4ab60a2..e9ba09f4d0a2 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -836,7 +836,7 @@ static int \
omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
struct snd_ctl_elem_value *uc) \
{ \
- s16 chgain; \
+ s16 chgain = 0; \
\
if (omap_st_get_chgain((id)-1, channel, &chgain)) \
return -EAGAIN; \
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index cca3f97dd31e..57824b676d55 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -70,7 +70,7 @@ struct omap_mcpdm {
struct delayed_work delayed_abe_work;
#endif
- spinlock_t lock;
+ struct mutex mutex;
struct omap_mcpdm_platform_data *pdata;
struct omap_mcpdm_link *downlink;
struct omap_mcpdm_link *uplink;
@@ -407,17 +407,15 @@ static int omap_mcpdm_request(struct omap_mcpdm *mcpdm)
pm_runtime_get_sync(&pdev->dev);
- spin_lock(&mcpdm->lock);
-
+ mutex_lock(&mcpdm->mutex);
if (!mcpdm->free) {
dev_err(mcpdm->dev, "McPDM interface is in use\n");
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
ret = -EBUSY;
goto err;
}
mcpdm->free = 0;
-
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
/* Disable lines while request is ongoing */
omap_mcpdm_write(mcpdm, MCPDM_CTRL, 0x00);
@@ -449,15 +447,15 @@ static void omap_mcpdm_free(struct omap_mcpdm *mcpdm)
pdev = to_platform_device(mcpdm->dev);
- spin_lock(&mcpdm->lock);
+ mutex_lock(&mcpdm->mutex);
if (mcpdm->free) {
dev_err(mcpdm->dev, "McPDM interface is already free\n");
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
return;
}
mcpdm->free = 1;
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
pm_runtime_put_sync(&pdev->dev);
@@ -661,7 +659,8 @@ static void omap_mcpdm_abe_dai_shutdown(struct snd_pcm_substream *substream,
if (!dai->active) {
if (!mcpdm->ul_active && substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
omap_mcpdm_capture_close(mcpdm, mcpdm->uplink);
- if (!mcpdm->free && !mcpdm->dn_channels)
+ if (!mcpdm->free && !mcpdm->dn_channels &&
+ !mcpdm->dl_active)
omap_mcpdm_free(mcpdm);
}
if (!mcpdm->dl_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -677,7 +676,7 @@ static void playback_abe_work(struct work_struct *work)
struct omap_mcpdm *mcpdm =
container_of(work, struct omap_mcpdm, delayed_abe_work.work);
- spin_lock(&mcpdm->lock);
+ mutex_lock(&mcpdm->mutex);
if (!mcpdm->dl_active && mcpdm->dn_channels) {
abe_disable_data_transfer(PDM_DL_PORT);
udelay(250);
@@ -685,8 +684,8 @@ static void playback_abe_work(struct work_struct *work)
omap_mcpdm_playback_close(mcpdm, mcpdm->downlink);
abe_dsp_shutdown();
}
- spin_unlock(&mcpdm->lock);
abe_dsp_pm_put();
+ mutex_unlock(&mcpdm->mutex);
if (!mcpdm->free && !mcpdm->ul_active)
omap_mcpdm_free(mcpdm);
@@ -708,8 +707,8 @@ static int omap_mcpdm_abe_dai_hw_params(struct snd_pcm_substream *substream,
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* Check if McPDM is already started */
if (!mcpdm->dn_channels) {
+ mutex_lock(&mcpdm->mutex);
abe_dsp_pm_get();
- spin_lock(&mcpdm->lock);
/* start ATC before McPDM IP */
abe_enable_data_transfer(PDM_DL_PORT);
udelay(250);
@@ -717,12 +716,12 @@ static int omap_mcpdm_abe_dai_hw_params(struct snd_pcm_substream *substream,
ret = omap_mcpdm_playback_open(mcpdm, &omap_mcpdm_links[0]);
if (ret < 0) {
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
goto out;
}
omap_mcpdm_start(mcpdm, stream);
- spin_unlock(&mcpdm->lock);
+ mutex_unlock(&mcpdm->mutex);
}
} else {
mcpdm->uplink->channels = PDM_UP1_EN | PDM_UP2_EN;
@@ -832,7 +831,7 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
mcpdm->downlink = &omap_mcpdm_links[0];
mcpdm->uplink = &omap_mcpdm_links[1];
- spin_lock_init(&mcpdm->lock);
+ mutex_init(&mcpdm->mutex);
mcpdm->free = 1;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 62bf2f4f07f5..e3741aac1fec 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -339,6 +339,14 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(codec->dapm, "Headset Mic");
snd_soc_dapm_disable_pin(codec->dapm, "Headset Stereophone");
+ /* allow audio paths from the audio modem to run during suspend */
+ snd_soc_dapm_ignore_suspend(codec, "Ext Mic");
+ snd_soc_dapm_ignore_suspend(codec, "Ext Spk");
+ snd_soc_dapm_ignore_suspend(codec, "AFML");
+ snd_soc_dapm_ignore_suspend(codec, "AFMR");
+ snd_soc_dapm_ignore_suspend(codec, "Headset Mic");
+ snd_soc_dapm_ignore_suspend(codec, "Headset Stereophone");
+
ret = snd_soc_dapm_sync(codec->dapm);
if (ret)
return ret;
@@ -408,8 +416,9 @@ static struct snd_soc_dai_driver dai[] = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
},
};
@@ -457,6 +466,9 @@ static const char *modem_be[] = {
static const char *mm_lp_be[] = {
OMAP_ABE_BE_PDM_DL1,
+ OMAP_ABE_BE_PDM_DL2,
+ OMAP_ABE_BE_BT_VX,
+ OMAP_ABE_BE_MM_EXT0,
};
/* Digital audio interface glue - connects codec <--> CPU */
@@ -548,6 +560,7 @@ static struct snd_soc_dai_link sdp4430_dai[] = {
.fe_playback_channels = 2,
.fe_capture_channels = 2,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
},
{
.name = "SDP4430 Media LP",
@@ -739,6 +752,7 @@ static struct snd_soc_dai_link sdp4430_dai[] = {
.be_hw_params_fixup = mcbsp_be_hw_params_fixup,
.ops = &sdp4430_mcbsp_ops,
.be_id = OMAP_ABE_DAI_MODEM,
+ .ignore_suspend = 1,
},
{
.name = OMAP_ABE_BE_DMIC0,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 12c822067d5a..7ccddee83e49 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3174,6 +3174,7 @@ static int snd_soc_register_card(struct snd_soc_card *card)
INIT_LIST_HEAD(&card->list);
card->instantiated = 0;
mutex_init(&card->mutex);
+ mutex_init(&card->dapm_mutex);
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 063cfc4d851a..5eeeffad8606 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1176,6 +1176,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down.
*/
+ mutex_lock(&card->dapm_mutex);
list_for_each_entry(w, &dapm->widgets, list) {
switch (w->id) {
case snd_soc_dapm_pre:
@@ -1208,6 +1209,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
break;
}
}
+ mutex_unlock(&card->dapm_mutex);
/* If there are no DAPM widgets then try to figure out power from the
* event type.