summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/mxc_spdif.c6
-rw-r--r--sound/soc/codecs/wm8994.c4
-rw-r--r--sound/soc/imx/Kconfig4
-rw-r--r--sound/soc/imx/Makefile1
-rwxr-xr-xsound/soc/imx/imx-wm8958.c89
5 files changed, 101 insertions, 3 deletions
diff --git a/sound/soc/codecs/mxc_spdif.c b/sound/soc/codecs/mxc_spdif.c
index 883aa4d26687..d22f84fa214b 100644
--- a/sound/soc/codecs/mxc_spdif.c
+++ b/sound/soc/codecs/mxc_spdif.c
@@ -1138,6 +1138,12 @@ static int mxc_spdif_startup(struct snd_pcm_substream *substream,
/* disable all the interrupts */
spdif_intr_enable(0xffffff, 0);
+ /* enable spdif_xtal_clk */
+ clk_enable(plat_data->spdif_core_clk);
+ spdif_softreset();
+ /* disable all the interrupts */
+ spdif_intr_enable(0xffffff, 0);
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = mxc_spdif_playback_startup(substream, dai);
else
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 171c1c720d7c..54099fdb413b 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2425,6 +2425,8 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
struct wm8994 *control = codec->control_data;
int i, ret;
+ pm_runtime_disable(codec->dev);
+
switch (control->type) {
case WM8994:
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
@@ -2504,6 +2506,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
break;
}
+ pm_runtime_enable(codec->dev);
+
return 0;
}
#else
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index e4b57c7ea337..72d85503d495 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -70,12 +70,12 @@ config SND_SOC_IMX_WM8958
a WM8958 codec.
config SND_SOC_IMX_WM8962
- tristate "SoC Audio support for IMX boards with WM8958"
+ tristate "SoC Audio support for IMX boards with WM8962"
select SND_MXC_SOC_MX2
select SND_SOC_WM8962
help
Say Y if you want to add support for SoC audio on an i.MX board with
- a WM8958 codec.
+ a WM8962 codec.
config SND_SOC_IMX_CS42888
tristate "SoC Audio support for i.MX boards with cs42888"
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index adeef06f3c7f..3c851809e26d 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -19,7 +19,6 @@ snd-soc-imx-wm8962-objs := imx-wm8962.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
snd-soc-imx-cs42888-objs := imx-cs42888.o
snd-soc-imx-spdif-objs := imx-spdif.o
-snd-soc-imx-si4763-objs := imx-si4763.o
snd-soc-imx-hdmi-objs := imx-hdmi.o imx-hdmi-dai.o imx-hdmi-dma.o hdmi_pcm.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
diff --git a/sound/soc/imx/imx-wm8958.c b/sound/soc/imx/imx-wm8958.c
index dc7a1f59b37c..328bb0b6ca10 100755
--- a/sound/soc/imx/imx-wm8958.c
+++ b/sound/soc/imx/imx-wm8958.c
@@ -26,6 +26,7 @@
#include <linux/io.h>
#include <linux/fsl_devices.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -46,11 +47,14 @@ struct imx_priv {
int sysclk; /*mclk from the outside*/
int codec_sysclk;
int dai_hifi;
+ int hp_status;
+ int hp_irq;
struct platform_device *pdev;
struct wm8994 *wm8958;
};
static struct imx_priv card_priv;
static struct snd_soc_card snd_soc_card_imx;
+
struct clk *codec_mclk;
static struct snd_soc_jack hs_jack;
@@ -105,6 +109,11 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
int ret = 0;
unsigned int pll_out;
u32 dai_format;
+ /* only need to do this once as capture and playback are sync */
+
+ if (priv->dai_hifi)
+ return 0;
+ priv->dai_hifi = 1;
dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
@@ -178,6 +187,71 @@ static const struct snd_soc_dapm_route audio_map[] = {
};
+static void headphone_detect_handler(struct work_struct *wor)
+{
+
+ struct imx_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+ char *envp[3];
+ char *buf;
+
+ /*sysfs_notify(&pdev->dev.kobj, NULL, "headphone");*/
+ priv->hp_status = gpio_get_value(plat->hp_gpio);
+
+ /* setup a message for userspace headphone in */
+ buf = kmalloc(32, GFP_ATOMIC);
+ if (!buf) {
+ pr_err("%s kmalloc failed\n", __func__);
+ return;
+ }
+
+ if (priv->hp_status == 0)
+ snprintf(buf, 32, "STATE=%d", 2);
+ else
+ snprintf(buf, 32, "STATE=%d", 0);
+
+ envp[0] = "NAME=headphone";
+ envp[1] = buf;
+ envp[2] = NULL;
+ kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
+ kfree(buf);
+
+ enable_irq(priv->hp_irq);
+
+ return;
+}
+
+static DECLARE_DELAYED_WORK(hp_event, headphone_detect_handler);
+
+static irqreturn_t imx_headphone_detect_handler(int irq, void *data)
+{
+ disable_irq_nosync(irq);
+ schedule_delayed_work(&hp_event, msecs_to_jiffies(200));
+ return IRQ_HANDLED;
+}
+
+static ssize_t show_headphone(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ /* determine whether hp is plugged in */
+ priv->hp_status = gpio_get_value(plat->hp_gpio);
+
+ if (priv->hp_status)
+ strcpy(buf, "speaker\n");
+ else
+ strcpy(buf, "headphone\n");
+
+ /*pr_info("show_headphone hp_status = %d \r",priv->hp_status);*/
+
+ return strlen(buf);
+}
+
+static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
+
static int imx_wm8958_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -282,6 +356,7 @@ static int __devinit imx_wm8958_probe(struct platform_device *pdev)
priv->pdev = pdev;
priv->wm8958 = wm8958;
+ priv->hp_irq = gpio_to_irq(plat->hp_gpio);
imx_audmux_config(plat->src_port, plat->ext_port);
@@ -291,9 +366,23 @@ static int __devinit imx_wm8958_probe(struct platform_device *pdev)
}
priv->sysclk = plat->sysclk;
+
+ ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
+ if (ret < 0) {
+ ret = -EINVAL;
+ return ret;
+ }
+
hs_jack_gpios[0].gpio = plat->hp_gpio;
hs_jack_gpios[0].invert = plat->hp_active_low;
+ if (plat->hp_gpio != -1) {
+ ret = request_irq(priv->hp_irq,
+ imx_headphone_detect_handler,
+ IRQ_TYPE_EDGE_BOTH, pdev->name, priv);
+ }
+
+
return ret;
}