summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorguoyin.chen <guoyin.chen@freescale.com>2013-03-14 09:48:51 +0800
committerguoyin.chen <guoyin.chen@freescale.com>2013-03-14 10:04:03 +0800
commitc007aff8141c7af8888dc6c0fd2d6962065a2fa2 (patch)
tree428e4dc1583b299618a5df3206b899c1c488cf84 /sound
parente6176003573fc973c8e296b8d30e810061d50420 (diff)
parentd0d90af2953bdc7a33b6aa0c90a33a01984a06d2 (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.c35
-rw-r--r--sound/soc/codecs/wm8962.c6
-rw-r--r--sound/soc/imx/imx-wm8962.c48
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;
}