summaryrefslogtreecommitdiff
path: root/sound/soc/imx
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/imx')
-rw-r--r--sound/soc/imx/Kconfig2
-rw-r--r--sound/soc/imx/imx-hdmi-dma.c13
-rw-r--r--sound/soc/imx/imx-sgtl5000.c30
-rw-r--r--sound/soc/imx/imx-wm8962.c100
4 files changed, 90 insertions, 55 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index e30ebbe7e131..9b01af01a45d 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -52,7 +52,7 @@ config SND_SOC_PHYCORE_AC97
config SND_SOC_IMX_SGTL5000
tristate "SoC Audio support for i.MX boards with sgtl5000"
- depends on I2C && (MACH_MX35_3DS || MACH_MX51_BABBAGE \
+ depends on I2C && (MACH_MX35_3DS || MACH_MX51_BABBAGE || MACH_MX53_SMD \
|| MACH_MX6Q_SABRELITE || MACH_MX6Q_ARM2)
select SND_SOC_SGTL5000
select SND_MXC_SOC_MX2
diff --git a/sound/soc/imx/imx-hdmi-dma.c b/sound/soc/imx/imx-hdmi-dma.c
index 84b350386328..c845672be6aa 100644
--- a/sound/soc/imx/imx-hdmi-dma.c
+++ b/sound/soc/imx/imx-hdmi-dma.c
@@ -578,6 +578,7 @@ static void hdmi_dma_mmap_copy(struct snd_pcm_substream *substream,
}
}
+#ifdef CONFIG_ARCH_MX6
static void hdmi_sdma_isr(void *data)
{
struct imx_hdmi_dma_runtime_data *rtd = data;
@@ -611,7 +612,7 @@ static void hdmi_sdma_isr(void *data)
return;
}
-
+#endif
static irqreturn_t hdmi_dma_isr(int irq, void *dev_id)
{
@@ -876,6 +877,7 @@ static int hdmi_dma_copy(struct snd_pcm_substream *substream, int channel,
return 0;
}
+#ifdef CONFIG_ARCH_MX6
static bool hdmi_filter(struct dma_chan *chan, void *param)
{
@@ -971,8 +973,7 @@ static int hdmi_sdma_config(struct imx_hdmi_dma_runtime_data *params)
return 0;
}
-
-
+#endif
static int hdmi_dma_hw_free(struct snd_pcm_substream *substream)
{
@@ -990,7 +991,9 @@ static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_hdmi_dma_runtime_data *rtd = runtime->private_data;
+#ifdef CONFIG_ARCH_MX6
int err;
+#endif
rtd->buffer_bytes = params_buffer_bytes(params);
rtd->periods = params_periods(params);
@@ -1021,6 +1024,7 @@ static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
}
rtd->dma_period_bytes = rtd->period_bytes * rtd->buffer_ratio;
+#ifdef CONFIG_ARCH_MX6
if (hdmi_SDMA_check()) {
rtd->sdma_params.buffer_num = rtd->periods;
rtd->sdma_params.phyaddr = rtd->phy_hdmi_sdma_t;
@@ -1038,6 +1042,7 @@ static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
if (err)
return err;
}
+#endif
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
@@ -1067,8 +1072,6 @@ static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!check_hdmi_state())
- return 0;
rtd->frame_idx = 0;
if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
appl_bytes = frames_to_bytes(runtime,
diff --git a/sound/soc/imx/imx-sgtl5000.c b/sound/soc/imx/imx-sgtl5000.c
index 9325dc8e346c..c73ab7ec19a4 100644
--- a/sound/soc/imx/imx-sgtl5000.c
+++ b/sound/soc/imx/imx-sgtl5000.c
@@ -3,7 +3,7 @@
* sgtl5000 codec
*
* Copyright 2009 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 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 as published by the
@@ -43,6 +43,11 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
},
+ {
+ .pin = "Ext Spk",
+ .mask = SND_JACK_HEADPHONE,
+ .invert = 1,
+ },
};
/* Headphones jack detection gpios */
@@ -195,11 +200,29 @@ static int sgtl5000_set_line_in(struct snd_kcontrol *kcontrol,
return 1;
}
+static int spk_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct imx_sgtl5000_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ if (plat->amp_enable == NULL)
+ return 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ plat->amp_enable(1);
+ else
+ plat->amp_enable(0);
+
+ return 0;
+}
+
/* imx_3stack card dapm widgets */
static const struct snd_soc_dapm_widget imx_3stack_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_LINE("Line In Jack", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", spk_amp_event),
SND_SOC_DAPM_HP("Headphone Jack", NULL),
};
@@ -246,7 +269,8 @@ static int imx_3stack_sgtl5000_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
snd_soc_dapm_disable_pin(&codec->dapm, "Line In Jack");
- snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+ snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+ snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
snd_soc_dapm_sync(&codec->dapm);
if (hs_jack_gpios[0].gpio != -1) {
diff --git a/sound/soc/imx/imx-wm8962.c b/sound/soc/imx/imx-wm8962.c
index 8cf4bdd577de..50da297c50f4 100644
--- a/sound/soc/imx/imx-wm8962.c
+++ b/sound/soc/imx/imx-wm8962.c
@@ -27,6 +27,7 @@
#include <linux/fsl_devices.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/switch.h>
#include <linux/kthread.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -53,6 +54,7 @@ struct imx_priv {
int amic_irq;
int amic_status;
struct platform_device *pdev;
+ struct switch_dev sdev;
struct snd_pcm_substream *first_stream;
struct snd_pcm_substream *second_stream;
};
@@ -64,7 +66,7 @@ static struct snd_soc_codec *gcodec;
static struct snd_soc_jack imx_hp_jack;
static struct snd_soc_jack_pin imx_hp_jack_pins[] = {
{
- .pin = "Ext Spk",
+ .pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
},
};
@@ -260,50 +262,25 @@ static void imx_resume_event(struct work_struct *wor)
return;
}
-static int imx_event_hp(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static int hp_jack_status_check(void)
{
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;
+ int ret = 0;
if (plat->hp_gpio != -1) {
priv->hp_status = gpio_get_value(plat->hp_gpio);
- buf = kmalloc(32, GFP_ATOMIC);
- if (!buf) {
- pr_err("%s kmalloc failed\n", __func__);
- return -ENOMEM;
- }
-
+ /* if headphone is inserted, disable speaker */
if (priv->hp_status != plat->hp_active_low)
- snprintf(buf, 32, "STATE=%d", 2);
+ snd_soc_dapm_nc_pin(&gcodec->dapm, "Ext Spk");
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);
- }
-
- return 0;
-}
-
-static int imx_event_mic(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- 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;
+ snd_soc_dapm_enable_pin(&gcodec->dapm, "Ext Spk");
- if (plat->mic_gpio != -1) {
- priv->amic_status = gpio_get_value(plat->mic_gpio);
+ snd_soc_dapm_sync(&gcodec->dapm);
buf = kmalloc(32, GFP_ATOMIC);
if (!buf) {
@@ -311,32 +288,30 @@ static int imx_event_mic(struct snd_soc_dapm_widget *w,
return -ENOMEM;
}
- if (priv->amic_status == 0)
+ if (priv->hp_status != plat->hp_active_low) {
+ switch_set_state(&priv->sdev, 2);
snprintf(buf, 32, "STATE=%d", 2);
- else
+ ret = imx_hp_jack_gpio.report;
+ } else {
+ switch_set_state(&priv->sdev, 0);
snprintf(buf, 32, "STATE=%d", 0);
-
- envp[0] = "NAME=amic";
+ }
+ envp[0] = "NAME=headphone";
envp[1] = buf;
envp[2] = NULL;
kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
kfree(buf);
}
- return 0;
+ return ret;
}
-
-static const struct snd_kcontrol_new controls[] = {
- SOC_DAPM_PIN_SWITCH("Ext Spk"),
-};
-
/* imx card dapm widgets */
static const struct snd_soc_dapm_widget imx_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", imx_event_hp),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
SND_SOC_DAPM_MIC("AMIC", NULL),
- SND_SOC_DAPM_MIC("DMIC", imx_event_mic),
+ SND_SOC_DAPM_MIC("DMIC", NULL),
};
/* imx machine connections to the codec pins */
@@ -361,6 +336,9 @@ static ssize_t show_headphone(struct device_driver *dev, char *buf)
struct platform_device *pdev = priv->pdev;
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+ if (plat->hp_gpio == -1)
+ return 0;
+
/* determine whether hp is plugged in */
priv->hp_status = gpio_get_value(plat->hp_gpio);
@@ -427,12 +405,14 @@ static int imx_wm8962_init(struct snd_soc_pcm_runtime *rtd)
/* Set up imx specific audio path audio_map */
snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+ snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
snd_soc_dapm_enable_pin(&codec->dapm, "AMIC");
if (plat->hp_gpio != -1) {
imx_hp_jack_gpio.gpio = plat->hp_gpio;
- snd_soc_jack_new(codec, "Ext Spk", SND_JACK_LINEOUT,
+ imx_hp_jack_gpio.jack_status_check = hp_jack_status_check;
+
+ snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
&imx_hp_jack);
snd_soc_jack_add_pins(&imx_hp_jack,
ARRAY_SIZE(imx_hp_jack_pins),
@@ -446,6 +426,14 @@ static int imx_wm8962_init(struct snd_soc_pcm_runtime *rtd)
ret = -EINVAL;
return ret;
}
+
+ priv->hp_status = gpio_get_value(plat->hp_gpio);
+
+ /* if headphone is inserted, disable speaker */
+ if (priv->hp_status != plat->hp_active_low)
+ snd_soc_dapm_nc_pin(&codec->dapm, "Ext Spk");
+ else
+ snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
}
if (plat->mic_gpio != -1) {
@@ -470,6 +458,8 @@ static int imx_wm8962_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync(&codec->dapm);
+
return 0;
}
@@ -542,6 +532,20 @@ static int __devinit imx_wm8962_probe(struct platform_device *pdev)
priv->sysclk = plat->sysclk;
+ priv->sdev.name = "h2w";
+ ret = switch_dev_register(&priv->sdev);
+ if (ret < 0) {
+ ret = -EINVAL;
+ return ret;
+ }
+
+ if (plat->hp_gpio != -1) {
+ priv->hp_status = gpio_get_value(plat->hp_gpio);
+ if (priv->hp_status != plat->hp_active_low)
+ switch_set_state(&priv->sdev, 2);
+ else
+ switch_set_state(&priv->sdev, 0);
+ }
priv->first_stream = NULL;
priv->second_stream = NULL;
@@ -553,9 +557,13 @@ static int __devexit imx_wm8962_remove(struct platform_device *pdev)
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
struct imx_priv *priv = &card_priv;
+ plat->clock_enable(0);
+
if (plat->finit)
plat->finit();
+ switch_dev_unregister(&priv->sdev);
+
if (priv->hp_irq)
free_irq(priv->hp_irq, priv);
if (priv->amic_irq)