diff options
author | guoyin.chen <guoyin.chen@freescale.com> | 2013-02-27 13:32:17 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2013-02-27 13:32:17 +0800 |
commit | 66c3a24a57bd9e721f5d0d45924c3c250bb37770 (patch) | |
tree | 5c467232e149c887a847cedb1cf762a6a6940924 /sound | |
parent | 57ee456c6db3bb07b4725b234ac0a4aefd1c80e1 (diff) | |
parent | 85b80e70a92ad66b86dc0a1636c59145b9fbf39c (diff) |
Merge remote-tracking branch 'fsl-linux-sdk/imx_3.0.35' into imx_3.0.35_android
Conflicts:
arch/arm/mach-mx6/Makefile
arch/arm/mach-mx6/board-mx6dl_hdmidongle.h
arch/arm/mach-mx6/board-mx6q_hdmidongle.c
arch/arm/mach-mx6/board-mx6q_hdmidongle.h
arch/arm/mach-mx6/board-mx6q_sabreauto.c
arch/arm/mach-mx6/board-mx6q_sabrelite.c
drivers/media/video/mxc/capture/csi_v4l2_capture.c
drivers/media/video/mxc/capture/ipu_csi_enc.c
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
drivers/mxc/vpu/mxc_vpu.c
drivers/usb/gadget/arcotg_udc.c
drivers/video/mxc/mxc_ipuv3_fb.c
drivers/video/mxc_hdmi.c
include/linux/mxcfb.h
sound/soc/imx/imx-wm8962.c
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/imx/Kconfig | 6 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.c | 96 | ||||
-rw-r--r-- | sound/soc/imx/imx-wm8962.c | 272 |
3 files changed, 266 insertions, 108 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 7fb135ab70f1..9b01af01a45d 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -124,4 +124,10 @@ config SND_SOC_IMX_HDMI help Say Y if you want to add support for SoC audio through IMX HDMI. +config SND_MXC_SOC_IRAM + bool "Locate SSI Audio DMA playback buffers in IRAM" + depends on MACH_MX6SL_EVK && MACH_MX6SL_ARM2 + help + Say Y if you don't want Audio playback buffers in external ram + endif # SND_IMX_SOC diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 060d093a0aa9..d398307873bf 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -1,7 +1,7 @@ /* * imx-ssi.c -- ALSA Soc Audio Layer * - * Copyright 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved. * * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> * @@ -53,6 +53,7 @@ #include <sound/soc.h> #include <mach/ssi.h> +#include <mach/iram.h> #include <mach/hardware.h> #include "imx-ssi.h" @@ -62,6 +63,9 @@ #define IMX_SSI_FORMATS \ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#ifdef CONFIG_SND_MXC_SOC_IRAM +static int UseIRAM; +#endif /* * SSI Network Mode or TDM slots configuration. @@ -419,15 +423,61 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .shutdown = imx_ssi_shutdown, }; +#ifdef CONFIG_SND_MXC_SOC_IRAM + +static struct vm_operations_struct snd_mxc_audio_playback_vm_ops = { + .open = snd_pcm_mmap_data_open, + .close = snd_pcm_mmap_data_close, +}; + +/* + enable user space access to iram buffer +*/ +static int imx_iram_audio_playback_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *area) +{ + struct snd_dma_buffer *buf = &substream->dma_buffer; + unsigned long off; + unsigned long phys; + unsigned long size; + int ret = 0; + + area->vm_ops = &snd_mxc_audio_playback_vm_ops; + area->vm_private_data = substream; + + off = area->vm_pgoff << PAGE_SHIFT; + phys = buf->addr + off; + size = area->vm_end - area->vm_start; + + area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); + area->vm_flags |= VM_IO; + ret = + remap_pfn_range(area, area->vm_start, phys >> PAGE_SHIFT, + size, area->vm_page_prot); + + return ret; +} +#endif + int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { struct snd_pcm_runtime *runtime = substream->runtime; int ret; +#ifdef CONFIG_SND_MXC_SOC_IRAM + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if ((!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) + && (UseIRAM & (1<<substream->stream))) + ret = imx_iram_audio_playback_mmap(substream, vma); + else + ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); +#else ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); - +#endif pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, runtime->dma_area, runtime->dma_addr, @@ -442,6 +492,9 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) struct snd_soc_pcm_runtime *rtd = pcm->private_data; struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size; +#ifdef CONFIG_SND_MXC_SOC_IRAM + unsigned long buf_paddr; +#endif if (!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) size = IMX_SSI_DMABUF_SIZE; @@ -455,11 +508,34 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.dev = pcm->card->dev; buf->private_data = NULL; + buf->bytes = size; + +#ifdef CONFIG_SND_MXC_SOC_IRAM + if (!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) { + buf->area = iram_alloc(size, &buf_paddr); + if (!buf->area) { + buf->area = + dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + } else { + buf->addr = buf_paddr; + UseIRAM |= 1<<substream->stream; + } + } else { + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + + } +#else buf->area = dma_alloc_writecombine(pcm->card->dev, size, &buf->addr, GFP_KERNEL); if (!buf->area) return -ENOMEM; - buf->bytes = size; +#endif return 0; } @@ -500,6 +576,9 @@ void imx_pcm_free(struct snd_pcm *pcm) struct snd_pcm_substream *substream; struct snd_dma_buffer *buf; int stream; +#ifdef CONFIG_SND_MXC_SOC_IRAM + struct snd_soc_pcm_runtime *rtd = pcm->private_data; +#endif for (stream = 0; stream < 2; stream++) { substream = pcm->streams[stream].substream; @@ -510,8 +589,19 @@ void imx_pcm_free(struct snd_pcm *pcm) if (!buf->area) continue; +#ifdef CONFIG_SND_MXC_SOC_IRAM + if ((!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) + && (UseIRAM & (1<<substream->stream))) { + iram_free(buf->addr, IMX_SSI_DMABUF_SIZE); + UseIRAM &= ~(1<<substream->stream); + } else { + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + } +#else dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, buf->addr); +#endif buf->area = NULL; } } diff --git a/sound/soc/imx/imx-wm8962.c b/sound/soc/imx/imx-wm8962.c index ad8e5fd94e02..d57ff16585aa 100644 --- a/sound/soc/imx/imx-wm8962.c +++ b/sound/soc/imx/imx-wm8962.c @@ -1,7 +1,7 @@ /* * imx-wm8962.c * - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -65,6 +65,34 @@ static int suspend_mic_flag; static int hp_irq; static int mic_irq; +static struct snd_soc_jack imx_hp_jack; +static struct snd_soc_jack_pin imx_hp_jack_pins[] = { + { + .pin = "Ext Spk", + .mask = SND_JACK_HEADPHONE, + }, +}; +static struct snd_soc_jack_gpio imx_hp_jack_gpio = { + .name = "headphone detect", + .report = SND_JACK_HEADPHONE, + .debounce_time = 150, + .invert = 0, +}; + +static struct snd_soc_jack imx_mic_jack; +static struct snd_soc_jack_pin imx_mic_jack_pins[] = { + { + .pin = "DMIC", + .mask = SND_JACK_MICROPHONE, + }, +}; +static struct snd_soc_jack_gpio imx_mic_jack_gpio = { + .name = "micphone detect", + .report = SND_JACK_MICROPHONE, + .debounce_time = 150, + .invert = 0, +}; + static int imx_hifi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -152,6 +180,115 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream, return 0; } +static void imx_resume_event(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; + struct snd_soc_jack *jack; + int enable; + int report; + + if (plat->hp_gpio != -1) { + jack = imx_hp_jack_gpio.jack; + + enable = gpio_get_value_cansleep(imx_hp_jack_gpio.gpio); + if (imx_hp_jack_gpio.invert) + enable = !enable; + + if (enable) + report = imx_hp_jack_gpio.report; + else + report = 0; + + snd_soc_jack_report(jack, report, imx_hp_jack_gpio.report); + } + + if (plat->mic_gpio != -1) { + jack = imx_mic_jack_gpio.jack; + + enable = gpio_get_value_cansleep(imx_mic_jack_gpio.gpio); + if (imx_mic_jack_gpio.invert) + enable = !enable; + + if (enable) + report = imx_mic_jack_gpio.report; + else + report = 0; + + snd_soc_jack_report(jack, report, imx_mic_jack_gpio.report); + } + + return; +} + +static int imx_event_hp(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; + + 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 (priv->hp_status != plat->hp_active_low) + 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); + } + + 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; + + if (plat->mic_gpio != -1) { + priv->amic_status = gpio_get_value(plat->mic_gpio); + + buf = kmalloc(32, GFP_ATOMIC); + if (!buf) { + pr_err("%s kmalloc failed\n", __func__); + return -ENOMEM; + } + + if (priv->amic_status == 0) + snprintf(buf, 32, "STATE=%d", 2); + else + snprintf(buf, 32, "STATE=%d", 0); + + envp[0] = "NAME=amic"; + envp[1] = buf; + envp[2] = NULL; + kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp); + kfree(buf); + } + + return 0; +} + + static const struct snd_kcontrol_new controls[] = { SOC_DAPM_PIN_SWITCH("Ext Spk"), }; @@ -159,9 +296,9 @@ static const struct snd_kcontrol_new controls[] = { /* 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", NULL), + SND_SOC_DAPM_SPK("Ext Spk", imx_event_hp), SND_SOC_DAPM_MIC("AMIC", NULL), - SND_SOC_DAPM_MIC("DMIC", NULL), + SND_SOC_DAPM_MIC("DMIC", imx_event_mic), }; /* imx machine connections to the codec pins */ @@ -264,64 +401,6 @@ static ssize_t show_headphone(struct device_driver *dev, char *buf) static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL); -static void amic_detect_handler(struct work_struct *work) -{ - 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, "amic"); */ - priv->amic_status = gpio_get_value(plat->mic_gpio); - - /* if amic is inserted, disable dmic */ - if (priv->amic_status != plat->mic_active_low) - snd_soc_dapm_nc_pin(&gcodec->dapm, "DMIC"); - else - snd_soc_dapm_enable_pin(&gcodec->dapm, "DMIC"); - - snd_soc_dapm_sync(&gcodec->dapm); - - /* setup a message for userspace headphone in */ - buf = kmalloc(32, GFP_ATOMIC); - if (!buf) { - pr_err("%s kmalloc failed\n", __func__); - return; - } - - if (priv->amic_status == 0) - snprintf(buf, 32, "STATE=%d", 2); - else - snprintf(buf, 32, "STATE=%d", 0); - - envp[0] = "NAME=amic"; - envp[1] = buf; - envp[2] = NULL; - kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp); - kfree(buf); - - if ((suspend_mic_flag == 1) && (mic_irq == 0)) { - suspend_mic_flag = 0; - return; - } - mic_irq = 0; - enable_irq(priv->amic_irq); -} - -static DECLARE_DELAYED_WORK(amic_event, amic_detect_handler); - -static irqreturn_t imx_amic_detect_handler(int irq, void *data) -{ - if (suspend_mic_flag == 1) - return IRQ_HANDLED; - - mic_irq = 1; - disable_irq_nosync(irq); - schedule_delayed_work(&amic_event, msecs_to_jiffies(200)); - return IRQ_HANDLED; -} - static ssize_t show_amic(struct device_driver *dev, char *buf) { struct imx_priv *priv = &card_priv; @@ -329,7 +408,7 @@ static ssize_t show_amic(struct device_driver *dev, char *buf) struct mxc_audio_platform_data *plat = pdev->dev.platform_data; /* determine whether amic is plugged in */ - priv->amic_status = gpio_get_value(plat->mic_gpio); + priv->amic_status = gpio_get_value(plat->hp_gpio); if (priv->amic_status != plat->mic_active_low) strcpy(buf, "amic\n"); @@ -341,9 +420,7 @@ static ssize_t show_amic(struct device_driver *dev, char *buf) static DRIVER_ATTR(amic, S_IRUGO | S_IWUSR, show_amic, NULL); -static DECLARE_DELAYED_WORK(resume_hp_event, headphone_detect_handler); -static DECLARE_DELAYED_WORK(resume_mic_event, amic_detect_handler); - +static DECLARE_DELAYED_WORK(resume_hp_event, imx_resume_event); int imx_hifi_trigger(struct snd_pcm_substream *substream, int cmd) { @@ -351,17 +428,10 @@ int imx_hifi_trigger(struct snd_pcm_substream *substream, int cmd) struct platform_device *pdev = priv->pdev; struct mxc_audio_platform_data *plat = pdev->dev.platform_data; - if (SNDRV_PCM_TRIGGER_SUSPEND == cmd) { - suspend_hp_flag = 1; - suspend_mic_flag = 1; - } if (SNDRV_PCM_TRIGGER_RESUME == cmd) { - if (plat->hp_gpio != -1) + if ((plat->hp_gpio != -1) || (plat->mic_gpio != -1)) schedule_delayed_work(&resume_hp_event, - msecs_to_jiffies(200)); - if (plat->mic_gpio != -1) - schedule_delayed_work(&resume_mic_event, - msecs_to_jiffies(200)); + msecs_to_jiffies(200)); } return 0; @@ -388,19 +458,17 @@ static int imx_wm8962_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_enable_pin(&codec->dapm, "AMIC"); if (plat->hp_gpio != -1) { - priv->hp_irq = gpio_to_irq(plat->hp_gpio); - - ret = request_irq(priv->hp_irq, - imx_headphone_detect_handler, - IRQ_TYPE_EDGE_BOTH, pdev->name, priv); - - if (ret < 0) { - ret = -EINVAL; - return ret; - } + imx_hp_jack_gpio.gpio = plat->hp_gpio; + snd_soc_jack_new(codec, "Ext Spk", SND_JACK_LINEOUT, + &imx_hp_jack); + snd_soc_jack_add_pins(&imx_hp_jack, + ARRAY_SIZE(imx_hp_jack_pins), + imx_hp_jack_pins); + snd_soc_jack_add_gpios(&imx_hp_jack, + 1, &imx_hp_jack_gpio); ret = driver_create_file(pdev->dev.driver, - &driver_attr_headphone); + &driver_attr_headphone); if (ret < 0) { ret = -EINVAL; return ret; @@ -416,32 +484,26 @@ static int imx_wm8962_init(struct snd_soc_pcm_runtime *rtd) } if (plat->mic_gpio != -1) { - priv->amic_irq = gpio_to_irq(plat->mic_gpio); - - ret = request_irq(priv->amic_irq, - imx_amic_detect_handler, - IRQ_TYPE_EDGE_BOTH, pdev->name, priv); + imx_mic_jack_gpio.gpio = plat->mic_gpio; + snd_soc_jack_new(codec, "DMIC", SND_JACK_MICROPHONE, + &imx_mic_jack); + snd_soc_jack_add_pins(&imx_mic_jack, + ARRAY_SIZE(imx_mic_jack_pins), + imx_mic_jack_pins); + snd_soc_jack_add_gpios(&imx_mic_jack, + 1, &imx_mic_jack_gpio); + ret = driver_create_file(pdev->dev.driver, + &driver_attr_amic); if (ret < 0) { ret = -EINVAL; return ret; } - - ret = driver_create_file(pdev->dev.driver, &driver_attr_amic); - if (ret < 0) { - ret = -EINVAL; - return ret; - } - - priv->amic_status = gpio_get_value(plat->mic_gpio); - - /* if amic is inserted, disable DMIC */ - if (priv->amic_status != plat->mic_active_low) - snd_soc_dapm_nc_pin(&codec->dapm, "DMIC"); - else - snd_soc_dapm_enable_pin(&codec->dapm, "DMIC"); - } else if (!snd_soc_dapm_get_pin_status(&codec->dapm, "DMICDAT")) + } else { snd_soc_dapm_nc_pin(&codec->dapm, "DMIC"); + } + + snd_soc_dapm_sync(&codec->dapm); snd_soc_dapm_sync(&codec->dapm); |