diff options
author | b02247 <b02247@freescale.com> | 2012-02-29 15:29:35 +0800 |
---|---|---|
committer | b02247 <b02247@freescale.com> | 2012-02-29 15:58:15 +0800 |
commit | 1275e8745ea9f5d5c62123b002fee4b4aec4b19f (patch) | |
tree | 857849c05e6d6f4e840f72318697430aeff960b1 /sound/soc/imx | |
parent | 516b8402190f3c9146c38cca493564ccf267c6ae (diff) |
ENGR00175702-1 add uevent for wm8958 in sabresd
add uevent for wm8958 in sabresd
Signed-off-by: b02247 <b02247@freescale.com>
Diffstat (limited to 'sound/soc/imx')
-rwxr-xr-x | sound/soc/imx/imx-wm8958.c | 98 |
1 files changed, 90 insertions, 8 deletions
diff --git a/sound/soc/imx/imx-wm8958.c b/sound/soc/imx/imx-wm8958.c index aadc51822dc0..f40d8adc347b 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 <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -45,6 +46,8 @@ 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; }; @@ -141,7 +144,7 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dapm_widget imx_dapm_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Main Mic", NULL), - SND_SOC_DAPM_HP("Headset Phone", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_SPK("Ext Spk", NULL), }; @@ -159,8 +162,8 @@ static const struct snd_soc_dapm_route audio_map[] = { /* ----output------------------- */ /* HP_OUT --> Headphone Jack */ - {"Headset Phone", NULL, "HPOUT1L"}, - {"Headset Phone", NULL, "HPOUT1R"}, + {"Headphone Jack", NULL, "HPOUT1L"}, + {"Headphone Jack", NULL, "HPOUT1R"}, /* LINE_OUT --> Ext Speaker */ {"Ext Spk", NULL, "SPKOUTLP"}, @@ -170,10 +173,75 @@ 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; - int ret; + int ret, i; /* Add imx specific widgets */ snd_soc_dapm_new_controls(&codec->dapm, imx_dapm_widgets, @@ -182,12 +250,11 @@ static int imx_wm8958_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, "Headset Phone"); - snd_soc_dapm_sync(&codec->dapm); +/*headphone detection conflict with the headphone jack*/ +/* if (hs_jack_gpios[0].gpio != -1) { - /* Jack detection API stuff */ ret = snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, &hs_jack); if (ret) @@ -205,7 +272,7 @@ static int imx_wm8958_init(struct snd_soc_pcm_runtime *rtd) if (ret) printk(KERN_WARNING "failed to call snd_soc_jack_add_gpios\n"); } - +*/ return 0; } @@ -268,6 +335,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); @@ -277,9 +345,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; } |