diff options
author | Manjunath G Kondaiah <manjugk@ti.com> | 2011-01-17 12:26:26 +0530 |
---|---|---|
committer | Manjunath G Kondaiah <manjugk@ti.com> | 2011-01-17 12:26:26 +0530 |
commit | 48f5ebdb916aabcaf03d8887386a95156b222163 (patch) | |
tree | 0968a1e7f2e958e376123d508b80262569b117f9 | |
parent | 186ec7763ba80b43ea5867958cf7eabb6c7244b5 (diff) | |
parent | e9354f603d68280d2e5af9597d5ad30b9b587139 (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.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.c | 8 | ||||
-rw-r--r-- | sound/soc/omap/abe/abe_seq.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe-dsp.c | 148 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe.c | 4 | ||||
-rw-r--r-- | sound/soc/omap/omap-dmic.c | 1 | ||||
-rw-r--r-- | sound/soc/omap/omap-hdmi.c | 101 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcpdm.c | 31 | ||||
-rw-r--r-- | sound/soc/omap/sdp4430.c | 18 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 1 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 2 |
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. |