diff options
author | guoyin.chen <guoyin.chen@freescale.com> | 2013-03-14 09:48:51 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2013-03-14 10:04:03 +0800 |
commit | c007aff8141c7af8888dc6c0fd2d6962065a2fa2 (patch) | |
tree | 428e4dc1583b299618a5df3206b899c1c488cf84 /sound | |
parent | e6176003573fc973c8e296b8d30e810061d50420 (diff) | |
parent | d0d90af2953bdc7a33b6aa0c90a33a01984a06d2 (diff) |
Merge remote-tracking branch 'fsl-linux-sdk/imx_3.0.35_4.0.0' into imx_3.0.35_android
Conflicts:
arch/arm/mach-mx6/board-mx6q_sabresd.c
arch/arm/plat-mxc/include/mach/mxc.h
drivers/video/mxc/mxc_ipuv3_fb.c
sound/soc/imx/imx-wm8962.c
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/mxc_spdif.c | 35 | ||||
-rw-r--r-- | sound/soc/codecs/wm8962.c | 6 | ||||
-rw-r--r-- | sound/soc/imx/imx-wm8962.c | 48 |
3 files changed, 83 insertions, 6 deletions
diff --git a/sound/soc/codecs/mxc_spdif.c b/sound/soc/codecs/mxc_spdif.c index 33b23371ea58..77e62aefe422 100644 --- a/sound/soc/codecs/mxc_spdif.c +++ b/sound/soc/codecs/mxc_spdif.c @@ -1,7 +1,7 @@ /* * MXC SPDIF ALSA Soc Codec Driver * - * Copyright (C) 2007-2012 Freescale Semiconductor, Inc. + * Copyright (C) 2007-2013 Freescale Semiconductor, Inc. */ /* @@ -881,8 +881,13 @@ static int mxc_spdif_info(struct snd_kcontrol *kcontrol, static int mxc_spdif_capture_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec); + struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data; unsigned int cstatus; + clk_enable(plat_data->spdif_clk); + if (!(__raw_readl(spdif_base_addr + SPDIF_REG_SIS) & INT_CNEW)) return -EAGAIN; @@ -898,6 +903,8 @@ static int mxc_spdif_capture_get(struct snd_kcontrol *kcontrol, /* clear intr */ __raw_writel(INT_CNEW, spdif_base_addr + SPDIF_REG_SIC); + clk_disable(plat_data->spdif_clk); + return 0; } @@ -980,12 +987,19 @@ static int mxc_spdif_vbit_info(struct snd_kcontrol *kcontrol, static int mxc_spdif_vbit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec); + struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data; unsigned int int_val; + clk_enable(plat_data->spdif_clk); + int_val = __raw_readl(spdif_base_addr + SPDIF_REG_SIS); ucontrol->value.integer.value[0] = (int_val & INT_VAL_NOGOOD) != 0; __raw_writel(INT_VAL_NOGOOD, spdif_base_addr + SPDIF_REG_SIC); + clk_disable(plat_data->spdif_clk); + return 0; } @@ -1016,9 +1030,11 @@ static int mxc_spdif_rxrate_get(struct snd_kcontrol *kcontrol, struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data; if (atomic_read(&spdif_priv->dpll_locked)) { + clk_enable(plat_data->spdif_clk); ucontrol->value.integer.value[0] = spdif_get_rxclk_rate(plat_data->spdif_clk, SPDIF_DEFAULT_GAINSEL); + clk_disable(plat_data->spdif_clk); } else { ucontrol->value.integer.value[0] = 0; } @@ -1046,9 +1062,18 @@ static int mxc_spdif_usync_info(struct snd_kcontrol *kcontrol, static int mxc_spdif_usync_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec); + struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data; unsigned int int_val; + + clk_enable(plat_data->spdif_clk); + int_val = __raw_readl(spdif_base_addr + SPDIF_REG_SRCD); ucontrol->value.integer.value[0] = (int_val & SRCD_CD_USER) != 0; + + clk_disable(plat_data->spdif_clk); + return 0; } @@ -1060,10 +1085,18 @@ static int mxc_spdif_usync_get(struct snd_kcontrol *kcontrol, static int mxc_spdif_usync_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec); + struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data; unsigned int int_val; + clk_enable(plat_data->spdif_clk); + int_val = ucontrol->value.integer.value[0] << SRCD_CD_USER_OFFSET; __raw_writel(int_val, spdif_base_addr + SPDIF_REG_SRCD); + + clk_disable(plat_data->spdif_clk); + return 0; } diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index b14531157067..6e7a5e9e9444 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -5,7 +5,7 @@ * * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> * - * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2013 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -4101,10 +4101,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) WM8962_SPKOUTL_VOL_MASK, 0x72); snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME, WM8962_SPKOUTR_VOL_MASK, 0x72); - snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME, - WM8962_DACL_VOL_MASK, 0xd8); - snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME, - WM8962_DACR_VOL_MASK, 0xd8); snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, WM8962_INL_VOL_MASK, 0x3f); diff --git a/sound/soc/imx/imx-wm8962.c b/sound/soc/imx/imx-wm8962.c index 7e6740b50cff..367c2f8e9aa6 100644 --- a/sound/soc/imx/imx-wm8962.c +++ b/sound/soc/imx/imx-wm8962.c @@ -55,6 +55,8 @@ struct imx_priv { int amic_status; struct platform_device *pdev; struct switch_dev sdev; + struct snd_pcm_substream *first_stream; + struct snd_pcm_substream *second_stream; }; unsigned int sample_format = SNDRV_PCM_FMTBIT_S16_LE; static struct imx_priv card_priv; @@ -128,6 +130,11 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream, u32 dai_format; unsigned int pll_out; + if (!priv->first_stream) + priv->first_stream = substream; + else + priv->second_stream = substream; + dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; @@ -176,6 +183,43 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream, return 0; } + +static int imx_hifi_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct imx_priv *priv = &card_priv; + int ret; + + if (priv->first_stream == substream) + priv->first_stream = priv->second_stream; + priv->second_stream = NULL; + + if (!priv->first_stream) { + /* + * wm8962 doesn't allow us to continuously setting FLL, + * So we set MCLK as sysclk once, which'd remove the limitation. + */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + pr_err("Failed to set SYSCLK: %d\n", ret); + return ret; + } + + /* + * Continuously setting FLL would cause playback distortion. + * We can fix it just by mute codec after playback. + */ + ret = snd_soc_dai_digital_mute(codec_dai, 1); + if (ret < 0) { + pr_err("Failed to set MUTE: %d\n", ret); + return ret; + } + } + return 0; +} + static void imx_resume_event(struct work_struct *wor) { struct imx_priv *priv = &card_priv; @@ -423,6 +467,7 @@ static struct snd_soc_ops imx_hifi_ops = { .startup = imx_hifi_startup, .shutdown = imx_hifi_shutdown, .hw_params = imx_hifi_hw_params, + .hw_free = imx_hifi_hw_free, .trigger = imx_hifi_trigger, }; @@ -501,6 +546,9 @@ static int __devinit imx_wm8962_probe(struct platform_device *pdev) else switch_set_state(&priv->sdev, 0); } + priv->first_stream = NULL; + priv->second_stream = NULL; + return ret; } |