diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/mxc_spdif.c | 6 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.c | 4 | ||||
-rw-r--r-- | sound/soc/imx/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/imx/Makefile | 1 | ||||
-rwxr-xr-x | sound/soc/imx/imx-wm8958.c | 89 |
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; } |