aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_lib.c3
-rw-r--r--sound/core/pcm_native.c7
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/atmel/atmel-pcm.c6
-rw-r--r--sound/soc/au1x/dbdma2.c7
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c6
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/omap-hdmi-codec.c492
-rw-r--r--sound/soc/codecs/twl6040.c1058
-rw-r--r--sound/soc/codecs/twl6040.h118
-rw-r--r--sound/soc/davinci/davinci-pcm.c6
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c6
-rw-r--r--sound/soc/fsl/fsl_dma.c6
-rw-r--r--sound/soc/fsl/mpc5200_dma.c7
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c8
-rw-r--r--sound/soc/imx/imx-ssi.c7
-rw-r--r--sound/soc/imx/imx-ssi.h3
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c6
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c6
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c7
-rw-r--r--sound/soc/omap/Kconfig34
-rw-r--r--sound/soc/omap/Makefile12
-rw-r--r--sound/soc/omap/abe/Makefile14
-rw-r--r--sound/soc/omap/abe/abe.h141
-rw-r--r--sound/soc/omap/abe/abe_aess.c191
-rw-r--r--sound/soc/omap/abe/abe_aess.h113
-rw-r--r--sound/soc/omap/abe/abe_api.h511
-rw-r--r--sound/soc/omap/abe/abe_asrc.c1231
-rw-r--r--sound/soc/omap/abe/abe_cm_addr.h221
-rw-r--r--sound/soc/omap/abe/abe_core.c929
-rw-r--r--sound/soc/omap/abe/abe_dat.c458
-rw-r--r--sound/soc/omap/abe/abe_dbg.c201
-rw-r--r--sound/soc/omap/abe/abe_dbg.h231
-rw-r--r--sound/soc/omap/abe/abe_def.h308
-rw-r--r--sound/soc/omap/abe/abe_define.h120
-rw-r--r--sound/soc/omap/abe/abe_dm_addr.h243
-rw-r--r--sound/soc/omap/abe/abe_ext.h242
-rw-r--r--sound/soc/omap/abe/abe_firmware.c14355
-rw-r--r--sound/soc/omap/abe/abe_functionsid.h122
-rw-r--r--sound/soc/omap/abe/abe_fw.h214
-rw-r--r--sound/soc/omap/abe/abe_gain.c790
-rw-r--r--sound/soc/omap/abe/abe_gain.h111
-rw-r--r--sound/soc/omap/abe/abe_ini.c455
-rw-r--r--sound/soc/omap/abe/abe_initxxx_labels.h460
-rw-r--r--sound/soc/omap/abe/abe_irq.c113
-rw-r--r--sound/soc/omap/abe/abe_legacy.h98
-rw-r--r--sound/soc/omap/abe/abe_main.c847
-rw-r--r--sound/soc/omap/abe/abe_main.h676
-rw-r--r--sound/soc/omap/abe/abe_mem.h99
-rw-r--r--sound/soc/omap/abe/abe_port.c1774
-rw-r--r--sound/soc/omap/abe/abe_port.h161
-rw-r--r--sound/soc/omap/abe/abe_ref.h152
-rw-r--r--sound/soc/omap/abe/abe_seq.c308
-rw-r--r--sound/soc/omap/abe/abe_seq.h64
-rw-r--r--sound/soc/omap/abe/abe_sm_addr.h363
-rw-r--r--sound/soc/omap/abe/abe_taskid.h196
-rw-r--r--sound/soc/omap/abe/abe_typ.h654
-rw-r--r--sound/soc/omap/abe/abe_typedef.h240
-rw-r--r--sound/soc/omap/abe/port_mgr.c345
-rw-r--r--sound/soc/omap/abe/port_mgr.h98
-rw-r--r--sound/soc/omap/mcpdm.c470
-rw-r--r--sound/soc/omap/mcpdm.h153
-rw-r--r--sound/soc/omap/omap-abe-dsp.c2876
-rw-r--r--sound/soc/omap/omap-abe-dsp.h177
-rw-r--r--sound/soc/omap/omap-abe.c1563
-rw-r--r--sound/soc/omap/omap-abe.h68
-rw-r--r--sound/soc/omap/omap-hdmi.c158
-rw-r--r--sound/soc/omap/omap-hdmi.h36
-rw-r--r--sound/soc/omap/omap-mcasp.c722
-rw-r--r--sound/soc/omap/omap-mcasp.h37
-rw-r--r--sound/soc/omap/omap-mcbsp.c2
-rw-r--r--sound/soc/omap/omap-mcpdm.c841
-rw-r--r--sound/soc/omap/omap-mcpdm.h120
-rw-r--r--sound/soc/omap/omap-pcm.c31
-rw-r--r--sound/soc/omap/omap4-hdmi-card.c133
-rwxr-xr-x[-rw-r--r--]sound/soc/omap/sdp4430.c679
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c6
-rw-r--r--sound/soc/s6000/s6000-pcm.c7
-rw-r--r--sound/soc/samsung/dma.c6
-rw-r--r--sound/soc/sh/dma-sh7760.c6
-rw-r--r--sound/soc/sh/fsi.c6
-rw-r--r--sound/soc/sh/siu_pcm.c5
-rw-r--r--sound/soc/soc-core.c611
-rw-r--r--sound/soc/soc-dapm.c604
-rw-r--r--sound/soc/soc-dsp.c1737
-rw-r--r--sound/soc/txx9/txx9aclc.c5
89 files changed, 39125 insertions, 1608 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3388442..cd69b38 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1961,6 +1961,9 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime;
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
+ /* TODO: consider and -EINVAL here */
+ if (substream->hw_no_buffer)
+ snd_printd("%s: warning this PCM is host less\n", __func__);
runtime = substream->runtime;
if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
return -EINVAL;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 7393551..4e9ebae 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -850,6 +850,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
return -EBADFD;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ !substream->hw_no_buffer &&
!snd_pcm_playback_data(substream))
return -EPIPE;
runtime->trigger_master = substream;
@@ -2048,6 +2049,12 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
goto error;
}
+ if (substream->ops == NULL) {
+ snd_printd("cannot open back end PCMs directly\n");
+ err = -ENODEV;
+ goto error;
+ }
+
if ((err = substream->ops->open(substream)) < 0)
goto error;
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 1ed61c5..0af7016 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
-snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
+snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o soc-dsp.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index d0e7532..42f699c 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -364,9 +364,11 @@ static struct snd_pcm_ops atmel_pcm_ops = {
\*--------------------------------------------------------------------------*/
static u64 atmel_pcm_dmamask = 0xffffffff;
-static int atmel_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 10fdd28..20bb53a 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -319,10 +319,11 @@ static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-static int au1xpsc_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1);
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 98b44b3..9e59f68 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -418,9 +418,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
pr_debug("%s enter\n", __func__);
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index f1fd95b..c42fb73 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -257,9 +257,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
pr_debug("%s enter\n", __func__);
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index 07cfc7a..c95cc03 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -283,9 +283,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 98175a0..40e3a82 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -240,6 +240,10 @@ config SND_SOC_TWL4030
tristate
config SND_SOC_TWL6040
+ select TWL6040_CODEC
+ tristate
+
+config SND_SOC_OMAP_HDMI_CODEC
tristate
config SND_SOC_UDA134X
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fd85584..04e7b26 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -36,6 +36,7 @@ snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
+snd-soc-omap-hdmi-codec-objs := omap-hdmi-codec.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
@@ -128,6 +129,7 @@ obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
+obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
diff --git a/sound/soc/codecs/omap-hdmi-codec.c b/sound/soc/codecs/omap-hdmi-codec.c
new file mode 100644
index 0000000..b1f3c72
--- /dev/null
+++ b/sound/soc/codecs/omap-hdmi-codec.c
@@ -0,0 +1,492 @@
+/*
+ * ALSA SoC HMDI codec driver
+ *
+ * Author: Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <plat/omap_hwmod.h>
+#include <video/omapdss.h>
+#include <video/hdmi_ti_4xxx_ip.h>
+
+#include "../../../drivers/video/omap2/dss/dss_features.h"
+#include "../../../drivers/video/omap2/dss/dss.h"
+
+#define HDMI_WP 0x0
+#define HDMI_CORE_SYS 0x400
+#define HDMI_CORE_AV 0x900
+#define HDMI_PLLCTRL 0x200
+#define HDMI_PHY 0x300
+
+/* hdmi configuration params */
+struct hdmi_params {
+ int format;
+ int sample_freq;
+ int channels_nr;
+};
+
+
+/* codec private data */
+struct hdmi_codec_data {
+ struct hdmi_audio_format audio_fmt;
+ struct hdmi_audio_dma audio_dma;
+ struct hdmi_core_audio_config audio_core_cfg;
+ struct hdmi_core_infoframe_audio aud_if_cfg;
+ struct hdmi_ip_data ip_data;
+ struct omap_hwmod *oh;
+ struct omap_dss_device *dssdev;
+ struct notifier_block notifier;
+ struct hdmi_params params;
+ struct delayed_work delayed_work;
+ struct workqueue_struct *workqueue;
+ int active;
+} hdmi_data;
+
+
+static int hdmi_audio_set_configuration(struct hdmi_codec_data *priv)
+{
+ struct hdmi_audio_format *audio_format = &priv->audio_fmt;
+ struct hdmi_audio_dma *audio_dma = &priv->audio_dma;
+ struct hdmi_core_audio_config *core_cfg = &priv->audio_core_cfg;
+ struct hdmi_core_infoframe_audio *aud_if_cfg = &priv->aud_if_cfg;
+ int err, n, cts, channel_alloc;
+ enum hdmi_core_audio_sample_freq sample_freq;
+ u32 pclk = omapdss_hdmi_get_pixel_clock();
+
+ switch (priv->params.format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ core_cfg->i2s_cfg.word_max_length =
+ HDMI_AUDIO_I2S_MAX_WORD_20BITS;
+ core_cfg->i2s_cfg.word_length =
+ HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
+ core_cfg->i2s_cfg.in_length_bits =
+ HDMI_AUDIO_I2S_INPUT_LENGTH_16;
+ core_cfg->i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
+ audio_format->samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
+ audio_format->sample_size = HDMI_AUDIO_SAMPLE_16BITS;
+ audio_format->justification = HDMI_AUDIO_JUSTIFY_LEFT;
+ audio_dma->transfer_size = 0x10;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ core_cfg->i2s_cfg.word_max_length =
+ HDMI_AUDIO_I2S_MAX_WORD_24BITS;
+ core_cfg->i2s_cfg.word_length =
+ HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
+ core_cfg->i2s_cfg.in_length_bits =
+ HDMI_AUDIO_I2S_INPUT_LENGTH_24;
+ audio_format->samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
+ audio_format->sample_size = HDMI_AUDIO_SAMPLE_24BITS;
+ audio_format->justification = HDMI_AUDIO_JUSTIFY_RIGHT;
+ core_cfg->i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
+ audio_dma->transfer_size = 0x20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+
+ switch (priv->params.sample_freq) {
+ case 32000:
+ sample_freq = HDMI_AUDIO_FS_32000;
+ break;
+ case 44100:
+ sample_freq = HDMI_AUDIO_FS_44100;
+ break;
+ case 48000:
+ sample_freq = HDMI_AUDIO_FS_48000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = hdmi_ti_4xxx_config_audio_acr(&priv->ip_data,
+ priv->params.sample_freq, &n, &cts, pclk);
+ if (err < 0)
+ return err;
+
+ /* Audio wrapper config */
+ audio_format->type = HDMI_AUDIO_TYPE_LPCM;
+ audio_format->sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
+ /* Disable start/stop signals of IEC 60958 blocks */
+ audio_format->en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF;
+
+ audio_dma->block_size = 0xC0;
+ audio_dma->mode = HDMI_AUDIO_TRANSF_DMA;
+ audio_dma->fifo_threshold = 0x20; /* in number of samples */
+
+ hdmi_ti_4xxx_wp_audio_config_dma(&priv->ip_data, audio_dma);
+ hdmi_ti_4xxx_wp_audio_config_format(&priv->ip_data, audio_format);
+
+ /*
+ * I2S config
+ */
+ core_cfg->i2s_cfg.en_high_bitrate_aud = false;
+ /* Only used with high bitrate audio */
+ core_cfg->i2s_cfg.cbit_order = false;
+ /* Serial data and word select should change on sck rising edge */
+ core_cfg->i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
+ core_cfg->i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
+ /* Set I2S word select polarity */
+ core_cfg->i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
+ core_cfg->i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
+ /* Set serial data to word select shift. See Phillips spec. */
+ core_cfg->i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
+
+ /* Core audio config */
+ core_cfg->freq_sample = sample_freq;
+ core_cfg->n = n;
+ core_cfg->cts = cts;
+ if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
+ core_cfg->aud_par_busclk = 0;
+ core_cfg->cts_mode = HDMI_AUDIO_CTS_MODE_SW;
+ core_cfg->use_mclk = cpu_is_omap446x();
+ } else {
+ core_cfg->aud_par_busclk = (((128 * 31) - 1) << 8);
+ core_cfg->cts_mode = HDMI_AUDIO_CTS_MODE_HW;
+ core_cfg->use_mclk = true;
+ core_cfg->mclk_mode = HDMI_AUDIO_MCLK_128FS;
+ }
+ core_cfg->en_spdif = false;
+ /* Use sample frequency from channel status word */
+ core_cfg->fs_override = true;
+ /* Enable ACR packets */
+ core_cfg->en_acr_pkt = true;
+ /* Disable direct streaming digital audio */
+ core_cfg->en_dsd_audio = false;
+ /* Use parallel audio interface */
+ core_cfg->en_parallel_aud_input = true;
+
+ /* Number of channels */
+
+ switch (priv->params.channels_nr) {
+ case 2:
+ core_cfg->layout = HDMI_AUDIO_LAYOUT_2CH;
+ channel_alloc = 0x0;
+ audio_format->stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
+ audio_format->active_chnnls_msk = 0x03;
+ /* Enable one of the four available serial data channels */
+ core_cfg->i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
+ break;
+ case 6:
+ core_cfg->layout = HDMI_AUDIO_LAYOUT_8CH;
+ channel_alloc = 0xB;
+ audio_format->stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
+ audio_format->active_chnnls_msk = 0x3f;
+ /* Enable all of the four available serial data channels */
+ core_cfg->i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
+ HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
+ HDMI_AUDIO_I2S_SD3_EN;
+ break;
+ case 8:
+ core_cfg->layout = HDMI_AUDIO_LAYOUT_8CH;
+ channel_alloc = 0x13;
+ audio_format->stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
+ audio_format->active_chnnls_msk = 0xff;
+ /* Enable all of the four available serial data channels */
+ core_cfg->i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
+ HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
+ HDMI_AUDIO_I2S_SD3_EN;
+ break;
+ default:
+ pr_err("Unsupported number of channels\n");
+ return -EINVAL;
+ }
+
+ hdmi_ti_4xxx_core_audio_config(&priv->ip_data, core_cfg);
+ hdmi_ti_4xxx_wp_audio_config_format(&priv->ip_data, audio_format);
+
+ /*
+ * Configure packet
+ * info frame audio see doc CEA861-D page 74
+ */
+ aud_if_cfg->db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
+ aud_if_cfg->db1_channel_count = priv->params.channels_nr;
+ aud_if_cfg->db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
+ aud_if_cfg->db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
+ aud_if_cfg->db4_channel_alloc = channel_alloc;
+ aud_if_cfg->db5_downmix_inh = false;
+ aud_if_cfg->db5_lsv = 0;
+
+ hdmi_ti_4xxx_core_audio_infoframe_config(&priv->ip_data, aud_if_cfg);
+ return 0;
+
+}
+
+int hdmi_audio_notifier_callback(struct notifier_block *nb,
+ unsigned long arg, void *ptr)
+{
+ enum omap_dss_display_state state = arg;
+
+ if (state == OMAP_DSS_DISPLAY_ACTIVE) {
+ /* this happens just after hdmi_power_on */
+ hdmi_audio_set_configuration(&hdmi_data);
+ if (hdmi_data.active) {
+ omap_hwmod_set_slave_idlemode(hdmi_data.oh,
+ HWMOD_IDLEMODE_NO);
+ hdmi_ti_4xxx_wp_audio_enable(&hdmi_data.ip_data, 1);
+ queue_delayed_work(hdmi_data.workqueue,
+ &hdmi_data.delayed_work,
+ msecs_to_jiffies(1));
+ }
+ } else {
+ cancel_delayed_work(&hdmi_data.delayed_work);
+ }
+ return 0;
+}
+
+static void hdmi_audio_work(struct work_struct *work)
+{
+ hdmi_ti_4xxx_audio_transfer_en(&hdmi_data.ip_data, 1);
+}
+
+int hdmi_audio_match(struct omap_dss_device *dssdev, void *arg)
+{
+ return sysfs_streq(dssdev->name , "hdmi");
+}
+
+static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct hdmi_codec_data *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->params.format = params_format(params);
+ priv->params.sample_freq = params_rate(params);
+ priv->params.channels_nr = params_channels(params);
+ return hdmi_audio_set_configuration(priv);
+}
+
+static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct hdmi_codec_data *priv = snd_soc_codec_get_drvdata(codec);
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /*
+ * switch to no-idle to avoid DSS_L3_ICLK clock
+ * to be shutdown during audio activity (as per TRM)
+ */
+ omap_hwmod_set_slave_idlemode(priv->oh,
+ HWMOD_IDLEMODE_NO);
+ hdmi_ti_4xxx_wp_audio_enable(&priv->ip_data, 1);
+ queue_delayed_work(priv->workqueue, &priv->delayed_work,
+ msecs_to_jiffies(1));
+
+ priv->active = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ cancel_delayed_work(&hdmi_data.delayed_work);
+ priv->active = 0;
+ hdmi_ti_4xxx_audio_transfer_en(&priv->ip_data, 0);
+ hdmi_ti_4xxx_wp_audio_enable(&priv->ip_data, 0);
+ /*
+ * switch back to smart-idle & wakeup capable
+ * after audio activity stops
+ */
+ omap_hwmod_set_slave_idlemode(priv->oh,
+ HWMOD_IDLEMODE_SMART_WKUP);
+ break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
+static int hdmi_audio_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ if (!omapdss_hdmi_get_mode()) {
+ pr_err("Current video settings do not support audio.\n");
+ return -EIO;
+ }
+ return 0;
+}
+static int hdmi_probe(struct snd_soc_codec *codec)
+{
+ struct platform_device *pdev = to_platform_device(codec->dev);
+ struct resource *hdmi_rsrc;
+ int ret = 0;
+
+ snd_soc_codec_set_drvdata(codec, &hdmi_data);
+
+ hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!hdmi_rsrc) {
+ dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
+ ret = -EINVAL;
+ goto res_err;
+ }
+
+
+ hdmi_data.oh = omap_hwmod_lookup("dss_hdmi");
+
+ if (!hdmi_data.oh) {
+ dev_err(&pdev->dev, "can't find omap_hwmod for hdmi\n");
+ ret = -ENODEV;
+ goto res_err;
+ }
+
+ /* Base address taken from platform */
+ hdmi_data.ip_data.base_wp = ioremap(hdmi_rsrc->start,
+ resource_size(hdmi_rsrc));
+
+ if (!hdmi_data.ip_data.base_wp) {
+ dev_err(&pdev->dev, "can't ioremap WP\n");
+ ret = -ENOMEM;
+ goto res_err;
+ }
+
+ hdmi_data.ip_data.hdmi_core_sys_offset = HDMI_CORE_SYS;
+ hdmi_data.ip_data.hdmi_core_av_offset = HDMI_CORE_AV;
+ hdmi_data.ip_data.hdmi_pll_offset = HDMI_PLLCTRL;
+ hdmi_data.ip_data.hdmi_phy_offset = HDMI_PHY;
+
+ hdmi_data.dssdev = omap_dss_find_device(NULL, hdmi_audio_match);
+
+ if (!hdmi_data.dssdev) {
+ dev_err(&pdev->dev, "can't find HDMI device\n");
+ ret = -ENODEV;
+ goto dssdev_err;
+ }
+
+ hdmi_data.notifier.notifier_call = hdmi_audio_notifier_callback;
+ blocking_notifier_chain_register(&hdmi_data.dssdev->state_notifiers,
+ &hdmi_data.notifier);
+
+ hdmi_data.workqueue = create_singlethread_workqueue("hdmi-codec");
+
+ INIT_DELAYED_WORK(&hdmi_data.delayed_work, hdmi_audio_work);
+
+ return 0;
+
+dssdev_err:
+ iounmap(hdmi_data.ip_data.base_wp);
+res_err:
+ return ret;
+
+}
+
+static int hdmi_remove(struct snd_soc_codec *codec)
+{
+ struct hdmi_codec_data *priv = snd_soc_codec_get_drvdata(codec);
+
+ blocking_notifier_chain_unregister(&priv->dssdev->state_notifiers,
+ &priv->notifier);
+ iounmap(priv->ip_data.base_wp);
+ kfree(priv);
+ return 0;
+}
+
+
+static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
+ .probe = hdmi_probe,
+ .remove = hdmi_remove,
+};
+
+static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
+ .hw_params = hdmi_audio_hw_params,
+ .trigger = hdmi_audio_trigger,
+ .startup = hdmi_audio_startup,
+};
+
+static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
+ .name = "hdmi-audio-codec",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ },
+ .ops = &hdmi_audio_codec_ops,
+};
+
+static __devinit int hdmi_codec_probe(struct platform_device *pdev)
+{
+ int r;
+
+ /* Register ASoC codec DAI */
+ r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+ &hdmi_codec_dai_drv, 1);
+ if (r) {
+ dev_err(&pdev->dev, "can't register ASoC HDMI audio codec\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static int __devexit hdmi_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+
+static struct platform_driver hdmi_codec_driver = {
+ .probe = hdmi_codec_probe,
+ .remove = __devexit_p(hdmi_codec_remove),
+ .driver = {
+ .name = "omap-hdmi-codec",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+static int __init hdmi_codec_init(void)
+{
+ return platform_driver_register(&hdmi_codec_driver);
+}
+module_init(hdmi_codec_init);
+
+static void __exit hdmi_codec_exit(void)
+{
+ platform_driver_unregister(&hdmi_codec_driver);
+}
+module_exit(hdmi_codec_exit);
+
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("ASoC HDMI codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 4c33663..b23fb26 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -29,6 +29,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040-codec.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -57,6 +58,8 @@
#define TWL6040_HSR_VOL_SHIFT 4
#define TWL6040_HF_VOL_MASK 0x1F
#define TWL6040_HF_VOL_SHIFT 0
+#define TWL6040_EP_VOL_MASK 0x1E
+#define TWL6040_EP_VOL_SHIFT 1
struct twl6040_output {
u16 active;
@@ -77,25 +80,32 @@ struct twl6040_jack_data {
/* codec private data */
struct twl6040_data {
- int audpwron;
- int naudint;
int codec_powered;
int pll;
- int non_lp;
+ int power_mode_forced;
+ int headset_mode;
+ unsigned int clk_in;
unsigned int sysclk;
+ u16 hs_left_step;
+ u16 hs_right_step;
+ u16 hf_left_step;
+ u16 hf_right_step;
+ u16 ep_step;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
- struct completion ready;
struct twl6040_jack_data hs_jack;
struct snd_soc_codec *codec;
struct workqueue_struct *workqueue;
struct delayed_work delayed_work;
struct mutex mutex;
struct twl6040_output headset;
+ struct twl6040_output earphone;
struct twl6040_output handsfree;
struct workqueue_struct *hf_workqueue;
struct workqueue_struct *hs_workqueue;
+ struct workqueue_struct *ep_workqueue;
struct delayed_work hs_delayed_work;
struct delayed_work hf_delayed_work;
+ struct delayed_work ep_delayed_work;
};
/*
@@ -120,12 +130,12 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
0x1B, /* TWL6040_LINEGAIN 0x0F */
0x00, /* TWL6040_HSLCTL 0x10 */
0x00, /* TWL6040_HSRCTL 0x11 */
- 0x00, /* TWL6040_HSGAIN 0x12 */
- 0x00, /* TWL6040_EARCTL 0x13 */
+ 0xFF, /* TWL6040_HSGAIN 0x12 */
+ 0x1E, /* TWL6040_EARCTL 0x13 */
0x00, /* TWL6040_HFLCTL 0x14 */
- 0x00, /* TWL6040_HFLGAIN 0x15 */
+ 0x1D, /* TWL6040_HFLGAIN 0x15 */
0x00, /* TWL6040_HFRCTL 0x16 */
- 0x00, /* TWL6040_HFRGAIN 0x17 */
+ 0x1D, /* TWL6040_HFRGAIN 0x17 */
0x00, /* TWL6040_VIBCTLL 0x18 */
0x00, /* TWL6040_VIBDATL 0x19 */
0x00, /* TWL6040_VIBCTLR 0x1A */
@@ -151,59 +161,59 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
0x00, /* TWL6040_STATUS (ro) 0x2E */
};
-/*
- * twl6040 vio/gnd registers:
- * registers under vio/gnd supply can be accessed
- * before the power-up sequence, after NRESPWRON goes high
- */
-static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
- TWL6040_REG_ASICID,
- TWL6040_REG_ASICREV,
- TWL6040_REG_INTID,
- TWL6040_REG_INTMR,
- TWL6040_REG_NCPCTL,
- TWL6040_REG_LDOCTL,
- TWL6040_REG_AMICBCTL,
- TWL6040_REG_DMICBCTL,
- TWL6040_REG_HKCTL1,
- TWL6040_REG_HKCTL2,
- TWL6040_REG_GPOCTL,
- TWL6040_REG_TRIM1,
- TWL6040_REG_TRIM2,
- TWL6040_REG_TRIM3,
- TWL6040_REG_HSOTRIM,
- TWL6040_REG_HFOTRIM,
- TWL6040_REG_ACCCTL,
- TWL6040_REG_STATUS,
-};
-/*
- * twl6040 vdd/vss registers:
- * registers under vdd/vss supplies can only be accessed
- * after the power-up sequence
- */
-static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
- TWL6040_REG_HPPLLCTL,
- TWL6040_REG_LPPLLCTL,
- TWL6040_REG_LPPLLDIV,
- TWL6040_REG_MICLCTL,
- TWL6040_REG_MICRCTL,
- TWL6040_REG_MICGAIN,
- TWL6040_REG_LINEGAIN,
- TWL6040_REG_HSLCTL,
- TWL6040_REG_HSRCTL,
- TWL6040_REG_HSGAIN,
- TWL6040_REG_EARCTL,
- TWL6040_REG_HFLCTL,
- TWL6040_REG_HFLGAIN,
- TWL6040_REG_HFRCTL,
- TWL6040_REG_HFRGAIN,
- TWL6040_REG_VIBCTLL,
- TWL6040_REG_VIBDATL,
- TWL6040_REG_VIBCTLR,
- TWL6040_REG_VIBDATR,
- TWL6040_REG_ALB,
- TWL6040_REG_DLB,
+/* twl6040 vio/gnd registers: registers under vio/gnd supply can be accessed
+ * twl6040 vdd/vss registers: registers under vdd/vss supplies can only be
+ * accessed after the power-up sequence */
+
+static const u8 twl6040_reg_supply[TWL6040_CACHEREGNUM] = {
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_VIO_SUPPLY, /* TWL6040_ASICID (ro) */
+ TWL6040_VIO_SUPPLY, /* TWL6040_ASICREV (ro) */
+ TWL6040_VIO_SUPPLY, /* TWL6040_INTID */
+ TWL6040_VIO_SUPPLY, /* TWL6040_INTMR */
+ TWL6040_VIO_SUPPLY, /* TWL6040_NCPCTRL */
+ TWL6040_VIO_SUPPLY, /* TWL6040_LDOCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HPPLLCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_LPPLLCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_LPPLLDIV */
+ TWL6040_VIO_SUPPLY, /* TWL6040_AMICBCTL */
+ TWL6040_VIO_SUPPLY, /* TWL6040_DMICBCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_MICLCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_MICRCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_MICGAIN */
+ TWL6040_VDD_SUPPLY, /* TWL6040_LINEGAIN */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HSLCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HSRCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HSGAIN */
+ TWL6040_VDD_SUPPLY, /* TWL6040_EARCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HFLCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HFLGAIN */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HFRCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_HFRGAIN */
+ TWL6040_VDD_SUPPLY, /* TWL6040_VIBCTLL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_VIBDATL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_VIBCTLR */
+ TWL6040_VDD_SUPPLY, /* TWL6040_VIBDATR */
+ TWL6040_VIO_SUPPLY, /* TWL6040_HKCTL1 */
+ TWL6040_VIO_SUPPLY, /* TWL6040_HKCTL2 */
+ TWL6040_VIO_SUPPLY, /* TWL6040_GPOCTL */
+ TWL6040_VDD_SUPPLY, /* TWL6040_ALB */
+ TWL6040_VDD_SUPPLY, /* TWL6040_DLB */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_NO_SUPPLY, /* not used */
+ TWL6040_VIO_SUPPLY, /* TWL6040_TRIM1 */
+ TWL6040_VIO_SUPPLY, /* TWL6040_TRIM2 */
+ TWL6040_VIO_SUPPLY, /* TWL6040_TRIM3 */
+ TWL6040_VIO_SUPPLY, /* TWL6040_HSOTRIM */
+ TWL6040_VIO_SUPPLY, /* TWL6040_HFOTRIM */
+ TWL6040_VIO_SUPPLY, /* TWL6040_ACCCTL */
+ TWL6040_VIO_SUPPLY, /* TWL6040_STATUS (ro) */
};
/*
@@ -237,14 +247,21 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
* read from twl6040 hardware register
*/
static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
- unsigned int reg)
+ unsigned int reg)
{
- u8 value;
+ struct twl6040 *twl6040 = codec->control_data;
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+ u8 value = 0;
if (reg >= TWL6040_CACHEREGNUM)
return -EIO;
- twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
+ /* read access not supported while in sleep state */
+ if ((twl6040_reg_supply[reg] == TWL6040_VDD_SUPPLY) &&
+ !priv->codec_powered)
+ return -EINVAL;
+
+ value = twl6040_reg_read(twl6040, reg);
twl6040_write_reg_cache(codec, reg, value);
return value;
@@ -256,29 +273,52 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
static int twl6040_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
+ struct twl6040 *twl6040 = codec->control_data;
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
if (reg >= TWL6040_CACHEREGNUM)
return -EIO;
twl6040_write_reg_cache(codec, reg, value);
- return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
+
+ if ((twl6040_reg_supply[reg] == TWL6040_VIO_SUPPLY) ||
+ priv->codec_powered)
+ ret = twl6040_reg_write(twl6040, reg, value);
+ else
+ dev_dbg(codec->dev, "deferring register 0x%02x write: %02x\n",
+ reg, value);
+
+ return ret;
}
static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
{
u8 *cache = codec->reg_cache;
- int reg, i;
-
- /* allow registers to be accessed by i2c */
- twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
+ int reg;
- for (i = 0; i < TWL6040_VIOREGNUM; i++) {
- reg = twl6040_vio_reg[i];
- /* skip read-only registers (ASICID, ASICREV, STATUS) */
+ for (reg = 0; reg < TWL6040_CACHEREGNUM; reg++) {
+ if (twl6040_reg_supply[reg] != TWL6040_VIO_SUPPLY)
+ continue;
+ /*
+ * skip read-only registers (ASICID, ASICREV, STATUS)
+ * and registers shared among MFD children
+ */
switch (reg) {
case TWL6040_REG_ASICID:
case TWL6040_REG_ASICREV:
+ case TWL6040_REG_INTID:
+ case TWL6040_REG_INTMR:
+ case TWL6040_REG_NCPCTL:
+ case TWL6040_REG_LDOCTL:
+ case TWL6040_REG_GPOCTL:
+ case TWL6040_REG_ACCCTL:
case TWL6040_REG_STATUS:
continue;
+ case TWL6040_REG_HSOTRIM:
+ case TWL6040_REG_HFOTRIM:
+ twl6040_read_reg_volatile(codec, reg);
+ continue;
default:
break;
}
@@ -289,10 +329,24 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
{
u8 *cache = codec->reg_cache;
- int reg, i;
+ int reg;
- for (i = 0; i < TWL6040_VDDREGNUM; i++) {
- reg = twl6040_vdd_reg[i];
+ for (reg = 0; reg < TWL6040_CACHEREGNUM; reg++) {
+ if (twl6040_reg_supply[reg] != TWL6040_VDD_SUPPLY)
+ continue;
+ /* skip vibra and pll registers */
+ switch (reg) {
+ case TWL6040_REG_VIBCTLL:
+ case TWL6040_REG_VIBDATL:
+ case TWL6040_REG_VIBCTLR:
+ case TWL6040_REG_VIBDATR:
+ case TWL6040_REG_HPPLLCTL:
+ case TWL6040_REG_LPPLLCTL:
+ case TWL6040_REG_LPPLLDIV:
+ continue;
+ default:
+ break;
+ }
twl6040_write(codec, reg, cache[reg]);
}
}
@@ -317,7 +371,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
if (headset->ramp == TWL6040_RAMP_UP) {
/* ramp step up */
if (val < headset->left_vol) {
- val += left_step;
+ if (val + left_step > headset->left_vol)
+ val = headset->left_vol;
+ else
+ val += left_step;
+
reg &= ~TWL6040_HSL_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HSGAIN,
(reg | (~val & TWL6040_HSL_VOL_MASK)));
@@ -327,7 +385,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
} else if (headset->ramp == TWL6040_RAMP_DOWN) {
/* ramp step down */
if (val > 0x0) {
- val -= left_step;
+ if ((int)val - (int)left_step < 0)
+ val = 0;
+ else
+ val -= left_step;
+
reg &= ~TWL6040_HSL_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
(~val & TWL6040_HSL_VOL_MASK));
@@ -344,7 +406,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
if (headset->ramp == TWL6040_RAMP_UP) {
/* ramp step up */
if (val < headset->right_vol) {
- val += right_step;
+ if (val + right_step > headset->right_vol)
+ val = headset->right_vol;
+ else
+ val += right_step;
+
reg &= ~TWL6040_HSR_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HSGAIN,
(reg | (~val << TWL6040_HSR_VOL_SHIFT)));
@@ -354,7 +420,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
} else if (headset->ramp == TWL6040_RAMP_DOWN) {
/* ramp step down */
if (val > 0x0) {
- val -= right_step;
+ if ((int)val - (int)right_step < 0)
+ val = 0;
+ else
+ val -= right_step;
+
reg &= ~TWL6040_HSR_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HSGAIN,
reg | (~val << TWL6040_HSR_VOL_SHIFT));
@@ -385,7 +455,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
if (handsfree->ramp == TWL6040_RAMP_UP) {
/* ramp step up */
if (val < handsfree->left_vol) {
- val += left_step;
+ if (val + left_step > handsfree->left_vol)
+ val = handsfree->left_vol;
+ else
+ val += left_step;
+
reg &= ~TWL6040_HF_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HFLGAIN,
reg | (0x1D - val));
@@ -395,7 +469,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
} else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
/* ramp step down */
if (val > 0) {
- val -= left_step;
+ if ((int)val - (int)left_step < 0)
+ val = 0;
+ else
+ val -= left_step;
+
reg &= ~TWL6040_HF_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HFLGAIN,
reg | (0x1D - val));
@@ -412,7 +490,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
if (handsfree->ramp == TWL6040_RAMP_UP) {
/* ramp step up */
if (val < handsfree->right_vol) {
- val += right_step;
+ if (val + right_step > handsfree->right_vol)
+ val = handsfree->right_vol;
+ else
+ val += right_step;
+
reg &= ~TWL6040_HF_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HFRGAIN,
reg | (0x1D - val));
@@ -422,10 +504,16 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
} else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
/* ramp step down */
if (val > 0) {
- val -= right_step;
+ if ((int)val - (int)right_step < 0)
+ val = 0;
+ else
+ val -= right_step;
+
reg &= ~TWL6040_HF_VOL_MASK;
twl6040_write(codec, TWL6040_REG_HFRGAIN,
reg | (0x1D - val));
+ } else {
+ right_complete = 1;
}
}
@@ -433,6 +521,57 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
}
/*
+ * Ramp Earpiece PGA volume to minimise pops at stream startup and shutdown.
+ */
+static inline int twl6040_ep_ramp_step(struct snd_soc_codec *codec,
+ unsigned int step)
+{
+
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+ struct twl6040_output *earphone = &priv->earphone;
+ int complete = 0;
+ u8 reg, val;
+
+ step = (step > 0xF) ? 0xF : step;
+ reg = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL);
+ val = (~reg & TWL6040_EP_VOL_MASK) >> TWL6040_EP_VOL_SHIFT;
+
+ if (earphone->ramp == TWL6040_RAMP_UP) {
+ /* ramp step up */
+ if (val < earphone->left_vol) {
+ if (val + step > earphone->left_vol)
+ val = earphone->left_vol;
+ else
+ val += step;
+
+ reg &= ~TWL6040_EP_VOL_MASK;
+ val = ~val << TWL6040_EP_VOL_SHIFT;
+ twl6040_write(codec, TWL6040_REG_EARCTL,
+ reg | (val & TWL6040_EP_VOL_MASK));
+ } else {
+ complete = 1;
+ }
+ } else if (earphone->ramp == TWL6040_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0x0) {
+ if ((int)val - (int)step < 0)
+ val = 0;
+ else
+ val -= step;
+
+ reg &= ~TWL6040_EP_VOL_MASK;
+ val = ~val << TWL6040_EP_VOL_SHIFT;
+ twl6040_write(codec, TWL6040_REG_EARCTL,
+ reg | (val & TWL6040_EP_VOL_MASK));
+ } else {
+ complete = 1;
+ }
+ }
+
+ return complete;
+}
+
+/*
* This work ramps both output PGAs at stream start/stop time to
* minimise pop associated with DAPM power switching.
*/
@@ -451,11 +590,9 @@ static void twl6040_pga_hs_work(struct work_struct *work)
/* HS PGA volumes have 4 bits of resolution to ramp */
for (i = 0; i <= 16; i++) {
- headset_complete = 1;
- if (headset->ramp != TWL6040_RAMP_NONE)
- headset_complete = twl6040_hs_ramp_step(codec,
- headset->left_step,
- headset->right_step);
+ headset_complete = twl6040_hs_ramp_step(codec,
+ headset->left_step,
+ headset->right_step);
/* ramp finished ? */
if (headset_complete)
@@ -496,11 +633,9 @@ static void twl6040_pga_hf_work(struct work_struct *work)
/* HF PGA volumes have 5 bits of resolution to ramp */
for (i = 0; i <= 32; i++) {
- handsfree_complete = 1;
- if (handsfree->ramp != TWL6040_RAMP_NONE)
- handsfree_complete = twl6040_hf_ramp_step(codec,
- handsfree->left_step,
- handsfree->right_step);
+ handsfree_complete = twl6040_hf_ramp_step(codec,
+ handsfree->left_step,
+ handsfree->right_step);
/* ramp finished ? */
if (handsfree_complete)
@@ -526,6 +661,48 @@ static void twl6040_pga_hf_work(struct work_struct *work)
handsfree->ramp = TWL6040_RAMP_NONE;
}
+static void twl6040_pga_ep_work(struct work_struct *work)
+{
+ struct twl6040_data *priv =
+ container_of(work, struct twl6040_data, ep_delayed_work.work);
+ struct snd_soc_codec *codec = priv->codec;
+ struct twl6040_output *earphone = &priv->earphone;
+ unsigned int delay = earphone->step_delay;
+ int i, earphone_complete;
+
+ /* do we need to ramp at all ? */
+ if (earphone->ramp == TWL6040_RAMP_NONE)
+ return;
+
+ /* Earpiece PGA volumes have 4 bits of resolution to ramp */
+ for (i = 0; i <= 16; i++) {
+ earphone_complete = twl6040_ep_ramp_step(codec,
+ earphone->left_step);
+
+ /* ramp finished ? */
+ if (earphone_complete)
+ break;
+
+ /*
+ * TODO: tune: delay is longer over 0dB
+ * as increases are larger.
+ */
+ if (i >= 8)
+ schedule_timeout_interruptible(msecs_to_jiffies(delay +
+ (delay >> 1)));
+ else
+ schedule_timeout_interruptible(msecs_to_jiffies(delay));
+ }
+
+ if (earphone->ramp == TWL6040_RAMP_DOWN) {
+ earphone->active = 0;
+ complete(&earphone->ramp_done);
+ } else {
+ earphone->active = 1;
+ }
+ earphone->ramp = TWL6040_RAMP_NONE;
+}
+
static int pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -536,22 +713,29 @@ static int pga_event(struct snd_soc_dapm_widget *w,
struct workqueue_struct *queue;
switch (w->shift) {
+ case 0:
+ out = &priv->earphone;
+ work = &priv->ep_delayed_work;
+ queue = priv->ep_workqueue;
+ out->left_step = priv->ep_step;
+ out->step_delay = 5; /* 5 ms between volume ramp steps */
+ break;
case 2:
case 3:
out = &priv->headset;
work = &priv->hs_delayed_work;
queue = priv->hs_workqueue;
+ out->left_step = priv->hs_left_step;
+ out->right_step = priv->hs_right_step;
out->step_delay = 5; /* 5 ms between volume ramp steps */
break;
case 4:
out = &priv->handsfree;
work = &priv->hf_delayed_work;
queue = priv->hf_workqueue;
+ out->left_step = priv->hf_left_step;
+ out->right_step = priv->hf_right_step;
out->step_delay = 5; /* 5 ms between volume ramp steps */
- if (SND_SOC_DAPM_EVENT_ON(event))
- priv->non_lp++;
- else
- priv->non_lp--;
break;
default:
return -1;
@@ -579,8 +763,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
if (!delayed_work_pending(work)) {
/* use volume ramp for power-down */
- out->left_step = 1;
- out->right_step = 1;
out->ramp = TWL6040_RAMP_DOWN;
INIT_COMPLETION(out->ramp_done);
@@ -596,88 +778,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
return 0;
}
-/* twl6040 codec manual power-up sequence */
-static void twl6040_power_up(struct snd_soc_codec *codec)
-{
- u8 ncpctl, ldoctl, lppllctl, accctl;
-
- ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
- ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
- lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
- accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
- /* enable reference system */
- ldoctl |= TWL6040_REFENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- msleep(10);
- /* enable internal oscillator */
- ldoctl |= TWL6040_OSCENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(10);
- /* enable high-side ldo */
- ldoctl |= TWL6040_HSLDOENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(244);
- /* enable negative charge pump */
- ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
- twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
- udelay(488);
- /* enable low-side ldo */
- ldoctl |= TWL6040_LSLDOENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(244);
- /* enable low-power pll */
- lppllctl |= TWL6040_LPLLENA;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
- /* reset state machine */
- accctl |= TWL6040_RESETSPLIT;
- twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
- mdelay(5);
- accctl &= ~TWL6040_RESETSPLIT;
- twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
- /* disable internal oscillator */
- ldoctl &= ~TWL6040_OSCENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-}
-
-/* twl6040 codec manual power-down sequence */
-static void twl6040_power_down(struct snd_soc_codec *codec)
-{
- u8 ncpctl, ldoctl, lppllctl, accctl;
-
- ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
- ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
- lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
- accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
- /* enable internal oscillator */
- ldoctl |= TWL6040_OSCENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(10);
- /* disable low-power pll */
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
- /* disable low-side ldo */
- ldoctl &= ~TWL6040_LSLDOENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(244);
- /* disable negative charge pump */
- ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
- twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
- udelay(488);
- /* disable high-side ldo */
- ldoctl &= ~TWL6040_HSLDOENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- udelay(244);
- /* disable internal oscillator */
- ldoctl &= ~TWL6040_OSCENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- /* disable reference system */
- ldoctl &= ~TWL6040_REFENA;
- twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
- msleep(10);
-}
-
/* set headset dac and driver power mode */
static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
{
@@ -701,27 +801,32 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
return 0;
}
-static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
+static int twl6040_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
msleep(1);
return 0;
}
-static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
+static int twl6040_ep_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
- if (SND_SOC_DAPM_EVENT_ON(event))
- priv->non_lp++;
- else
- priv->non_lp--;
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Earphone doesn't support low power mode */
+ priv->power_mode_forced = 1;
+ ret = headset_power_mode(codec, 1);
+ } else {
+ priv->power_mode_forced = 0;
+ ret = headset_power_mode(codec, priv->headset_mode);
+ }
msleep(1);
- return 0;
+ return ret;
}
static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
@@ -766,32 +871,18 @@ static void twl6040_accessory_work(struct work_struct *work)
}
/* audio interrupt handler */
-static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+static irqreturn_t twl6040_audio_handler(int irq, void *data)
{
struct snd_soc_codec *codec = data;
+ struct twl6040 *twl6040 = codec->control_data;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
u8 intid;
- twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
-
- if (intid & TWL6040_THINT)
- dev_alert(codec->dev, "die temp over-limit detection\n");
+ intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
queue_delayed_work(priv->workqueue, &priv->delayed_work,
- msecs_to_jiffies(200));
-
- if (intid & TWL6040_HOOKINT)
- dev_info(codec->dev, "hook detection\n");
-
- if (intid & TWL6040_HFINT)
- dev_alert(codec->dev, "hf drivers over current detection\n");
-
- if (intid & TWL6040_VIBINT)
- dev_alert(codec->dev, "vib drivers over current detection\n");
-
- if (intid & TWL6040_READYINT)
- complete(&priv->ready);
+ msecs_to_jiffies(200));
return IRQ_HANDLED;
}
@@ -807,13 +898,16 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
int ret;
unsigned int reg = mc->reg;
- /* For HS and HF we shadow the values and only actually write
+ /* For HS and EP we shadow the values and only actually write
* them out when active in order to ensure the amplifier comes on
* as quietly as possible. */
switch (reg) {
case TWL6040_REG_HSGAIN:
out = &twl6040_priv->headset;
break;
+ case TWL6040_REG_EARCTL:
+ out = &twl6040_priv->earphone;
+ break;
default:
break;
}
@@ -848,7 +942,10 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = out->left_vol;
ucontrol->value.integer.value[1] = out->right_vol;
return 0;
-
+ case TWL6040_REG_EARCTL:
+ out = &twl6040_priv->earphone;
+ ucontrol->value.integer.value[0] = out->left_vol;
+ return 0;
default:
break;
}
@@ -919,33 +1016,6 @@ static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
return snd_soc_get_volsw_2r(kcontrol, ucontrol);
}
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
- xinvert, tlv_array)\
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
- .put = twl6040_put_volsw, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
- .max = xmax, .platform_max = xmax, .invert = xinvert} }
-
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
- xinvert, tlv_array)\
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
/*
* MICATT volume control:
* from -6 to 0 dB in 6 dB steps
@@ -954,9 +1024,9 @@ static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
/*
* MICGAIN volume control:
- * from -6 to 30 dB in 6 dB steps
+ * from 6 to 30 dB in 6 dB steps
*/
-static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0);
+static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
/*
* AFMGAIN volume control:
@@ -1040,6 +1110,44 @@ static const struct snd_kcontrol_new hfr_mux_controls =
static const struct snd_kcontrol_new ep_driver_switch_controls =
SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
+/* Headset power mode */
+static const char *twl6040_headset_power_texts[] = {
+ "Low-Power", "High-Performance",
+};
+
+static const struct soc_enum twl6040_headset_power_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_headset_power_texts),
+ twl6040_headset_power_texts);
+
+static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.enumerated.item[0] = priv->headset_mode;
+
+ return 0;
+}
+
+static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+ int high_perf = ucontrol->value.enumerated.item[0];
+ int ret;
+
+ if (priv->power_mode_forced)
+ return -EPERM;
+
+ ret = headset_power_mode(codec, high_perf);
+ if (!ret)
+ priv->headset_mode = high_perf;
+
+ return ret;
+}
+
static const struct snd_kcontrol_new twl6040_snd_controls[] = {
/* Capture gains */
SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1052,12 +1160,19 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
/* Playback gains */
- SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
- TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
- SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
- TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
- SOC_SINGLE_TLV("Earphone Playback Volume",
- TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
+ SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+ TWL6040_REG_HSGAIN, 0, 4, 0xF, 1,
+ twl6040_get_volsw, twl6040_put_volsw, hs_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
+ TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
+ twl6040_get_volsw_2r, twl6040_put_volsw_2r_vu, hf_tlv),
+ SOC_SINGLE_EXT_TLV("Earphone Playback Volume",
+ TWL6040_REG_EARCTL, 1, 0xF, 1,
+ twl6040_get_volsw, twl6040_put_volsw, ep_tlv),
+
+ SOC_ENUM_EXT("Headset Power Mode", twl6040_headset_power_enum,
+ twl6040_headset_power_get_enum,
+ twl6040_headset_power_put_enum),
};
static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
@@ -1112,19 +1227,19 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
/* DACs */
SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
TWL6040_REG_HSLCTL, 0, 0,
- twl6040_hs_dac_event,
+ twl6040_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
TWL6040_REG_HSRCTL, 0, 0,
- twl6040_hs_dac_event,
+ twl6040_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
TWL6040_REG_HFLCTL, 0, 0,
- twl6040_power_mode_event,
+ twl6040_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
TWL6040_REG_HFRCTL, 0, 0,
- twl6040_power_mode_event,
+ twl6040_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("HF Left Playback",
@@ -1154,10 +1269,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
pga_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_SWITCH_E("Earphone Driver",
+ SND_SOC_DAPM_SWITCH_E("Earphone Enable",
SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
- twl6040_power_mode_event,
+ twl6040_ep_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
+ SND_SOC_NOPM, 0, 0, NULL, 0,
+ pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
/* Analog playback PGAs */
SND_SOC_DAPM_PGA("HFDAC Left PGA",
@@ -1200,7 +1319,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HSOR", NULL, "Headset Right Driver"},
/* Earphone playback path */
- {"Earphone Driver", "Switch", "HSDAC Left"},
+ {"Earphone Enable", "Switch", "HSDAC Left"},
+ {"Earphone Driver", NULL, "Earphone Enable"},
{"EP", NULL, "Earphone Driver"},
{"HF Left Playback", "HF DAC", "HFDAC Left"},
@@ -1231,37 +1351,43 @@ static int twl6040_add_widgets(struct snd_soc_codec *codec)
return 0;
}
-static int twl6040_power_up_completion(struct snd_soc_codec *codec,
- int naudint)
-{
- struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- int time_left;
- u8 intid;
+/* set of rates for each pll: low-power and high-performance */
- time_left = wait_for_completion_timeout(&priv->ready,
- msecs_to_jiffies(144));
+static unsigned int lp_rates[] = {
+ 8000,
+ 11250,
+ 16000,
+ 22500,
+ 32000,
+ 44100,
+ 48000,
+ 88200,
+ 96000,
+};
- if (!time_left) {
- twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
- TWL6040_REG_INTID);
- if (!(intid & TWL6040_READYINT)) {
- dev_err(codec->dev, "timeout waiting for READYINT\n");
- return -ETIMEDOUT;
- }
- }
+static struct snd_pcm_hw_constraint_list lp_constraints = {
+ .count = ARRAY_SIZE(lp_rates),
+ .list = lp_rates,
+};
- priv->codec_powered = 1;
+static unsigned int hp_rates[] = {
+ 8000,
+ 16000,
+ 32000,
+ 48000,
+ 96000,
+};
- return 0;
-}
+static struct snd_pcm_hw_constraint_list hp_constraints = {
+ .count = ARRAY_SIZE(hp_rates),
+ .list = hp_rates,
+};
static int twl6040_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct twl6040 *twl6040 = codec->control_data;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- int audpwron = priv->audpwron;
- int naudint = priv->naudint;
- int ret;
switch (level) {
case SND_SOC_BIAS_ON:
@@ -1272,88 +1398,32 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
if (priv->codec_powered)
break;
- if (gpio_is_valid(audpwron)) {
- /* use AUDPWRON line */
- gpio_set_value(audpwron, 1);
-
- /* wait for power-up completion */
- ret = twl6040_power_up_completion(codec, naudint);
- if (ret)
- return ret;
+ twl6040_enable(twl6040);
+ priv->codec_powered = 1;
- /* sync registers updated during power-up sequence */
- twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
- twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
- twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
- } else {
- /* use manual power-up sequence */
- twl6040_power_up(codec);
- priv->codec_powered = 1;
- }
+ priv->sysclk_constraints = &lp_constraints;
/* initialize vdd/vss registers with reg_cache */
twl6040_init_vdd_regs(codec);
- /* Set external boost GPO */
- twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
-
- /* Set initial minimal gain values */
- twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
- twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E);
- twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
- twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
break;
case SND_SOC_BIAS_OFF:
if (!priv->codec_powered)
break;
- if (gpio_is_valid(audpwron)) {
- /* use AUDPWRON line */
- gpio_set_value(audpwron, 0);
-
- /* power-down sequence latency */
- udelay(500);
-
- /* sync registers updated during power-down sequence */
- twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
- twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
- twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
- 0x00);
- } else {
- /* use manual power-down sequence */
- twl6040_power_down(codec);
- }
-
+ twl6040_disable(twl6040);
priv->codec_powered = 0;
break;
}
codec->dapm.bias_level = level;
+ /* get pll and sysclk after power transition */
+ priv->pll = twl6040_get_pll(twl6040);
+ priv->sysclk = twl6040_get_sysclk(twl6040);
return 0;
}
-/* set of rates for each pll: low-power and high-performance */
-
-static unsigned int lp_rates[] = {
- 88200,
- 96000,
-};
-
-static struct snd_pcm_hw_constraint_list lp_constraints = {
- .count = ARRAY_SIZE(lp_rates),
- .list = lp_rates,
-};
-
-static unsigned int hp_rates[] = {
- 96000,
-};
-
-static struct snd_pcm_hw_constraint_list hp_constraints = {
- .count = ARRAY_SIZE(hp_rates),
- .list = hp_rates,
-};
-
static int twl6040_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -1374,15 +1444,11 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
+ struct twl6040 *twl6040 = codec->control_data;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- u8 lppllctl;
+ unsigned int sysclk;
int rate;
-
- /* nothing to do for high-perf pll, it supports only 48 kHz */
- if (priv->pll == TWL6040_HPPLL_ID)
- return 0;
-
- lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
+ int ret;
rate = params_rate(params);
switch (rate) {
@@ -1390,23 +1456,27 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
case 22500:
case 44100:
case 88200:
- lppllctl |= TWL6040_LPLLFIN;
- priv->sysclk = 17640000;
+ sysclk = 17640000;
break;
case 8000:
case 16000:
case 32000:
case 48000:
case 96000:
- lppllctl &= ~TWL6040_LPLLFIN;
- priv->sysclk = 19200000;
+ sysclk = 19200000;
break;
default:
dev_err(codec->dev, "unsupported rate %d\n", rate);
return -EINVAL;
}
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
+ ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, sysclk);
+ if (ret) {
+ dev_err(codec->dev, "failed to configure PLL %d", ret);
+ return ret;
+ }
+
+ priv->sysclk = sysclk;
return 0;
}
@@ -1425,23 +1495,19 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
}
/*
- * capture is not supported at 17.64 MHz,
- * it's reserved for headset low-power playback scenario
+ * In the capture, the Analog path should be turn on and stabilized
+ * before McPDM prepare itself to avoid pop noises.
+ * So the codec startup event is sending through dapm in prepare itself
+ * to ensure that the codec analog path is up before McPDM Uplink FIFO
+ * is going to be activated.
*/
- if ((priv->sysclk == 17640000) &&
- substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- dev_err(codec->dev,
- "capture mode is not supported at %dHz\n",
- priv->sysclk);
- return -EINVAL;
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ snd_soc_dapm_codec_stream_event(dai->codec,
+ dai->driver->capture.stream_name,
+ SND_SOC_DAPM_STREAM_START);
+ msleep(150);
}
- if ((priv->sysclk == 17640000) && priv->non_lp) {
- dev_err(codec->dev,
- "some enabled paths aren't supported at %dHz\n",
- priv->sysclk);
- return -EPERM;
- }
return 0;
}
@@ -1450,98 +1516,12 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- u8 hppllctl, lppllctl;
-
- hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
- lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
switch (clk_id) {
- case TWL6040_SYSCLK_SEL_LPPLL:
- switch (freq) {
- case 32768:
- /* headset dac and driver must be in low-power mode */
- headset_power_mode(codec, 0);
-
- /* clk32k input requires low-power pll */
- lppllctl |= TWL6040_LPLLENA;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
- mdelay(5);
- lppllctl &= ~TWL6040_HPLLSEL;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
- hppllctl &= ~TWL6040_HPLLENA;
- twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
- break;
- default:
- dev_err(codec->dev, "unknown mclk freq %d\n", freq);
- return -EINVAL;
- }
-
- /* lppll divider */
- switch (priv->sysclk) {
- case 17640000:
- lppllctl |= TWL6040_LPLLFIN;
- break;
- case 19200000:
- lppllctl &= ~TWL6040_LPLLFIN;
- break;
- default:
- /* sysclk not yet configured */
- lppllctl &= ~TWL6040_LPLLFIN;
- priv->sysclk = 19200000;
- break;
- }
-
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
- priv->pll = TWL6040_LPPLL_ID;
+ case TWL6040_LPPLL_ID:
priv->sysclk_constraints = &lp_constraints;
break;
- case TWL6040_SYSCLK_SEL_HPPLL:
- hppllctl &= ~TWL6040_MCLK_MSK;
-
- switch (freq) {
- case 12000000:
- /* mclk input, pll enabled */
- hppllctl |= TWL6040_MCLK_12000KHZ |
- TWL6040_HPLLSQRBP |
- TWL6040_HPLLENA;
- break;
- case 19200000:
- /* mclk input, pll disabled */
- hppllctl |= TWL6040_MCLK_19200KHZ |
- TWL6040_HPLLSQRENA |
- TWL6040_HPLLBP;
- break;
- case 26000000:
- /* mclk input, pll enabled */
- hppllctl |= TWL6040_MCLK_26000KHZ |
- TWL6040_HPLLSQRBP |
- TWL6040_HPLLENA;
- break;
- case 38400000:
- /* clk slicer, pll disabled */
- hppllctl |= TWL6040_MCLK_38400KHZ |
- TWL6040_HPLLSQRENA |
- TWL6040_HPLLBP;
- break;
- default:
- dev_err(codec->dev, "unknown mclk freq %d\n", freq);
- return -EINVAL;
- }
-
- /* headset dac and driver must be in high-performance mode */
- headset_power_mode(codec, 1);
-
- twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
- udelay(500);
- lppllctl |= TWL6040_HPLLSEL;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
- /* high-performance pll can provide only 19.2 MHz */
- priv->pll = TWL6040_HPPLL_ID;
- priv->sysclk = 19200000;
+ case TWL6040_HPPLL_ID:
priv->sysclk_constraints = &hp_constraints;
break;
default:
@@ -1549,6 +1529,23 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
+ priv->pll = clk_id;
+ priv->clk_in = freq;
+
+ return 0;
+}
+
+static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ /*
+ * pop-noise reduction sequence requires to shutdown
+ * analog side before CPU DAI
+ */
+ if (mute)
+ snd_soc_dapm_codec_stream_event(dai->codec,
+ dai->driver->playback.stream_name,
+ SND_SOC_DAPM_STREAM_STOP);
+
return 0;
}
@@ -1557,25 +1554,54 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
.hw_params = twl6040_hw_params,
.prepare = twl6040_prepare,
.set_sysclk = twl6040_set_dai_sysclk,
+ .digital_mute = twl6040_digital_mute,
};
-static struct snd_soc_dai_driver twl6040_dai = {
- .name = "twl6040-hifi",
+static struct snd_soc_dai_driver twl6040_dai[] = {
+{
+ .name = "twl6040-ul",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TWL6040_RATES,
+ .formats = TWL6040_FORMATS,
+ },
+ .ops = &twl6040_dai_ops,
+},
+{
+ .name = "twl6040-dl1",
.playback = {
- .stream_name = "Playback",
+ .stream_name = "Headset Playback",
.channels_min = 1,
- .channels_max = 4,
+ .channels_max = 2,
.rates = TWL6040_RATES,
.formats = TWL6040_FORMATS,
},
- .capture = {
- .stream_name = "Capture",
+ .ops = &twl6040_dai_ops,
+},
+{
+ .name = "twl6040-dl2",
+ .playback = {
+ .stream_name = "Handsfree Playback",
.channels_min = 1,
.channels_max = 2,
.rates = TWL6040_RATES,
.formats = TWL6040_FORMATS,
},
.ops = &twl6040_dai_ops,
+},
+{
+ .name = "twl6040-vib",
+ .playback = {
+ .stream_name = "Vibra Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = TWL6040_FORMATS,
+ },
+ .ops = &twl6040_dai_ops,
+},
};
#ifdef CONFIG_PM
@@ -1588,8 +1614,10 @@ static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int twl6040_resume(struct snd_soc_codec *codec)
{
- twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level);
+ if (codec->dapm.bias_level != codec->dapm.suspend_bias_level) {
+ twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level);
+ }
return 0;
}
@@ -1600,11 +1628,9 @@ static int twl6040_resume(struct snd_soc_codec *codec)
static int twl6040_probe(struct snd_soc_codec *codec)
{
- struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
struct twl6040_data *priv;
- int audpwron, naudint;
+ struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
int ret = 0;
- u8 icrev, intmr = TWL6040_ALLINT_MSK;
priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
if (priv == NULL)
@@ -1612,21 +1638,33 @@ static int twl6040_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_drvdata(codec, priv);
priv->codec = codec;
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ codec->dapm.idle_bias_off = 1;
- twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
+ if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
+ priv->hs_left_step = pdata->hs_left_step;
+ priv->hs_right_step = pdata->hs_right_step;
+ } else {
+ priv->hs_left_step = 1;
+ priv->hs_right_step = 1;
+ }
- if (twl_codec && (icrev > 0))
- audpwron = twl_codec->audpwron_gpio;
- else
- audpwron = -EINVAL;
+ if (pdata && pdata->hf_left_step && pdata->hf_right_step) {
+ priv->hf_left_step = pdata->hf_left_step;
+ priv->hf_right_step = pdata->hf_right_step;
+ } else {
+ priv->hf_left_step = 1;
+ priv->hf_right_step = 1;
+ }
- if (twl_codec)
- naudint = twl_codec->naudint_irq;
+ if (pdata && pdata->ep_step)
+ priv->ep_step = pdata->ep_step;
else
- naudint = 0;
+ priv->ep_step = 1;
- priv->audpwron = audpwron;
- priv->naudint = naudint;
+ /* default is low-power mode */
+ priv->headset_mode = 1;
+ priv->sysclk_constraints = &lp_constraints;
priv->workqueue = create_singlethread_workqueue("twl6040-codec");
if (!priv->workqueue) {
@@ -1638,55 +1676,40 @@ static int twl6040_probe(struct snd_soc_codec *codec)
mutex_init(&priv->mutex);
- init_completion(&priv->ready);
init_completion(&priv->headset.ramp_done);
init_completion(&priv->handsfree.ramp_done);
-
- if (gpio_is_valid(audpwron)) {
- ret = gpio_request(audpwron, "audpwron");
- if (ret)
- goto gpio1_err;
-
- ret = gpio_direction_output(audpwron, 0);
- if (ret)
- goto gpio2_err;
-
- priv->codec_powered = 0;
-
- /* enable only codec ready interrupt */
- intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
-
- /* reset interrupt status to allow correct power up sequence */
- twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
- }
- twl6040_write(codec, TWL6040_REG_INTMR, intmr);
-
- if (naudint) {
- /* audio interrupt */
- ret = request_threaded_irq(naudint, NULL,
- twl6040_naudint_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "twl6040_codec", codec);
- if (ret)
- goto gpio2_err;
- }
-
- /* init vio registers */
- twl6040_init_vio_regs(codec);
+ init_completion(&priv->earphone.ramp_done);
priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
if (priv->hf_workqueue == NULL) {
ret = -ENOMEM;
- goto irq_err;
+ goto hfwork_err;
}
priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
if (priv->hs_workqueue == NULL) {
ret = -ENOMEM;
- goto wq_err;
+ goto hswork_err;
+ }
+ priv->ep_workqueue = create_singlethread_workqueue("twl6040-ep");
+ if (priv->ep_workqueue == NULL) {
+ ret = -ENOMEM;
+ goto epwork_err;
}
INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
+ INIT_DELAYED_WORK(&priv->ep_delayed_work, twl6040_pga_ep_work);
+
+ ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG,
+ twl6040_audio_handler, "twl6040_irq_plug",
+ codec);
+ if (ret) {
+ dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
+ goto irq_err;
+ }
+
+ /* init vio registers */
+ twl6040_init_vio_regs(codec);
/* power on device */
ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1700,16 +1723,14 @@ static int twl6040_probe(struct snd_soc_codec *codec)
return 0;
bias_err:
+ twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
+irq_err:
+ destroy_workqueue(priv->ep_workqueue);
+epwork_err:
destroy_workqueue(priv->hs_workqueue);
-wq_err:
+hswork_err:
destroy_workqueue(priv->hf_workqueue);
-irq_err:
- if (naudint)
- free_irq(naudint, codec);
-gpio2_err:
- if (gpio_is_valid(audpwron))
- gpio_free(audpwron);
-gpio1_err:
+hfwork_err:
destroy_workqueue(priv->workqueue);
work_err:
kfree(priv);
@@ -1719,20 +1740,13 @@ work_err:
static int twl6040_remove(struct snd_soc_codec *codec)
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- int audpwron = priv->audpwron;
- int naudint = priv->naudint;
twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- if (gpio_is_valid(audpwron))
- gpio_free(audpwron);
-
- if (naudint)
- free_irq(naudint, codec);
-
+ twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
destroy_workqueue(priv->workqueue);
destroy_workqueue(priv->hf_workqueue);
destroy_workqueue(priv->hs_workqueue);
+ destroy_workqueue(priv->ep_workqueue);
kfree(priv);
return 0;
@@ -1754,7 +1768,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
static int __devinit twl6040_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
- &soc_codec_dev_twl6040, &twl6040_dai, 1);
+ &soc_codec_dev_twl6040, twl6040_dai, ARRAY_SIZE(twl6040_dai));
}
static int __devexit twl6040_codec_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index 23aeed0..105a6fd 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -22,123 +22,7 @@
#ifndef __TWL6040_H__
#define __TWL6040_H__
-#define TWL6040_REG_ASICID 0x01
-#define TWL6040_REG_ASICREV 0x02
-#define TWL6040_REG_INTID 0x03
-#define TWL6040_REG_INTMR 0x04
-#define TWL6040_REG_NCPCTL 0x05
-#define TWL6040_REG_LDOCTL 0x06
-#define TWL6040_REG_HPPLLCTL 0x07
-#define TWL6040_REG_LPPLLCTL 0x08
-#define TWL6040_REG_LPPLLDIV 0x09
-#define TWL6040_REG_AMICBCTL 0x0A
-#define TWL6040_REG_DMICBCTL 0x0B
-#define TWL6040_REG_MICLCTL 0x0C
-#define TWL6040_REG_MICRCTL 0x0D
-#define TWL6040_REG_MICGAIN 0x0E
-#define TWL6040_REG_LINEGAIN 0x0F
-#define TWL6040_REG_HSLCTL 0x10
-#define TWL6040_REG_HSRCTL 0x11
-#define TWL6040_REG_HSGAIN 0x12
-#define TWL6040_REG_EARCTL 0x13
-#define TWL6040_REG_HFLCTL 0x14
-#define TWL6040_REG_HFLGAIN 0x15
-#define TWL6040_REG_HFRCTL 0x16
-#define TWL6040_REG_HFRGAIN 0x17
-#define TWL6040_REG_VIBCTLL 0x18
-#define TWL6040_REG_VIBDATL 0x19
-#define TWL6040_REG_VIBCTLR 0x1A
-#define TWL6040_REG_VIBDATR 0x1B
-#define TWL6040_REG_HKCTL1 0x1C
-#define TWL6040_REG_HKCTL2 0x1D
-#define TWL6040_REG_GPOCTL 0x1E
-#define TWL6040_REG_ALB 0x1F
-#define TWL6040_REG_DLB 0x20
-#define TWL6040_REG_TRIM1 0x28
-#define TWL6040_REG_TRIM2 0x29
-#define TWL6040_REG_TRIM3 0x2A
-#define TWL6040_REG_HSOTRIM 0x2B
-#define TWL6040_REG_HFOTRIM 0x2C
-#define TWL6040_REG_ACCCTL 0x2D
-#define TWL6040_REG_STATUS 0x2E
-
-#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
-
-#define TWL6040_VIOREGNUM 18
-#define TWL6040_VDDREGNUM 21
-
-/* INTID (0x03) fields */
-
-#define TWL6040_THINT 0x01
-#define TWL6040_PLUGINT 0x02
-#define TWL6040_UNPLUGINT 0x04
-#define TWL6040_HOOKINT 0x08
-#define TWL6040_HFINT 0x10
-#define TWL6040_VIBINT 0x20
-#define TWL6040_READYINT 0x40
-
-/* INTMR (0x04) fields */
-
-#define TWL6040_PLUGMSK 0x02
-#define TWL6040_READYMSK 0x40
-#define TWL6040_ALLINT_MSK 0x7B
-
-/* NCPCTL (0x05) fields */
-
-#define TWL6040_NCPENA 0x01
-#define TWL6040_NCPOPEN 0x40
-
-/* LDOCTL (0x06) fields */
-
-#define TWL6040_LSLDOENA 0x01
-#define TWL6040_HSLDOENA 0x04
-#define TWL6040_REFENA 0x40
-#define TWL6040_OSCENA 0x80
-
-/* HPPLLCTL (0x07) fields */
-
-#define TWL6040_HPLLENA 0x01
-#define TWL6040_HPLLRST 0x02
-#define TWL6040_HPLLBP 0x04
-#define TWL6040_HPLLSQRENA 0x08
-#define TWL6040_HPLLSQRBP 0x10
-#define TWL6040_MCLK_12000KHZ (0 << 5)
-#define TWL6040_MCLK_19200KHZ (1 << 5)
-#define TWL6040_MCLK_26000KHZ (2 << 5)
-#define TWL6040_MCLK_38400KHZ (3 << 5)
-#define TWL6040_MCLK_MSK 0x60
-
-/* LPPLLCTL (0x08) fields */
-
-#define TWL6040_LPLLENA 0x01
-#define TWL6040_LPLLRST 0x02
-#define TWL6040_LPLLSEL 0x04
-#define TWL6040_LPLLFIN 0x08
-#define TWL6040_HPLLSEL 0x10
-
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL 0x02
-#define TWL6040_HSDRVMODEL 0x08
-
-/* HSRCTL (0x11) fields */
-
-#define TWL6040_HSDACMODER 0x02
-#define TWL6040_HSDRVMODER 0x08
-
-/* ACCCTL (0x2D) fields */
-
-#define TWL6040_RESETSPLIT 0x04
-
-#define TWL6040_SYSCLK_SEL_LPPLL 1
-#define TWL6040_SYSCLK_SEL_HPPLL 2
-
-#define TWL6040_HPPLL_ID 1
-#define TWL6040_LPPLL_ID 2
-
-/* STATUS (0x2E) fields */
-
-#define TWL6040_PLUGCOMP 0x02
+#include <linux/mfd/twl6040-codec.h>
void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report);
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 9d35b8c..29759e1 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -811,9 +811,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
static u64 davinci_pcm_dmamask = 0xffffffff;
-static int davinci_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret;
if (!card->dev->dma_mask)
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index a456e49..e27c417 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -266,9 +266,11 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 ep93xx_pcm_dmamask = 0xffffffff;
-static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 6680c0b..5312d1b 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -294,9 +294,11 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
* Regardless of where the memory is actually allocated, since the device can
* technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
*/
-static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
int ret;
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index cbaf8b7..61d2ecc 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -299,10 +299,11 @@ static struct snd_pcm_ops psc_dma_ops = {
};
static u64 psc_dma_dmamask = 0xffffffff;
-static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
size_t size = psc_dma_hardware.buffer_bytes_max;
int rc = 0;
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 413b78d..309c59e 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -238,12 +238,14 @@ static struct snd_pcm_ops imx_pcm_ops = {
static int ssi_irq = 0;
-static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret;
- ret = imx_pcm_new(card, dai, pcm);
+ ret = imx_pcm_new(rtd);
if (ret)
return ret;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 3b56254..3a676cd 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -388,10 +388,11 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
-
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index dc8a875..0a84cec 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -225,8 +225,7 @@ struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
struct imx_ssi *ssi);
int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm);
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
void imx_pcm_free(struct snd_pcm *pcm);
/*
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index fb1483f..a7c9578 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -299,9 +299,11 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
-int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index e13c6ce..cd33de1 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -312,9 +312,11 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
return 0;
}
-static int kirkwood_dma_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret;
if (!card->dev->dma_mask)
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index 8263f56..d589ef1 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -315,9 +315,12 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm)
}
static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
-static int nuc900_dma_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
+
if (!card->dev->dma_mask)
card->dev->dma_mask = &nuc900_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 99054cf..ffcfeee 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -2,6 +2,14 @@ config SND_OMAP_SOC
tristate "SoC Audio for the Texas Instruments OMAP chips"
depends on ARCH_OMAP
+config SND_OMAP_SOC_ABE_DSP
+ tristate
+ select SND_DYNAMIC_MINORS
+
+config SND_OMAP_SOC_MCASP
+ tristate
+ select SND_SOC_SPDIF
+
config SND_OMAP_SOC_MCBSP
tristate
select OMAP_MCBSP
@@ -9,6 +17,12 @@ config SND_OMAP_SOC_MCBSP
config SND_OMAP_SOC_MCPDM
tristate
+config SND_OMAP_SOC_ABE
+ tristate
+
+config SND_OMAP_SOC_HDMI
+ tristate
+
config SND_OMAP_SOC_N810
tristate "SoC Audio support for Nokia N810"
depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
@@ -92,13 +106,27 @@ config SND_OMAP_SOC_SDP3430
SDP3430.
config SND_OMAP_SOC_SDP4430
- tristate "SoC Audio support for Texas Instruments SDP4430"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+ tristate "SoC Audio support for Texas Instruments SDP4430 or PandaBoard"
+ depends on TWL4030_CORE && (MACH_OMAP_4430SDP || MACH_OMAP4_PANDA)
select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040
+ select SND_OMAP_SOC_ABE
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_DMIC
+ select SND_OMAP_SOC_DMIC
+ select SND_OMAP_SOC_ABE_DSP
help
Say Y if you want to add support for SoC audio on Texas Instruments
- SDP4430.
+ SDP4430 or PandaBoard.
+
+config SND_OMAP_SOC_OMAP4_HDMI
+ tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
+ depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
+ select SND_OMAP_SOC_HDMI
+ select SND_SOC_OMAP_HDMI_CODEC
+ help
+ Say Y if you want to add support for SoC HDMI audio on Texas Instruments
+ OMAP4 chips
config SND_OMAP_SOC_OMAP3_PANDORA
tristate "SoC Audio support for OMAP3 Pandora"
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 6c2c87e..f1deddc 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,11 +1,19 @@
# OMAP Platform Support
snd-soc-omap-objs := omap-pcm.o
+snd-soc-omap-mcasp-objs := omap-mcasp.o
snd-soc-omap-mcbsp-objs := omap-mcbsp.o
-snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
+snd-soc-omap-abe-objs := omap-abe.o
+snd-soc-omap-abe-dsp-objs := omap-abe-dsp.o
+snd-soc-omap-hdmi-objs := omap-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
+obj-$(CONFIG_SND_OMAP_SOC_MCASP) += snd-soc-omap-mcasp.o
obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
+obj-$(CONFIG_SND_OMAP_SOC_ABE) += snd-soc-omap-abe.o
+obj-$(CONFIG_SND_OMAP_SOC_ABE_DSP) += snd-soc-omap-abe-dsp.o abe/
+obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
@@ -21,6 +29,7 @@ snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
snd-soc-zoom2-objs := zoom2.o
snd-soc-igep0020-objs := igep0020.o
+snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
@@ -36,3 +45,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
diff --git a/sound/soc/omap/abe/Makefile b/sound/soc/omap/abe/Makefile
new file mode 100644
index 0000000..0d5649b
--- /dev/null
+++ b/sound/soc/omap/abe/Makefile
@@ -0,0 +1,14 @@
+snd-soc-abe-hal-objs += abe_main.o \
+ abe_core.o \
+ abe_gain.o \
+ abe_port.o \
+ abe_aess.o \
+ abe_dbg.o \
+ abe_dat.o \
+ abe_ini.o \
+ abe_irq.o \
+ abe_seq.o \
+ abe_asrc.o \
+ port_mgr.o \
+
+obj-$(CONFIG_SND_OMAP_SOC_ABE_DSP) += snd-soc-abe-hal.o
diff --git a/sound/soc/omap/abe/abe.h b/sound/soc/omap/abe/abe.h
new file mode 100644
index 0000000..103a57c
--- /dev/null
+++ b/sound/soc/omap/abe/abe.h
@@ -0,0 +1,141 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_H_
+#define _ABE_H_
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include "abe_def.h"
+#include "abe_define.h"
+#include "abe_fw.h"
+#include "abe_ext.h"
+#include "abe_dbg.h"
+
+/*
+ * BASIC TYPES
+ */
+#define MAX_UINT8 ((((1L << 7) - 1) << 1) + 1)
+#define MAX_UINT16 ((((1L << 15) - 1) << 1) + 1)
+#define MAX_UINT32 ((((1L << 31) - 1) << 1) + 1)
+
+#define s8 char
+#define u8 unsigned char
+#define s16 short
+#define u16 unsigned short
+#define s32 int
+#define u32 unsigned int
+
+struct omap_abe_equ {
+ /* type of filter */
+ u32 equ_type;
+ /* filter length */
+ u32 equ_length;
+ union {
+ /* parameters are the direct and recursive coefficients in */
+ /* Q6.26 integer fixed-point format. */
+ s32 type1[NBEQ1];
+ struct {
+ /* center frequency of the band [Hz] */
+ s32 freq[NBEQ2];
+ /* gain of each band. [dB] */
+ s32 gain[NBEQ2];
+ /* Q factor of this band [dB] */
+ s32 q[NBEQ2];
+ } type2;
+ } coef;
+ s32 equ_param3;
+};
+
+extern struct omap_abe *abe;
+
+void omap_abe_dbg_log(struct omap_abe *abe, u32 x, u32 y, u32 z, u32 t);
+void omap_abe_dbg_error(struct omap_abe *abe, int level, int error);
+int omap_abe_set_opp_processing(struct omap_abe *abe, u32 opp);
+int omap_abe_connect_debug_trace(struct omap_abe *abe,
+ struct omap_abe_dma *dma2);
+
+int omap_abe_use_compensated_gain(struct omap_abe *abe, int on_off);
+int omap_abe_write_equalizer(struct omap_abe *abe,
+ u32 id, struct omap_abe_equ *param);
+
+int omap_abe_disable_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_enable_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_mute_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_unmute_gain(struct omap_abe *abe, u32 id, u32 p);
+
+int omap_abe_write_gain(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 ramp, u32 p);
+int omap_abe_write_mixer(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 f_ramp, u32 p);
+int omap_abe_read_gain(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p);
+int omap_abe_read_mixer(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p);
+
+/*
+ * MACROS
+ */
+#define _log(x, y, z, t) { if (x & abe->dbg.mask) omap_abe_dbg_log(abe, x, y, z, t); }
+
+#endif/* _ABE_H_ */
diff --git a/sound/soc/omap/abe/abe_aess.c b/sound/soc/omap/abe/abe_aess.c
new file mode 100644
index 0000000..eb35b58
--- /dev/null
+++ b/sound/soc/omap/abe/abe_aess.c
@@ -0,0 +1,191 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dbg.h"
+#include "abe.h"
+#include "abe_mem.h"
+#include "abe_aess.h"
+
+/**
+ * omap_abe_hw_configuration
+ *
+ */
+void omap_abe_hw_configuration(struct omap_abe *abe)
+{
+ /* enables the DMAreq from AESS AESS_DMAENABLE_SET = 255 */
+ omap_abe_reg_writel(abe, AESS_DMAENABLE_SET, DMA_ENABLE_ALL);
+ /* enables the MCU IRQ from AESS to Cortex A9 */
+ omap_abe_reg_writel(abe, AESS_MCU_IRQENABLE_SET, INT_SET);
+}
+
+/**
+ * omap_abe_clear_irq - clear ABE interrupt
+ * @abe: Pointer on abe handle
+ *
+ * This subroutine is call to clear MCU Irq
+ */
+int omap_abe_clear_irq(struct omap_abe *abe)
+{
+ omap_abe_reg_writel(abe, ABE_MCU_IRQSTATUS, INT_CLR);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_clear_irq);
+
+/**
+ * abe_write_event_generator - Selects event generator source
+ * @abe: Pointer on abe handle
+ * @e: Event Generation Counter, McPDM, DMIC or default.
+ *
+ * Loads the AESS event generator hardware source.
+ * Loads the firmware parameters accordingly.
+ * Indicates to the FW which data stream is the most important to preserve
+ * in case all the streams are asynchronous.
+ * If the parameter is "default", then HAL decides which Event source
+ * is the best appropriate based on the opened ports.
+ *
+ * When neither the DMIC and the McPDM are activated, the AE will have
+ * its EVENT generator programmed with the EVENT_COUNTER.
+ * The event counter will be tuned in order to deliver a pulse frequency higher
+ * than 96 kHz.
+ * The DPLL output at 100% OPP is MCLK = (32768kHz x6000) = 196.608kHz
+ * The ratio is (MCLK/96000)+(1<<1) = 2050
+ * (1<<1) in order to have the same speed at 50% and 100% OPP
+ * (only 15 MSB bits are used at OPP50%)
+ */
+int omap_abe_write_event_generator(struct omap_abe *abe, u32 e)
+{
+ u32 event, selection;
+ u32 counter = EVENT_GENERATOR_COUNTER_DEFAULT;
+
+ _log(ABE_ID_WRITE_EVENT_GENERATOR, e, 0, 0);
+
+ switch (e) {
+ case EVENT_TIMER:
+ selection = EVENT_SOURCE_COUNTER;
+ event = 0;
+ break;
+ case EVENT_44100:
+ selection = EVENT_SOURCE_COUNTER;
+ event = 0;
+ counter = EVENT_GENERATOR_COUNTER_44100;
+ break;
+ default:
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API, ABE_BLOCK_COPY_ERR);
+ }
+ omap_abe_reg_writel(abe, EVENT_GENERATOR_COUNTER, counter);
+ omap_abe_reg_writel(abe, EVENT_SOURCE_SELECTION, selection);
+ omap_abe_reg_writel(abe, EVENT_GENERATOR_START, EVENT_GENERATOR_ON);
+ omap_abe_reg_writel(abe, AUDIO_ENGINE_SCHEDULER, event);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_write_event_generator);
+
+/**
+ * omap_abe_start_event_generator - Starts event generator source
+ * @abe: Pointer on abe handle
+ *
+ * Start the event genrator of AESS. No more event will be send to AESS engine.
+ * Upper layer must wait 1/96kHz to be sure that engine reaches
+ * the IDLE instruction.
+ */
+int omap_abe_start_event_generator(struct omap_abe *abe)
+{
+ /* Start the event Generator */
+ omap_abe_reg_writel(abe, EVENT_GENERATOR_START, 1);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_start_event_generator);
+
+/**
+ * omap_abe_stop_event_generator - Stops event generator source
+ * @abe: Pointer on abe handle
+ *
+ * Stop the event genrator of AESS. No more event will be send to AESS engine.
+ * Upper layer must wait 1/96kHz to be sure that engine reaches
+ * the IDLE instruction.
+ */
+int omap_abe_stop_event_generator(struct omap_abe *abe)
+{
+ /* Stop the event Generator */
+ omap_abe_reg_writel(abe, EVENT_GENERATOR_START, 0);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_stop_event_generator);
+
+/**
+ * omap_abe_disable_irq - disable MCU/DSP ABE interrupt
+ * @abe: Pointer on abe handle
+ *
+ * This subroutine is disabling ABE MCU/DSP Irq
+ */
+int omap_abe_disable_irq(struct omap_abe *abe)
+{
+ /* disables the DMAreq from AESS AESS_DMAENABLE_CLR = 127
+ * DMA_Req7 will still be enabled as it is used for ABE trace */
+ omap_abe_reg_writel(abe, AESS_DMAENABLE_CLR, 0x7F);
+ /* disables the MCU IRQ from AESS to Cortex A9 */
+ omap_abe_reg_writel(abe, AESS_MCU_IRQENABLE_CLR, 0x01);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_disable_irq);
diff --git a/sound/soc/omap/abe/abe_aess.h b/sound/soc/omap/abe/abe_aess.h
new file mode 100644
index 0000000..70c54f8e
--- /dev/null
+++ b/sound/soc/omap/abe/abe_aess.h
@@ -0,0 +1,113 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_AESS_H_
+#define _ABE_AESS_H_
+
+#define AESS_REVISION 0x00
+#define AESS_MCU_IRQSTATUS 0x28
+#define AESS_MCU_IRQENABLE_SET 0x3C
+#define AESS_MCU_IRQENABLE_CLR 0x40
+#define AESS_DMAENABLE_SET 0x60
+#define AESS_DMAENABLE_CLR 0x64
+#define EVENT_GENERATOR_COUNTER 0x68
+#define EVENT_GENERATOR_START 0x6C
+#define EVENT_SOURCE_SELECTION 0x70
+#define AUDIO_ENGINE_SCHEDULER 0x74
+
+/*
+ * AESS_MCU_IRQSTATUS bit field
+ */
+#define INT_CLEAR 0x01
+
+/*
+ * AESS_MCU_IRQENABLE_SET bit field
+ */
+#define INT_SET 0x01
+
+/*
+ * AESS_MCU_IRQENABLE_CLR bit field
+ */
+#define INT_CLR 0x01
+
+/*
+ * AESS_DMAENABLE_SET bit fields
+ */
+#define DMA_ENABLE_ALL 0xFF
+
+/*
+ * AESS_DMAENABLE_CLR bit fields
+ */
+#define DMA_DISABLE_ALL 0xFF
+
+/*
+ * EVENT_GENERATOR_COUNTER COUNTER_VALUE bit field
+ */
+/* PLL output/desired sampling rate = (32768 * 6000)/96000 */
+#define EVENT_GENERATOR_COUNTER_DEFAULT (2048-1)
+/* PLL output/desired sampling rate = (32768 * 6000)/88200 */
+#define EVENT_GENERATOR_COUNTER_44100 (2228-1)
+
+
+int omap_abe_start_event_generator(struct omap_abe *abe);
+int omap_abe_stop_event_generator(struct omap_abe *abe);
+int omap_abe_write_event_generator(struct omap_abe *abe, u32 e);
+
+void omap_abe_hw_configuration(struct omap_abe *abe);
+
+#endif/* _ABE_AESS_H_ */
diff --git a/sound/soc/omap/abe/abe_api.h b/sound/soc/omap/abe/abe_api.h
new file mode 100644
index 0000000..a24ec96
--- /dev/null
+++ b/sound/soc/omap/abe/abe_api.h
@@ -0,0 +1,511 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_API_H_
+#define _ABE_API_H_
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dm_addr.h"
+#include "abe_dbg.h"
+
+#define ABE_TASK_ID(ID) (OMAP_ABE_D_TASKSLIST_ADDR + sizeof(ABE_STask)*(ID))
+
+#define TASK_ASRC_VX_DL_SLT 0
+#define TASK_ASRC_VX_DL_IDX 3
+#define TASK_VX_DL_SLT 1
+#define TASK_VX_DL_IDX 3
+#define TASK_DL2Mixer_SLT 1
+#define TASK_DL2Mixer_IDX 6
+#define TASK_DL1Mixer_SLT 2
+#define TASK_DL1Mixer_IDX 0
+#define TASK_VX_UL_SLT 12
+#define TASK_VX_UL_IDX 5
+#define TASK_BT_DL_48_8_SLT 14
+#define TASK_BT_DL_48_8_IDX 4
+#define TASK_ASRC_BT_UL_SLT 15
+#define TASK_ASRC_BT_UL_IDX 6
+#define TASK_ASRC_VX_UL_SLT 16
+#define TASK_ASRC_VX_UL_IDX 2
+#define TASK_BT_UL_8_48_SLT 17
+#define TASK_BT_UL_8_48_IDX 2
+#define TASK_IO_MM_DL_SLT 18
+#define TASK_IO_MM_DL_IDX 0
+#define TASK_ASRC_BT_DL_SLT 18
+#define TASK_ASRC_BT_DL_IDX 6
+
+/**
+ * abe_reset_hal - reset the ABE/HAL
+ * @rdev: regulator source
+ * @constraints: constraints to apply
+ *
+ * Operations : reset the HAL by reloading the static variables and
+ * default AESS registers.
+ * Called after a PRCM cold-start reset of ABE
+ */
+abehal_status abe_reset_hal(void);
+/**
+ * abe_load_fw_param - Load ABE Firmware memories
+ * @PMEM: Pointer of Program memory data
+ * @PMEM_SIZE: Size of PMEM data
+ * @CMEM: Pointer of Coeffients memory data
+ * @CMEM_SIZE: Size of CMEM data
+ * @SMEM: Pointer of Sample memory data
+ * @SMEM_SIZE: Size of SMEM data
+ * @DMEM: Pointer of Data memory data
+ * @DMEM_SIZE: Size of DMEM data
+ *
+ */
+abehal_status abe_load_fw_param(u32 *FW);
+/**
+ * abe_irq_processing - Process ABE interrupt
+ *
+ * This subroutine is call upon reception of "MA_IRQ_99 ABE_MPU_IRQ" Audio
+ * back-end interrupt. This subroutine will check the ATC Hrdware, the
+ * IRQ_FIFO from the AE and act accordingly. Some IRQ source are originated
+ * for the delivery of "end of time sequenced tasks" notifications, some are
+ * originated from the Ping-Pong protocols, some are generated from
+ * the embedded debugger when the firmware stops on programmable break-points,
+ * etc ...
+ */
+abehal_status abe_irq_processing(void);
+/**
+ * abe_irq_clear - clear ABE interrupt
+ *
+ * This subroutine is call to clear MCU Irq
+ */
+abehal_status abe_clear_irq(void);
+/**
+ * abe_disable_irq - disable MCU/DSP ABE interrupt
+ *
+ * This subroutine is disabling ABE MCU/DSP Irq
+ */
+abehal_status abe_disable_irq(void);
+/*
+ * abe_check_activity - check all ports are closed
+ */
+u32 abe_check_activity(void);
+/**
+ * abe_wakeup - Wakeup ABE
+ *
+ * Wakeup ABE in case of retention
+ */
+abehal_status abe_wakeup(void);
+/**
+ * abe_start_event_generator - Stops event generator source
+ *
+ * Start the event genrator of AESS. No more event will be send to AESS engine.
+ * Upper layer must wait 1/96kHz to be sure that engine reaches
+ * the IDLE instruction.
+ */
+abehal_status abe_start_event_generator(void);
+/**
+ * abe_stop_event_generator - Stops event generator source
+ *
+ * Stop the event genrator of AESS. No more event will be send to AESS engine.
+ * Upper layer must wait 1/96kHz to be sure that engine reaches
+ * the IDLE instruction.
+ */
+abehal_status abe_stop_event_generator(void);
+
+/**
+ * abe_write_event_generator - Selects event generator source
+ * @e: Event Generation Counter, McPDM, DMIC or default.
+ *
+ * Loads the AESS event generator hardware source.
+ * Loads the firmware parameters accordingly.
+ * Indicates to the FW which data stream is the most important to preserve
+ * in case all the streams are asynchronous.
+ * If the parameter is "default", then HAL decides which Event source
+ * is the best appropriate based on the opened ports.
+ *
+ * When neither the DMIC and the McPDM are activated, the AE will have
+ * its EVENT generator programmed with the EVENT_COUNTER.
+ * The event counter will be tuned in order to deliver a pulse frequency higher
+ * than 96 kHz.
+ * The DPLL output at 100% OPP is MCLK = (32768kHz x6000) = 196.608kHz
+ * The ratio is (MCLK/96000)+(1<<1) = 2050
+ * (1<<1) in order to have the same speed at 50% and 100% OPP
+ * (only 15 MSB bits are used at OPP50%)
+ */
+abehal_status abe_write_event_generator(u32 e);
+/**
+ * abe_set_opp_processing - Set OPP mode for ABE Firmware
+ * @opp: OOPP mode
+ *
+ * New processing network and OPP:
+ * 0: Ultra Lowest power consumption audio player (no post-processing, no mixer)
+ * 1: OPP 25% (simple multimedia features, including low-power player)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (EANC, multimedia complex use-cases)
+ *
+ * Rearranges the FW task network to the corresponding OPP list of features.
+ * The corresponding AE ports are supposed to be set/reset accordingly before
+ * this switch.
+ *
+ */
+abehal_status abe_set_opp_processing(u32 opp);
+/**
+ * abe_set_ping_pong_buffer
+ * @port: ABE port ID
+ * @n_bytes: Size of Ping/Pong buffer
+ *
+ * Updates the next ping-pong buffer with "size" bytes copied from the
+ * host processor. This API notifies the FW that the data transfer is done.
+ */
+abehal_status abe_set_ping_pong_buffer(u32 port, u32 n_bytes);
+/**
+ * abe_read_next_ping_pong_buffer
+ * @port: ABE portID
+ * @p: Next buffer address (pointer)
+ * @n: Next buffer size (pointer)
+ *
+ * Tell the next base address of the next ping_pong Buffer and its size
+ */
+abehal_status abe_read_next_ping_pong_buffer(u32 port, u32 *p, u32 *n);
+/**
+ * abe_init_ping_pong_buffer
+ * @id: ABE port ID
+ * @size_bytes:size of the ping pong
+ * @n_buffers:number of buffers (2 = ping/pong)
+ * @p:returned address of the ping-pong list of base address (byte offset
+ from DMEM start)
+ *
+ * Computes the base address of the ping_pong buffers
+ */
+abehal_status abe_init_ping_pong_buffer(u32 id, u32 size_bytes, u32 n_buffers,
+ u32 *p);
+/**
+ * abe_read_offset_from_ping_buffer
+ * @id: ABE port ID
+ * @n: returned address of the offset
+ * from the ping buffer start address (in samples)
+ *
+ * Computes the current firmware ping pong read pointer location,
+ * expressed in samples, as the offset from the start address of ping buffer.
+ */
+abehal_status abe_read_offset_from_ping_buffer(u32 id, u32 *n);
+/**
+ * abe_plug_subroutine
+ * @id: returned sequence index after plugging a new subroutine
+ * @f: subroutine address to be inserted
+ * @n: number of parameters of this subroutine
+ * @params: pointer on parameters
+ *
+ * register a list of subroutines for call-back purpose
+ */
+abehal_status abe_plug_subroutine(u32 *id, abe_subroutine2 f, u32 n,
+ u32 *params);
+/**
+ * abe_set_sequence_time_accuracy
+ * @fast: fast counter
+ * @slow: slow counter
+ *
+ */
+abehal_status abe_set_sequence_time_accuracy(u32 fast, u32 slow);
+/**
+ * abe_reset_port
+ * @id: ABE port ID
+ *
+ * stop the port activity and reload default parameters on the associated
+ * processing features.
+ * Clears the internal AE buffers.
+ */
+abehal_status abe_reset_port(u32 id);
+/**
+ * abe_read_remaining_data
+ * @id: ABE port_ID
+ * @n: size pointer to the remaining number of 32bits words
+ *
+ * computes the remaining amount of data in the buffer.
+ */
+abehal_status abe_read_remaining_data(u32 port, u32 *n);
+/**
+ * abe_disable_data_transfer
+ * @id: ABE port id
+ *
+ * disables the ATC descriptor and stop IO/port activities
+ * disable the IO task (@f = 0)
+ * clear ATC DMEM buffer, ATC enabled
+ */
+abehal_status abe_disable_data_transfer(u32 id);
+/**
+ * abe_enable_data_transfer
+ * @ip: ABE port id
+ *
+ * enables the ATC descriptor
+ * reset ATC pointers
+ * enable the IO task (@f <> 0)
+ */
+abehal_status abe_enable_data_transfer(u32 id);
+/**
+ * abe_set_dmic_filter
+ * @d: DMIC decimation ratio : 16/25/32/40
+ *
+ * Loads in CMEM a specific list of coefficients depending on the DMIC sampling
+ * frequency (2.4MHz or 3.84MHz). This table compensates the DMIC decimator
+ * roll-off at 20kHz.
+ * The default table is loaded with the DMIC 2.4MHz recommended configuration.
+ */
+abehal_status abe_set_dmic_filter(u32 d);
+/**
+ * abe_connect_cbpr_dmareq_port
+ * @id: port name
+ * @f: desired data format
+ * @d: desired dma_request line (0..7)
+ * @a: returned pointer to the base address of the CBPr register and number of
+ * samples to exchange during a DMA_request.
+ *
+ * enables the data echange between a DMA and the ABE through the
+ * CBPr registers of AESS.
+ */
+abehal_status abe_connect_cbpr_dmareq_port(u32 id, abe_data_format_t *f, u32 d,
+ abe_dma_t *returned_dma_t);
+/**
+ * abe_connect_irq_ping_pong_port
+ * @id: port name
+ * @f: desired data format
+ * @I: index of the call-back subroutine to call
+ * @s: half-buffer (ping) size
+ * @p: returned base address of the first (ping) buffer)
+ *
+ * enables the data echanges between a direct access to the DMEM
+ * memory of ABE using cache flush. On each IRQ activation a subroutine
+ * registered with "abe_plug_subroutine" will be called. This subroutine
+ * will generate an amount of samples, send them to DMEM memory and call
+ * "abe_set_ping_pong_buffer" to notify the new amount of samples in the
+ * pong buffer.
+ */
+abehal_status abe_connect_irq_ping_pong_port(u32 id, abe_data_format_t *f,
+ u32 subroutine_id, u32 size,
+ u32 *sink, u32 dsp_mcu_flag);
+/**
+ * abe_connect_serial_port()
+ * @id: port name
+ * @f: data format
+ * @i: peripheral ID (McBSP #1, #2, #3)
+ *
+ * Operations : enables the data echanges between a McBSP and an ATC buffer in
+ * DMEM. This API is used connect 48kHz McBSP streams to MM_DL and 8/16kHz
+ * voice streams to VX_UL, VX_DL, BT_VX_UL, BT_VX_DL. It abstracts the
+ * abe_write_port API.
+ */
+abehal_status abe_connect_serial_port(u32 id, abe_data_format_t *f,
+ u32 mcbsp_id);
+/**
+ * abe_read_port_address
+ * @dma: output pointer to the DMA iteration and data destination pointer
+ *
+ * This API returns the address of the DMA register used on this audio port.
+ * Depending on the protocol being used, adds the base address offset L3
+ * (DMA) or MPU (ARM)
+ */
+abehal_status abe_read_port_address(u32 port, abe_dma_t *dma2);
+/**
+ * abe_write_equalizer
+ * @id: name of the equalizer
+ * @param : equalizer coefficients
+ *
+ * Load the coefficients in CMEM.
+ */
+abehal_status abe_write_equalizer(u32 id, abe_equ_t *param);
+/**
+ * abe_write_asrc
+ * @id: name of the port
+ * @param: drift value to compensate [ppm]
+ *
+ * Load the drift variables to the FW memory. This API can be called only
+ * when the corresponding port has been already opened and the ASRC has
+ * been correctly initialized with API abe_init_asrc_... If this API is
+ * used such that the drift has been changed from positive to negative drift
+ * or vice versa, there will be click in the output signal. Loading the drift
+ * value with zero disables the feature.
+ */
+abehal_status abe_write_asrc(u32 port, s32 dppm);
+/**
+ * abe_write_aps
+ * @id: name of the aps filter
+ * @param: table of filter coefficients
+ *
+ * Load the filters and thresholds coefficients in FW memory. This AP
+ * can be called when the corresponding APS is not activated. After
+ * reloading the firmware the default coefficients corresponds to "no APS
+ * activated".
+ * Loading all the coefficients value with zero disables the feature.
+ */
+abehal_status abe_write_aps(u32 id, struct abe_aps_t *param);
+/**
+ * abe_write_mixer
+ * @id: name of the mixer
+ * @param: list of input gains of the mixer
+ * @p: list of port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's gain
+ * in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+abehal_status abe_write_gain(u32 id, s32 f_g, u32 ramp, u32 p);
+abehal_status abe_use_compensated_gain(u32 on_off);
+abehal_status abe_enable_gain(u32 id, u32 p);
+abehal_status abe_disable_gain(u32 id, u32 p);
+abehal_status abe_mute_gain(u32 id, u32 p);
+abehal_status abe_unmute_gain(u32 id, u32 p);
+/**
+ * abe_write_mixer
+ * @id: name of the mixer
+ * @param: input gains and delay ramp of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+abehal_status abe_write_mixer(u32 id, s32 f_g, u32 f_ramp, u32 p);
+/**
+ * abe_read_gain
+ * @id: name of the mixer
+ * @param: list of input gains of the mixer
+ * @p: list of port corresponding to the above gains
+ *
+ */
+abehal_status abe_read_gain(u32 id, u32 *f_g, u32 p);
+/**
+ * abe_read_mixer
+ * @id: name of the mixer
+ * @param: gains of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+abehal_status abe_read_mixer(u32 id, u32 *f_g, u32 p);
+/**
+ * abe_set_router_configuration
+ * @Id: name of the router
+ * @Conf: id of the configuration
+ * @param: list of output index of the route
+ *
+ * The uplink router takes its input from DMIC (6 samples), AMIC (2 samples)
+ * and PORT1/2 (2 stereo ports). Each sample will be individually stored in
+ * an intermediate table of 10 elements. The intermediate table is used to
+ * route the samples to three directions : REC1 mixer, 2 EANC DMIC source of
+ * filtering and MM recording audio path.
+ */
+abehal_status abe_set_router_configuration(u32 id, u32 k, u32 *param);
+/**
+ * ABE_READ_DEBUG_TRACE
+ *
+ * Parameters :
+ * @data: data destination pointer
+ * @n : max number of read data
+ *
+ * Operations :
+ * Reads the AE circular data pointer that holds pairs of debug data +
+ * timestamps, and stores the pairs, via linear addressing, to the parameter
+ * pointer.
+ * Stops the copy when the max parameter is reached or when the FIFO is empty.
+ *
+ * Return value :
+ * None.
+ */
+abehal_status abe_read_debug_trace(u32 *data, u32 *n);
+/**
+ * abe_connect_debug_trace
+ * @dma2:pointer to the DMEM trace buffer
+ *
+ * returns the address and size of the real-time debug trace buffer,
+ * the content of which will vary from one firmware release to an other
+ */
+abehal_status abe_connect_debug_trace(abe_dma_t *dma2);
+/**
+ * abe_set_debug_trace
+ * @debug: debug ID from a list to be defined
+ *
+ * load a mask which filters the debug trace to dedicated types of data
+ */
+abehal_status abe_set_debug_trace(abe_dbg_t debug);
+/**
+ * abe_init_mem - Allocate Kernel space memory map for ABE
+ *
+ * Memory map of ABE memory space for PMEM/DMEM/SMEM/DMEM
+ */
+void abe_init_mem(void __iomem **_io_base);
+
+/**
+ * abe_write_pdmdl_offset - write the desired offset on the DL1/DL2 paths
+ *
+ * Parameters:
+ * path: 1 for the DL1 ABE path, 2 for the DL2 ABE path
+ * offset_left: integer value that will be added on all PDM left samples
+ * offset_right: integer value that will be added on all PDM right samples
+ *
+ */
+void abe_write_pdmdl_offset(u32 path, u32 offset_left, u32 offset_right);
+
+#endif/* _ABE_API_H_ */
diff --git a/sound/soc/omap/abe/abe_asrc.c b/sound/soc/omap/abe/abe_asrc.c
new file mode 100644
index 0000000..4a52235
--- /dev/null
+++ b/sound/soc/omap/abe/abe_asrc.c
@@ -0,0 +1,1231 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_legacy.h"
+#include "abe_dbg.h"
+
+#include "abe_typedef.h"
+#include "abe_initxxx_labels.h"
+#include "abe_dbg.h"
+#include "abe_mem.h"
+#include "abe_sm_addr.h"
+#include "abe_cm_addr.h"
+
+/**
+ * abe_write_fifo
+ * @mem_bank: currently only ABE_DMEM supported
+ * @addr: FIFO descriptor address ( descriptor fields : READ ptr, WRITE ptr,
+ * FIFO START_ADDR, FIFO END_ADDR)
+ * @data: data to write to FIFO
+ * @number: number of 32-bit words to write to DMEM FIFO
+ *
+ * write DMEM FIFO and update FIFO descriptor,
+ * it is assumed that FIFO descriptor is located in DMEM
+ */
+void abe_write_fifo(u32 memory_bank, u32 descr_addr, u32 *data, u32 nb_data32)
+{
+ u32 fifo_addr[4];
+ u32 i;
+ /* read FIFO descriptor from DMEM */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, descr_addr,
+ &fifo_addr[0], 4 * sizeof(u32));
+ /* WRITE ptr < FIFO start address */
+ if (fifo_addr[1] < fifo_addr[2])
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_DBG,
+ ABE_FW_FIFO_WRITE_PTR_ERR);
+ /* WRITE ptr > FIFO end address */
+ if (fifo_addr[1] > fifo_addr[3])
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_DBG,
+ ABE_FW_FIFO_WRITE_PTR_ERR);
+ switch (memory_bank) {
+ case ABE_DMEM:
+ for (i = 0; i < nb_data32; i++) {
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (s32) fifo_addr[1], (u32 *) (data + i),
+ 4);
+ /* increment WRITE pointer */
+ fifo_addr[1] = fifo_addr[1] + 4;
+ if (fifo_addr[1] > fifo_addr[3])
+ fifo_addr[1] = fifo_addr[2];
+ if (fifo_addr[1] == fifo_addr[0])
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_DBG,
+ ABE_FW_FIFO_WRITE_PTR_ERR);
+ }
+ /* update WRITE pointer in DMEM */
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, descr_addr +
+ sizeof(u32), &fifo_addr[1], 4);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * abe_write_asrc
+ * @id: name of the port
+ * @param: drift value to compensate [ppm]
+ *
+ * Load the drift variables to the FW memory. This API can be called only
+ * when the corresponding port has been already opened and the ASRC has
+ * been correctly initialized with API abe_init_asrc_... If this API is
+ * used such that the drift has been changed from positive to negative drift
+ * or vice versa, there will be click in the output signal. Loading the drift
+ * value with zero disables the feature.
+ */
+abehal_status abe_write_asrc(u32 port, s32 dppm)
+{
+ s32 dtempvalue, adppm, drift_sign, drift_sign_addr, alpha_params_addr;
+ s32 alpha_params[3];
+ _log(ABE_ID_WRITE_ASRC, port, dppm, dppm >> 8);
+ /*
+ * x = ppm
+ *
+ * - 1000000/x must be multiple of 16
+ * - deltaalpha = round(2^20*x*16/1000000)=round(2^18/5^6*x) on 22 bits.
+ * then shifted by 2bits
+ * - minusdeltaalpha
+ * - oneminusepsilon = 1-deltaalpha/2.
+ *
+ * ppm = 250
+ * - 1000000/250=4000
+ * - deltaalpha = 4194.3 ~ 4195 => 0x00418c
+ */
+ /* examples for -6250 ppm */
+ /* atempvalue32[1] = -1; d_driftsign */
+ /* atempvalue32[3] = 0x00066668; d_deltaalpha */
+ /* atempvalue32[4] = 0xfff99998; d_minusdeltaalpha */
+ /* atempvalue32[5] = 0x003ccccc; d_oneminusepsilon */
+ /* example for 100 ppm */
+ /* atempvalue32[1] = 1;* d_driftsign */
+ /* atempvalue32[3] = 0x00001a38; d_deltaalpha */
+ /* atempvalue32[4] = 0xffffe5c8; d_minusdeltaalpha */
+ /* atempvalue32[5] = 0x003ccccc; d_oneminusepsilon */
+ /* compute new value for the ppm */
+ if (dppm >= 0) {
+ /* d_driftsign */
+ drift_sign = 1;
+ adppm = dppm;
+ } else {
+ /* d_driftsign */
+ drift_sign = -1;
+ adppm = (-1 * dppm);
+ }
+ if (dppm == 0) {
+ /* delta_alpha */
+ alpha_params[0] = 0;
+ /* minusdelta_alpha */
+ alpha_params[1] = 0;
+ /* one_minusepsilon */
+ alpha_params[2] = 0x003ffff0;
+ } else {
+ dtempvalue = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* delta_alpha */
+ alpha_params[0] = dtempvalue << 2;
+ /* minusdelta_alpha */
+ alpha_params[1] = (-dtempvalue) << 2;
+ /* one_minusepsilon */
+ alpha_params[2] = (0x00100000 - (dtempvalue / 2)) << 2;
+ }
+ switch (port) {
+ /* asynchronous sample-rate-converter for the uplink voice path */
+ case OMAP_ABE_VX_DL_PORT:
+ drift_sign_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (1 * sizeof(s32));
+ alpha_params_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (3 * sizeof(s32));
+ break;
+ /* asynchronous sample-rate-converter for the downlink voice path */
+ case OMAP_ABE_VX_UL_PORT:
+ drift_sign_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (1 * sizeof(s32));
+ alpha_params_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (3 * sizeof(s32));
+ break;
+ /* asynchronous sample-rate-converter for the BT_UL path */
+ case OMAP_ABE_BT_VX_UL_PORT:
+ drift_sign_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (1 * sizeof(s32));
+ alpha_params_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (3 * sizeof(s32));
+ break;
+ /* asynchronous sample-rate-converter for the BT_DL path */
+ case OMAP_ABE_BT_VX_DL_PORT:
+ drift_sign_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (1 * sizeof(s32));
+ alpha_params_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (3 * sizeof(s32));
+ break;
+ default:
+ /* asynchronous sample-rate-converter for the MM_EXT_IN path */
+ case OMAP_ABE_MM_EXT_IN_PORT:
+ drift_sign_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (1 * sizeof(s32));
+ alpha_params_addr =
+ OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (3 * sizeof(s32));
+ break;
+ }
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, drift_sign_addr,
+ (u32 *) &drift_sign, 4);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, alpha_params_addr,
+ (u32 *) &alpha_params[0], 12);
+ return 0;
+}
+EXPORT_SYMBOL(abe_write_asrc);
+/**
+ * abe_init_asrc_vx_dl
+ *
+ * Initialize the following ASRC VX_DL parameters :
+ * 1. DriftSign = D_AsrcVars[1] = 1 or -1
+ * 2. Subblock = D_AsrcVars[2] = 0
+ * 3. DeltaAlpha = D_AsrcVars[3] =
+ * (round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 4. MinusDeltaAlpha = D_AsrcVars[4] =
+ * (-round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 5. OneMinusEpsilon = D_AsrcVars[5] = 1 - DeltaAlpha/2
+ * 6. AlphaCurrent = 0x000020 (CMEM), initial value of Alpha parameter
+ * 7. BetaCurrent = 0x3fffe0 (CMEM), initial value of Beta parameter
+ * AlphaCurrent + BetaCurrent = 1 (=0x400000 in CMEM = 2^20 << 2)
+ * 8. drift_ASRC = 0 & drift_io = 0
+ * 9. SMEM for ASRC_DL_VX_Coefs pointer
+ * 10. CMEM for ASRC_DL_VX_Coefs pointer
+ * ASRC_DL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ * C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1
+ * 11. SMEM for XinASRC_DL_VX pointer
+ * 12. CMEM for XinASRC_DL_VX pointer
+ * XinASRC_DL_VX = S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/0/1/0/0/0/0
+ * 13. SMEM for IO_VX_DL_ASRC pointer
+ * 14. CMEM for IO_VX_DL_ASRC pointer
+ * IO_VX_DL_ASRC =
+ * S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/
+ * ASRC_DL_VX_FIR_L+ASRC_margin/1/0/0/0/0
+ */
+void abe_init_asrc_vx_dl(s32 dppm)
+{
+ s32 el[45];
+ s32 temp0, temp1, adppm, dtemp, mem_tag, mem_addr;
+ u32 i = 0;
+ u32 n_fifo_el = 42;
+ temp0 = 0;
+ temp1 = 1;
+ /* 1. DriftSign = D_AsrcVars[1] = 1 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (1 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm >= 0) {
+ el[i + 1] = 1;
+ adppm = dppm;
+ } else {
+ el[i + 1] = -1;
+ adppm = (-1 * dppm);
+ }
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ dtemp = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* 2. Subblock = D_AsrcVars[2] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (2 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 3. DeltaAlpha = D_AsrcVars[3] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (3 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = dtemp << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 4. MinusDeltaAlpha = D_AsrcVars[4] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (4 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = (-dtemp) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /*5. OneMinusEpsilon = D_AsrcVars[5] = 0x00400000 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_DL_VX_ADDR + (5 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0x00400000;
+ else
+ el[i + 1] = (0x00100000 - (dtemp / 2)) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 6. AlphaCurrent = 0x000020 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_ALPHACURRENT_DL_VX_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x00000020;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 7. BetaCurrent = 0x3fffe0 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_BETACURRENT_DL_VX_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x003fffe0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 8. drift_ASRC = 0 & drift_io = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_VX_DL_PORT * sizeof(struct ABE_SIODescriptor))
+ + drift_asrc_;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 9. SMEM for ASRC_DL_VX_Coefs pointer */
+ /* ASRC_DL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_SMEM;
+ mem_addr = ASRC_DL_VX_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ if (dppm == 0) {
+ el[i + 1] = OMAP_ABE_C_COEFASRC16_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC16_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC15_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC15_VX_SIZE >> 2);
+ } else {
+ el[i + 1] = OMAP_ABE_C_COEFASRC1_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC1_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC2_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC2_VX_SIZE >> 2);
+ }
+ i = i + 3;
+ /* 10. CMEM for ASRC_DL_VX_Coefs pointer */
+ /* ASRC_DL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_CMEM;
+ mem_addr = ASRC_DL_VX_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp1;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 11. SMEM for XinASRC_DL_VX pointer */
+ /* XinASRC_DL_VX =
+ S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = XinASRC_DL_VX_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_DL_VX_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_DL_VX_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 12. CMEM for XinASRC_DL_VX pointer */
+ /* XinASRC_DL_VX =
+ S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = XinASRC_DL_VX_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 13. SMEM for IO_VX_DL_ASRC pointer */
+ /* IO_VX_DL_ASRC = S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/
+ ASRC_DL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = IO_VX_DL_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_DL_VX_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_DL_VX_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 14. CMEM for IO_VX_DL_ASRC pointer */
+ /* IO_VX_DL_ASRC = S_XinASRC_DL_VX_ADDR/S_XinASRC_DL_VX_sizeof/
+ ASRC_DL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = IO_VX_DL_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_DL_VX_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ abe_write_fifo(ABE_DMEM, OMAP_ABE_D_FWMEMINITDESCR_ADDR, (u32 *) &el[0],
+ n_fifo_el);
+}
+/**
+ * abe_init_asrc_vx_ul
+ *
+ * Initialize the following ASRC VX_UL parameters :
+ * 1. DriftSign = D_AsrcVars[1] = 1 or -1
+ * 2. Subblock = D_AsrcVars[2] = 0
+ * 3. DeltaAlpha = D_AsrcVars[3] =
+ * (round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 4. MinusDeltaAlpha = D_AsrcVars[4] =
+ * (-round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 5. OneMinusEpsilon = D_AsrcVars[5] = 1 - DeltaAlpha/2
+ * 6. AlphaCurrent = 0x000020 (CMEM), initial value of Alpha parameter
+ * 7. BetaCurrent = 0x3fffe0 (CMEM), initial value of Beta parameter
+ * AlphaCurrent + BetaCurrent = 1 (=0x400000 in CMEM = 2^20 << 2)
+ * 8. drift_ASRC = 0 & drift_io = 0
+ * 9. SMEM for ASRC_UL_VX_Coefs pointer
+ * 10. CMEM for ASRC_UL_VX_Coefs pointer
+ * ASRC_UL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ * C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1
+ * 11. SMEM for XinASRC_UL_VX pointer
+ * 12. CMEM for XinASRC_UL_VX pointer
+ * XinASRC_UL_VX = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/0/1/0/0/0/0
+ * 13. SMEM for UL_48_8_DEC pointer
+ * 14. CMEM for UL_48_8_DEC pointer
+ * UL_48_8_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ * ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0
+ * 15. SMEM for UL_48_16_DEC pointer
+ * 16. CMEM for UL_48_16_DEC pointer
+ * UL_48_16_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ * ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0
+ */
+void abe_init_asrc_vx_ul(s32 dppm)
+{
+ s32 el[51];
+ s32 temp0, temp1, adppm, dtemp, mem_tag, mem_addr;
+ u32 i = 0;
+ u32 n_fifo_el = 48;
+ temp0 = 0;
+ temp1 = 1;
+ /* 1. DriftSign = D_AsrcVars[1] = 1 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (1 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm >= 0) {
+ el[i + 1] = 1;
+ adppm = dppm;
+ } else {
+ el[i + 1] = -1;
+ adppm = (-1 * dppm);
+ }
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ dtemp = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* 2. Subblock = D_AsrcVars[2] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (2 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 3. DeltaAlpha = D_AsrcVars[3] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (3 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = dtemp << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 4. MinusDeltaAlpha = D_AsrcVars[4] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (4 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = (-dtemp) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 5. OneMinusEpsilon = D_AsrcVars[5] = 0x00400000 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_UL_VX_ADDR + (5 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0x00400000;
+ else
+ el[i + 1] = (0x00100000 - (dtemp / 2)) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 6. AlphaCurrent = 0x000020 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_ALPHACURRENT_UL_VX_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x00000020;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 7. BetaCurrent = 0x3fffe0 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_BETACURRENT_UL_VX_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x003fffe0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 8. drift_ASRC = 0 & drift_io = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_VX_UL_PORT * sizeof(struct ABE_SIODescriptor))
+ + drift_asrc_;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 9. SMEM for ASRC_UL_VX_Coefs pointer */
+ /* ASRC_UL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_SMEM;
+ mem_addr = ASRC_UL_VX_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ if (dppm == 0) {
+ el[i + 1] = OMAP_ABE_C_COEFASRC16_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC16_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC15_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC15_VX_SIZE >> 2);
+ } else {
+ el[i + 1] = OMAP_ABE_C_COEFASRC1_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC1_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC2_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC2_VX_SIZE >> 2);
+ }
+ i = i + 3;
+ /* 10. CMEM for ASRC_UL_VX_Coefs pointer */
+ /* ASRC_UL_VX_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_CMEM;
+ mem_addr = ASRC_UL_VX_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp1;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 11. SMEM for XinASRC_UL_VX pointer */
+ /* XinASRC_UL_VX = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/0/1/
+ 0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = XinASRC_UL_VX_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_UL_VX_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_UL_VX_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 12. CMEM for XinASRC_UL_VX pointer */
+ /* XinASRC_UL_VX = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/0/1/
+ 0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = XinASRC_UL_VX_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 13. SMEM for UL_48_8_DEC pointer */
+ /* UL_48_8_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = UL_48_8_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_UL_VX_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_UL_VX_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 14. CMEM for UL_48_8_DEC pointer */
+ /* UL_48_8_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = UL_48_8_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_UL_VX_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 15. SMEM for UL_48_16_DEC pointer */
+ /* UL_48_16_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = UL_48_16_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_UL_VX_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_UL_VX_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 16. CMEM for UL_48_16_DEC pointer */
+ /* UL_48_16_DEC = S_XinASRC_UL_VX_ADDR/S_XinASRC_UL_VX_sizeof/
+ ASRC_UL_VX_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = UL_48_16_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_UL_VX_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ abe_write_fifo(ABE_DMEM, OMAP_ABE_D_FWMEMINITDESCR_ADDR, (u32 *) &el[0],
+ n_fifo_el);
+}
+/**
+ * abe_init_asrc_mm_ext_in
+ *
+ * Initialize the following ASRC MM_EXT_IN parameters :
+ * 1. DriftSign = D_AsrcVars[1] = 1 or -1
+ * 2. Subblock = D_AsrcVars[2] = 0
+ * 3. DeltaAlpha = D_AsrcVars[3] =
+ * (round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 4. MinusDeltaAlpha = D_AsrcVars[4] =
+ * (-round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 5. OneMinusEpsilon = D_AsrcVars[5] = 1 - DeltaAlpha/2
+ * 6. AlphaCurrent = 0x000020 (CMEM), initial value of Alpha parameter
+ * 7. BetaCurrent = 0x3fffe0 (CMEM), initial value of Beta parameter
+ * AlphaCurrent + BetaCurrent = 1 (=0x400000 in CMEM = 2^20 << 2)
+ * 8. drift_ASRC = 0 & drift_io = 0
+ * 9. SMEM for ASRC_MM_EXT_IN_Coefs pointer
+ * 10. CMEM for ASRC_MM_EXT_IN_Coefs pointer
+ * ASRC_MM_EXT_IN_Coefs = C_CoefASRC16_MM_ADDR/C_CoefASRC16_MM_sizeof/0/1/
+ * C_CoefASRC15_MM_ADDR/C_CoefASRC15_MM_sizeof/0/1
+ * 11. SMEM for XinASRC_MM_EXT_IN pointer
+ * 12. CMEM for XinASRC_MM_EXT_IN pointer
+ * XinASRC_MM_EXT_IN = S_XinASRC_MM_EXT_IN_ADDR/S_XinASRC_MM_EXT_IN_sizeof/0/1/
+ * 0/0/0/0
+ * 13. SMEM for IO_MM_EXT_IN_ASRC pointer
+ * 14. CMEM for IO_MM_EXT_IN_ASRC pointer
+ * IO_MM_EXT_IN_ASRC = S_XinASRC_MM_EXT_IN_ADDR/S_XinASRC_MM_EXT_IN_sizeof/
+ * ASRC_MM_EXT_IN_FIR_L+ASRC_margin+ASRC_N_48k/1/0/0/0/0
+ */
+void abe_init_asrc_mm_ext_in(s32 dppm)
+{
+ s32 el[45];
+ s32 temp0, temp1, adppm, dtemp, mem_tag, mem_addr;
+ u32 i = 0;
+ u32 n_fifo_el = 42;
+ temp0 = 0;
+ temp1 = 1;
+ /* 1. DriftSign = D_AsrcVars[1] = 1 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (1 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm >= 0) {
+ el[i + 1] = 1;
+ adppm = dppm;
+ } else {
+ el[i + 1] = -1;
+ adppm = (-1 * dppm);
+ }
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ dtemp = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* 2. Subblock = D_AsrcVars[2] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (2 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 3. DeltaAlpha = D_AsrcVars[3] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (3 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = dtemp << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 4. MinusDeltaAlpha = D_AsrcVars[4] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (4 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = (-dtemp) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 5. OneMinusEpsilon = D_AsrcVars[5] = 0x00400000 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR + (5 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0x00400000;
+ else
+ el[i + 1] = (0x00100000 - (dtemp / 2)) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 6. AlphaCurrent = 0x000020 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_ALPHACURRENT_MM_EXT_IN_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x00000020;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 7. BetaCurrent = 0x3fffe0 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_BETACURRENT_MM_EXT_IN_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x003fffe0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 8. drift_ASRC = 0 & drift_io = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_MM_EXT_IN_PORT * sizeof(struct ABE_SIODescriptor))
+ + drift_asrc_;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 9. SMEM for ASRC_MM_EXT_IN_Coefs pointer */
+ /* ASRC_MM_EXT_IN_Coefs = C_CoefASRC16_MM_ADDR/C_CoefASRC16_MM_sizeof/
+ 0/1/C_CoefASRC15_MM_ADDR/C_CoefASRC15_MM_sizeof/0/1 */
+ mem_tag = ABE_SMEM;
+ mem_addr = ASRC_MM_EXT_IN_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ if (dppm == 0) {
+ el[i + 1] = OMAP_ABE_C_COEFASRC16_MM_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC16_MM_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC15_MM_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC15_MM_SIZE >> 2);
+ } else {
+ el[i + 1] = OMAP_ABE_C_COEFASRC1_MM_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC1_MM_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC2_MM_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC2_MM_SIZE >> 2);
+ }
+ i = i + 3;
+ /*10. CMEM for ASRC_MM_EXT_IN_Coefs pointer */
+ /* ASRC_MM_EXT_IN_Coefs = C_CoefASRC16_MM_ADDR/C_CoefASRC16_MM_sizeof/
+ 0/1/C_CoefASRC15_MM_ADDR/C_CoefASRC15_MM_sizeof/0/1 */
+ mem_tag = ABE_CMEM;
+ mem_addr = ASRC_MM_EXT_IN_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp1;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 11. SMEM for XinASRC_MM_EXT_IN pointer */
+ /* XinASRC_MM_EXT_IN = S_XinASRC_MM_EXT_IN_ADDR/
+ S_XinASRC_MM_EXT_IN_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = XinASRC_MM_EXT_IN_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_MM_EXT_IN_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_MM_EXT_IN_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 12. CMEM for XinASRC_MM_EXT_IN pointer */
+ /* XinASRC_MM_EXT_IN = S_XinASRC_MM_EXT_IN_ADDR/
+ S_XinASRC_MM_EXT_IN_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = XinASRC_MM_EXT_IN_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 13. SMEM for IO_MM_EXT_IN_ASRC pointer */
+ /* IO_MM_EXT_IN_ASRC =
+ S_XinASRC_MM_EXT_IN_ADDR/S_XinASRC_MM_EXT_IN_sizeof/
+ ASRC_MM_EXT_IN_FIR_L+ASRC_margin+ASRC_N_48k/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = IO_MM_EXT_IN_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_MM_EXT_IN_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_MM_EXT_IN_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 14. CMEM for IO_MM_EXT_IN_ASRC pointer */
+ /* IO_MM_EXT_IN_ASRC =
+ S_XinASRC_MM_EXT_IN_ADDR/S_XinASRC_MM_EXT_IN_sizeof/
+ ASRC_MM_EXT_IN_FIR_L+ASRC_margin+ASRC_N_48k/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = IO_MM_EXT_IN_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_MM_EXT_IN_FIR_L + ASRC_margin + ASRC_N_48k) << 16) +
+ (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ abe_write_fifo(ABE_DMEM, OMAP_ABE_D_FWMEMINITDESCR_ADDR, (u32 *) &el[0],
+ n_fifo_el);
+}
+/**
+ * abe_init_asrc_bt_ul
+ *
+ * Initialize the following ASRC BT_UL parameters :
+ * 1. DriftSign = D_AsrcVars[1] = 1 or -1
+ * 2. Subblock = D_AsrcVars[2] = 0
+ * 3. DeltaAlpha = D_AsrcVars[3] =
+ * (round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 4. MinusDeltaAlpha = D_AsrcVars[4] =
+ * (-round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 5. OneMinusEpsilon = D_AsrcVars[5] = 1 - DeltaAlpha/2
+ * 6. AlphaCurrent = 0x000020 (CMEM), initial value of Alpha parameter
+ * 7. BetaCurrent = 0x3fffe0 (CMEM), initial value of Beta parameter
+ * AlphaCurrent + BetaCurrent = 1 (=0x400000 in CMEM = 2^20 << 2)
+ * 8. drift_ASRC = 0 & drift_io = 0
+ * 9. SMEM for ASRC_BT_UL_Coefs pointer
+ * 10. CMEM for ASRC_BT_UL_Coefs pointer
+ * ASRC_BT_UL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ * C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1
+ * 11. SMEM for XinASRC_BT_UL pointer
+ * 12. CMEM for XinASRC_BT_UL pointer
+ * XinASRC_BT_UL = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/0/1/0/0/0/0
+ * 13. SMEM for IO_BT_UL_ASRC pointer
+ * 14. CMEM for IO_BT_UL_ASRC pointer
+ * IO_BT_UL_ASRC = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/
+ * ASRC_BT_UL_FIR_L+ASRC_margin/1/0/0/0/0
+ */
+void abe_init_asrc_bt_ul(s32 dppm)
+{
+ s32 el[45];
+ s32 temp0, temp1, adppm, dtemp, mem_tag, mem_addr;
+ u32 i = 0;
+ u32 n_fifo_el = 42;
+ temp0 = 0;
+ temp1 = 1;
+ /* 1. DriftSign = D_AsrcVars[1] = 1 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (1 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm >= 0) {
+ el[i + 1] = 1;
+ adppm = dppm;
+ } else {
+ el[i + 1] = -1;
+ adppm = (-1 * dppm);
+ }
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ dtemp = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* 2. Subblock = D_AsrcVars[2] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (2 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 3. DeltaAlpha = D_AsrcVars[3] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (3 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = dtemp << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 4. MinusDeltaAlpha = D_AsrcVars[4] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (4 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = (-dtemp) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /*5. OneMinusEpsilon = D_AsrcVars[5] = 0x00400000 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_UL_ADDR + (5 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0x00400000;
+ else
+ el[i + 1] = (0x00100000 - (dtemp / 2)) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 6. AlphaCurrent = 0x000020 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_ALPHACURRENT_BT_UL_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x00000020;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 7. BetaCurrent = 0x3fffe0 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_BETACURRENT_BT_UL_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x003fffe0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 8. drift_ASRC = 0 & drift_io = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_BT_VX_UL_PORT * sizeof(struct ABE_SIODescriptor))
+ + drift_asrc_;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 9. SMEM for ASRC_BT_UL_Coefs pointer */
+ /* ASRC_BT_UL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_SMEM;
+ mem_addr = ASRC_BT_UL_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ if (dppm == 0) {
+ el[i + 1] = OMAP_ABE_C_COEFASRC16_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC16_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC15_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC15_VX_SIZE >> 2);
+ } else {
+ el[i + 1] = OMAP_ABE_C_COEFASRC1_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC1_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC2_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC2_VX_SIZE >> 2);
+ }
+ i = i + 3;
+ /* 10. CMEM for ASRC_BT_UL_Coefs pointer */
+ /* ASRC_BT_UL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_CMEM;
+ mem_addr = ASRC_BT_UL_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp1;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 11. SMEM for XinASRC_BT_UL pointer */
+ /* XinASRC_BT_UL = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/0/1/
+ 0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = XinASRC_BT_UL_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_BT_UL_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_BT_UL_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 12. CMEM for XinASRC_BT_UL pointer */
+ /* XinASRC_BT_UL = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/0/1/
+ 0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = XinASRC_BT_UL_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 13. SMEM for IO_BT_UL_ASRC pointer */
+ /* IO_BT_UL_ASRC = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/
+ ASRC_BT_UL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = IO_BT_UL_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_BT_UL_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_BT_UL_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 14. CMEM for IO_BT_UL_ASRC pointer */
+ /* IO_BT_UL_ASRC = S_XinASRC_BT_UL_ADDR/S_XinASRC_BT_UL_sizeof/
+ ASRC_BT_UL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = IO_BT_UL_ASRC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_BT_UL_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ abe_write_fifo(ABE_DMEM, OMAP_ABE_D_FWMEMINITDESCR_ADDR, (u32 *) &el[0],
+ n_fifo_el);
+}
+/**
+ * abe_init_asrc_bt_dl
+ *
+ * Initialize the following ASRC BT_DL parameters :
+ * 1. DriftSign = D_AsrcVars[1] = 1 or -1
+ * 2. Subblock = D_AsrcVars[2] = 0
+ * 3. DeltaAlpha = D_AsrcVars[3] =
+ * (round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 4. MinusDeltaAlpha = D_AsrcVars[4] =
+ * (-round(nb_phases * drift[ppm] * 10^-6 * 2^20)) << 2
+ * 5. OneMinusEpsilon = D_AsrcVars[5] = 1 - DeltaAlpha/2
+ * 6. AlphaCurrent = 0x000020 (CMEM), initial value of Alpha parameter
+ * 7. BetaCurrent = 0x3fffe0 (CMEM), initial value of Beta parameter
+ * AlphaCurrent + BetaCurrent = 1 (=0x400000 in CMEM = 2^20 << 2)
+ * 8. drift_ASRC = 0 & drift_io = 0
+ * 9. SMEM for ASRC_BT_DL_Coefs pointer
+ * 10. CMEM for ASRC_BT_DL_Coefs pointer
+ * ASRC_BT_DL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ * C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1
+ * 11. SMEM for XinASRC_BT_DL pointer
+ * 12. CMEM for XinASRC_BT_DL pointer
+ * XinASRC_BT_DL = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/0/1/0/0/0/0
+ * 13. SMEM for DL_48_8_DEC pointer
+ * 14. CMEM for DL_48_8_DEC pointer
+ * DL_48_8_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ * ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0
+ * 15. SMEM for DL_48_16_DEC pointer
+ * 16. CMEM for DL_48_16_DEC pointer
+ * DL_48_16_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ * ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0
+ */
+void abe_init_asrc_bt_dl(s32 dppm)
+{
+ s32 el[51];
+ s32 temp0, temp1, adppm, dtemp, mem_tag, mem_addr;
+ u32 i = 0;
+ u32 n_fifo_el = 48;
+ temp0 = 0;
+ temp1 = 1;
+ /* 1. DriftSign = D_AsrcVars[1] = 1 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (1 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm >= 0) {
+ el[i + 1] = 1;
+ adppm = dppm;
+ } else {
+ el[i + 1] = -1;
+ adppm = (-1 * dppm);
+ }
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ dtemp = (adppm << 4) + adppm - ((adppm * 3481L) / 15625L);
+ /* 2. Subblock = D_AsrcVars[2] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (2 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 3. DeltaAlpha = D_AsrcVars[3] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (3 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = dtemp << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 4. MinusDeltaAlpha = D_AsrcVars[4] = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (4 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0;
+ else
+ el[i + 1] = (-dtemp) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 5. OneMinusEpsilon = D_AsrcVars[5] = 0x00400000 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_ASRCVARS_BT_DL_ADDR + (5 * sizeof(s32));
+ el[i] = (mem_tag << 16) + mem_addr;
+ if (dppm == 0)
+ el[i + 1] = 0x00400000;
+ else
+ el[i + 1] = (0x00100000 - (dtemp / 2)) << 2;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 6. AlphaCurrent = 0x000020 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_ALPHACURRENT_BT_DL_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x00000020;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 7. BetaCurrent = 0x3fffe0 (CMEM) */
+ mem_tag = ABE_CMEM;
+ mem_addr = OMAP_ABE_C_BETACURRENT_BT_DL_ADDR;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = 0x003fffe0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 8. drift_ASRC = 0 & drift_io = 0 */
+ mem_tag = ABE_DMEM;
+ mem_addr = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_BT_VX_DL_PORT * sizeof(struct ABE_SIODescriptor))
+ + drift_asrc_;
+ el[i] = (mem_tag << 16) + mem_addr;
+ el[i + 1] = temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 9. SMEM for ASRC_BT_DL_Coefs pointer */
+ /* ASRC_BT_DL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_SMEM;
+ mem_addr = ASRC_BT_DL_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ if (dppm == 0) {
+ el[i + 1] = OMAP_ABE_C_COEFASRC16_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC16_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC15_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC15_VX_SIZE >> 2);
+ } else {
+ el[i + 1] = OMAP_ABE_C_COEFASRC1_VX_ADDR >> 2;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_C_COEFASRC1_VX_SIZE >> 2);
+ el[i + 2] = OMAP_ABE_C_COEFASRC2_VX_ADDR >> 2;
+ el[i + 2] = (el[i + 2] << 8) + (OMAP_ABE_C_COEFASRC2_VX_SIZE >> 2);
+ }
+ i = i + 3;
+ /* 10. CMEM for ASRC_BT_DL_Coefs pointer */
+ /* ASRC_BT_DL_Coefs = C_CoefASRC16_VX_ADDR/C_CoefASRC16_VX_sizeof/0/1/
+ C_CoefASRC15_VX_ADDR/C_CoefASRC15_VX_sizeof/0/1 */
+ mem_tag = ABE_CMEM;
+ mem_addr = ASRC_BT_DL_Coefs_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp1;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 11. SMEM for XinASRC_BT_DL pointer */
+ /* XinASRC_BT_DL =
+ S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = XinASRC_BT_DL_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_BT_DL_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_BT_DL_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 12. CMEM for XinASRC_BT_DL pointer */
+ /* XinASRC_BT_DL =
+ S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/0/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = XinASRC_BT_DL_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = (temp0 << 16) + (temp1 << 12) + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 13. SMEM for DL_48_8_DEC pointer */
+ /* DL_48_8_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = DL_48_8_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_BT_DL_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_BT_DL_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 14. CMEM for DL_48_8_DEC pointer */
+ /* DL_48_8_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = DL_48_8_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_BT_DL_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 15. SMEM for DL_48_16_DEC pointer */
+ /* DL_48_16_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_SMEM;
+ mem_addr = DL_48_16_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ el[i + 1] = OMAP_ABE_S_XINASRC_BT_DL_ADDR >> 3;
+ el[i + 1] = (el[i + 1] << 8) + (OMAP_ABE_S_XINASRC_BT_DL_SIZE >> 3);
+ el[i + 2] = temp0;
+ i = i + 3;
+ /* 16. CMEM for DL_48_16_DEC pointer */
+ /* DL_48_16_DEC = S_XinASRC_BT_DL_ADDR/S_XinASRC_BT_DL_sizeof/
+ ASRC_BT_DL_FIR_L+ASRC_margin/1/0/0/0/0 */
+ mem_tag = ABE_CMEM;
+ mem_addr = DL_48_16_DEC_labelID;
+ el[i] = (mem_tag << 16) + (mem_addr << 2);
+ /* el[i+1] = iam1<<16 + inc1<<12 + iam2<<4 + inc2 */
+ el[i + 1] = ((ASRC_BT_DL_FIR_L + ASRC_margin) << 16) + (temp1 << 12)
+ + (temp0 << 4) + temp0;
+ /* dummy field */
+ el[i + 2] = temp0;
+ abe_write_fifo(ABE_DMEM, OMAP_ABE_D_FWMEMINITDESCR_ADDR, (u32 *) &el[0],
+ n_fifo_el);
+}
diff --git a/sound/soc/omap/abe/abe_cm_addr.h b/sound/soc/omap/abe/abe_cm_addr.h
new file mode 100644
index 0000000..2715002
--- /dev/null
+++ b/sound/soc/omap/abe/abe_cm_addr.h
@@ -0,0 +1,221 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define OMAP_ABE_INIT_CM_ADDR 0x0
+#define OMAP_ABE_INIT_CM_SIZE 0x640
+#define OMAP_ABE_C_DATA_LSB_2_ADDR 0x640
+#define OMAP_ABE_C_DATA_LSB_2_SIZE 0x4
+#define OMAP_ABE_C_1_ALPHA_ADDR 0x644
+#define OMAP_ABE_C_1_ALPHA_SIZE 0x48
+#define OMAP_ABE_C_ALPHA_ADDR 0x68C
+#define OMAP_ABE_C_ALPHA_SIZE 0x48
+#define OMAP_ABE_C_GAINSWRAMP_ADDR 0x6D4
+#define OMAP_ABE_C_GAINSWRAMP_SIZE 0x38
+#define OMAP_ABE_C_GAINS_DL1M_ADDR 0x70C
+#define OMAP_ABE_C_GAINS_DL1M_SIZE 0x10
+#define OMAP_ABE_C_GAINS_DL2M_ADDR 0x71C
+#define OMAP_ABE_C_GAINS_DL2M_SIZE 0x10
+#define OMAP_ABE_C_GAINS_ECHOM_ADDR 0x72C
+#define OMAP_ABE_C_GAINS_ECHOM_SIZE 0x8
+#define OMAP_ABE_C_GAINS_SDTM_ADDR 0x734
+#define OMAP_ABE_C_GAINS_SDTM_SIZE 0x8
+#define OMAP_ABE_C_GAINS_VXRECM_ADDR 0x73C
+#define OMAP_ABE_C_GAINS_VXRECM_SIZE 0x10
+#define OMAP_ABE_C_GAINS_ULM_ADDR 0x74C
+#define OMAP_ABE_C_GAINS_ULM_SIZE 0x10
+#define OMAP_ABE_C_GAINS_BTUL_ADDR 0x75C
+#define OMAP_ABE_C_GAINS_BTUL_SIZE 0x8
+#define OMAP_ABE_C_SDT_COEFS_ADDR 0x764
+#define OMAP_ABE_C_SDT_COEFS_SIZE 0x24
+#define OMAP_ABE_C_COEFASRC1_VX_ADDR 0x788
+#define OMAP_ABE_C_COEFASRC1_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC2_VX_ADDR 0x7D4
+#define OMAP_ABE_C_COEFASRC2_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC3_VX_ADDR 0x820
+#define OMAP_ABE_C_COEFASRC3_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC4_VX_ADDR 0x86C
+#define OMAP_ABE_C_COEFASRC4_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC5_VX_ADDR 0x8B8
+#define OMAP_ABE_C_COEFASRC5_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC6_VX_ADDR 0x904
+#define OMAP_ABE_C_COEFASRC6_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC7_VX_ADDR 0x950
+#define OMAP_ABE_C_COEFASRC7_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC8_VX_ADDR 0x99C
+#define OMAP_ABE_C_COEFASRC8_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC9_VX_ADDR 0x9E8
+#define OMAP_ABE_C_COEFASRC9_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC10_VX_ADDR 0xA34
+#define OMAP_ABE_C_COEFASRC10_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC11_VX_ADDR 0xA80
+#define OMAP_ABE_C_COEFASRC11_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC12_VX_ADDR 0xACC
+#define OMAP_ABE_C_COEFASRC12_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC13_VX_ADDR 0xB18
+#define OMAP_ABE_C_COEFASRC13_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC14_VX_ADDR 0xB64
+#define OMAP_ABE_C_COEFASRC14_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC15_VX_ADDR 0xBB0
+#define OMAP_ABE_C_COEFASRC15_VX_SIZE 0x4C
+#define OMAP_ABE_C_COEFASRC16_VX_ADDR 0xBFC
+#define OMAP_ABE_C_COEFASRC16_VX_SIZE 0x4C
+#define OMAP_ABE_C_ALPHACURRENT_UL_VX_ADDR 0xC48
+#define OMAP_ABE_C_ALPHACURRENT_UL_VX_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_UL_VX_ADDR 0xC4C
+#define OMAP_ABE_C_BETACURRENT_UL_VX_SIZE 0x4
+#define OMAP_ABE_C_ALPHACURRENT_DL_VX_ADDR 0xC50
+#define OMAP_ABE_C_ALPHACURRENT_DL_VX_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_DL_VX_ADDR 0xC54
+#define OMAP_ABE_C_BETACURRENT_DL_VX_SIZE 0x4
+#define OMAP_ABE_C_COEFASRC1_MM_ADDR 0xC58
+#define OMAP_ABE_C_COEFASRC1_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC2_MM_ADDR 0xCA0
+#define OMAP_ABE_C_COEFASRC2_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC3_MM_ADDR 0xCE8
+#define OMAP_ABE_C_COEFASRC3_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC4_MM_ADDR 0xD30
+#define OMAP_ABE_C_COEFASRC4_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC5_MM_ADDR 0xD78
+#define OMAP_ABE_C_COEFASRC5_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC6_MM_ADDR 0xDC0
+#define OMAP_ABE_C_COEFASRC6_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC7_MM_ADDR 0xE08
+#define OMAP_ABE_C_COEFASRC7_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC8_MM_ADDR 0xE50
+#define OMAP_ABE_C_COEFASRC8_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC9_MM_ADDR 0xE98
+#define OMAP_ABE_C_COEFASRC9_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC10_MM_ADDR 0xEE0
+#define OMAP_ABE_C_COEFASRC10_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC11_MM_ADDR 0xF28
+#define OMAP_ABE_C_COEFASRC11_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC12_MM_ADDR 0xF70
+#define OMAP_ABE_C_COEFASRC12_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC13_MM_ADDR 0xFB8
+#define OMAP_ABE_C_COEFASRC13_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC14_MM_ADDR 0x1000
+#define OMAP_ABE_C_COEFASRC14_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC15_MM_ADDR 0x1048
+#define OMAP_ABE_C_COEFASRC15_MM_SIZE 0x48
+#define OMAP_ABE_C_COEFASRC16_MM_ADDR 0x1090
+#define OMAP_ABE_C_COEFASRC16_MM_SIZE 0x48
+#define OMAP_ABE_C_ALPHACURRENT_MM_EXT_IN_ADDR 0x10D8
+#define OMAP_ABE_C_ALPHACURRENT_MM_EXT_IN_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_MM_EXT_IN_ADDR 0x10DC
+#define OMAP_ABE_C_BETACURRENT_MM_EXT_IN_SIZE 0x4
+#define OMAP_ABE_C_DL2_L_COEFS_ADDR 0x10E0
+#define OMAP_ABE_C_DL2_L_COEFS_SIZE 0x64
+#define OMAP_ABE_C_DL2_R_COEFS_ADDR 0x1144
+#define OMAP_ABE_C_DL2_R_COEFS_SIZE 0x64
+#define OMAP_ABE_C_DL1_COEFS_ADDR 0x11A8
+#define OMAP_ABE_C_DL1_COEFS_SIZE 0x64
+#define OMAP_ABE_C_SRC_3_LP_COEFS_ADDR 0x120C
+#define OMAP_ABE_C_SRC_3_LP_COEFS_SIZE 0x34
+#define OMAP_ABE_C_SRC_3_LP_GAIN_COEFS_ADDR 0x1240
+#define OMAP_ABE_C_SRC_3_LP_GAIN_COEFS_SIZE 0x34
+#define OMAP_ABE_C_SRC_3_HP_COEFS_ADDR 0x1274
+#define OMAP_ABE_C_SRC_3_HP_COEFS_SIZE 0x14
+#define OMAP_ABE_C_SRC_6_LP_COEFS_ADDR 0x1288
+#define OMAP_ABE_C_SRC_6_LP_COEFS_SIZE 0x34
+#define OMAP_ABE_C_SRC_6_LP_GAIN_COEFS_ADDR 0x12BC
+#define OMAP_ABE_C_SRC_6_LP_GAIN_COEFS_SIZE 0x34
+#define OMAP_ABE_C_SRC_6_HP_COEFS_ADDR 0x12F0
+#define OMAP_ABE_C_SRC_6_HP_COEFS_SIZE 0x1C
+#define OMAP_ABE_C_ALPHACURRENT_ECHO_REF_ADDR 0x130C
+#define OMAP_ABE_C_ALPHACURRENT_ECHO_REF_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_ECHO_REF_ADDR 0x1310
+#define OMAP_ABE_C_BETACURRENT_ECHO_REF_SIZE 0x4
+#define OMAP_ABE_C_VIBRA2_CONSTS_ADDR 0x1314
+#define OMAP_ABE_C_VIBRA2_CONSTS_SIZE 0x10
+#define OMAP_ABE_C_VIBRA1_COEFFS_ADDR 0x1324
+#define OMAP_ABE_C_VIBRA1_COEFFS_SIZE 0x2C
+#define OMAP_ABE_C_48_96_LP_COEFS_ADDR 0x1350
+#define OMAP_ABE_C_48_96_LP_COEFS_SIZE 0x3C
+#define OMAP_ABE_C_96_48_AMIC_COEFS_ADDR 0x138C
+#define OMAP_ABE_C_96_48_AMIC_COEFS_SIZE 0x4C
+#define OMAP_ABE_C_96_48_DMIC_COEFS_ADDR 0x13D8
+#define OMAP_ABE_C_96_48_DMIC_COEFS_SIZE 0x4C
+#define OMAP_ABE_C_INPUT_SCALE_ADDR 0x1424
+#define OMAP_ABE_C_INPUT_SCALE_SIZE 0x4
+#define OMAP_ABE_C_OUTPUT_SCALE_ADDR 0x1428
+#define OMAP_ABE_C_OUTPUT_SCALE_SIZE 0x4
+#define OMAP_ABE_C_MUTE_SCALING_ADDR 0x142C
+#define OMAP_ABE_C_MUTE_SCALING_SIZE 0x4
+#define OMAP_ABE_C_GAINS_0DB_ADDR 0x1430
+#define OMAP_ABE_C_GAINS_0DB_SIZE 0x8
+#define OMAP_ABE_C_ALPHACURRENT_BT_DL_ADDR 0x1438
+#define OMAP_ABE_C_ALPHACURRENT_BT_DL_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_BT_DL_ADDR 0x143C
+#define OMAP_ABE_C_BETACURRENT_BT_DL_SIZE 0x4
+#define OMAP_ABE_C_ALPHACURRENT_BT_UL_ADDR 0x1440
+#define OMAP_ABE_C_ALPHACURRENT_BT_UL_SIZE 0x4
+#define OMAP_ABE_C_BETACURRENT_BT_UL_ADDR 0x1444
+#define OMAP_ABE_C_BETACURRENT_BT_UL_SIZE 0x4
+#define OMAP_ABE_C_SRC_FIR6_LP_GAIN_COEFS_ADDR 0x1448
+#define OMAP_ABE_C_SRC_FIR6_LP_GAIN_COEFS_SIZE 0x2A0
+#define OMAP_ABE_C_SRC_44P1_COEFS_ADDR 0x16E8
+#define OMAP_ABE_C_SRC_44P1_COEFS_SIZE 0x480
+#define OMAP_ABE_C_SRC_MM_DL_44P1_STEP_ADDR 0x1B68
+#define OMAP_ABE_C_SRC_MM_DL_44P1_STEP_SIZE 0x8
+#define OMAP_ABE_C_SRC_TONES_44P1_STEP_ADDR 0x1B70
+#define OMAP_ABE_C_SRC_TONES_44P1_STEP_SIZE 0x8
+#define OMAP_ABE_C_SRC_44P1_MULFAC2_ADDR 0x1B78
+#define OMAP_ABE_C_SRC_44P1_MULFAC2_SIZE 0x8
+#define OMAP_ABE_C_SRC_FIR12_LP_GAIN_COEFS_ADDR 0x1B80
+#define OMAP_ABE_C_SRC_FIR12_LP_GAIN_COEFS_SIZE 0x1E4
+#define OMAP_ABE_C_SRC_6_HP_NEW_COEFS_ADDR 0x1D64
+#define OMAP_ABE_C_SRC_6_HP_NEW_COEFS_SIZE 0x1C
diff --git a/sound/soc/omap/abe/abe_core.c b/sound/soc/omap/abe/abe_core.c
new file mode 100644
index 0000000..7a9ae11
--- /dev/null
+++ b/sound/soc/omap/abe/abe_core.c
@@ -0,0 +1,929 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dbg.h"
+#include "abe.h"
+#include "abe_gain.h"
+#include "abe_aess.h"
+#include "abe_port.h"
+#include "abe_mem.h"
+#include "abe_taskid.h"
+
+#define OMAP_ABE_IRQ_FIFO_MASK ((OMAP_ABE_D_MCUIRQFIFO_SIZE >> 2) - 1)
+
+void abe_init_asrc_vx_dl(s32 dppm);
+void abe_init_asrc_vx_ul(s32 dppm);
+void abe_init_asrc_mm_ext_in(s32 dppm);
+void abe_init_asrc_bt_ul(s32 dppm);
+void abe_init_asrc_bt_dl(s32 dppm);
+
+void abe_src_filters_saturation_monitoring(void);
+void abe_irq_aps(u32 aps_info);
+void abe_irq_ping_pong(void);
+void abe_irq_check_for_sequences(u32 seq_info);
+extern u32 abe_size_pingpong;
+extern u32 abe_base_address_pingpong[];
+
+void abe_add_subroutine(u32 *id, abe_subroutine2 f, u32 nparam, u32 *params);
+
+
+/**
+ * abe_omap_abe_reset_hal - reset the ABE/HAL
+ * @abe: Pointer on abe handle
+ *
+ * Operations : reset the ABE by reloading the static variables and
+ * default AESS registers.
+ * Called after a PRCM cold-start reset of ABE
+ */
+int omap_abe_reset_hal(struct omap_abe *abe)
+{
+ u32 i;
+
+ omap_abe_dbg_reset(&abe->dbg);
+
+ _log(ABE_ID_RESET_HAL, 0, 0, 0);
+
+ /* IRQ & DBG circular read pointer in DMEM */
+ abe->irq_dbg_read_ptr = 0;
+
+ /* default = disable the mixer's adaptive gain control */
+ omap_abe_use_compensated_gain(abe, 0);
+
+ /* reset the default gain values */
+ for (i = 0; i < MAX_NBGAIN_CMEM; i++) {
+ abe->muted_gains_indicator[i] = 0;
+ abe->desired_gains_decibel[i] = (u32) GAIN_MUTE;
+ abe->desired_gains_linear[i] = 0;
+ abe->desired_ramp_delay_ms[i] = 0;
+ abe->muted_gains_decibel[i] = (u32) GAIN_TOOLOW;
+ }
+ omap_abe_hw_configuration(abe);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_hal);
+
+/**
+ * omap_abe_wakeup - Wakeup ABE
+ * @abe: Pointer on abe handle
+ *
+ * Wakeup ABE in case of retention
+ */
+int omap_abe_wakeup(struct omap_abe *abe)
+{
+ /* Restart event generator */
+ omap_abe_write_event_generator(abe, EVENT_TIMER);
+
+ /* reconfigure DMA Req and MCU Irq visibility */
+ omap_abe_hw_configuration(abe);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_wakeup);
+
+/**
+ * abe_monitoring
+ *
+ * checks the internal status of ABE and HAL
+ */
+void abe_monitoring(void)
+{
+
+}
+
+/**
+ * omap_abe_irq_processing - Process ABE interrupt
+ * @abe: Pointer on abe handle
+ *
+ * This subroutine is call upon reception of "MA_IRQ_99 ABE_MPU_IRQ" Audio
+ * back-end interrupt. This subroutine will check the ATC Hrdware, the
+ * IRQ_FIFO from the AE and act accordingly. Some IRQ source are originated
+ * for the delivery of "end of time sequenced tasks" notifications, some are
+ * originated from the Ping-Pong protocols, some are generated from
+ * the embedded debugger when the firmware stops on programmable break-points,
+ * etc ...
+ */
+int omap_abe_irq_processing(struct omap_abe *abe)
+{
+ u32 abe_irq_dbg_write_ptr, i, cmem_src, sm_cm;
+ abe_irq_data_t IRQ_data;
+
+ _log(ABE_ID_IRQ_PROCESSING, 0, 0, 0);
+
+ /* extract the write pointer index from CMEM memory (INITPTR format) */
+ /* CMEM address of the write pointer in bytes */
+ cmem_src = MCU_IRQ_FIFO_ptr_labelID << 2;
+ omap_abe_mem_read(abe, OMAP_ABE_CMEM, cmem_src,
+ &sm_cm, sizeof(abe_irq_dbg_write_ptr));
+ /* AESS left-pointer index located on MSBs */
+ abe_irq_dbg_write_ptr = sm_cm >> 16;
+ abe_irq_dbg_write_ptr &= 0xFF;
+ /* loop on the IRQ FIFO content */
+ for (i = 0; i < OMAP_ABE_D_MCUIRQFIFO_SIZE; i++) {
+ /* stop when the FIFO is empty */
+ if (abe_irq_dbg_write_ptr == abe->irq_dbg_read_ptr)
+ break;
+ /* read the IRQ/DBG FIFO */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ (OMAP_ABE_D_MCUIRQFIFO_ADDR +
+ (abe->irq_dbg_read_ptr << 2)),
+ (u32 *) &IRQ_data, sizeof(IRQ_data));
+ abe->irq_dbg_read_ptr = (abe->irq_dbg_read_ptr + 1) & OMAP_ABE_IRQ_FIFO_MASK;
+ /* select the source of the interrupt */
+ switch (IRQ_data.tag) {
+ case IRQtag_APS:
+ _log(ABE_ID_IRQ_PROCESSING, IRQ_data.data, 0, 1);
+ abe_irq_aps(IRQ_data.data);
+ break;
+ case IRQtag_PP:
+ _log(ABE_ID_IRQ_PROCESSING, 0, 0, 2);
+ abe_irq_ping_pong();
+ break;
+ case IRQtag_COUNT:
+ _log(ABE_ID_IRQ_PROCESSING, IRQ_data.data, 0, 3);
+ abe_irq_check_for_sequences(IRQ_data.data);
+ abe_monitoring();
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_irq_processing);
+
+/**
+ * oamp_abe_set_ping_pong_buffer
+ * @abe: Pointer on abe handle
+ * @port: ABE port ID
+ * @n_bytes: Size of Ping/Pong buffer
+ *
+ * Updates the next ping-pong buffer with "size" bytes copied from the
+ * host processor. This API notifies the FW that the data transfer is done.
+ */
+int omap_abe_set_ping_pong_buffer(struct omap_abe *abe, u32 port, u32 n_bytes)
+{
+ u32 sio_pp_desc_address, struct_offset, n_samples, datasize,
+ base_and_size, *src;
+ struct ABE_SPingPongDescriptor desc_pp;
+
+ _log(ABE_ID_SET_PING_PONG_BUFFER, port, n_bytes, n_bytes >> 8);
+
+ /* ping_pong is only supported on MM_DL */
+ if (port != OMAP_ABE_MM_DL_PORT) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+ /* translates the number of bytes in samples */
+ /* data size in DMEM words */
+ datasize = omap_abe_dma_port_iter_factor((struct omap_abe_data_format *)&((abe_port[port]).format));
+ /* data size in bytes */
+ datasize = datasize << 2;
+ n_samples = n_bytes / datasize;
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, OMAP_ABE_D_PINGPONGDESC_ADDR,
+ (u32 *) &desc_pp, sizeof(desc_pp));
+ /*
+ * read the port SIO descriptor and extract the current pointer
+ * address after reading the counter
+ */
+ if ((desc_pp.counter & 0x1) == 0) {
+ struct_offset = (u32) &(desc_pp.nextbuff0_BaseAddr) -
+ (u32) &(desc_pp);
+ base_and_size = desc_pp.nextbuff0_BaseAddr;
+ } else {
+ struct_offset = (u32) &(desc_pp.nextbuff1_BaseAddr) -
+ (u32) &(desc_pp);
+ base_and_size = desc_pp.nextbuff1_BaseAddr;
+ }
+
+ base_and_size = abe->pp_buf_addr[abe->pp_buf_id_next];
+ abe->pp_buf_id_next = (abe->pp_buf_id_next + 1) & 0x03;
+
+ base_and_size = (base_and_size & 0xFFFFL) + (n_samples << 16);
+ sio_pp_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR + struct_offset;
+ src = &base_and_size;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, sio_pp_desc_address,
+ (u32 *) &base_and_size, sizeof(u32));
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_set_ping_pong_buffer);
+
+/**
+ * omap_abe_read_next_ping_pong_buffer
+ * @abe: Pointer on abe handle
+ * @port: ABE portID
+ * @p: Next buffer address (pointer)
+ * @n: Next buffer size (pointer)
+ *
+ * Tell the next base address of the next ping_pong Buffer and its size
+ */
+int omap_abe_read_next_ping_pong_buffer(struct omap_abe *abe, u32 port, u32 *p, u32 *n)
+{
+ u32 sio_pp_desc_address;
+ struct ABE_SPingPongDescriptor desc_pp;
+
+ _log(ABE_ID_READ_NEXT_PING_PONG_BUFFER, port, 0, 0);
+
+ /* ping_pong is only supported on MM_DL */
+ if (port != OMAP_ABE_MM_DL_PORT) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+ /* read the port SIO descriptor and extract the current pointer
+ address after reading the counter */
+ sio_pp_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR;
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, sio_pp_desc_address,
+ (u32 *) &desc_pp, sizeof(struct ABE_SPingPongDescriptor));
+ if ((desc_pp.counter & 0x1) == 0) {
+ _log(ABE_ID_READ_NEXT_PING_PONG_BUFFER, port, 0, 0);
+ *p = desc_pp.nextbuff0_BaseAddr;
+ } else {
+ _log(ABE_ID_READ_NEXT_PING_PONG_BUFFER, port, 1, 0);
+ *p = desc_pp.nextbuff1_BaseAddr;
+ }
+ /* translates the number of samples in bytes */
+ *n = abe_size_pingpong;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_read_next_ping_pong_buffer);
+
+/**
+ * omap_abe_init_ping_pong_buffer
+ * @abe: Pointer on abe handle
+ * @id: ABE port ID
+ * @size_bytes:size of the ping pong
+ * @n_buffers:number of buffers (2 = ping/pong)
+ * @p:returned address of the ping-pong list of base addresses
+ * (byte offset from DMEM start)
+ *
+ * Computes the base address of the ping_pong buffers
+ */
+int omap_abe_init_ping_pong_buffer(struct omap_abe *abe,
+ u32 id, u32 size_bytes, u32 n_buffers,
+ u32 *p)
+{
+ u32 i, dmem_addr;
+
+ _log(ABE_ID_INIT_PING_PONG_BUFFER, id, size_bytes, n_buffers);
+
+ /* ping_pong is supported in 2 buffers configuration right now but FW
+ is ready for ping/pong/pung/pang... */
+ if (id != OMAP_ABE_MM_DL_PORT || n_buffers > MAX_PINGPONG_BUFFERS) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+ for (i = 0; i < n_buffers; i++) {
+ dmem_addr = OMAP_ABE_D_PING_ADDR + (i * size_bytes);
+ /* base addresses of the ping pong buffers in U8 unit */
+ abe_base_address_pingpong[i] = dmem_addr;
+ }
+
+ for (i = 0; i < 4; i++)
+ abe->pp_buf_addr[i] = OMAP_ABE_D_PING_ADDR + (i * size_bytes);
+ abe->pp_buf_id = 0;
+ abe->pp_buf_id_next = 0;
+ abe->pp_first_irq = 1;
+
+ /* global data */
+ abe_size_pingpong = size_bytes;
+ *p = (u32) OMAP_ABE_D_PING_ADDR;
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_init_ping_pong_buffer);
+
+/**
+ * omap_abe_read_offset_from_ping_buffer
+ * @abe: Pointer on abe handle
+ * @id: ABE port ID
+ * @n: returned address of the offset
+ * from the ping buffer start address (in samples)
+ *
+ * Computes the current firmware ping pong read pointer location,
+ * expressed in samples, as the offset from the start address of ping buffer.
+ */
+int omap_abe_read_offset_from_ping_buffer(struct omap_abe *abe,
+ u32 id, u32 *n)
+{
+ u32 sio_pp_desc_address;
+ struct ABE_SPingPongDescriptor desc_pp;
+
+ /* ping_pong is only supported on MM_DL */
+ if (OMAP_ABE_MM_DL_PORT != id) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ } else {
+ /* read the port SIO ping pong descriptor */
+ sio_pp_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR;
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ sio_pp_desc_address, (u32 *) &desc_pp,
+ sizeof(struct ABE_SPingPongDescriptor));
+ /* extract the current ping pong buffer read pointer based on
+ the value of the counter */
+ if ((desc_pp.counter & 0x1) == 0) {
+ /* the next is buffer0, hence the current is buffer1 */
+ *n = desc_pp.nextbuff1_Samples -
+ desc_pp.workbuff_Samples;
+ } else {
+ /* the next is buffer1, hence the current is buffer0 */
+ *n = desc_pp.nextbuff0_Samples -
+ desc_pp.workbuff_Samples;
+ }
+ switch (abe_port[OMAP_ABE_MM_DL_PORT].format.samp_format) {
+ case MONO_MSB:
+ case MONO_RSHIFTED_16:
+ case STEREO_16_16:
+ *n += abe->pp_buf_id * abe_size_pingpong / 4;
+ break;
+ case STEREO_MSB:
+ case STEREO_RSHIFTED_16:
+ *n += abe->pp_buf_id * abe_size_pingpong / 8;
+ break;
+ default:
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_read_offset_from_ping_buffer);
+
+/**
+ * abe_set_router_configuration
+ * @Id: name of the router
+ * @Conf: id of the configuration
+ * @param: list of output index of the route
+ *
+ * The uplink router takes its input from DMIC (6 samples), AMIC (2 samples)
+ * and PORT1/2 (2 stereo ports). Each sample will be individually stored in
+ * an intermediate table of 10 elements.
+ *
+ * Example of router table parameter for voice uplink with phoenix microphones
+ *
+ * indexes 0 .. 9 = MM_UL description (digital MICs and MMEXTIN)
+ * DMIC1_L_labelID, DMIC1_R_labelID, DMIC2_L_labelID, DMIC2_R_labelID,
+ * MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID, ZERO_labelID, ZERO_labelID,
+ * ZERO_labelID, ZERO_labelID,
+ * indexes 10 .. 11 = MM_UL2 description (recording on DMIC3)
+ * DMIC3_L_labelID, DMIC3_R_labelID,
+ * indexes 12 .. 13 = VX_UL description (VXUL based on PDMUL data)
+ * AMIC_L_labelID, AMIC_R_labelID,
+ * indexes 14 .. 15 = RESERVED (NULL)
+ * ZERO_labelID, ZERO_labelID,
+ */
+int omap_abe_set_router_configuration(struct omap_abe *abe,
+ u32 id, u32 k, u32 *param)
+{
+ _log(ABE_ID_SET_ROUTER_CONFIGURATION, id, (u32) param, (u32) param >> 8);
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_AUPLINKROUTING_ADDR,
+ param, OMAP_ABE_D_AUPLINKROUTING_SIZE);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_set_router_configuration);
+
+/**
+ * abe_set_opp_processing - Set OPP mode for ABE Firmware
+ * @opp: OOPP mode
+ *
+ * New processing network and OPP:
+ * 0: Ultra Lowest power consumption audio player (no post-processing, no mixer)
+ * 1: OPP 25% (simple multimedia features, including low-power player)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% ( multimedia complex use-cases)
+ *
+ * Rearranges the FW task network to the corresponding OPP list of features.
+ * The corresponding AE ports are supposed to be set/reset accordingly before
+ * this switch.
+ *
+ */
+int omap_abe_set_opp_processing(struct omap_abe *abe, u32 opp)
+{
+ u32 dOppMode32, sio_desc_address;
+ struct ABE_SIODescriptor sio_desc;
+
+ _log(ABE_ID_SET_OPP_PROCESSING, opp, 0, 0);
+
+ switch (opp) {
+ case ABE_OPP25:
+ /* OPP25% */
+ dOppMode32 = DOPPMODE32_OPP25;
+ break;
+ case ABE_OPP50:
+ /* OPP50% */
+ dOppMode32 = DOPPMODE32_OPP50;
+ break;
+ default:
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_BLOCK_COPY_ERR);
+ case ABE_OPP100:
+ /* OPP100% */
+ dOppMode32 = DOPPMODE32_OPP100;
+ break;
+ }
+ /* Write Multiframe inside DMEM */
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MAXTASKBYTESINSLOT_ADDR, &dOppMode32, sizeof(u32));
+
+#if 0
+ /* Disable BT / MM Ext ASRC dynamic switch */
+
+ sio_desc_address = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_MM_EXT_IN_PORT *
+ sizeof(struct ABE_SIODescriptor));
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ /* ASRC input buffer, size 40 */
+ sio_desc.smem_addr1 = smem_mm_ext_in_opp100;
+ /* Init MM_EXT_IN ASRC and enable its adaptation */
+ abe_init_asrc_mm_ext_in(250);
+ } else
+ /* at OPP 50 or without ASRC */
+ sio_desc.smem_addr1 = smem_mm_ext_in_opp50;
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+
+ sio_desc_address = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_BT_VX_UL_PORT *
+ sizeof(struct ABE_SIODescriptor));
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+
+ if (abe_port[OMAP_ABE_BT_VX_UL_PORT].format.f == 8000) {
+ if (dOppMode32 == DOPPMODE32_OPP100)
+ /* ASRC input buffer, size 40 */
+ sio_desc.smem_addr1 = smem_bt_vx_ul_opp100;
+ else
+ /* at OPP 50 without ASRC */
+ sio_desc.smem_addr1 = BT_UL_8k_labelID;
+ } else {
+ if (dOppMode32 == DOPPMODE32_OPP100)
+ /* ASRC input buffer, size 40 */
+ sio_desc.smem_addr1 = smem_bt_vx_ul_opp100;
+ else
+ /* at OPP 50 without ASRC */
+ sio_desc.smem_addr1 = BT_UL_16k_labelID;
+ }
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+
+ sio_desc_address = OMAP_ABE_D_IODESCR_ADDR + (OMAP_ABE_BT_VX_DL_PORT *
+ sizeof(struct ABE_SIODescriptor));
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+
+#define ABE_TASK_ID(ID) (OMAP_ABE_D_TASKSLIST_ADDR + sizeof(ABE_STask)*(ID))
+#define TASK_BT_DL_48_8_SLT 14
+#define TASK_BT_DL_48_8_IDX 4
+ if (abe_port[OMAP_ABE_BT_VX_DL_PORT].format.f == 8000) {
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_8_FIR_OPP100);
+ sio_desc.smem_addr1 = BT_DL_8k_opp100_labelID;
+ } else {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_8_FIR);
+ sio_desc.smem_addr1 = BT_DL_8k_labelID;
+ }
+ } else {
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_16_OPP100);
+ sio_desc.smem_addr1 = BT_DL_16k_opp100_labelID;
+ } else {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_16);
+ sio_desc.smem_addr1 = BT_DL_16k_labelID;
+ }
+ }
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_MULTIFRAME_ADDR,
+ (u32 *) abe->MultiFrame, sizeof(abe->MultiFrame));
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, sio_desc_address,
+ (u32 *) &sio_desc, sizeof(sio_desc));
+
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ /* Init BT_VX_UL ASRC and enable its adaptation */
+ abe_init_asrc_bt_ul(250);
+ /* Init BT_VX_DL ASRC and enable its adaptation */
+ abe_init_asrc_bt_dl(-250);
+ }
+#endif
+ return 0;
+
+}
+EXPORT_SYMBOL(omap_abe_set_opp_processing);
+
+/**
+ * omap_abe_reset_vx_ul_src_filters - reset VX-UL port SRC filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_vx_ul_src_filters(struct omap_abe *abe)
+{
+ if (abe_port[OMAP_ABE_VX_UL_PORT].format.f == 8000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_8_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_8_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_8_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_8_HP_DATA_SIZE);
+ } else if (abe_port[OMAP_ABE_VX_UL_PORT].format.f == 16000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_16_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_16_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_16_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_16_HP_DATA_SIZE);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_vx_ul_src_filters);
+
+/**
+ * omap_abe_reset_mic_ul_src_filters - reset AMIC or DMICs or BT UL SRC filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_mic_ul_src_filters(struct omap_abe *abe)
+{
+ u16 vx[NBROUTE_UL];
+
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_AUPLINKROUTING_ADDR,
+ (u32 *)vx, OMAP_ABE_D_AUPLINKROUTING_SIZE);
+
+ switch (vx[12]) {
+ case ZERO_labelID:
+ /* no MIC used */
+ return 0;
+ case DMIC1_L_labelID:
+ case DMIC1_R_labelID:
+ /* DMIC0 used */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC0_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC0_96_48_DATA_SIZE);
+ break;
+ case DMIC2_L_labelID:
+ case DMIC2_R_labelID:
+ /* DMIC1 used */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC1_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC1_96_48_DATA_SIZE);
+ break;
+ case DMIC3_L_labelID:
+ case DMIC3_R_labelID:
+ /* DMIC2 used */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC2_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC2_96_48_DATA_SIZE);
+ break;
+ case BT_UL_L_labelID:
+ case BT_UL_R_labelID:
+ /* BT MIC used */
+ if (abe_port[OMAP_ABE_BT_VX_UL_PORT].format.f == 8000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_8_48_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_8_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_8_48_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_8_48_LP_DATA_SIZE);
+ } else if (abe_port[OMAP_ABE_BT_VX_UL_PORT].format.f == 16000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_16_48_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_16_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_16_48_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_16_48_LP_DATA_SIZE);
+ }
+ break;
+ case AMIC_L_labelID:
+ case AMIC_R_labelID:
+ /* AMIC used */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_AMIC_96_48_DATA_ADDR,
+ OMAP_ABE_S_AMIC_96_48_DATA_SIZE);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_mic_ul_src_filters);
+
+/**
+ * omap_abe_reset_vx_dl_src_filters - reset VX-DL port SRC filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_vx_dl_src_filters(struct omap_abe *abe)
+{
+ if (abe_port[OMAP_ABE_VX_DL_PORT].format.f == 8000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_8_48_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_8_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_8_48_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_8_48_LP_DATA_SIZE);
+ } else if (abe_port[OMAP_ABE_VX_DL_PORT].format.f == 16000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_16_48_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_16_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_16_48_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_16_48_LP_DATA_SIZE);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_vx_dl_src_filters);
+
+/**
+ * omap_abe_reset_dl1_src_filters - reset DL1 path filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_dl1_src_filters(struct omap_abe *abe)
+{
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DL1_M_EQ_DATA_ADDR,
+ OMAP_ABE_S_DL1_M_EQ_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_EARP_48_96_LP_DATA_ADDR,
+ OMAP_ABE_S_EARP_48_96_LP_DATA_SIZE);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_dl1_src_filters);
+
+/**
+ * omap_abe_reset_dl2_src_filters - reset DL2 path filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_dl2_src_filters(struct omap_abe *abe)
+{
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DL2_M_LR_EQ_DATA_ADDR,
+ OMAP_ABE_S_DL2_M_LR_EQ_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_IHF_48_96_LP_DATA_ADDR,
+ OMAP_ABE_S_IHF_48_96_LP_DATA_SIZE);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_dl2_src_filters);
+
+/**
+ * omap_abe_reset_bt_dl_src_filters - reset bluetooth DL SRC path filters
+ *
+ * it is assumed that filters are located in SMEM
+ */
+int omap_abe_reset_bt_dl_src_filters(struct omap_abe *abe)
+{
+ if (abe_port[OMAP_ABE_BT_VX_DL_PORT].format.f == 8000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_8_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_8_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_8_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_8_HP_DATA_SIZE);
+ } else if (abe_port[OMAP_ABE_BT_VX_DL_PORT].format.f == 16000) {
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_16_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_16_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_16_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_16_HP_DATA_SIZE);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reset_bt_dl_src_filters);
+
+/**
+ * abe_check_filter_is_saturating
+ * @abe: pointer to omap_abe struct
+ * @address: filter address
+ * @size: filter size in byte
+ *
+ * Check if filter is saturating
+ * it is assumed that filter is located in SMEM
+ * if saturated return 1 otherwise 0.
+ */
+int abe_check_filter_is_saturating(struct omap_abe *abe, u32 address, u32 size)
+{
+ /* largest buffer size among all filter buffers in SMEM */
+ u32 filter[OMAP_ABE_S_XINASRC_UL_VX_SIZE >> 2];
+ int found = 0, i = 0;
+
+ omap_abe_mem_read(abe, ABE_SMEM, address, filter, size);
+
+ size >>= 2;
+ while ((i < size) && (filter[i] < 0x700000 || filter[i] > 0x900000))
+ i++;
+
+ if (i < size)
+ found = 1;
+
+ return found;
+}
+
+/**
+ * abe_ul_src_filters_saturation_monitoring - monitor ABE UL SRC filters and
+ * check if some are saturating, if it's the case then reset these filters.
+ *
+ * it is assumed that filter is located in SMEM
+ */
+void abe_ul_src_filters_saturation_monitoring(struct omap_abe *abe)
+{
+ int saturating = 0;
+ u16 vx[NBROUTE_UL];
+
+ omap_abe_mem_read(abe, ABE_DMEM,
+ OMAP_ABE_D_AUPLINKROUTING_ADDR,
+ (u32 *)vx, OMAP_ABE_D_AUPLINKROUTING_SIZE);
+
+ switch (vx[12]) {
+ case ZERO_labelID:
+ /* no MIC used */
+ return;
+ case DMIC1_L_labelID:
+ case DMIC1_R_labelID:
+ /* DMIC0 used */
+ saturating = abe_check_filter_is_saturating(abe,
+ OMAP_ABE_S_DMIC1_ADDR,
+ OMAP_ABE_S_DMIC1_SIZE);
+ break;
+ case DMIC2_L_labelID:
+ case DMIC2_R_labelID:
+ /* DMIC1 used */
+ saturating = abe_check_filter_is_saturating(abe,
+ OMAP_ABE_S_DMIC2_ADDR,
+ OMAP_ABE_S_DMIC2_SIZE);
+ break;
+ case DMIC3_L_labelID:
+ case DMIC3_R_labelID:
+ /* DMIC2 used */
+ saturating = abe_check_filter_is_saturating(abe,
+ OMAP_ABE_S_DMIC3_ADDR,
+ OMAP_ABE_S_DMIC3_SIZE);
+ break;
+ case BT_UL_L_labelID:
+ case BT_UL_R_labelID:
+ /* BT MIC used */
+ saturating = abe_check_filter_is_saturating(abe,
+ OMAP_ABE_S_BT_UL_ADDR,
+ OMAP_ABE_S_BT_UL_SIZE);
+ break;
+ case AMIC_L_labelID:
+ case AMIC_R_labelID:
+ /* AMIC used */
+ saturating = abe_check_filter_is_saturating(abe,
+ OMAP_ABE_S_AMIC_ADDR,
+ OMAP_ABE_S_AMIC_SIZE);
+ break;
+ default:
+ return;
+ }
+
+ if (saturating) {
+ omap_abe_reset_mic_ul_src_filters(abe);
+ omap_abe_reset_vx_ul_src_filters(abe);
+ }
+}
+
+/**
+ * abe_vx_dl_src_filters_saturation_monitoring - monitor ABE VX-DL SRC filters and
+ * check if some are saturating, if it's the case then reset these filters.
+ *
+ * it is assumed that filter is located in SMEM
+ */
+void abe_vx_dl_src_filters_saturation_monitoring(struct omap_abe *abe)
+{
+ if (abe_check_filter_is_saturating(abe, OMAP_ABE_S_VX_DL_ADDR,
+ OMAP_ABE_S_VX_DL_SIZE)) {
+ omap_abe_reset_vx_dl_src_filters(abe);
+ omap_abe_reset_dl1_src_filters(abe);
+ omap_abe_reset_dl2_src_filters(abe);
+ }
+
+ if (abe_check_filter_is_saturating(abe, OMAP_ABE_S_BT_DL_ADDR,
+ OMAP_ABE_S_BT_DL_SIZE))
+ omap_abe_reset_bt_dl_src_filters(abe);
+}
+
+/**
+ * abe_src_filters_saturation_monitoring - monitor ABE SRC filters and
+ * check if some are saturating, if it's the case then reset these filters.
+ *
+ * it is assumed that filter is located in SMEM
+ */
+void omap_abe_src_filters_saturation_monitoring(struct omap_abe *abe)
+{
+ abe_ul_src_filters_saturation_monitoring(abe);
+ abe_vx_dl_src_filters_saturation_monitoring(abe);
+}
+
+/**
+ * omap_abe_check_activity - Check if some ABE activity.
+ *
+ * Check if any ABE ports are running.
+ * return 1: still activity on ABE
+ * return 0: no more activity on ABE. Event generator can be stopped
+ *
+ */
+int omap_abe_check_activity(struct omap_abe *abe)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < (LAST_PORT_ID - 1); i++) {
+ if (abe_port[abe_port_priority[i]].status ==
+ OMAP_ABE_PORT_ACTIVITY_RUNNING)
+ break;
+ }
+ if (i < (LAST_PORT_ID - 1))
+ ret = 1;
+ return ret;
+}
+EXPORT_SYMBOL(omap_abe_check_activity);
+
+/**
+ * abe_plug_subroutine
+ * @id: returned sequence index after plugging a new subroutine
+ * @f: subroutine address to be inserted
+ * @n: number of parameters of this subroutine
+ * @params: pointer on parameters
+ *
+ * register a list of subroutines for call-back purpose
+ */
+abehal_status abe_plug_subroutine(u32 *id, abe_subroutine2 f, u32 n,
+ u32 *params)
+{
+ _log(ABE_ID_PLUG_SUBROUTINE, (u32) (*id), (u32) f, n);
+
+ abe_add_subroutine(id, (abe_subroutine2) f, n, (u32 *) params);
+ return 0;
+}
+EXPORT_SYMBOL(abe_plug_subroutine);
diff --git a/sound/soc/omap/abe/abe_dat.c b/sound/soc/omap/abe/abe_dat.c
new file mode 100644
index 0000000..0111bae
--- /dev/null
+++ b/sound/soc/omap/abe/abe_dat.c
@@ -0,0 +1,458 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "abe_legacy.h"
+
+struct omap_abe *abe;
+
+/*
+ * HAL/FW ports status / format / sampling / protocol(call_back) / features
+ * / gain / name
+ */
+abe_port_t abe_port[LAST_PORT_ID]; /* list of ABE ports */
+const abe_port_t abe_port_init[LAST_PORT_ID] = {
+ /* Status Data Format Drift Call-Back Protocol+selector desc_addr;
+ buf_addr; buf_size; iter; irq_addr irq_data DMA_T $Features
+ reseted at start Port Name for the debug trace */
+ /* DMIC */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {96000, SIX_MSB},
+ NODRIFT, NOCALLBACK, 1, (DMIC_ITER/6),
+ {
+ SNK_P, DMIC_PORT_PROT,
+ {{dmem_dmic, dmem_dmic_size, DMIC_ITER} }
+ },
+ {0, 0},
+ {EQDMIC, 0}, "DMIC"},
+ /* PDM_UL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {96000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_amic, (MCPDM_UL_ITER/2),
+ {
+ SNK_P, MCPDMUL_PORT_PROT,
+ {{dmem_amic, dmem_amic_size, MCPDM_UL_ITER} }
+ },
+ {0, 0},
+ {EQAMIC, 0}, "PDM_UL"},
+ /* BT_VX_UL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {8000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_bt_vx_ul_opp50, 1,
+ {
+ SNK_P, SERIAL_PORT_PROT, {{
+ (MCBSP1_DMA_TX*ATC_SIZE),
+ dmem_bt_vx_ul,
+ dmem_bt_vx_ul_size,
+ (1*SCHED_LOOP_8kHz)
+ } }
+ },
+ {0, 0}, {0}, "BT_VX_UL"},
+ /* MM_UL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_mm_ul, 1,
+ {
+ SRC_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX3*ATC_SIZE),
+ dmem_mm_ul, dmem_mm_ul_size,
+ (10*SCHED_LOOP_48kHz),
+ ABE_DMASTATUS_RAW, (1 << 3)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__3, 120},
+ {UPROUTE, 0}, "MM_UL"},
+ /* MM_UL2 */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_mm_ul2, 1,
+ {
+ SRC_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX4*ATC_SIZE),
+ dmem_mm_ul2, dmem_mm_ul2_size,
+ (2*SCHED_LOOP_48kHz),
+ ABE_DMASTATUS_RAW, (1 << 4)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__4, 24},
+ {UPROUTE, 0}, "MM_UL2"},
+ /* VX_UL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {8000, MONO_MSB},
+ NODRIFT, NOCALLBACK, smem_vx_ul, 1,
+ {
+ SRC_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX2*ATC_SIZE),
+ dmem_vx_ul, dmem_vx_ul_size,
+ (1*SCHED_LOOP_8kHz),
+ ABE_DMASTATUS_RAW, (1 << 2)
+ } }
+ }, {
+ CIRCULAR_BUFFER_PERIPHERAL_R__2, 2},
+ {ASRC2, 0}, "VX_UL"},
+ /* MM_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_mm_dl, 1,
+ {
+ SNK_P, PINGPONG_PORT_PROT, {{
+ (CBPr_DMA_RTX0*ATC_SIZE),
+ dmem_mm_dl, dmem_mm_dl_size,
+ (2*SCHED_LOOP_48kHz),
+ ABE_DMASTATUS_RAW, (1 << 0)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__0, 24},
+ {ASRC3, 0}, "MM_DL"},
+ /* VX_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {8000, MONO_MSB},
+ NODRIFT, NOCALLBACK, smem_vx_dl, 1,
+ {
+ SNK_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX1*ATC_SIZE),
+ dmem_vx_dl, dmem_vx_dl_size,
+ (1*SCHED_LOOP_8kHz),
+ ABE_DMASTATUS_RAW, (1 << 1)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__1, 2},
+ {ASRC1, 0}, "VX_DL"},
+ /* TONES_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_tones_dl, 1,
+ {
+ SNK_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX5*ATC_SIZE),
+ dmem_tones_dl,
+ dmem_tones_dl_size,
+ (2*SCHED_LOOP_48kHz),
+ ABE_DMASTATUS_RAW, (1 << 5)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__5, 24},
+ {0}, "TONES_DL"},
+ /* VIB_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {24000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_vib, 1,
+ {
+ SNK_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX6*ATC_SIZE),
+ dmem_vib_dl, dmem_vib_dl_size,
+ (2*SCHED_LOOP_24kHz),
+ ABE_DMASTATUS_RAW, (1 << 6)
+ } }
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__6, 12},
+ {0}, "VIB_DL"},
+ /* BT_VX_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {8000, MONO_MSB},
+ NODRIFT, NOCALLBACK, smem_bt_vx_dl_opp50, 1,
+ {
+ SRC_P, SERIAL_PORT_PROT, {{
+ (MCBSP1_DMA_RX*ATC_SIZE),
+ dmem_bt_vx_dl,
+ dmem_bt_vx_dl_size,
+ (1*SCHED_LOOP_8kHz),
+ } }
+ },
+ {0, 0}, {0}, "BT_VX_DL"},
+ /* PDM_DL */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {96000, SIX_MSB},
+ NODRIFT, NOCALLBACK, 1, (MCPDM_DL_ITER/6),
+ {SRC_P, MCPDMDL_PORT_PROT, {{dmem_mcpdm,
+ dmem_mcpdm_size} } },
+ {0, 0},
+ {MIXDL1, EQ1, APS1, MIXDL2, EQ2L, EQ2R, APS2L, APS2R, 0},
+ "PDM_DL"},
+ /* MM_EXT_OUT */
+ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_mm_ext_out, 1,
+ {
+ SRC_P, SERIAL_PORT_PROT, {{
+ (MCBSP1_DMA_TX*ATC_SIZE),
+ dmem_mm_ext_out, dmem_mm_ext_out_size,
+ (2*SCHED_LOOP_48kHz)
+ } }
+ }, {0, 0}, {0}, "MM_EXT_OUT"},
+ /* MM_EXT_IN */
+ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, smem_mm_ext_in_opp100, 1,
+ {
+ SNK_P, SERIAL_PORT_PROT, {{
+ (MCBSP1_DMA_RX*ATC_SIZE),
+ dmem_mm_ext_in, dmem_mm_ext_in_size,
+ (2*SCHED_LOOP_48kHz)
+ } }
+ },
+ {0, 0}, {0}, "MM_EXT_IN"},
+ /* PCM3_TX */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, 1, 1,
+ {
+ SRC_P, TDM_SERIAL_PORT_PROT, {{
+ (MCBSP3_DMA_TX *
+ ATC_SIZE),
+ dmem_mm_ext_out,
+ dmem_mm_ext_out_size,
+ (2*SCHED_LOOP_48kHz)
+ } }
+ },
+ {0, 0}, {0}, "TDM_OUT"},
+ /* PCM3_RX */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, STEREO_MSB},
+ NODRIFT, NOCALLBACK, 1, 1,
+ {
+ SRC_P, TDM_SERIAL_PORT_PROT, {{
+ (MCBSP3_DMA_RX *
+ ATC_SIZE),
+ dmem_mm_ext_in,
+ dmem_mm_ext_in_size,
+ (2*SCHED_LOOP_48kHz)
+ } }
+ },
+ {0, 0}, {0}, "TDM_IN"},
+ /* SCHD_DBG_PORT */ {
+ OMAP_ABE_PORT_ACTIVITY_IDLE, {48000, MONO_MSB},
+ NODRIFT, NOCALLBACK, 1, 1,
+ {
+ SRC_P, DMAREQ_PORT_PROT, {{
+ (CBPr_DMA_RTX7 *
+ ATC_SIZE),
+ dmem_mm_trace,
+ dmem_mm_trace_size,
+ (2*SCHED_LOOP_48kHz),
+ ABE_DMASTATUS_RAW,
+ (1 << 4)
+ } }
+ }, {CIRCULAR_BUFFER_PERIPHERAL_R__7, 24},
+ {FEAT_SEQ, FEAT_CTL, FEAT_GAINS, 0}, "SCHD_DBG"},
+};
+/*
+ * AESS/ATC destination and source address translation (except McASPs)
+ * from the original 64bits words address
+ */
+const u32 abe_atc_dstid[ABE_ATC_DESC_SIZE >> 3] = {
+ /* DMA_0 DMIC PDM_DL PDM_UL McB1TX McB1RX McB2TX McB2RX 0 .. 7 */
+ 0, 0, 12, 0, 1, 0, 2, 0,
+ /* McB3TX McB3RX SLIMT0 SLIMT1 SLIMT2 SLIMT3 SLIMT4 SLIMT5 8 .. 15 */
+ 3, 0, 4, 5, 6, 7, 8, 9,
+ /* SLIMT6 SLIMT7 SLIMR0 SLIMR1 SLIMR2 SLIMR3 SLIMR4 SLIMR5 16 .. 23 */
+ 10, 11, 0, 0, 0, 0, 0, 0,
+ /* SLIMR6 SLIMR7 McASP1X ----- ----- McASP1R ----- ----- 24 .. 31 */
+ 0, 0, 14, 0, 0, 0, 0, 0,
+ /* CBPrT0 CBPrT1 CBPrT2 CBPrT3 CBPrT4 CBPrT5 CBPrT6 CBPrT7 32 .. 39 */
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ /* CBP_T0 CBP_T1 CBP_T2 CBP_T3 CBP_T4 CBP_T5 CBP_T6 CBP_T7 40 .. 47 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* CBP_T8 CBP_T9 CBP_T10 CBP_T11 CBP_T12 CBP_T13 CBP_T14
+ CBP_T15 48 .. 63 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const u32 abe_atc_srcid[ABE_ATC_DESC_SIZE >> 3] = {
+ /* DMA_0 DMIC PDM_DL PDM_UL McB1TX McB1RX McB2TX McB2RX 0 .. 7 */
+ 0, 12, 0, 13, 0, 1, 0, 2,
+ /* McB3TX McB3RX SLIMT0 SLIMT1 SLIMT2 SLIMT3 SLIMT4 SLIMT5 8 .. 15 */
+ 0, 3, 0, 0, 0, 0, 0, 0,
+ /* SLIMT6 SLIMT7 SLIMR0 SLIMR1 SLIMR2 SLIMR3 SLIMR4 SLIMR5 16 .. 23 */
+ 0, 0, 4, 5, 6, 7, 8, 9,
+ /* SLIMR6 SLIMR7 McASP1X ----- ----- McASP1R ----- ----- 24 .. 31 */
+ 10, 11, 0, 0, 0, 14, 0, 0,
+ /* CBPrT0 CBPrT1 CBPrT2 CBPrT3 CBPrT4 CBPrT5 CBPrT6 CBPrT7 32 .. 39 */
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ /* CBP_T0 CBP_T1 CBP_T2 CBP_T3 CBP_T4 CBP_T5 CBP_T6 CBP_T7 40 .. 47 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* CBP_T8 CBP_T9 CBP_T10 CBP_T11 CBP_T12 CBP_T13 CBP_T14
+ CBP_T15 48 .. 63 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+/*
+ * preset default routing configurations
+ * This is given as implementation EXAMPLES
+ * the programmer uses "abe_set_router_configuration" with its own tables
+ */
+const abe_router_t abe_router_ul_table_preset[NBROUTE_CONFIG][NBROUTE_UL] = {
+ /* VOICE UPLINK WITH PHOENIX MICROPHONES - UPROUTE_CONFIG_AMIC */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC1_L_labelID, DMIC1_R_labelID, DMIC2_L_labelID, DMIC2_R_labelID,
+ MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID, AMIC_L_labelID,
+ AMIC_L_labelID,
+ ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ AMIC_L_labelID, AMIC_L_labelID,
+ /* 12 .. 13 = VX_UL */
+ AMIC_L_labelID, AMIC_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+ /* VOICE UPLINK WITH THE FIRST DMIC PAIR - UPROUTE_CONFIG_DMIC1 */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC2_L_labelID, DMIC2_R_labelID, DMIC3_L_labelID, DMIC3_R_labelID,
+ DMIC1_L_labelID, DMIC1_R_labelID, ZERO_labelID, ZERO_labelID,
+ ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ DMIC1_L_labelID, DMIC1_R_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC1_L_labelID, DMIC1_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+ /* VOICE UPLINK WITH THE SECOND DMIC PAIR - UPROUTE_CONFIG_DMIC2 */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC3_L_labelID, DMIC3_R_labelID, DMIC1_L_labelID, DMIC1_R_labelID,
+ DMIC2_L_labelID, DMIC2_R_labelID, ZERO_labelID, ZERO_labelID,
+ ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ DMIC2_L_labelID, DMIC2_R_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC2_L_labelID, DMIC2_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+ /* VOICE UPLINK WITH THE LAST DMIC PAIR - UPROUTE_CONFIG_DMIC3 */
+ {
+ /* 0 .. 9 = MM_UL */
+ AMIC_L_labelID, AMIC_R_labelID, DMIC2_L_labelID, DMIC2_R_labelID,
+ DMIC3_L_labelID, DMIC3_R_labelID, ZERO_labelID, ZERO_labelID,
+ ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ DMIC3_L_labelID, DMIC3_R_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC3_L_labelID, DMIC3_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+ /* VOICE UPLINK WITH THE BT - UPROUTE_CONFIG_BT */
+ {
+ /* 0 .. 9 = MM_UL */
+ BT_UL_L_labelID, BT_UL_R_labelID, DMIC2_L_labelID, DMIC2_R_labelID,
+ DMIC3_L_labelID, DMIC3_R_labelID, DMIC1_L_labelID, DMIC1_R_labelID,
+ ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ AMIC_L_labelID, AMIC_R_labelID,
+ /* 12 .. 13 = VX_UL */
+ BT_UL_L_labelID, BT_UL_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+ /* VOICE UPLINK WITH THE BT - UPROUTE_ECHO_MMUL2 */
+ {
+ /* 0 .. 9 = MM_UL */
+ MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID, BT_UL_L_labelID,
+ BT_UL_R_labelID, AMIC_L_labelID, AMIC_R_labelID,
+ ZERO_labelID, ZERO_labelID, ZERO_labelID, ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ EchoRef_L_labelID, EchoRef_R_labelID,
+ /* 12 .. 13 = VX_UL */
+ AMIC_L_labelID, AMIC_L_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID, ZERO_labelID,
+ },
+};
+/* all default routing configurations */
+abe_router_t abe_router_ul_table[NBROUTE_CONFIG_MAX][NBROUTE_UL];
+
+const abe_sequence_t seq_null = {
+ NOMASK, {CL_M1, 0, {0, 0, 0, 0}, 0}, {CL_M1, 0, {0, 0, 0, 0}, 0}
+};
+/* table of new subroutines called in the sequence */
+abe_subroutine2 abe_all_subsubroutine[MAXNBSUBROUTINE];
+/* number of parameters per calls */
+u32 abe_all_subsubroutine_nparam[MAXNBSUBROUTINE];
+/* index of the subroutine */
+u32 abe_subroutine_id[MAXNBSUBROUTINE];
+/* paramters of the subroutine (if any) */
+u32 *abe_all_subroutine_params[MAXNBSUBROUTINE];
+u32 abe_subroutine_write_pointer;
+/* table of all sequences */
+abe_sequence_t abe_all_sequence[MAXNBSEQUENCE];
+u32 abe_sequence_write_pointer;
+/* current number of pending sequences (avoids to look in the table) */
+u32 abe_nb_pending_sequences;
+/* pending sequences due to ressource collision */
+u32 abe_pending_sequences[MAXNBSEQUENCE];
+/* mask of unsharable ressources among other sequences */
+u32 abe_global_sequence_mask;
+/* table of active sequences */
+abe_seq_t abe_active_sequence[MAXACTIVESEQUENCE][MAXSEQUENCESTEPS];
+/* index of the plugged subroutine doing ping-pong cache-flush DMEM accesses */
+u32 abe_irq_pingpong_player_id;
+EXPORT_SYMBOL(abe_irq_pingpong_player_id);
+/* index of the plugged subroutine doing acoustics protection adaptation */
+u32 abe_irq_aps_adaptation_id;
+/* base addresses of the ping pong buffers in bytes addresses */
+u32 abe_base_address_pingpong[MAX_PINGPONG_BUFFERS];
+/* size of each ping/pong buffers */
+u32 abe_size_pingpong;
+/* number of ping/pong buffer being used */
+u32 abe_nb_pingpong;
+/*
+ * MAIN PORT SELECTION
+ */
+const u32 abe_port_priority[LAST_PORT_ID - 1] = {
+ OMAP_ABE_PDM_DL_PORT,
+ OMAP_ABE_PDM_UL_PORT,
+ OMAP_ABE_MM_EXT_OUT_PORT,
+ OMAP_ABE_MM_EXT_IN_PORT,
+ OMAP_ABE_DMIC_PORT,
+ OMAP_ABE_MM_UL_PORT,
+ OMAP_ABE_MM_UL2_PORT,
+ OMAP_ABE_MM_DL_PORT,
+ OMAP_ABE_TONES_DL_PORT,
+ OMAP_ABE_VX_UL_PORT,
+ OMAP_ABE_VX_DL_PORT,
+ OMAP_ABE_BT_VX_DL_PORT,
+ OMAP_ABE_BT_VX_UL_PORT,
+ OMAP_ABE_VIB_DL_PORT,
+};
diff --git a/sound/soc/omap/abe/abe_dbg.c b/sound/soc/omap/abe/abe_dbg.c
new file mode 100644
index 0000000..d1b160f
--- /dev/null
+++ b/sound/soc/omap/abe/abe_dbg.c
@@ -0,0 +1,201 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dbg.h"
+#include "abe.h"
+#include "abe_mem.h"
+
+/**
+ * omap_abe_dbg_reset
+ * @dbg: Pointer on abe debug handle
+ *
+ * Called in order to reset Audio Back End debug global data.
+ * This ensures that ABE debug trace pointer is reset correctly.
+ */
+int omap_abe_dbg_reset(struct omap_abe_dbg *dbg)
+{
+ dbg->activity_log_write_pointer = 0;
+ dbg->mask = 0;
+
+ return 0;
+}
+
+/**
+ * omap_abe_connect_debug_trace
+ * @abe: Pointer on abe handle
+ * @dma2:pointer to the DMEM trace buffer
+ *
+ * returns the address and size of the real-time debug trace buffer,
+ * the content of which will vary from one firmware release to another
+ */
+int omap_abe_connect_debug_trace(struct omap_abe *abe,
+ struct omap_abe_dma *dma2)
+{
+ _log(ABE_ID_CONNECT_DEBUG_TRACE, 0, 0, 0);
+
+ /* return tohe base address of the ping buffer in L3 and L4 spaces */
+ (*dma2).data = (void *)(OMAP_ABE_D_DEBUG_FIFO_ADDR +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).l3_dmem = (void *)(OMAP_ABE_D_DEBUG_FIFO_ADDR +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).l4_dmem = (void *)(OMAP_ABE_D_DEBUG_FIFO_ADDR +
+ ABE_DEFAULT_BASE_ADDRESS_L4 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).iter = (OMAP_ABE_D_DEBUG_FIFO_SIZE + OMAP_ABE_D_DEBUG_FIFO_HAL_SIZE)>>2;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_connect_debug_trace);
+
+/**
+ * omap_abe_set_debug_trace
+ * @dbg: Pointer on abe debug handle
+ * @debug: debug log level
+ *
+ * Set the debug level for ABE trace. This level allows to manage the number
+ * of information put inside the ABE trace buffer. This buffer can contains
+ * both AESS firmware and MPU traces.
+ */
+int omap_abe_set_debug_trace(struct omap_abe_dbg *dbg, int debug)
+{
+ _log(ABE_ID_SET_DEBUG_TRACE, 0, 0, 0);
+
+ dbg->mask = debug;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_set_debug_trace);
+
+/**
+ * omap_abe_dbg_log - Log ABE trace inside circular buffer
+ * @x: data to be logged
+ * @y: data to be logged
+ * @z: data to be logged
+ * @t: data to be logged
+ * Parameter :
+ *
+ * abe_dbg_activity_log : global circular buffer holding the data
+ * abe_dbg_activity_log_write_pointer : circular write pointer
+ *
+ * saves data in the log file
+ */
+void omap_abe_dbg_log(struct omap_abe *abe, u32 x, u32 y, u32 z, u32 t)
+{
+ u32 time_stamp, data;
+ struct omap_abe_dbg *dbg = &abe->dbg;
+
+ if (dbg->activity_log_write_pointer >=
+ (OMAP_ABE_D_DEBUG_HAL_TASK_SIZE - 2))
+ dbg->activity_log_write_pointer = 0;
+
+ /* copy in DMEM trace buffer and CortexA9 local buffer and a small 7
+ words circular buffer of the DMA trace ending with 0x55555555
+ (tag for last word) */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, OMAP_ABE_D_LOOPCOUNTER_ADDR,
+ (u32 *) &time_stamp, sizeof(time_stamp));
+ dbg->activity_log[dbg->activity_log_write_pointer] = time_stamp;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_DEBUG_HAL_TASK_ADDR +
+ (dbg->activity_log_write_pointer << 2),
+ (u32 *) &time_stamp, sizeof(time_stamp));
+ dbg->activity_log_write_pointer++;
+
+ data = ((x & MAX_UINT8) << 24) | ((y & MAX_UINT8) << 16) |
+ ((z & MAX_UINT8) << 8)
+ | (t & MAX_UINT8);
+ dbg->activity_log[dbg->activity_log_write_pointer] = data;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_DEBUG_HAL_TASK_ADDR +
+ (dbg->activity_log_write_pointer << 2),
+ (u32 *) &data, sizeof(data));
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_DEBUG_FIFO_HAL_ADDR +
+ ((dbg->activity_log_write_pointer << 2) &
+ (OMAP_ABE_D_DEBUG_FIFO_HAL_SIZE - 1)), (u32 *) &data,
+ sizeof(data));
+
+ data = ABE_DBG_MAGIC_NUMBER;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_DEBUG_FIFO_HAL_ADDR +
+ (((dbg->activity_log_write_pointer + 1) << 2) &
+ (OMAP_ABE_D_DEBUG_FIFO_HAL_SIZE - 1)),
+ (u32 *) &data, sizeof(data));
+ dbg->activity_log_write_pointer++;
+
+ if (dbg->activity_log_write_pointer >= OMAP_ABE_D_DEBUG_HAL_TASK_SIZE)
+ dbg->activity_log_write_pointer = 0;
+}
+
+/**
+ * omap_abe_dbg_error_log - Log ABE error
+ * @abe: Pointer on abe handle
+ * @level: level of error
+ * @error: error ID to log
+ *
+ * Log the ABE errors.
+ */
+void omap_abe_dbg_error(struct omap_abe *abe, int level, int error)
+{
+ omap_abe_dbg_log(abe, error, MAX_UINT8, MAX_UINT8, MAX_UINT8);
+}
diff --git a/sound/soc/omap/abe/abe_dbg.h b/sound/soc/omap/abe/abe_dbg.h
new file mode 100644
index 0000000..8639806
--- /dev/null
+++ b/sound/soc/omap/abe/abe_dbg.h
@@ -0,0 +1,231 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_DBG_H_
+#define _ABE_DBG_H_
+
+#include <linux/mutex.h>
+
+#include "abe_typ.h"
+#include "abe_dm_addr.h"
+
+/*
+ * Debug trace format
+ * TIME 2 bytes from ABE : 4kHz period of the FW scheduler
+ * SUBID 1 byte : HAL API index
+ * From 0 to 16 bytes : parameters of the subroutine
+ * on every 32 dumps a tag is pushed on the debug trace : 0x55555555
+ */
+#define dbg_bitfield_offset 8
+#define dbg_api_calls 0
+#define dbg_mapi (1L << (dbg_api_calls + dbg_bitfield_offset))
+#define dbg_external_data_access 1
+#define dbg_mdata (1L << (dbg_external_data_access + dbg_bitfield_offset))
+#define dbg_err_codes 2
+#define dbg_merr (1L << (dbg_api_calls + dbg_bitfield_offset))
+#define ABE_DBG_MAGIC_NUMBER 0x55555555
+/*
+ * IDs used for traces
+ */
+#define ABE_ID_RESET_HAL (1 + dbg_mapi)
+#define ABE_ID_LOAD_FW (2 + dbg_mapi)
+#define ABE_ID_DEFAULT_CONFIGURATION (3 + dbg_mapi)
+#define ABE_ID_IRQ_PROCESSING (4 + dbg_mapi)
+#define ABE_ID_EVENT_GENERATOR_SWITCH (5 + dbg_mapi)
+#define ABE_ID_READ_HARDWARE_CONFIGURATION (6 + dbg_mapi)
+#define ABE_ID_READ_LOWEST_OPP (7 + dbg_mapi)
+#define ABE_ID_WRITE_GAIN (8 + dbg_mapi)
+#define ABE_ID_SET_ASRC_DRIFT_CONTROL (9 + dbg_mapi)
+#define ABE_ID_PLUG_SUBROUTINE (10 + dbg_mapi)
+#define ABE_ID_UNPLUG_SUBROUTINE (11 + dbg_mapi)
+#define ABE_ID_PLUG_SEQUENCE (12 + dbg_mapi)
+#define ABE_ID_LAUNCH_SEQUENCE (13 + dbg_mapi)
+#define ABE_ID_LAUNCH_SEQUENCE_param (14 + dbg_mapi)
+#define ABE_ID_CONNECT_IRQ_PING_PONG_PORT (15 + dbg_mapi)
+#define ABE_ID_READ_ANALOG_GAIN_DL (16 + dbg_mapi)
+#define ABE_ID_READ_ANALOG_GAIN_UL (17 + dbg_mapi)
+#define ABE_ID_ENABLE_DYN_UL_GAIN (18 + dbg_mapi)
+#define ABE_ID_DISABLE_DYN_UL_GAIN (19 + dbg_mapi)
+#define ABE_ID_ENABLE_DYN_EXTENSION (20 + dbg_mapi)
+#define ABE_ID_DISABLE_DYN_EXTENSION (21 + dbg_mapi)
+#define ABE_ID_NOTIFY_ANALOG_GAIN_CHANGED (22 + dbg_mapi)
+#define ABE_ID_RESET_PORT (23 + dbg_mapi)
+#define ABE_ID_READ_REMAINING_DATA (24 + dbg_mapi)
+#define ABE_ID_DISABLE_DATA_TRANSFER (25 + dbg_mapi)
+#define ABE_ID_ENABLE_DATA_TRANSFER (26 + dbg_mapi)
+#define ABE_ID_READ_GLOBAL_COUNTER (27 + dbg_mapi)
+#define ABE_ID_SET_DMIC_FILTER (28 + dbg_mapi)
+#define ABE_ID_SET_OPP_PROCESSING (29 + dbg_mapi)
+#define ABE_ID_SET_PING_PONG_BUFFER (30 + dbg_mapi)
+#define ABE_ID_READ_PORT_ADDRESS (31 + dbg_mapi)
+#define ABE_ID_LOAD_FW_param (32 + dbg_mapi)
+#define ABE_ID_WRITE_HEADSET_OFFSET (33 + dbg_mapi)
+#define ABE_ID_READ_GAIN_RANGES (34 + dbg_mapi)
+#define ABE_ID_WRITE_EQUALIZER (35 + dbg_mapi)
+#define ABE_ID_WRITE_ASRC (36 + dbg_mapi)
+#define ABE_ID_WRITE_APS (37 + dbg_mapi)
+#define ABE_ID_WRITE_MIXER (38 + dbg_mapi)
+#define ABE_ID_WRITE_EANC (39 + dbg_mapi)
+#define ABE_ID_WRITE_ROUTER (40 + dbg_mapi)
+#define ABE_ID_READ_PORT_GAIN (41 + dbg_mapi)
+#define ABE_ID_ASRC (42 + dbg_mapi)
+#define ABE_ID_READ_APS (43 + dbg_mapi)
+#define ABE_ID_READ_APS_energy (44 + dbg_mapi)
+#define ABE_ID_READ_MIXER (45 + dbg_mapi)
+#define ABE_READ_EANC (46 + dbg_mapi)
+#define ABE_ID_READ_ROUTER (47 + dbg_mapi)
+#define ABE_ID_READ_DEBUG_TRACE (48 + dbg_mapi)
+#define ABE_ID_SET_SEQUENCE_TIME_ACCURACY (49 + dbg_mapi)
+#define ABE_ID_SET_DEBUG_PINS (50 + dbg_mapi)
+#define ABE_ID_SELECT_MAIN_PORT (51 + dbg_mapi)
+#define ABE_ID_WRITE_EVENT_GENERATOR (52 + dbg_mapi)
+#define ABE_ID_READ_USE_CASE_OPP (53 + dbg_mapi)
+#define ABE_ID_SELECT_DATA_SOURCE (54 + dbg_mapi)
+#define ABE_ID_READ_NEXT_PING_PONG_BUFFER (55 + dbg_mapi)
+#define ABE_ID_INIT_PING_PONG_BUFFER (56 + dbg_mapi)
+#define ABE_ID_CONNECT_CBPR_DMAREQ_PORT (57 + dbg_mapi)
+#define ABE_ID_CONNECT_DMAREQ_PORT (58 + dbg_mapi)
+#define ABE_ID_CONNECT_DMAREQ_PING_PONG_PORT (59 + dbg_mapi)
+#define ABE_ID_CONNECT_SERIAL_PORT (60 + dbg_mapi)
+#define ABE_ID_CONNECT_SLIMBUS_PORT (61 + dbg_mapi)
+#define ABE_ID_READ_GAIN (62 + dbg_mapi)
+#define ABE_ID_SET_ROUTER_CONFIGURATION (63 + dbg_mapi)
+#define ABE_ID_CONNECT_DEBUG_TRACE (64 + dbg_mapi)
+#define ABE_ID_SET_DEBUG_TRACE (65 + dbg_mapi)
+#define ABE_ID_REMOTE_DEBUGGER_INTERFACE (66 + dbg_mapi)
+#define ABE_ID_ENABLE_TEST_PATTERN (67 + dbg_mapi)
+#define ABE_ID_CONNECT_TDM_PORT (68 + dbg_mapi)
+/*
+ * IDs used for error codes
+ */
+#define NOERR 0
+#define ABE_SET_MEMORY_CONFIG_ERR (1 + dbg_merr)
+#define ABE_BLOCK_COPY_ERR (2 + dbg_merr)
+#define ABE_SEQTOOLONG (3 + dbg_merr)
+#define ABE_BADSAMPFORMAT (4 + dbg_merr)
+#define ABE_SET_ATC_ABE_BLOCK_COPY_ERR MEMORY_CONFIG_ERR (5 + dbg_merr)
+#define ABE_PROTOCOL_ERROR (6 + dbg_merr)
+#define ABE_PARAMETER_ERROR (7 + dbg_merr)
+/* port programmed while still running */
+#define ABE_PORT_REPROGRAMMING (8 + dbg_merr)
+#define ABE_READ_USE_CASE_OPP_ERR (9 + dbg_merr)
+#define ABE_PARAMETER_OVERFLOW (10 + dbg_merr)
+#define ABE_FW_FIFO_WRITE_PTR_ERR (11 + dbg_merr)
+
+/*
+ * IDs used for error codes
+ */
+#define OMAP_ABE_ERR_LIB (1 << 1)
+#define OMAP_ABE_ERR_API (1 << 2)
+#define OMAP_ABE_ERR_INI (1 << 3)
+#define OMAP_ABE_ERR_SEQ (1 << 4)
+#define OMAP_ABE_ERR_DBG (1 << 5)
+#define OMAP_ABE_ERR_EXT (1 << 6)
+
+struct omap_abe_dbg {
+ /* Debug Data */
+ u32 activity_log[OMAP_ABE_D_DEBUG_HAL_TASK_SIZE];
+ u32 activity_log_write_pointer;
+ u32 mask;
+};
+
+struct omap_abe_dma {
+ /* OCP L3 pointer to the first address of the */
+ void *data;
+ /* destination buffer (either DMA or Ping-Pong read/write pointers). */
+ /* address L3 when addressing the DMEM buffer instead of CBPr */
+ void *l3_dmem;
+ /* address L3 translated to L4 the ARM memory space */
+ void *l4_dmem;
+ /* number of iterations for the DMA data moves. */
+ u32 iter;
+};
+
+struct omap_abe {
+ void __iomem *io_base[5];
+ u32 firmware_version_number;
+ u16 MultiFrame[25][8];
+ u32 compensated_mixer_gain;
+ u8 muted_gains_indicator[MAX_NBGAIN_CMEM];
+ u32 desired_gains_decibel[MAX_NBGAIN_CMEM];
+ u32 muted_gains_decibel[MAX_NBGAIN_CMEM];
+ u32 desired_gains_linear[MAX_NBGAIN_CMEM];
+ u32 desired_ramp_delay_ms[MAX_NBGAIN_CMEM];
+ int pp_buf_id;
+ int pp_buf_id_next;
+ int pp_buf_addr[4];
+ int pp_first_irq;
+ struct mutex mutex;
+ u32 warm_boot;
+
+ u32 irq_dbg_read_ptr;
+ u32 dbg_param;
+
+ struct omap_abe_dbg dbg;
+};
+
+/**
+ * omap_abe_dbg_reset
+ * @dbg: Pointer on abe debug handle
+ *
+ * Called in order to reset Audio Back End debug global data.
+ * This ensures that ABE debug trace pointer is reset correctly.
+ */
+int omap_abe_dbg_reset(struct omap_abe_dbg *dbg);
+
+#endif /* _ABE_DBG_H_ */
diff --git a/sound/soc/omap/abe/abe_def.h b/sound/soc/omap/abe/abe_def.h
new file mode 100644
index 0000000..0051bab
--- /dev/null
+++ b/sound/soc/omap/abe/abe_def.h
@@ -0,0 +1,308 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_DEF_H_
+#define _ABE_DEF_H_
+/*
+ * HARDWARE AND PERIPHERAL DEFINITIONS
+ */
+/* MM_DL */
+#define ABE_CBPR0_IDX 0
+/* VX_DL */
+#define ABE_CBPR1_IDX 1
+/* VX_UL */
+#define ABE_CBPR2_IDX 2
+/* MM_UL */
+#define ABE_CBPR3_IDX 3
+/* MM_UL2 */
+#define ABE_CBPR4_IDX 4
+/* TONES */
+#define ABE_CBPR5_IDX 5
+/* VIB */
+#define ABE_CBPR6_IDX 6
+/* DEBUG/CTL */
+#define ABE_CBPR7_IDX 7
+#define CIRCULAR_BUFFER_PERIPHERAL_R__0 (0x100 + ABE_CBPR0_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__1 (0x100 + ABE_CBPR1_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__2 (0x100 + ABE_CBPR2_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__3 (0x100 + ABE_CBPR3_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__4 (0x100 + ABE_CBPR4_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__5 (0x100 + ABE_CBPR5_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__6 (0x100 + ABE_CBPR6_IDX*4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__7 (0x100 + ABE_CBPR7_IDX*4)
+#define PING_PONG_WITH_MCU_IRQ 1
+#define PING_PONG_WITH_DSP_IRQ 2
+/* ID used for LIB memory copy subroutines */
+#define COPY_FROM_ABE_TO_HOST 1
+#define COPY_FROM_HOST_TO_ABE 2
+/*
+ * INTERNAL DEFINITIONS
+ */
+#define ABE_FIRMWARE_MAX_SIZE 26629
+/* 24 Q6.26 coefficients */
+#define NBEQ1 25
+/* 2x12 Q6.26 coefficients */
+#define NBEQ2 13
+/* TBD APS first set of parameters */
+#define NBAPS1 10
+/* TBD APS second set of parameters */
+#define NBAPS2 10
+/* Mixer used for sending tones to the uplink voice path */
+#define NBMIX_AUDIO_UL 2
+/* Main downlink mixer */
+#define NBMIX_DL1 4
+/* Handsfree downlink mixer */
+#define NBMIX_DL2 4
+/* Side-tone mixer */
+#define NBMIX_SDT 2
+/* Echo reference mixer */
+#define NBMIX_ECHO 2
+/* Voice record mixer */
+#define NBMIX_VXREC 4
+/* unsigned version of (-1) */
+#define CC_M1 0xFF
+#define CS_M1 0xFFFF
+#define CL_M1 0xFFFFFFFFL
+/*
+ Mixer ID Input port ID Comments
+ DL1_MIXER 0 MMDL path
+ 1 MMUL2 path
+ 2 VXDL path
+ 3 TONES path
+ SDT_MIXER 0 Uplink path
+ 1 Downlink path
+ ECHO_MIXER 0 DL1_MIXER path
+ 1 DL2_MIXER path
+ AUDUL_MIXER 0 TONES_DL path
+ 1 Uplink path
+ 2 MM_DL path
+ VXREC_MIXER 0 TONES_DL path
+ 1 VX_DL path
+ 2 MM_DL path
+ 3 VX_UL path
+*/
+#define MIX_VXUL_INPUT_MM_DL 0
+#define MIX_VXUL_INPUT_TONES 1
+#define MIX_VXUL_INPUT_VX_UL 2
+#define MIX_VXUL_INPUT_VX_DL 3
+#define MIX_DL1_INPUT_MM_DL 0
+#define MIX_DL1_INPUT_MM_UL2 1
+#define MIX_DL1_INPUT_VX_DL 2
+#define MIX_DL1_INPUT_TONES 3
+#define MIX_DL2_INPUT_MM_DL 0
+#define MIX_DL2_INPUT_MM_UL2 1
+#define MIX_DL2_INPUT_VX_DL 2
+#define MIX_DL2_INPUT_TONES 3
+#define MIX_SDT_INPUT_UP_MIXER 0
+#define MIX_SDT_INPUT_DL1_MIXER 1
+#define MIX_AUDUL_INPUT_MM_DL 0
+#define MIX_AUDUL_INPUT_TONES 1
+#define MIX_AUDUL_INPUT_UPLINK 2
+#define MIX_AUDUL_INPUT_VX_DL 3
+#define MIX_VXREC_INPUT_MM_DL 0
+#define MIX_VXREC_INPUT_TONES 1
+#define MIX_VXREC_INPUT_VX_UL 2
+#define MIX_VXREC_INPUT_VX_DL 3
+#define MIX_ECHO_DL1 0
+#define MIX_ECHO_DL2 1
+/* nb of samples to route */
+#define NBROUTE_UL 16
+/* 10 routing tables max */
+#define NBROUTE_CONFIG_MAX 10
+/* 5 pre-computed routing tables */
+#define NBROUTE_CONFIG 6
+/* AMIC on VX_UL */
+#define UPROUTE_CONFIG_AMIC 0
+/* DMIC first pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC1 1
+/* DMIC second pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC2 2
+/* DMIC last pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC3 3
+/* BT_UL on VX_UL */
+#define UPROUTE_CONFIG_BT 4
+/* ECHO_REF on MM_UL2 */
+#define UPROUTE_ECHO_MMUL2 5
+/* call-back indexes */
+#define MAXCALLBACK 100
+/* subroutines */
+#define MAXNBSUBROUTINE 100
+/* time controlled sequenced */
+#define MAXNBSEQUENCE 20
+/* maximum simultaneous active sequences */
+#define MAXACTIVESEQUENCE 20
+/* max number of steps in the sequences */
+#define MAXSEQUENCESTEPS 2
+/* max number of feature associated to a port */
+#define MAXFEATUREPORT 12
+#define SUB_0_PARAM 0
+/* number of parameters per sequence calls */
+#define SUB_1_PARAM 1
+#define SUB_2_PARAM 2
+#define SUB_3_PARAM 3
+#define SUB_4_PARAM 4
+/* active sequence mask = 0 means the line is free */
+#define FREE_LINE 0
+/* no ask for collision protection */
+#define NOMASK (1 << 0)
+/* do not allow a PDM OFF during the execution of this sequence */
+#define MASK_PDM_OFF (1 << 1)
+/* do not allow a PDM ON during the execution of this sequence */
+#define MASK_PDM_ON (1 << 2)
+/* explicit name of the feature */
+#define NBCHARFEATURENAME 16
+/* explicit name of the port */
+#define NBCHARPORTNAME 16
+/* sink / input port from Host point of view (or AESS for DMIC/McPDM/.. */
+#define SNK_P ABE_ATC_DIRECTION_IN
+/* source / ouptut port */
+#define SRC_P ABE_ATC_DIRECTION_OUT
+/* no ASRC applied */
+#define NODRIFT 0
+/* for abe_set_asrc_drift_control */
+#define FORCED_DRIFT_CONTROL 1
+/* for abe_set_asrc_drift_control */
+#define ADPATIVE_DRIFT_CONTROL 2
+/* number of task/slot depending on the OPP value */
+#define DOPPMODE32_OPP100 (0x00000010)
+#define DOPPMODE32_OPP50 (0x0000000C)
+#define DOPPMODE32_OPP25 (0x0000004)
+/*
+ * ABE CONST AREA FOR PARAMETERS TRANSLATION
+ */
+#define GAIN_MAXIMUM 3000L
+#define GAIN_24dB 2400L
+#define GAIN_18dB 1800L
+#define GAIN_12dB 1200L
+#define GAIN_6dB 600L
+/* default gain = 1 */
+#define GAIN_0dB 0L
+#define GAIN_M6dB -600L
+#define GAIN_M7dB -700L
+#define GAIN_M12dB -1200L
+#define GAIN_M18dB -1800L
+#define GAIN_M24dB -2400L
+#define GAIN_M30dB -3000L
+#define GAIN_M40dB -4000L
+#define GAIN_M50dB -5000L
+/* muted gain = -120 decibels */
+#define MUTE_GAIN -12000L
+#define GAIN_TOOLOW -13000L
+#define GAIN_MUTE MUTE_GAIN
+#define RAMP_MINLENGTH 0L
+/* ramp_t is in milli- seconds */
+#define RAMP_0MS 0L
+#define RAMP_1MS 1L
+#define RAMP_2MS 2L
+#define RAMP_5MS 5L
+#define RAMP_10MS 10L
+#define RAMP_20MS 20L
+#define RAMP_50MS 50L
+#define RAMP_100MS 100L
+#define RAMP_200MS 200L
+#define RAMP_500MS 500L
+#define RAMP_1000MS 1000L
+#define RAMP_MAXLENGTH 10000L
+/* for abe_translate_gain_format */
+#define LINABE_TO_DECIBELS 1
+#define DECIBELS_TO_LINABE 2
+/* for abe_translate_ramp_format */
+#define IIRABE_TO_MICROS 1
+#define MICROS_TO_IIABE 2
+/*
+ * ABE CONST AREA FOR PERIPHERAL TUNING
+ */
+/* port idled IDLE_P */
+#define OMAP_ABE_PORT_ACTIVITY_IDLE 1
+/* port initialized, ready to be activated */
+#define OMAP_ABE_PORT_INITIALIZED 3
+/* port activated RUN_P */
+#define OMAP_ABE_PORT_ACTIVITY_RUNNING 2
+#define NOCALLBACK 0
+#define NOPARAMETER 0
+/* number of ATC access upon AMIC DMArequests, all the FIFOs are enabled */
+#define MCPDM_UL_ITER 4
+/* All the McPDM FIFOs are enabled simultaneously */
+#define MCPDM_DL_ITER 24
+/* All the DMIC FIFOs are enabled simultaneously */
+#define DMIC_ITER 12
+/* TBD later if needed */
+#define MAX_PINGPONG_BUFFERS 2
+/*
+ * Indexes to the subroutines
+ */
+#define SUB_WRITE_MIXER 1
+#define SUB_WRITE_PORT_GAIN 2
+/* OLD WAY */
+#define c_feat_init_eq 1
+#define c_feat_read_eq1 2
+#define c_write_eq1 3
+#define c_feat_read_eq2 4
+#define c_write_eq2 5
+#define c_feat_read_eq3 6
+#define c_write_eq3 7
+/* max number of gain to be controlled by HAL */
+#define MAX_NBGAIN_CMEM 36
+/*
+ * MACROS
+ */
+#define maximum(a, b) (((a) < (b)) ? (b) : (a))
+#define minimum(a, b) (((a) > (b)) ? (b) : (a))
+#define absolute(a) (((a) > 0) ? (a) : ((-1)*(a)))
+#define HAL_VERSIONS 9
+#endif/* _ABE_DEF_H_ */
diff --git a/sound/soc/omap/abe/abe_define.h b/sound/soc/omap/abe/abe_define.h
new file mode 100644
index 0000000..412fea8
--- /dev/null
+++ b/sound/soc/omap/abe/abe_define.h
@@ -0,0 +1,120 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _ABE_DEFINE_H_
+#define _ABE_DEFINE_H_
+#define ATC_DESCRIPTOR_NUMBER 64
+#define PROCESSING_SLOTS 25
+#define TASK_POOL_LENGTH 136
+#define MCU_IRQ 0x24
+#define MCU_IRQ_SHIFT2 0x90
+#define DMA_REQ_SHIFT2 0x210
+#define DSP_IRQ 0x4c
+#define IRQtag_APS 0x000a
+#define IRQtag_COUNT 0x000c
+#define IRQtag_PP 0x000d
+#define DMAreq_7 0x0080
+#define IRQ_FIFO_LENGTH 16
+#define SDT_EQ_ORDER 4
+#define DL_EQ_ORDER 12
+#define MIC_FILTER_ORDER 4
+#define GAINS_WITH_RAMP1 14
+#define GAINS_WITH_RAMP2 22
+#define GAINS_WITH_RAMP_TOTAL 36
+#define ASRC_MEMLENGTH 40
+#define ASRC_UL_VX_FIR_L 19
+#define ASRC_DL_VX_FIR_L 19
+#define ASRC_MM_EXT_IN_FIR_L 18
+#define ASRC_margin 2
+#define ASRC_N_8k 2
+#define ASRC_N_16k 4
+#define ASRC_N_48k 12
+#define VIBRA_N 5
+#define VIBRA1_IIR_MEMSIZE 11
+#define SAMP_LOOP_96K 24
+#define SAMP_LOOP_48K 12
+#define SAMP_LOOP_48KM1 11
+#define SAMP_LOOP_48KM2 10
+#define SAMP_LOOP_16K 4
+#define SAMP_LOOP_8K 2
+#define INPUT_SCALE_SHIFTM2 5156
+#define SATURATION 8420
+#define SATURATION_7FFF 8416
+#define OUTPUT_SCALE_SHIFTM2 5160
+#define NTAPS_SRC_44P1 24
+#define NTAPS_SRC_44P1_M4 96
+#define NTAPS_SRC_44P1_THR 60
+#define NTAPS_SRC_44P1_THRM4 240
+#define DRIFT_COUNTER_44P1M1 443
+#define NB_OF_PHASES_SRC44P1 12
+#define NB_OF_PHASES_SRC44P1M1 11
+#define SRC44P1_BUFFER_SIZE 96
+#define SRC44P1_BUFFER_SIZE_M4 384
+#define SRC44P1_INIT_RPTR 60
+#define MUTE_SCALING 5164
+#define ABE_PMEM 1
+#define ABE_CMEM 2
+#define ABE_SMEM 3
+#define ABE_DMEM 4
+#define ABE_ATC 5
+#define ASRC_BT_UL_FIR_L 19
+#define ASRC_BT_DL_FIR_L 19
+#define SRC44P1_COEF_ADDR 1466
+#define NTAPS_P_SRC_44P1_M4 192
+#define MAX_SMEM_CHECK 32
+#define SATURATION_EQ 9780
+#endif /* _ABE_DEFINE_H_ */
diff --git a/sound/soc/omap/abe/abe_dm_addr.h b/sound/soc/omap/abe/abe_dm_addr.h
new file mode 100644
index 0000000..3abf5a5
--- /dev/null
+++ b/sound/soc/omap/abe/abe_dm_addr.h
@@ -0,0 +1,243 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define OMAP_ABE_D_ATCDESCRIPTORS_ADDR 0x0
+#define OMAP_ABE_D_ATCDESCRIPTORS_SIZE 0x200
+#define OMAP_ABE_STACK_ADDR 0x200
+#define OMAP_ABE_STACK_SIZE 0x70
+#define OMAP_ABE_D_VERSION_ADDR 0x270
+#define OMAP_ABE_D_VERSION_SIZE 0x4
+#define OMAP_ABE_D_IODESCR_ADDR 0x274
+#define OMAP_ABE_D_IODESCR_SIZE 0x280
+#define OMAP_ABE_D_ZERO_ADDR 0x4F4
+#define OMAP_ABE_D_ZERO_SIZE 0x4
+#define OMAP_ABE_DBG_TRACE1_ADDR 0x4F8
+#define OMAP_ABE_DBG_TRACE1_SIZE 0x1
+#define OMAP_ABE_DBG_TRACE2_ADDR 0x4F9
+#define OMAP_ABE_DBG_TRACE2_SIZE 0x1
+#define OMAP_ABE_DBG_TRACE3_ADDR 0x4FA
+#define OMAP_ABE_DBG_TRACE3_SIZE 0x1
+#define OMAP_ABE_D_MULTIFRAME_ADDR 0x4FC
+#define OMAP_ABE_D_MULTIFRAME_SIZE 0x190
+#define OMAP_ABE_D_IDLETASK_ADDR 0x68C
+#define OMAP_ABE_D_IDLETASK_SIZE 0x2
+#define OMAP_ABE_D_TYPELENGTHCHECK_ADDR 0x68E
+#define OMAP_ABE_D_TYPELENGTHCHECK_SIZE 0x2
+#define OMAP_ABE_D_MAXTASKBYTESINSLOT_ADDR 0x690
+#define OMAP_ABE_D_MAXTASKBYTESINSLOT_SIZE 0x2
+#define OMAP_ABE_D_REWINDTASKBYTES_ADDR 0x692
+#define OMAP_ABE_D_REWINDTASKBYTES_SIZE 0x2
+#define OMAP_ABE_D_PCURRENTTASK_ADDR 0x694
+#define OMAP_ABE_D_PCURRENTTASK_SIZE 0x2
+#define OMAP_ABE_D_PFASTLOOPBACK_ADDR 0x696
+#define OMAP_ABE_D_PFASTLOOPBACK_SIZE 0x2
+#define OMAP_ABE_D_PNEXTFASTLOOPBACK_ADDR 0x698
+#define OMAP_ABE_D_PNEXTFASTLOOPBACK_SIZE 0x4
+#define OMAP_ABE_D_PPCURRENTTASK_ADDR 0x69C
+#define OMAP_ABE_D_PPCURRENTTASK_SIZE 0x2
+#define OMAP_ABE_D_SLOTCOUNTER_ADDR 0x6A0
+#define OMAP_ABE_D_SLOTCOUNTER_SIZE 0x2
+#define OMAP_ABE_D_LOOPCOUNTER_ADDR 0x6A4
+#define OMAP_ABE_D_LOOPCOUNTER_SIZE 0x4
+#define OMAP_ABE_D_REWINDFLAG_ADDR 0x6A8
+#define OMAP_ABE_D_REWINDFLAG_SIZE 0x2
+#define OMAP_ABE_D_SLOT23_CTRL_ADDR 0x6AC
+#define OMAP_ABE_D_SLOT23_CTRL_SIZE 0x4
+#define OMAP_ABE_D_MCUIRQFIFO_ADDR 0x6B0
+#define OMAP_ABE_D_MCUIRQFIFO_SIZE 0x40
+#define OMAP_ABE_D_PINGPONGDESC_ADDR 0x6F0
+#define OMAP_ABE_D_PINGPONGDESC_SIZE 0x20
+#define OMAP_ABE_D_PP_MCU_IRQ_ADDR 0x710
+#define OMAP_ABE_D_PP_MCU_IRQ_SIZE 0x2
+#define OMAP_ABE_D_SRC44P1_MMDL_STRUCT_ADDR 0x714
+#define OMAP_ABE_D_SRC44P1_MMDL_STRUCT_SIZE 0x12
+#define OMAP_ABE_D_SRC44P1_TONES_STRUCT_ADDR 0x728
+#define OMAP_ABE_D_SRC44P1_TONES_STRUCT_SIZE 0x12
+#define OMAP_ABE_D_CTRLPORTFIFO_ADDR 0x740
+#define OMAP_ABE_D_CTRLPORTFIFO_SIZE 0x10
+#define OMAP_ABE_D_IDLE_STATE_ADDR 0x750
+#define OMAP_ABE_D_IDLE_STATE_SIZE 0x4
+#define OMAP_ABE_D_STOP_REQUEST_ADDR 0x754
+#define OMAP_ABE_D_STOP_REQUEST_SIZE 0x4
+#define OMAP_ABE_D_REF0_ADDR 0x758
+#define OMAP_ABE_D_REF0_SIZE 0x2
+#define OMAP_ABE_D_DEBUGREGISTER_ADDR 0x75C
+#define OMAP_ABE_D_DEBUGREGISTER_SIZE 0x8C
+#define OMAP_ABE_D_GCOUNT_ADDR 0x7E8
+#define OMAP_ABE_D_GCOUNT_SIZE 0x2
+#define OMAP_ABE_D_FASTCOUNTER_ADDR 0x7EC
+#define OMAP_ABE_D_FASTCOUNTER_SIZE 0x4
+#define OMAP_ABE_D_SLOWCOUNTER_ADDR 0x7F0
+#define OMAP_ABE_D_SLOWCOUNTER_SIZE 0x4
+#define OMAP_ABE_D_AUPLINKROUTING_ADDR 0x7F4
+#define OMAP_ABE_D_AUPLINKROUTING_SIZE 0x20
+#define OMAP_ABE_D_VIRTAUDIOLOOP_ADDR 0x814
+#define OMAP_ABE_D_VIRTAUDIOLOOP_SIZE 0x4
+#define OMAP_ABE_D_ASRCVARS_DL_VX_ADDR 0x818
+#define OMAP_ABE_D_ASRCVARS_DL_VX_SIZE 0x20
+#define OMAP_ABE_D_ASRCVARS_UL_VX_ADDR 0x838
+#define OMAP_ABE_D_ASRCVARS_UL_VX_SIZE 0x20
+#define OMAP_ABE_D_COEFADDRESSES_VX_ADDR 0x858
+#define OMAP_ABE_D_COEFADDRESSES_VX_SIZE 0x20
+#define OMAP_ABE_D_ASRCVARS_MM_EXT_IN_ADDR 0x878
+#define OMAP_ABE_D_ASRCVARS_MM_EXT_IN_SIZE 0x20
+#define OMAP_ABE_D_COEFADDRESSES_MM_ADDR 0x898
+#define OMAP_ABE_D_COEFADDRESSES_MM_SIZE 0x20
+#define OMAP_ABE_D_TRACEBUFADR_ADDR 0x8B8
+#define OMAP_ABE_D_TRACEBUFADR_SIZE 0x2
+#define OMAP_ABE_D_TRACEBUFOFFSET_ADDR 0x8BA
+#define OMAP_ABE_D_TRACEBUFOFFSET_SIZE 0x2
+#define OMAP_ABE_D_TRACEBUFLENGTH_ADDR 0x8BC
+#define OMAP_ABE_D_TRACEBUFLENGTH_SIZE 0x2
+#define OMAP_ABE_D_MAXTASKBYTESINSLOT_SAVED_ADDR 0x8C0
+#define OMAP_ABE_D_MAXTASKBYTESINSLOT_SAVED_SIZE 0x4
+#define OMAP_ABE_D_PEMPTY_ADDR 0x8C4
+#define OMAP_ABE_D_PEMPTY_SIZE 0x50
+#define OMAP_ABE_D_ECHO_REF_48_16_WRAP_ADDR 0x914
+#define OMAP_ABE_D_ECHO_REF_48_16_WRAP_SIZE 0x8
+#define OMAP_ABE_D_ECHO_REF_48_8_WRAP_ADDR 0x91C
+#define OMAP_ABE_D_ECHO_REF_48_8_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_UL_16_48_WRAP_ADDR 0x924
+#define OMAP_ABE_D_BT_UL_16_48_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_UL_8_48_WRAP_ADDR 0x92C
+#define OMAP_ABE_D_BT_UL_8_48_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_DL_48_16_WRAP_ADDR 0x934
+#define OMAP_ABE_D_BT_DL_48_16_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_DL_48_8_WRAP_ADDR 0x93C
+#define OMAP_ABE_D_BT_DL_48_8_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_DL_16_48_WRAP_ADDR 0x944
+#define OMAP_ABE_D_VX_DL_16_48_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_DL_8_48_WRAP_ADDR 0x94C
+#define OMAP_ABE_D_VX_DL_8_48_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_UL_48_16_WRAP_ADDR 0x954
+#define OMAP_ABE_D_VX_UL_48_16_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_UL_48_8_WRAP_ADDR 0x95C
+#define OMAP_ABE_D_VX_UL_48_8_WRAP_SIZE 0x8
+#define OMAP_ABE_D_ASRCVARS_BT_UL_ADDR 0x964
+#define OMAP_ABE_D_ASRCVARS_BT_UL_SIZE 0x20
+#define OMAP_ABE_D_ASRCVARS_BT_DL_ADDR 0x984
+#define OMAP_ABE_D_ASRCVARS_BT_DL_SIZE 0x20
+#define OMAP_ABE_D_BT_DL_48_8_OPP100_WRAP_ADDR 0x9A4
+#define OMAP_ABE_D_BT_DL_48_8_OPP100_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_DL_48_16_OPP100_WRAP_ADDR 0x9AC
+#define OMAP_ABE_D_BT_DL_48_16_OPP100_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_DL_8_48_FIR_WRAP_ADDR 0x9B4
+#define OMAP_ABE_D_VX_DL_8_48_FIR_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_UL_8_48_FIR_WRAP_ADDR 0x9BC
+#define OMAP_ABE_D_BT_UL_8_48_FIR_WRAP_SIZE 0x8
+#define OMAP_ABE_D_TASKSLIST_ADDR 0x9C4
+#define OMAP_ABE_D_TASKSLIST_SIZE 0x880
+#define OMAP_ABE_D_HW_TEST_ADDR 0x1244
+#define OMAP_ABE_D_HW_TEST_SIZE 0x28
+#define OMAP_ABE_D_TRACEBUFADR_HAL_ADDR 0x126C
+#define OMAP_ABE_D_TRACEBUFADR_HAL_SIZE 0x4
+#define OMAP_ABE_D_CHECK_LIST_SMEM_ADDR 0x1270
+#define OMAP_ABE_D_CHECK_LIST_SMEM_SIZE 0x80
+#define OMAP_ABE_D_CHECK_LIST_LEFT_IDX_ADDR 0x12F0
+#define OMAP_ABE_D_CHECK_LIST_LEFT_IDX_SIZE 0x2
+#define OMAP_ABE_D_CHECK_LIST_RIGHT_IDX_ADDR 0x12F2
+#define OMAP_ABE_D_CHECK_LIST_RIGHT_IDX_SIZE 0x2
+#define OMAP_ABE_D_BT_DL_48_8_FIR_WRAP_ADDR 0x12F4
+#define OMAP_ABE_D_BT_DL_48_8_FIR_WRAP_SIZE 0x8
+#define OMAP_ABE_D_BT_DL_48_8_FIR_OPP100_WRAP_ADDR 0x12FC
+#define OMAP_ABE_D_BT_DL_48_8_FIR_OPP100_WRAP_SIZE 0x8
+#define OMAP_ABE_D_VX_UL_48_8_FIR_WRAP_ADDR 0x1304
+#define OMAP_ABE_D_VX_UL_48_8_FIR_WRAP_SIZE 0x8
+#define OMAP_ABE_D_DEBUG_FW_TASK_ADDR 0x1400
+#define OMAP_ABE_D_DEBUG_FW_TASK_SIZE 0x100
+#define OMAP_ABE_D_DEBUG_FIFO_ADDR 0x1500
+#define OMAP_ABE_D_DEBUG_FIFO_SIZE 0x60
+#define OMAP_ABE_D_DEBUG_FIFO_HAL_ADDR 0x1560
+#define OMAP_ABE_D_DEBUG_FIFO_HAL_SIZE 0x20
+#define OMAP_ABE_D_FWMEMINIT_ADDR 0x1580
+#define OMAP_ABE_D_FWMEMINIT_SIZE 0x3C0
+#define OMAP_ABE_D_FWMEMINITDESCR_ADDR 0x1940
+#define OMAP_ABE_D_FWMEMINITDESCR_SIZE 0x10
+#define OMAP_ABE_D_BT_DL_FIFO_ADDR 0x1C00
+#define OMAP_ABE_D_BT_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_BT_UL_FIFO_ADDR 0x1E00
+#define OMAP_ABE_D_BT_UL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MM_EXT_OUT_FIFO_ADDR 0x2000
+#define OMAP_ABE_D_MM_EXT_OUT_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MM_EXT_IN_FIFO_ADDR 0x2200
+#define OMAP_ABE_D_MM_EXT_IN_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MM_UL2_FIFO_ADDR 0x2400
+#define OMAP_ABE_D_MM_UL2_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_DMIC_UL_FIFO_ADDR 0x2600
+#define OMAP_ABE_D_DMIC_UL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MM_UL_FIFO_ADDR 0x2800
+#define OMAP_ABE_D_MM_UL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MM_DL_FIFO_ADDR 0x2A00
+#define OMAP_ABE_D_MM_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_TONES_DL_FIFO_ADDR 0x2C00
+#define OMAP_ABE_D_TONES_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_VIB_DL_FIFO_ADDR 0x2E00
+#define OMAP_ABE_D_VIB_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_DEBUG_HAL_TASK_ADDR 0x3000
+#define OMAP_ABE_D_DEBUG_HAL_TASK_SIZE 0x800
+#define OMAP_ABE_D_MCPDM_DL_FIFO_ADDR 0x3800
+#define OMAP_ABE_D_MCPDM_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_MCPDM_UL_FIFO_ADDR 0x3A00
+#define OMAP_ABE_D_MCPDM_UL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_VX_UL_FIFO_ADDR 0x3C00
+#define OMAP_ABE_D_VX_UL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_VX_DL_FIFO_ADDR 0x3E00
+#define OMAP_ABE_D_VX_DL_FIFO_SIZE 0x1E0
+#define OMAP_ABE_D_PING_ADDR 0x4000
+#define OMAP_ABE_D_PING_SIZE 0x6000
+#define OMAP_ABE_D_PONG_ADDR 0xA000
+#define OMAP_ABE_D_PONG_SIZE 0x6000
diff --git a/sound/soc/omap/abe/abe_ext.h b/sound/soc/omap/abe/abe_ext.h
new file mode 100644
index 0000000..8fb1aac
--- /dev/null
+++ b/sound/soc/omap/abe/abe_ext.h
@@ -0,0 +1,242 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_EXT_H_
+#define _ABE_EXT_H_
+
+/*
+ * OS DEPENDENT MMU CONFIGURATION
+ */
+#define ABE_PMEM_BASE_OFFSET_MPU 0xe0000
+#define ABE_CMEM_BASE_OFFSET_MPU 0xa0000
+#define ABE_SMEM_BASE_OFFSET_MPU 0xc0000
+#define ABE_DMEM_BASE_OFFSET_MPU 0x80000
+#define ABE_ATC_BASE_OFFSET_MPU 0xf1000
+/* default base address for io_base */
+#define ABE_DEFAULT_BASE_ADDRESS_L3 0x49000000L
+#define ABE_DEFAULT_BASE_ADDRESS_L4 0x40100000L
+#define ABE_DEFAULT_BASE_ADDRESS_DEFAULT ABE_DEFAULT_BASE_ADDRESS_L3
+/*
+ * HARDWARE AND PERIPHERAL DEFINITIONS
+ */
+/* PMEM SIZE in bytes (1024 words of 64 bits: : #32bits words x 4)*/
+#define ABE_PMEM_SIZE 8192
+/* CMEM SIZE in bytes (2048 coeff : #32bits words x 4)*/
+#define ABE_CMEM_SIZE 8192
+/* SMEM SIZE in bytes (3072 stereo samples : #32bits words x 4)*/
+#define ABE_SMEM_SIZE 24576
+/* DMEM SIZE in bytes */
+#define ABE_DMEM_SIZE 65536L
+/* ATC REGISTERS SIZE in bytes */
+#define ABE_ATC_DESC_SIZE 512
+/* holds the MCU Irq signal */
+#define ABE_MCU_IRQSTATUS_RAW 0x24
+/* status : clear the IRQ */
+#define ABE_MCU_IRQSTATUS 0x28
+/* holds the DSP Irq signal */
+#define ABE_DSP_IRQSTATUS_RAW 0x4C
+/* holds the DMA req lines to the sDMA */
+#define ABE_DMASTATUS_RAW 0x84
+#define EVENT_GENERATOR_COUNTER 0x68
+/* PLL output/desired sampling rate = (32768 * 6000)/96000 */
+#define EVENT_GENERATOR_COUNTER_DEFAULT (2048-1)
+/* PLL output/desired sampling rate = (32768 * 6000)/88200 */
+#define EVENT_GENERATOR_COUNTER_44100 (2228-1)
+/* start / stop the EVENT generator */
+#define EVENT_GENERATOR_START 0x6C
+#define EVENT_GENERATOR_ON 1
+#define EVENT_GENERATOR_OFF 0
+/* selection of the EVENT generator source */
+#define EVENT_SOURCE_SELECTION 0x70
+#define EVENT_SOURCE_DMA 0
+#define EVENT_SOURCE_COUNTER 1
+/* selection of the ABE DMA req line from ATC */
+#define AUDIO_ENGINE_SCHEDULER 0x74
+#define ABE_ATC_DMIC_DMA_REQ 1
+#define ABE_ATC_MCPDMDL_DMA_REQ 2
+#define ABE_ATC_MCPDMUL_DMA_REQ 3
+/* Direction=0 means input from ABE point of view */
+#define ABE_ATC_DIRECTION_IN 0
+/* Direction=1 means output from ABE point of view */
+#define ABE_ATC_DIRECTION_OUT 1
+/*
+ * DMA requests
+ */
+/*Internal connection doesn't connect at ABE boundary */
+#define External_DMA_0 0
+/*Transmit request digital microphone */
+#define DMIC_DMA_REQ 1
+/*Multichannel PDM downlink */
+#define McPDM_DMA_DL 2
+/*Multichannel PDM uplink */
+#define McPDM_DMA_UP 3
+/*MCBSP module 1 - transmit request */
+#define MCBSP1_DMA_TX 4
+/*MCBSP module 1 - receive request */
+#define MCBSP1_DMA_RX 5
+/*MCBSP module 2 - transmit request */
+#define MCBSP2_DMA_TX 6
+/*MCBSP module 2 - receive request */
+#define MCBSP2_DMA_RX 7
+/*MCBSP module 3 - transmit request */
+#define MCBSP3_DMA_TX 8
+/*MCBSP module 3 - receive request */
+#define MCBSP3_DMA_RX 9
+/*SLIMBUS module 1 - transmit request channel 0 */
+#define SLIMBUS1_DMA_TX0 10
+/*SLIMBUS module 1 - transmit request channel 1 */
+#define SLIMBUS1_DMA_TX1 11
+/*SLIMBUS module 1 - transmit request channel 2 */
+#define SLIMBUS1_DMA_TX2 12
+/*SLIMBUS module 1 - transmit request channel 3 */
+#define SLIMBUS1_DMA_TX3 13
+/*SLIMBUS module 1 - transmit request channel 4 */
+#define SLIMBUS1_DMA_TX4 14
+/*SLIMBUS module 1 - transmit request channel 5 */
+#define SLIMBUS1_DMA_TX5 15
+/*SLIMBUS module 1 - transmit request channel 6 */
+#define SLIMBUS1_DMA_TX6 16
+/*SLIMBUS module 1 - transmit request channel 7 */
+#define SLIMBUS1_DMA_TX7 17
+/*SLIMBUS module 1 - receive request channel 0 */
+#define SLIMBUS1_DMA_RX0 18
+/*SLIMBUS module 1 - receive request channel 1 */
+#define SLIMBUS1_DMA_RX1 19
+/*SLIMBUS module 1 - receive request channel 2 */
+#define SLIMBUS1_DMA_RX2 20
+/*SLIMBUS module 1 - receive request channel 3 */
+#define SLIMBUS1_DMA_RX3 21
+/*SLIMBUS module 1 - receive request channel 4 */
+#define SLIMBUS1_DMA_RX4 22
+/*SLIMBUS module 1 - receive request channel 5 */
+#define SLIMBUS1_DMA_RX5 23
+/*SLIMBUS module 1 - receive request channel 6 */
+#define SLIMBUS1_DMA_RX6 24
+/*SLIMBUS module 1 - receive request channel 7 */
+#define SLIMBUS1_DMA_RX7 25
+/*McASP - Data transmit DMA request line */
+#define McASP1_AXEVT 26
+/*McASP - Data receive DMA request line */
+#define McASP1_AREVT 29
+/*DUMMY FIFO @@@ */
+#define _DUMMY_FIFO_ 30
+/*DMA of the Circular buffer peripheral 0 */
+#define CBPr_DMA_RTX0 32
+/*DMA of the Circular buffer peripheral 1 */
+#define CBPr_DMA_RTX1 33
+/*DMA of the Circular buffer peripheral 2 */
+#define CBPr_DMA_RTX2 34
+/*DMA of the Circular buffer peripheral 3 */
+#define CBPr_DMA_RTX3 35
+/*DMA of the Circular buffer peripheral 4 */
+#define CBPr_DMA_RTX4 36
+/*DMA of the Circular buffer peripheral 5 */
+#define CBPr_DMA_RTX5 37
+/*DMA of the Circular buffer peripheral 6 */
+#define CBPr_DMA_RTX6 38
+/*DMA of the Circular buffer peripheral 7 */
+#define CBPr_DMA_RTX7 39
+/*
+ * ATC DESCRIPTORS - DESTINATIONS
+ */
+#define DEST_DMEM_access 0x00
+#define DEST_MCBSP1_ TX 0x01
+#define DEST_MCBSP2_ TX 0x02
+#define DEST_MCBSP3_TX 0x03
+#define DEST_SLIMBUS1_TX0 0x04
+#define DEST_SLIMBUS1_TX1 0x05
+#define DEST_SLIMBUS1_TX2 0x06
+#define DEST_SLIMBUS1_TX3 0x07
+#define DEST_SLIMBUS1_TX4 0x08
+#define DEST_SLIMBUS1_TX5 0x09
+#define DEST_SLIMBUS1_TX6 0x0A
+#define DEST_SLIMBUS1_TX7 0x0B
+#define DEST_MCPDM_DL 0x0C
+#define DEST_MCASP_TX0 0x0D
+#define DEST_MCASP_TX1 0x0E
+#define DEST_MCASP_TX2 0x0F
+#define DEST_MCASP_TX3 0x10
+#define DEST_EXTPORT0 0x11
+#define DEST_EXTPORT1 0x12
+#define DEST_EXTPORT2 0x13
+#define DEST_EXTPORT3 0x14
+#define DEST_MCPDM_ON 0x15
+#define DEST_CBP_CBPr 0x3F
+/*
+ * ATC DESCRIPTORS - SOURCES
+ */
+#define SRC_DMEM_access 0x0
+#define SRC_MCBSP1_ RX 0x01
+#define SRC_MCBSP2_RX 0x02
+#define SRC_MCBSP3_RX 0x03
+#define SRC_SLIMBUS1_RX0 0x04
+#define SRC_SLIMBUS1_RX1 0x05
+#define SRC_SLIMBUS1_RX2 0x06
+#define SRC_SLIMBUS1_RX3 0x07
+#define SRC_SLIMBUS1_RX4 0x08
+#define SRC_SLIMBUS1_RX5 0x09
+#define SRC_SLIMBUS1_RX6 0x0A
+#define SRC_SLIMBUS1_RX7 0x0B
+#define SRC_DMIC_UP 0x0C
+#define SRC_MCPDM_UP 0x0D
+#define SRC_MCASP_RX0 0x0E
+#define SRC_MCASP_RX1 0x0F
+#define SRC_MCASP_RX2 0x10
+#define SRC_MCASP_RX3 0x11
+#define SRC_CBP_CBPr 0x3F
+#endif/* _ABE_EXT_H_ */
diff --git a/sound/soc/omap/abe/abe_firmware.c b/sound/soc/omap/abe/abe_firmware.c
new file mode 100644
index 0000000..1676f3c
--- /dev/null
+++ b/sound/soc/omap/abe/abe_firmware.c
@@ -0,0 +1,14355 @@
+0xabeabe00,
+0x00000000,
+0x0000d2a4,
+0x00000d8c,
+0x00000001,
+0x00009495,
+0x00000006,
+0x20314c44,
+0x61757145,
+0x657a696c,
+0x00000072,
+0x00000000,
+0x00000005,
+0x00000019,
+0x74616c46,
+0x73657220,
+0x736e6f70,
+0x00000065,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x322d2073,
+0x00426430,
+0x00000000,
+0x7a684b34,
+0x46504c20,
+0x30202020,
+0x00004264,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x20324c44,
+0x7466654c,
+0x75714520,
+0x7a696c61,
+0x00007265,
+0x00000005,
+0x00000019,
+0x74616c46,
+0x73657220,
+0x736e6f70,
+0x00000065,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x322d2073,
+0x00426430,
+0x00000000,
+0x48303534,
+0x6948207a,
+0x702d6867,
+0x00737361,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x20324c44,
+0x68676952,
+0x71452074,
+0x696c6175,
+0x0072657a,
+0x00000005,
+0x00000019,
+0x74616c46,
+0x73657220,
+0x736e6f70,
+0x00000065,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x322d2073,
+0x00426430,
+0x00000000,
+0x48303534,
+0x6948207a,
+0x702d6867,
+0x00737361,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x65646953,
+0x656e6f74,
+0x75714520,
+0x7a696c61,
+0x00007265,
+0x00000004,
+0x00000009,
+0x74616c46,
+0x73657220,
+0x736e6f70,
+0x00000065,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426438,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x43494d41,
+0x75714520,
+0x7a696c61,
+0x00007265,
+0x00000000,
+0x00000003,
+0x00000013,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426438,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x43494d44,
+0x75714520,
+0x7a696c61,
+0x00007265,
+0x00000000,
+0x00000003,
+0x00000013,
+0x68676948,
+0x7361702d,
+0x64302073,
+0x00000042,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426432,
+0x00000000,
+0x68676948,
+0x7361702d,
+0x312d2073,
+0x00426438,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8cbb51,
+0x000ace72,
+0xfff53192,
+0x007344b1,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffc65da8,
+0x00567385,
+0xffa98c7d,
+0x0039a258,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffe8f244,
+0x00452938,
+0xffbad6c8,
+0x00170dbc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0002e630,
+0x0008b290,
+0x0008b290,
+0x0002e630,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0058ae58,
+0xfffa666a,
+0x0007da1e,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8cbb51,
+0x000ace72,
+0xfff53192,
+0x007344b1,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffc65da8,
+0x00567385,
+0xffa98c7d,
+0x0039a258,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffe8f244,
+0x00452938,
+0xffbad6c8,
+0x00170dbc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x007ac72d,
+0xfff8538e,
+0x007ac72d,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8a3b19,
+0x0007aac2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8cbb51,
+0x000ace72,
+0xfff53192,
+0x007344b1,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffc65da8,
+0x00567385,
+0xffa98c7d,
+0x0039a258,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xffe8f244,
+0x00452938,
+0xffbad6c8,
+0x00170dbc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x007ac72d,
+0xfff8538e,
+0x007ac72d,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8a3b19,
+0x0007aac2,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xff8cbb51,
+0x000ace72,
+0xfff53192,
+0x007344b1,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0xffc65da8,
+0x00567385,
+0xffa98c7d,
+0x0039a258,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0x00000000,
+0xffe8f244,
+0x00452938,
+0xffbad6c8,
+0x00170dbc,
+0x00000000,
+0x0067cd91,
+0xfff596e6,
+0x000b29a2,
+0xffc1248b,
+0xfffd1080,
+0xfffaca4c,
+0xfffab048,
+0xfffdb0ac,
+0x00024f54,
+0x00054fb8,
+0x000535b4,
+0x0002ef80,
+0x003edb7b,
+0x001d92ec,
+0xff962b59,
+0x000bd422,
+0xffe48132,
+0x002dbdc2,
+0xffc7a94a,
+0x0033fbe6,
+0xffdd3502,
+0x000fea26,
+0xfff0490f,
+0xffd10817,
+0xffaca4df,
+0xffab0493,
+0xffdb0acb,
+0x0024f537,
+0x0054fb6f,
+0x00535b23,
+0x002ef7eb,
+0x000fb6f3,
+0x001d930c,
+0xff962afd,
+0x000bd42a,
+0xffe48122,
+0x002dbdda,
+0xffc7a932,
+0x0033fbf6,
+0xffdd34fa,
+0x000fea26,
+0xfff82487,
+0xffe8840b,
+0xffd6526f,
+0xffd5824b,
+0xffed8567,
+0x00127a9b,
+0x002a7db7,
+0x0029ad93,
+0x00177bf7,
+0x0007db7b,
+0x001d930c,
+0xff962afd,
+0x000bd42a,
+0xffe48122,
+0x002dbdda,
+0xffc7a932,
+0x0033fbf6,
+0xffdd34fa,
+0x000fea26,
+0xffc1248b,
+0xfffd1080,
+0xfffaca4c,
+0xfffab048,
+0xfffdb0ac,
+0x00024f54,
+0x00054fb8,
+0x000535b4,
+0x0002ef80,
+0x003edb7b,
+0x001d92ec,
+0xff962b59,
+0x000bd422,
+0xffe48132,
+0x002dbdc2,
+0xffc7a94a,
+0x0033fbe6,
+0xffdd3502,
+0x000fea26,
+0xfff0490f,
+0xffd10817,
+0xffaca4df,
+0xffab0493,
+0xffdb0acb,
+0x0024f537,
+0x0054fb6f,
+0x00535b23,
+0x002ef7eb,
+0x000fb6f3,
+0x001d930c,
+0xff962afd,
+0x000bd42a,
+0xffe48122,
+0x002dbdda,
+0xffc7a932,
+0x0033fbf6,
+0xffdd34fa,
+0x000fea26,
+0xfff82487,
+0xffe8840b,
+0xffd6526f,
+0xffd5824b,
+0xffed8567,
+0x00127a9b,
+0x002a7db7,
+0x0029ad93,
+0x00177bf7,
+0x0007db7b,
+0x001d930c,
+0xff962afd,
+0x000bd42a,
+0xffe48122,
+0x002dbdda,
+0xffc7a932,
+0x0033fbf6,
+0xffdd34fa,
+0x000fea26,
+0x00009495,
+0x00002000,
+0x00001d80,
+0x00004000,
+0x00005510,
+0x1600200f,
+0x0a000960,
+0x08200000,
+0x08200000,
+0x07800000,
+0x160075ce,
+0x014000e0,
+0x014000e1,
+0x014000e2,
+0x014000e3,
+0x014000e4,
+0x014000e5,
+0x014000e6,
+0x014000e7,
+0x014000e8,
+0x014000e9,
+0x014000ea,
+0x014000eb,
+0x014000ec,
+0x014000ed,
+0x014000ef,
+0x014000ef,
+0x144000e4,
+0x9e000000,
+0x0a200e30,
+0x9e000040,
+0x0a200e30,
+0x9e000080,
+0x0a200e30,
+0x9e0000c0,
+0x0a200e30,
+0x9e080000,
+0x0a200e30,
+0x9e080100,
+0x0a200e30,
+0x9e080200,
+0x0a200e30,
+0x9e080300,
+0x0a200e30,
+0x9e080400,
+0x0a200e30,
+0x9e080500,
+0x0a200e30,
+0x9e080600,
+0x0a200e30,
+0x9e080700,
+0x0a200e30,
+0x9c050800,
+0x0a200e30,
+0x16000010,
+0x16000001,
+0x17000102,
+0x01400042,
+0x17800103,
+0x01400043,
+0x98020000,
+0x160003c6,
+0x07800000,
+0x07800000,
+0x9c03b660,
+0x0a0003f0,
+0x9d0c8118,
+0x07800000,
+0x9c0c07b0,
+0x9f16001a,
+0x9f12021a,
+0x9f12031a,
+0x9f12051a,
+0x9f092020,
+0x9f082030,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x988003d0,
+0x07800000,
+0x9d0c8118,
+0x08200000,
+0x160003c6,
+0x07800000,
+0x07800000,
+0x9c03b660,
+0x0a000540,
+0x9d0c8158,
+0x07800000,
+0x9c0c07b0,
+0x9f16001a,
+0x9f12021a,
+0x9f12031a,
+0x9f12051a,
+0x9f040040,
+0x9c0c07b0,
+0x9f03fc10,
+0x07800000,
+0x9f092060,
+0x9f082070,
+0x07800000,
+0x98800520,
+0x07800000,
+0x9d0c8158,
+0x08200000,
+0x160003c6,
+0x07800000,
+0x07800000,
+0x9c03b660,
+0x0a0006b0,
+0x9d0c8118,
+0x07800000,
+0x9c0c07b0,
+0x9f15001a,
+0x9f11041a,
+0x9f092020,
+0x9f082030,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x98800690,
+0x07800000,
+0x9d0c8118,
+0x08200000,
+0x400002c0,
+0x048002ff,
+0x000000c5,
+0x000004c6,
+0x9c028000,
+0x400006c7,
+0x12000155,
+0x013ffefe,
+0xc00008c4,
+0x1e080000,
+0x020005de,
+0x00000ac3,
+0xdc02b160,
+0x04c3ff2d,
+0xdc01ba70,
+0x128002dd,
+0xdc02a440,
+0x048fffdd,
+0x9c061830,
+0x0b200000,
+0x003ffefe,
+0x000002c4,
+0x400004c5,
+0x048ffeff,
+0x000006c6,
+0x000008c7,
+0x9d02a040,
+0x9d02a950,
+0x9d01b260,
+0x9d02bc70,
+0x08200000,
+0x16006906,
+0x00000068,
+0x16008c05,
+0x01000058,
+0x160069ca,
+0x000000a9,
+0x16008c06,
+0x00000068,
+0x0400089b,
+0x4000009c,
+0x1600694e,
+0x410000ec,
+0x0600000c,
+0x160130cd,
+0x0a800a60,
+0x0a200770,
+0x04800299,
+0x410000a9,
+0x05c00b90,
+0x4ac009f0,
+0x04a01085,
+0x16006a04,
+0x40000047,
+0x16006a8e,
+0x04200599,
+0x400000e1,
+0x04800177,
+0x010000a9,
+0x41000047,
+0x04a00111,
+0x410000e1,
+0x06000001,
+0x4aa00c40,
+0x16006a4d,
+0x400000d6,
+0x16004fc9,
+0x400002d7,
+0x04800166,
+0x410000a9,
+0x04900077,
+0x010000d6,
+0x010002d7,
+0x16006906,
+0x00000068,
+0x16008c05,
+0x01000058,
+0x1600c005,
+0x16007541,
+0x16000002,
+0x40000011,
+0x16007500,
+0x9e0e0550,
+0xdd140530,
+0x160ffff4,
+0x41000002,
+0x06000001,
+0x08400000,
+0x01000004,
+0x9d140550,
+0x0a8009a0,
+0x0a000c40,
+0x048006ff,
+0x013ffafb,
+0x013ffcfc,
+0x413ffefe,
+0x04a0020b,
+0x004002bc,
+0x0600000c,
+0x160130cd,
+0x0a800de0,
+0x0a200770,
+0x0a000d80,
+0x003ffefe,
+0x003ffcfc,
+0x003ffafb,
+0x048ffaff,
+0x08200000,
+0x07800000,
+0x01400040,
+0x01400041,
+0x01400042,
+0x01400043,
+0x08200000,
+0x160004a4,
+0x160004b5,
+0x160004c6,
+0x16000007,
+0x9c032040,
+0x9c032950,
+0x9c033260,
+0x9e0f0070,
+0x9e0f0170,
+0x9e0f0270,
+0x9d032040,
+0x9d032950,
+0x9d033260,
+0x08200000,
+0x9f158048,
+0x9c0c07b0,
+0x9f092020,
+0x9f082030,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x07800000,
+0x07800000,
+0x9d088118,
+0x98800f70,
+0x08200000,
+0x9f158048,
+0x9f040040,
+0x9c0c07b0,
+0x9f03fc10,
+0x07800000,
+0x9f092020,
+0x9f082030,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x07800000,
+0x07800000,
+0x9d188148,
+0x98801030,
+0x08200000,
+0x9f158048,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x9c0c07b0,
+0x9f092020,
+0x9f082030,
+0x07800000,
+0x9d188148,
+0x9d188108,
+0x98801120,
+0x08200000,
+0x9f158048,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x9c0c07b0,
+0x9f092020,
+0x9f082030,
+0x07800000,
+0x9d1e8148,
+0x9d1e8108,
+0x988011e0,
+0x08200000,
+0x9f158018,
+0x9f040010,
+0x9c0c07b0,
+0x9f03fc10,
+0x9f092020,
+0x9f082030,
+0x9c0c07b0,
+0x9f092060,
+0x9f082070,
+0x9d1e8108,
+0x988012a0,
+0x08200000,
+0x9c080048,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8118,
+0x98801360,
+0x08200000,
+0x9c180028,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8108,
+0x988013d0,
+0x08200000,
+0x9c180068,
+0x9c180028,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8148,
+0x98801440,
+0x08200000,
+0x9c1e0048,
+0x9c1e0008,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8148,
+0x988014c0,
+0x08200000,
+0x9c1e0008,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8108,
+0x98801540,
+0x08200000,
+0x160004a4,
+0x160004b5,
+0x160004c6,
+0x160000bd,
+0x9c032340,
+0x9c032c50,
+0x9c033560,
+0x9c180028,
+0x9c180068,
+0x9f1d0010,
+0x9c1800a8,
+0x9c1800e8,
+0x9f1d00b0,
+0x07800000,
+0x9d0c8318,
+0x9d0c84b8,
+0x9c180028,
+0x9c180068,
+0x9f1d0010,
+0x07800000,
+0x07800000,
+0x9d0c8518,
+0x98801620,
+0x9d032340,
+0x9d032c50,
+0x9d033560,
+0x08200000,
+0x160003c2,
+0x16000504,
+0x16000515,
+0x16000526,
+0x9c011720,
+0x9c03a440,
+0x9c03ad50,
+0x9c03b660,
+0x160000bd,
+0x9f158418,
+0x9c0c02b0,
+0x9f091020,
+0x9f081030,
+0x9c0c02b0,
+0x9f091060,
+0x9f081070,
+0x07800000,
+0x9d180108,
+0x9d180148,
+0x9f158518,
+0x9c0c02b0,
+0x9f091020,
+0x9f081030,
+0x9c0c02b0,
+0x9f091060,
+0x9f081070,
+0x07800000,
+0x9d180108,
+0x9d180148,
+0x9c0c0618,
+0x07800000,
+0x07800000,
+0x9d180108,
+0x9d180148,
+0x988017f0,
+0x9d032440,
+0x9d032d50,
+0x9d033660,
+0x08200000,
+0x1600000d,
+0x9e0f00d0,
+0x00800e0d,
+0x9f158038,
+0x07800000,
+0x04a002dd,
+0x9d188108,
+0x9f158038,
+0x07800000,
+0x98801a30,
+0x9d188108,
+0x08200000,
+0x9e088100,
+0x07800000,
+0x07800000,
+0x12800277,
+0x04c0ff77,
+0x04a00174,
+0x12800266,
+0x04c0ff66,
+0x04000645,
+0x060ffff4,
+0x17000454,
+0x12000244,
+0x9e0f0140,
+0x07800000,
+0x07800000,
+0x9c0c0118,
+0x07800000,
+0x07800000,
+0x9d0c8118,
+0x98801bb0,
+0x08200000,
+0x08200000,
+0x08200000,
+0x08200000,
+0x9c038600,
+0x07800000,
+0x07800000,
+0x9c180770,
+0xdc100348,
+0x160fff05,
+0x9f000810,
+0x9f118412,
+0x9f001010,
+0x9f002810,
+0x9c0c00b8,
+0x160ffd80,
+0x9d0c8410,
+0x9f1d8012,
+0x9f001810,
+0x9f0400d0,
+0x9c0c0210,
+0x16000204,
+0xdd0e00b0,
+0x16000005,
+0x9f1d80b2,
+0x9f0000b0,
+0x9f0020b0,
+0x9f0400d0,
+0x05800560,
+0x0a801dd0,
+0x9c0c0510,
+0x0a001de0,
+0x9c0c0618,
+0x16000014,
+0x9d0c81e8,
+0x9d0c8148,
+0x0a801e50,
+0x9c0c05b0,
+0x9c0c0510,
+0x0a001e70,
+0x9c0c06b8,
+0x9c0c0618,
+0x07800000,
+0x9d0c81e8,
+0x9d0c8148,
+0x98801c50,
+0x9d180750,
+0x08200000,
+0x9d019220,
+0x048002ff,
+0x14400004,
+0x413ffefe,
+0x16000040,
+0x9c010910,
+0x0a203df0,
+0x14400040,
+0x9c030810,
+0x16000171,
+0x9c009f30,
+0x9c019220,
+0x0a2038f0,
+0x003ffefe,
+0x9c009830,
+0x048ffeff,
+0x08200000,
+0x08200000,
+0x08200000,
+0x08200000,
+0x08200000,
+0x40000024,
+0x048002ff,
+0x41000224,
+0x16000005,
+0x413ffefe,
+0x04000400,
+0x9e0f0150,
+0x01000025,
+0x0a202390,
+0x403ffefe,
+0x16000007,
+0x9e0f0170,
+0x048ffeff,
+0x08200000,
+0x40000024,
+0x048002ff,
+0x41000224,
+0x16000005,
+0x413ffefe,
+0x16000016,
+0x41800dc6,
+0x04000400,
+0x9e0f0150,
+0x01000025,
+0x0a202cd0,
+0x403ffefe,
+0x16000007,
+0x9e0f0170,
+0x048ffeff,
+0x08200000,
+0x048002ff,
+0x413ffefe,
+0x16000005,
+0x01000025,
+0x0a202390,
+0x40000024,
+0x16000005,
+0x403ffefe,
+0x04200454,
+0x41000224,
+0x048ffeff,
+0x08200000,
+0x048002ff,
+0x413ffefe,
+0x16000005,
+0x01000025,
+0x01800dc5,
+0x0a202cd0,
+0x40000024,
+0x16000005,
+0x403ffefe,
+0x04200454,
+0x41000224,
+0x048ffeff,
+0x08200000,
+0x048008ff,
+0x413ff8f8,
+0x1440000d,
+0x9c038e10,
+0x413ffaf9,
+0x04a001dd,
+0x413ffcfa,
+0x16000001,
+0x413ffefb,
+0x160000f0,
+0x9c100400,
+0x9c100480,
+0x9c1d06c4,
+0x9f085030,
+0x9c180674,
+0x9c180650,
+0x058001a0,
+0x0aa02890,
+0x04800144,
+0x04400044,
+0x05800040,
+0x0aa025d0,
+0x05800160,
+0x0ac02570,
+0x9e090000,
+0x07800000,
+0x07800000,
+0x9e0d0500,
+0x9d040508,
+0x0a002760,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x9d040008,
+0x9e0d0500,
+0x0a002760,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x07800000,
+0x9e0d0500,
+0x1280010a,
+0x048001a9,
+0x05800940,
+0x0aa02760,
+0x05800160,
+0x40000628,
+0x160ffff9,
+0x0ac026f0,
+0x05800180,
+0x0ae02760,
+0x160ffff6,
+0x160ffff7,
+0x0a002730,
+0x05800810,
+0x0ae02760,
+0x16000016,
+0x16000007,
+0x9d044690,
+0x04a00144,
+0x9d180674,
+0x05800160,
+0x9d180654,
+0x0ac027d0,
+0x0420040a,
+0x04a001ab,
+0x4a002800,
+0x044000bb,
+0x0480014b,
+0x044000bb,
+0x1440004a,
+0x120001aa,
+0x42000a38,
+0x120001bb,
+0x42000b39,
+0x12000288,
+0x12000299,
+0x9e0e8280,
+0xca0029a0,
+0x1e0e8390,
+0xdd040604,
+0x05800160,
+0x0ac02940,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x05800040,
+0x9e0d0500,
+0x0aa029a0,
+0x9d040508,
+0x0a0029a0,
+0x9e090000,
+0x05800040,
+0x9d040008,
+0x9e0d0500,
+0x0a8029a0,
+0x9d040508,
+0x9c1d06c4,
+0xdc1d0644,
+0x1f0400b0,
+0x9c100700,
+0xdc1d06c4,
+0x1f040010,
+0x9d108480,
+0x9f0940b0,
+0x9d108700,
+0x00000cc9,
+0x06000008,
+0x0aa02ba0,
+0xdc1d0684,
+0x14400005,
+0xdc1d0604,
+0x160fff8a,
+0x04a00255,
+0xdd108480,
+0x16000017,
+0xdd108700,
+0x160ffff8,
+0x05800540,
+0x0aa02b60,
+0x05800160,
+0x0ac02b50,
+0x01000027,
+0x0a002b60,
+0x01000028,
+0x9e088000,
+0xa0054dba,
+0xa005c81a,
+0x0a002c30,
+0x9e088000,
+0xa0054dba,
+0xa005c81a,
+0x160fffaa,
+0x9f1f80b0,
+0x9f1e0010,
+0x9f040020,
+0x9f040070,
+0x9f020810,
+0x9d0446a0,
+0x9e0f0070,
+0x9d0c8118,
+0x98802430,
+0x003ffefb,
+0x003ffcfa,
+0x003ffaf9,
+0x003ff8f8,
+0x048ff8ff,
+0x08200000,
+0x048008ff,
+0x413ff8f8,
+0x1440000d,
+0x9c038e10,
+0x413ffaf9,
+0x04a001dd,
+0x413ffcfa,
+0x16000001,
+0x413ffefb,
+0x04a00100,
+0x9c100400,
+0x9c100480,
+0x9c1d06c4,
+0x9f085030,
+0x9c180674,
+0x9c180650,
+0x058001a0,
+0x4aa03200,
+0x160000f7,
+0x04800144,
+0x04400744,
+0x05800740,
+0x0aa02f20,
+0x05800160,
+0x0ac02ec0,
+0x9e090000,
+0x07800000,
+0x07800000,
+0x9e0d0500,
+0x9d040508,
+0x0a0030c0,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x9d040008,
+0x9e0d0500,
+0x0a0030c0,
+0x9d040008,
+0x9e090000,
+0x160000f7,
+0x07800000,
+0x9e0d0500,
+0x1280017a,
+0x048001a9,
+0x05800940,
+0x0aa030c0,
+0x05800160,
+0x00000ec8,
+0x40000688,
+0x160ffff9,
+0x0ac03050,
+0x05800810,
+0x0ae030c0,
+0x160ffff6,
+0x160ffff7,
+0x0a003090,
+0x05800180,
+0x0ae030c0,
+0x16000016,
+0x16000007,
+0x9d044690,
+0x04a00144,
+0x9d180674,
+0x05800160,
+0x9d180654,
+0x4ac03140,
+0x160000f7,
+0x0420047a,
+0x04a001ab,
+0x4a003170,
+0x044007bb,
+0x0480014b,
+0x044007bb,
+0x1440004a,
+0x120001aa,
+0x42000a38,
+0x120001bb,
+0x42000b39,
+0x12000288,
+0x12000299,
+0x9e0e8280,
+0xca003310,
+0x1e0e8390,
+0xdd040604,
+0x05800160,
+0x0ac032b0,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x060000f4,
+0x9e0d0500,
+0x0aa03310,
+0x9d040508,
+0x0a003310,
+0x9e090000,
+0x060000f4,
+0x9d040008,
+0x9e0d0500,
+0x0a803310,
+0x9d040508,
+0x060000f4,
+0x0aa03590,
+0x9c1d0600,
+0x9f065060,
+0x9f020830,
+0x9f095010,
+0xdc1d0600,
+0x160fffe9,
+0x9f065060,
+0x9f020c30,
+0x0600000a,
+0x0a803590,
+0x9f095010,
+0x00800dcb,
+0x16000028,
+0x0600000a,
+0x0aa03590,
+0x0600000b,
+0x0a803500,
+0x0600000d,
+0x0aa03590,
+0x9d044480,
+0x9d044780,
+0x9c100480,
+0x9c100700,
+0x9d044490,
+0x9d044790,
+0x9d044680,
+0x9d108480,
+0x9d108700,
+0x0a003610,
+0x058000d0,
+0x0aa03590,
+0x9d044490,
+0x9c100700,
+0x9d044790,
+0x9d108480,
+0x9d108700,
+0x9d044480,
+0x9d044780,
+0x9c1d06c4,
+0xdc1d0644,
+0x1f0400b0,
+0x9c100700,
+0x9f040010,
+0x9d108480,
+0x07800000,
+0x9d108700,
+0x9c1d06c4,
+0x07800000,
+0x9f0940b0,
+0x07800000,
+0x00800cc9,
+0x06000008,
+0x0aa037c0,
+0xdc1d0684,
+0x160000f5,
+0xdc1d0604,
+0x160fff8a,
+0x04a00255,
+0xdd108480,
+0x16000017,
+0xdd108700,
+0x160ffff8,
+0x05800540,
+0x0aa03780,
+0x05800160,
+0x0ac03770,
+0x01000027,
+0x0a003780,
+0x01000028,
+0x9e088000,
+0xa0054dba,
+0xa005c81a,
+0x0a003850,
+0x9e088000,
+0xa0054dba,
+0xa005c81a,
+0x160fffaa,
+0x9f1f80b0,
+0x9f1e0010,
+0x9f040020,
+0x9f040070,
+0x9f020810,
+0x9d0446a0,
+0x9e0f0070,
+0x9d0c8118,
+0x98802d70,
+0x003ffefb,
+0x003ffcfa,
+0x003ffaf9,
+0x003ff8f8,
+0x048ff8ff,
+0x08200000,
+0x9c0c0018,
+0x1440001d,
+0x04a001dd,
+0x9d0c8318,
+0x07800000,
+0x9c0c0018,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x98803940,
+0x07800000,
+0xa00602ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x9d0c82b8,
+0x08200000,
+0x9c0c0018,
+0x160000ad,
+0x07800000,
+0x9d0c8318,
+0x07800000,
+0x9c0c0018,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x07800000,
+0x9c0c0018,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c02b8,
+0x98803a70,
+0x9c0c0018,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x07800000,
+0xa00602ba,
+0x07800000,
+0x07800000,
+0x9d0c02b8,
+0x08200000,
+0x9c0c0038,
+0x1440001d,
+0x04a001dd,
+0x9d0c8338,
+0x07800000,
+0xa00602ba,
+0xa006821a,
+0x9c0c0038,
+0x07800000,
+0x9d0c8298,
+0x9d0c8338,
+0x9d0c8198,
+0x98803c50,
+0x07800000,
+0xa00602ba,
+0xa006821a,
+0x07800000,
+0x07800000,
+0x9d0c8298,
+0x9d0c8198,
+0x08200000,
+0xdc0c0018,
+0x04a00201,
+0x04a001dd,
+0xdd040008,
+0x06000001,
+0x04a00111,
+0x0aa03d70,
+0x9d0c8118,
+0x98803d50,
+0x08200000,
+0x9c0c02b0,
+0x9c0c0018,
+0x04a00205,
+0x07800000,
+0x9d0c8118,
+0xdd0c81b8,
+0x06000005,
+0x04a00155,
+0x0aa03e40,
+0x98803e00,
+0x08200000,
+0x9c039e30,
+0x07800000,
+0x9c0c0018,
+0x9f138510,
+0x1600004d,
+0x07800000,
+0x9d0c8318,
+0x07800000,
+0x9c0c0510,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x07800000,
+0x9c0c0018,
+0x9f138510,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x98803f20,
+0x9c0c0510,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c02b8,
+0x07800000,
+0xa00602ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x9d0c82b8,
+0x08200000,
+0x9c0c0018,
+0x1440001d,
+0x04a001dd,
+0x9d0c8218,
+0x07800000,
+0x9c0c0018,
+0xa00582ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x98804140,
+0x1440001d,
+0x9d0c8218,
+0x04a001dd,
+0xa00582ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x988041c0,
+0x08200000,
+0x9c0c0018,
+0x1440001d,
+0x04a002dd,
+0xa00582ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x9d0c8218,
+0x07800000,
+0x07800000,
+0x9c0c0018,
+0x07800000,
+0x07800000,
+0x9d0c8218,
+0x9d0c81b8,
+0x988042c0,
+0x9c0c0018,
+0x1440001d,
+0x04a002dd,
+0xa00582ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x9d0c8218,
+0x07800000,
+0x07800000,
+0x9c0c0018,
+0x07800000,
+0x07800000,
+0x9d0c8218,
+0x9d0c81b8,
+0x988043c0,
+0x08200000,
+0x9f160028,
+0x9f168298,
+0x04a001dd,
+0x07800000,
+0x9d0c8128,
+0x07800000,
+0x9f160028,
+0x9f168298,
+0x98804470,
+0x9d0c8128,
+0x08200000,
+0x9f160020,
+0x9f168098,
+0x9c0c03b0,
+0x9f092020,
+0x9f082030,
+0x9c0c03b0,
+0x9f092060,
+0x9f082070,
+0x07800000,
+0x07800000,
+0x9d0c8108,
+0x9d0c8258,
+0x988044e0,
+0x08200000,
+0x9f160020,
+0x9f168098,
+0x9c0c02b0,
+0x9f092020,
+0x9f082030,
+0x9c0c02b0,
+0x9f092060,
+0x9f082070,
+0x07800000,
+0x07800000,
+0x9d0c8118,
+0x988045c0,
+0x08200000,
+0x9d008810,
+0x1280020d,
+0x07800000,
+0x9c038810,
+0x9e0e0620,
+0x04a001dd,
+0x9f16801a,
+0x9f12011a,
+0x9f039810,
+0x9f026810,
+0x9f118610,
+0x9f1680ba,
+0x9f1201ba,
+0x9f0398b0,
+0x9f0268b0,
+0x9f1186b0,
+0x9d0c8718,
+0x9d108248,
+0x9d108208,
+0x9d0c87b8,
+0x9d1082c8,
+0x9d108288,
+0x988046f0,
+0x08200000,
+0x00000003,
+0x00000205,
+0x1440001d,
+0x9c039830,
+0x9c03aa50,
+0x07800000,
+0x9c0c0018,
+0x9c0c02b8,
+0x07800000,
+0x07800000,
+0x9d0c8128,
+0x98804870,
+0x08200000,
+0x00001007,
+0x048002ff,
+0x013ffefe,
+0x06000007,
+0x00801605,
+0x16013523,
+0x0a804a30,
+0x12000155,
+0x0200035e,
+0x0b200000,
+0x00800405,
+0x16013523,
+0x12000155,
+0x0200035e,
+0x0b200000,
+0x00801705,
+0x16013523,
+0x12000155,
+0x0200035e,
+0x0b200000,
+0x003ffefe,
+0x048ffeff,
+0x07800000,
+0x08200000,
+0x00800b03,
+0x16000181,
+0x048004ff,
+0x40800a0d,
+0x04000101,
+0x00000212,
+0x00000017,
+0x9e0e0420,
+0x00000416,
+0xdc180404,
+0x06000003,
+0x9c180480,
+0x0aa04ee0,
+0x9c052b20,
+0x9c042820,
+0x9c023970,
+0x40800e04,
+0x16000005,
+0x40800503,
+0x0600000d,
+0x9d01b060,
+0x4a804c40,
+0x0400033d,
+0x04200427,
+0x04200d77,
+0x05800750,
+0x0ae04c40,
+0x16000006,
+0x16000145,
+0x0a004ec0,
+0x160fffd6,
+0x05800420,
+0x0ae04dc0,
+0x160fffe6,
+0x04000344,
+0x05800420,
+0x0ae04eb0,
+0x160ffff6,
+0x04000344,
+0x05800420,
+0x0ae04eb0,
+0x16000006,
+0x04000344,
+0x05800420,
+0x0ae04eb0,
+0x16000016,
+0x04000344,
+0x05800420,
+0x0ae04eb0,
+0x16000026,
+0x04000344,
+0x05800420,
+0x0ae04eb0,
+0x16000036,
+0x013ffcf6,
+0x12000132,
+0x04000233,
+0x9e088300,
+0x40800e02,
+0x16000005,
+0x04000233,
+0x12000233,
+0x04200377,
+0x05800570,
+0x16001e02,
+0x17800523,
+0x04000377,
+0x9e0f0070,
+0x003ffcf6,
+0x00800715,
+0x01000606,
+0x0a0052f0,
+0x9c042b20,
+0x9c052920,
+0x9c023870,
+0x07800000,
+0x07800000,
+0x9d00b360,
+0x16000004,
+0x16000005,
+0x160fffb6,
+0x00800503,
+0x05800420,
+0x0ae051f0,
+0x160fffc6,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x160fffd6,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x160fffe6,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x160ffff6,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000006,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000016,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000026,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000036,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000046,
+0x04000344,
+0x05800420,
+0x0ae052d0,
+0x16000056,
+0x013ffcf6,
+0x12000232,
+0x04000233,
+0x9e088300,
+0x16000005,
+0x12000233,
+0x04000377,
+0x04a1e077,
+0x05800570,
+0x16001e02,
+0x17800523,
+0x04000377,
+0x9e0f0170,
+0x003ffcf6,
+0x01000606,
+0x00800715,
+0x16013526,
+0x413ffefe,
+0x12000155,
+0x00000202,
+0x00800d04,
+0x0200056e,
+0x16020e05,
+0x16014246,
+0x16014287,
+0x0400042d,
+0x04a001dd,
+0x9e0e0750,
+0x9e0e0260,
+0x9e0e0370,
+0x0b200000,
+0x00000806,
+0x003ffefe,
+0x0000021d,
+0x9e0e0560,
+0x40800b05,
+0x048ffcff,
+0x408007d7,
+0x06000005,
+0x40800f02,
+0x04c07f77,
+0x4a805540,
+0x04500273,
+0x00800a02,
+0x9e088100,
+0x00000011,
+0x418007d3,
+0x16000003,
+0x12800277,
+0x018003d7,
+0x9d140530,
+0x9d038810,
+0x08200000,
+0x00800a02,
+0x9e088000,
+0x00000011,
+0x418007d3,
+0x16000003,
+0x12800277,
+0x018000d7,
+0x9d140530,
+0x9d038910,
+0x08200000,
+0x00001807,
+0x00801e02,
+0x16000003,
+0x9c01b970,
+0x06000082,
+0x17000233,
+0x9e088100,
+0x07800000,
+0x12000c33,
+0x04c3ff66,
+0x04500366,
+0x07800000,
+0x16000003,
+0x9e0c8100,
+0x16007f46,
+0x00000064,
+0x1600003d,
+0x04a00122,
+0x9c03a040,
+0x04800266,
+0x9e0f0130,
+0x04800433,
+0x06000002,
+0x9c0c0038,
+0x9c0c0078,
+0x9c0c00b8,
+0x9d0c810c,
+0x9d0c815c,
+0x9d0c81ac,
+0x98805750,
+0x0aa056d0,
+0x9e0f0120,
+0x08200000,
+0x00001004,
+0x0080070d,
+0x06000004,
+0x00800203,
+0x0b800000,
+0x40800905,
+0x048002ff,
+0x40001604,
+0x040003dd,
+0x413ffefe,
+0x06000004,
+0x9c03a950,
+0x4aa05920,
+0x144000d2,
+0x0a205be0,
+0x40001604,
+0x1440002d,
+0x06000004,
+0x0a805a60,
+0x05800d40,
+0x0ae05960,
+0x0a205a90,
+0x0a005a10,
+0x042004d2,
+0x1440004d,
+0x0a205a90,
+0x0a205be0,
+0x06000002,
+0x0a805a10,
+0x1440002d,
+0x00001604,
+0x05800d40,
+0x0ac05a60,
+0x0a205a90,
+0x003ffefe,
+0x40800905,
+0x048ffeff,
+0x9d03a950,
+0x08200000,
+0x04a0012d,
+0x0a201a90,
+0x0a005a10,
+0x16014246,
+0x40800605,
+0x048002ff,
+0x413ffefe,
+0x144000d3,
+0x1601352e,
+0x9e0e0260,
+0x12000155,
+0x420005ee,
+0x04a001dd,
+0x0b200000,
+0x9e088000,
+0x403ffefe,
+0x16000006,
+0x40001605,
+0x048ffeff,
+0x9e0e8040,
+0x9e0f0060,
+0x04200355,
+0x01001605,
+0x08200000,
+0x40800b0d,
+0x16000246,
+0x40000403,
+0x04c001d7,
+0x06000007,
+0x4a805cd0,
+0x16000017,
+0x00001e04,
+0x06000004,
+0x0a805df0,
+0x40001c05,
+0x048001dd,
+0x01001604,
+0x01001405,
+0x0a005d40,
+0x00001a04,
+0x06000004,
+0x0a805df0,
+0x40001805,
+0x048001dd,
+0x01001604,
+0x01001405,
+0x9e0e8050,
+0x41800b0d,
+0x16000005,
+0x40800a04,
+0x05c00630,
+0x0a805de0,
+0x12000233,
+0x9e0e0530,
+0x9d140550,
+0x0a005df0,
+0x01800017,
+0x08200000,
+0x048008ff,
+0x413ff8f8,
+0x1440001d,
+0x013ffaf9,
+0x413ffcfa,
+0x16006a49,
+0x413ffefb,
+0x16015002,
+0x00000095,
+0x00000296,
+0x9c018201,
+0x01000025,
+0x41400226,
+0x16002743,
+0x04800122,
+0x9e088200,
+0x9e090300,
+0x07800000,
+0x12800277,
+0x128002bb,
+0x01c00127,
+0x01c0012b,
+0x9c018201,
+0x98805ef0,
+0x04800633,
+0x1440001d,
+0x00000034,
+0x04802833,
+0x01c00124,
+0x98805fa0,
+0x16002102,
+0x9e0e0220,
+0x16000806,
+0x16007eca,
+0x16007f0b,
+0x9d140270,
+0x000000a8,
+0x000000b9,
+0x04a00188,
+0x04a00199,
+0x16000005,
+0x16000006,
+0x06000008,
+0x0aa060e0,
+0x16000015,
+0x000002a8,
+0x06000009,
+0x0aa06120,
+0x16000016,
+0x000002b9,
+0x16007102,
+0x410000a8,
+0x12000166,
+0x410000b9,
+0x04500655,
+0x40800021,
+0x16006a4d,
+0x41800027,
+0x06000004,
+0x0aa06210,
+0x06000005,
+0x0aa06290,
+0x06000001,
+0x0aa06320,
+0x0a006410,
+0x160000a8,
+0x400000d6,
+0x12000c88,
+0x04500487,
+0x07800000,
+0x06000005,
+0x9d180078,
+0x0a806300,
+0x160000c8,
+0x400000d6,
+0x12000c88,
+0x04500587,
+0x07800000,
+0x07800000,
+0x9d180078,
+0x06000001,
+0x0a806390,
+0x160000d8,
+0x400000d6,
+0x12000c88,
+0x04500187,
+0x07800000,
+0x07800000,
+0x9d180078,
+0x16000903,
+0x16000fb9,
+0x16000016,
+0x9e0e0530,
+0x16000007,
+0x9d03c890,
+0x07800000,
+0x9d140570,
+0x16006ac8,
+0x40000280,
+0x16000013,
+0x00000084,
+0x06000000,
+0x40000049,
+0x16006a82,
+0x4a8064b0,
+0x16000005,
+0x04200959,
+0x05800590,
+0x41000045,
+0x160ffff6,
+0x17000353,
+0x17800363,
+0x04800233,
+0x01000023,
+0x16015002,
+0x01004a23,
+0x403ffefb,
+0x16002202,
+0x9e0e0220,
+0x403ffcfa,
+0x16000806,
+0x003ffaf9,
+0x003ff8f8,
+0x9d140270,
+0x048ff8ff,
+0x08200000,
+0x048008ff,
+0x413ff8f8,
+0x16015002,
+0x013ffaf9,
+0x013ffcfa,
+0x413ffefb,
+0x04803322,
+0x16008385,
+0x16000e0d,
+0x00000454,
+0x00000856,
+0x9c0768d0,
+0x01c00124,
+0x01c00126,
+0x40000087,
+0x16003129,
+0x0000028d,
+0x40000c54,
+0x12000299,
+0x00000e56,
+0x01c00127,
+0x0180012d,
+0x9e0e0490,
+0x41400224,
+0x16003138,
+0x41400226,
+0x12000288,
+0x9c100480,
+0x9f03e0b0,
+0x9e0e0580,
+0x9e010080,
+0xdc1005c0,
+0x1600060d,
+0x9f03e0b0,
+0x01400229,
+0x9e0080c0,
+0x0140022a,
+0x9c01ead0,
+0x01400225,
+0x41400226,
+0x16000633,
+0x9e090200,
+0x04800122,
+0x9c029c30,
+0x128002bb,
+0x01c0012b,
+0x160005bd,
+0x9e088400,
+0x07800000,
+0x9c01ead0,
+0x12800277,
+0x01c00127,
+0x9e090200,
+0x16000023,
+0x1600005d,
+0x128002bb,
+0x9c029c30,
+0x01c0012b,
+0x04800122,
+0x9e088400,
+0x9c01ead0,
+0x07800000,
+0x12800277,
+0x9e090200,
+0x07800000,
+0x01c00127,
+0x128002bb,
+0x01c0012b,
+0x04800222,
+0x16008185,
+0x16000e2d,
+0x00000454,
+0x00000856,
+0x9c0768d0,
+0x01c00124,
+0x01c00126,
+0x40000087,
+0x16003149,
+0x0000028d,
+0x40000c54,
+0x12000299,
+0x00000e56,
+0x01c00127,
+0x0180012d,
+0x9e0e0490,
+0x41400224,
+0x16003158,
+0x41400226,
+0x12000288,
+0x9c100480,
+0x9f03e0b0,
+0x9e0e0580,
+0x9e010080,
+0xdc1005c0,
+0x1600009d,
+0x9f03e0b0,
+0x01400229,
+0x9e0080c0,
+0x0140022a,
+0x9c01ead0,
+0x01400225,
+0x16000563,
+0x01400226,
+0x9e090200,
+0x9c029c30,
+0x07800000,
+0x128002bb,
+0x9e088400,
+0x01c0022b,
+0x07800000,
+0x12800277,
+0x01c00227,
+0x003ffefb,
+0x003ffcfa,
+0x003ffaf9,
+0x003ff8f8,
+0x048ff8ff,
+0x08200000,
+0x16000023,
+0x16012f01,
+0x16000bf5,
+0x00000010,
+0x04800200,
+0x9c01aa50,
+0x04c07f00,
+0x16012704,
+0x01000010,
+0x04000400,
+0x00000005,
+0x07800000,
+0x07800000,
+0x9c00a850,
+0x07800000,
+0x07800000,
+0x9e088000,
+0x9f038490,
+0x07800000,
+0x12800266,
+0x04c0ff6d,
+0x9c0c0018,
+0x9f0b0010,
+0x9f092080,
+0x98806e90,
+0x9c0c0330,
+0x07800000,
+0x07800000,
+0x9f0920e0,
+0x07800000,
+0x07800000,
+0x06000004,
+0x0a8070e0,
+0x00000010,
+0x04800200,
+0x9c01aa50,
+0x04c07f00,
+0x16012704,
+0x04000400,
+0x00000005,
+0x07800000,
+0x07800000,
+0x9c00a850,
+0x07800000,
+0x07800000,
+0x9e088000,
+0x9f038490,
+0x07800000,
+0x12800266,
+0x04c0ff6d,
+0x9f038410,
+0x07800000,
+0x07800000,
+0x9c0c00b0,
+0x07800000,
+0x07800000,
+0x9d0c8038,
+0x98807090,
+0x00000010,
+0x04800200,
+0x04c07f00,
+0x07800000,
+0x01000010,
+0x04a00133,
+0x06000003,
+0x0aa06d50,
+0x08200000,
+0x16000023,
+0x16012f21,
+0x16000bf5,
+0x00000010,
+0x04800200,
+0x9c01aa50,
+0x04c07f00,
+0x16012704,
+0x01000010,
+0x04000400,
+0x00000005,
+0x07800000,
+0x07800000,
+0x9c00a850,
+0x07800000,
+0x07800000,
+0x9e088000,
+0x9f038490,
+0x07800000,
+0x12800266,
+0x04c0ff6d,
+0x9c0c0018,
+0x9f0b0010,
+0x9f092090,
+0x988072c0,
+0x9c0c0330,
+0x07800000,
+0x07800000,
+0x9f0920e0,
+0x07800000,
+0x07800000,
+0x06000004,
+0x0a807510,
+0x00000010,
+0x04800200,
+0x9c01aa50,
+0x04c07f00,
+0x16012704,
+0x04000400,
+0x00000005,
+0x07800000,
+0x07800000,
+0x9c00a850,
+0x07800000,
+0x07800000,
+0x9e088000,
+0x9f038490,
+0x07800000,
+0x12800266,
+0x04c0ff6d,
+0x9f038410,
+0x07800000,
+0x07800000,
+0x9c0c00b0,
+0x07800000,
+0x07800000,
+0x9d0c8098,
+0x988074c0,
+0x00000010,
+0x04800200,
+0x04c07f00,
+0x07800000,
+0x01000010,
+0x04a00133,
+0x06000003,
+0x0aa07180,
+0x08200000,
+0x00000004,
+0x00000405,
+0x00000806,
+0x00000c07,
+0x05c00540,
+0x0b800000,
+0x9e0e8040,
+0x9c180034,
+0x07800000,
+0x07800000,
+0x06000033,
+0x9e0e8220,
+0x0aa076c0,
+0x9c1d0004,
+0x9c1d0044,
+0x07800000,
+0x9d0c0210,
+0x0a007770,
+0x06000023,
+0x0aa07720,
+0x9c1d0004,
+0x9d040004,
+0x9d100200,
+0x0a007770,
+0x06000043,
+0x0aa07770,
+0x9c180024,
+0x9d040004,
+0x9d180200,
+0x04800c44,
+0x05c00740,
+0x17800644,
+0x01000004,
+0x0a0075e0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x07800000,
+0x07800000,
+0x07800000,
+0x08400000,
+0x0a000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00151000,
+0x00201000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00000000,
+0x00001011,
+0x00001011,
+0x00021031,
+0x00041051,
+0x00061071,
+0x00081091,
+0x000a10b1,
+0x000c10d1,
+0x00001001,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00001011,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001041,
+0x00001000,
+0x00000000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00000000,
+0x00000000,
+0x00001001,
+0x00001001,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001001,
+0x00000001,
+0x00001000,
+0x00000858,
+0x00001000,
+0x00001001,
+0x00000001,
+0x00001000,
+0x00000858,
+0x00151000,
+0x00000858,
+0x00000858,
+0x00151000,
+0x00001000,
+0x00001001,
+0x00000001,
+0x00001000,
+0x00000898,
+0x00001000,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001001,
+0x000010c1,
+0x00001000,
+0x000010c1,
+0x00001001,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001061,
+0x00001031,
+0x00001061,
+0x00001021,
+0x00001061,
+0x00001031,
+0x00001061,
+0x00001021,
+0x00001061,
+0x00001031,
+0x00001061,
+0x00001021,
+0x00001061,
+0x00001031,
+0x00001061,
+0x00001021,
+0x00001061,
+0x00001021,
+0x00001061,
+0x00001031,
+0x00151000,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001071,
+0x000000aa,
+0x00001071,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001000,
+0x0000004d,
+0x000000a8,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x003c1000,
+0x00001000,
+0x003c1000,
+0x00001001,
+0x00001000,
+0x0000004d,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001001,
+0x00001001,
+0x00001000,
+0x00001051,
+0x00001000,
+0x00001001,
+0x00001051,
+0x00001001,
+0x000000c6,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001001,
+0x00001001,
+0x0000fff9,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00001001,
+0x00001091,
+0x00001000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00001091,
+0x00001091,
+0x00001091,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00001001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00001001,
+0x00000000,
+0x00011001,
+0x00001000,
+0x00151000,
+0x00001001,
+0x00000001,
+0x00001000,
+0x00000858,
+0x00000858,
+0x00001000,
+0x00151000,
+0x00151000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001000,
+0x00001001,
+0x00000001,
+0x00001000,
+0x00000858,
+0x00000858,
+0x00000000,
+0x00000000,
+0x00001001,
+0x00000000,
+0x00000000,
+0x00001000,
+0x00000000,
+0x00000000,
+0x00001001,
+0x00000000,
+0x00001001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000008,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00700001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00100001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00fc4793,
+0x000a8b43,
+0x00e7110b,
+0x003411d3,
+0x009d1cfb,
+0x0002b6a8,
+0x00fb8ca8,
+0x0006dac8,
+0x00f610e8,
+0x000d8628,
+0x00eed498,
+0x0013f0e8,
+0x00eb9d08,
+0x000f02e8,
+0x00056260,
+0x00bf42f0,
+0x006a9a5d,
+0x005ed280,
+0x00023c94,
+0x00fb2e83,
+0x000c8ac3,
+0x00e408e3,
+0x0037ceab,
+0x0099fe5b,
+0x0002b430,
+0x00fbb618,
+0x000661c0,
+0x00f71850,
+0x000b9710,
+0x00f220d0,
+0x000eb9d8,
+0x00f37700,
+0x0003c304,
+0x00142c90,
+0x00b09170,
+0x0066c791,
+0x006d23e0,
+0x000208b8,
+0x00fa9443,
+0x000d8413,
+0x00e2e293,
+0x00386703,
+0x009badeb,
+0x000296d8,
+0x00fc0144,
+0x0005c418,
+0x00f83d98,
+0x0009a2c0,
+0x00f53c30,
+0x000a1678,
+0x00fa10a0,
+0x00fadbf0,
+0x001ef5c0,
+0x00a7ab80,
+0x0061b101,
+0x00782010,
+0x000464a8,
+0x00fa1fab,
+0x000e2353,
+0x00e28193,
+0x003770b3,
+0x00a04a0b,
+0x000264f0,
+0x00fc6e8c,
+0x0004f108,
+0x00f9b218,
+0x00073f50,
+0x00f8ea80,
+0x0004be58,
+0x005c1863,
+0x00f141c8,
+0x002a0528,
+0x009fa4a8,
+0x005b6439,
+0x0042ccf5,
+0x0005d8f0,
+0x00f9f08b,
+0x000e2e23,
+0x00e33ce3,
+0x00348833,
+0x00a80de3,
+0x00022008,
+0x00fcf654,
+0x0003fc0c,
+0x00fb4d68,
+0x0004b6b0,
+0x00fcaf74,
+0x00dcf75b,
+0x000875d0,
+0x00e88c00,
+0x00334af8,
+0x009a9170,
+0x0053f3c9,
+0x00498425,
+0x0007d850,
+0x00fa0193,
+0x000db28b,
+0x00e4f083,
+0x0030005b,
+0x00b24bfb,
+0x007356ab,
+0x00fd8f38,
+0x0002f50c,
+0x00fcf624,
+0x00022f7c,
+0x0014e623,
+0x00fa8240,
+0x000ec210,
+0x00e12888,
+0x003a6068,
+0x00989408,
+0x004b98d9,
+0x004fdc61,
+0x000aadb0,
+0x00fa47fb,
+0x000cc843,
+0x00e76cb3,
+0x002a3303,
+0x00be6543,
+0x005c437b,
+0x008ca913,
+0x007977d3,
+0x00a7922b,
+0x00ef1dc3,
+0x0003bf5c,
+0x00f604a8,
+0x00143b08,
+0x00db27e8,
+0x003f50c0,
+0x009968b8,
+0x00427b21,
+0x0055cb8d,
+0x000e5198,
+0x00faba2b,
+0x000b83a3,
+0x00ea894b,
+0x00236a23,
+0x00cbda13,
+0x004398b3,
+0x00b6e5bb,
+0x003575db,
+0x000eee5b,
+0x00fd6ac0,
+0x0006e2f8,
+0x00f20c30,
+0x0018d298,
+0x00d68e40,
+0x00423000,
+0x009cd148,
+0x00716ee8,
+0x005b537d,
+0x0012b270,
+0x00fb4feb,
+0x0009f65b,
+0x00ee2313,
+0x001be763,
+0x00da372b,
+0x002a1533,
+0x00e15813,
+0x00f2fbd3,
+0x007127a3,
+0x00fb4778,
+0x0009ae08,
+0x00eeab88,
+0x001c7728,
+0x00d365f8,
+0x004306e0,
+0x00a2a0d0,
+0x005cd070,
+0x00606a75,
+0x0017d078,
+0x00fc00bb,
+0x0008330b,
+0x00f2141b,
+0x0013f29b,
+0x00e8fcc3,
+0x00108f73,
+0x000aabc3,
+0x00b409ab,
+0x00032d94,
+0x00f961f0,
+0x000c0d48,
+0x00ebf900,
+0x001f1310,
+0x00d1bd70,
+0x0041db98,
+0x00aaa7f0,
+0x004768e0,
+0x0064f695,
+0x001db640,
+0x00fcc40b,
+0x00064cab,
+0x00f635fb,
+0x000bd423,
+0x00f7ab83,
+0x00f7da9b,
+0x00319613,
+0x00fdea24,
+0x00046be0,
+0x00f7c838,
+0x000def88,
+0x00ea0778,
+0x002095b8,
+0x00d19bf0,
+0x003ebd10,
+0x00b4aec0,
+0x00318e40,
+0x0068d739,
+0x002477b8,
+0x00fd9103,
+0x000456bb,
+0x00fa6163,
+0x0003d51b,
+0x0005c47b,
+0x00e0c55b,
+0x0054da23,
+0x00fd2110,
+0x000575e0,
+0x00f68680,
+0x000f46d0,
+0x00e8e4e8,
+0x0020f5c0,
+0x00d2fe70,
+0x0039c7a8,
+0x00c06ee8,
+0x001ba3e0,
+0x006be82d,
+0x002c29d8,
+0x00fe5ef3,
+0x000264b3,
+0x00fe6f83,
+0x00fc3c73,
+0x0012cf0b,
+0x00cc0f3b,
+0x00735b43,
+0x00fc7b10,
+0x00064398,
+0x00f5a608,
+0x001009d8,
+0x00e89830,
+0x002033b8,
+0x00d5d488,
+0x003327e0,
+0x00cd9208,
+0x000617a0,
+0x006e0619,
+0x0034dcb8,
+0x00ff2633,
+0x0000878b,
+0x00023efb,
+0x00f54613,
+0x001e683b,
+0x00ba501b,
+0x00023104,
+0x00fbfc98,
+0x0006cfe8,
+0x00f52c00,
+0x001034f8,
+0x00e92088,
+0x001e5960,
+0x00da0390,
+0x002b1358,
+0x00dbbf58,
+0x00f14c40,
+0x006f129d,
+0x003ea030,
+0x00ffdfeb,
+0x00feceb3,
+0x0005b193,
+0x00ef271b,
+0x00283a63,
+0x00ac06cb,
+0x00027b84,
+0x00fba8d8,
+0x00071778,
+0x00f51a98,
+0x000fc900,
+0x00ea7720,
+0x001b7880,
+0x00df6710,
+0x0021ca50,
+0x00ea95d0,
+0x00dda780,
+0x006ef2a5,
+0x00497dd8,
+0x00000003,
+0x00fd4a6b,
+0x0008a803,
+0x00ea151b,
+0x002ff333,
+0x00a1a463,
+0x0002aad0,
+0x00fb81d8,
+0x00071978,
+0x00f56fc8,
+0x000ecde0,
+0x00ec89f0,
+0x0017b2e0,
+0x00e5c408,
+0x0017aaa0,
+0x00f99118,
+0x00cbaf78,
+0x006d93e5,
+0x005561e0,
+0x00000020,
+0x003fffe0,
+0x00000020,
+0x003fffe0,
+0x00069cf3,
+0x00eda3d3,
+0x00284343,
+0x00b2821b,
+0x000228bc,
+0x00fc4508,
+0x0006a660,
+0x00f19bc0,
+0x007f26c5,
+0x00107398,
+0x00f8cbc0,
+0x0003fef8,
+0x00fdafb8,
+0x00539323,
+0x00d40cc3,
+0x0014740b,
+0x00f855f3,
+0x0001b16b,
+0x000c0373,
+0x00ddec9b,
+0x004b880b,
+0x00fdb6d0,
+0x00041728,
+0x00f8ede8,
+0x000c8b38,
+0x00e57730,
+0x007ca649,
+0x0022b568,
+0x00f146b8,
+0x00081d20,
+0x00fb4da0,
+0x0002a8ac,
+0x00a5ff43,
+0x002a4a93,
+0x00efdbfb,
+0x0003c6eb,
+0x00101e33,
+0x00d13c0b,
+0x0068d11b,
+0x00fcce9c,
+0x0005bc08,
+0x00f61488,
+0x001185c8,
+0x00dbb070,
+0x00788dfd,
+0x00367598,
+0x00e9b5b8,
+0x000c31f8,
+0x00f8f1a0,
+0x00040178,
+0x00fdde98,
+0x0040ab93,
+0x00e6e21b,
+0x0006309b,
+0x0012ea3b,
+0x00c7c91b,
+0x007f746f,
+0x00fc1754,
+0x00070c10,
+0x00f3cc50,
+0x00157878,
+0x00d45408,
+0x0072f70d,
+0x004b56d0,
+0x00e26390,
+0x001012a8,
+0x00f6b500,
+0x00054a20,
+0x00fd2bf0,
+0x0056a233,
+0x00ddc993,
+0x0008d62b,
+0x00147503,
+0x00c1a1c3,
+0x00023c70,
+0x00fb9490,
+0x0007fff0,
+0x00f221f8,
+0x00185148,
+0x00cf5d50,
+0x006c0395,
+0x0060f058,
+0x00db9f08,
+0x00139340,
+0x00f4b188,
+0x00067398,
+0x00fc8844,
+0x006b2573,
+0x00d501e3,
+0x000b96fb,
+0x0014d9d3,
+0x00beae3b,
+0x00025f04,
+0x00fb4790,
+0x00089470,
+0x00f11b68,
+0x001a0988,
+0x00ccb738,
+0x0063ddc5,
+0x0076d0d4,
+0x00d5b880,
+0x001688a8,
+0x00f30060,
+0x00076f18,
+0x00fbfbf8,
+0x007d228f,
+0x00cd04b3,
+0x000e4b13,
+0x00143ecb,
+0x00beb5b3,
+0x000266a0,
+0x00fb2f48,
+0x0008ca48,
+0x00f0b7e8,
+0x001aa578,
+0x00cc3da8,
+0x005ab67d,
+0x004640a1,
+0x00d0ff50,
+0x0018ca30,
+0x00f1b920,
+0x00082ea8,
+0x00fb8f00,
+0x00022e24,
+0x00c650c3,
+0x0010c49b,
+0x0012d1ab,
+0x00c1642b,
+0x0002555c,
+0x00fb48b0,
+0x0008a5d0,
+0x00f0f0a0,
+0x001a3350,
+0x00cdbf38,
+0x0050c415,
+0x0050c415,
+0x00cdbf38,
+0x001a3350,
+0x00f0f0a0,
+0x0008a5d0,
+0x00fb48b0,
+0x0002555c,
+0x00c1642b,
+0x0012d1ab,
+0x0010c49b,
+0x00c650c3,
+0x00022e24,
+0x00fb8f00,
+0x00082ea8,
+0x00f1b920,
+0x0018ca30,
+0x00d0ff50,
+0x004640a1,
+0x005ab67d,
+0x00cc3da8,
+0x001aa578,
+0x00f0b7e8,
+0x0008ca48,
+0x00fb2f48,
+0x000266a0,
+0x00beb5b3,
+0x00143ecb,
+0x000e4b13,
+0x00cd04b3,
+0x007d228f,
+0x00fbfbf8,
+0x00076f18,
+0x00f30060,
+0x001688a8,
+0x00d5b880,
+0x0076d0d4,
+0x0063ddc5,
+0x00ccb738,
+0x001a0988,
+0x00f11b68,
+0x00089470,
+0x00fb4790,
+0x00025f04,
+0x00beae3b,
+0x0014d9d3,
+0x000b96fb,
+0x00d501e3,
+0x006b2573,
+0x00fc8844,
+0x00067398,
+0x00f4b188,
+0x00139340,
+0x00db9f08,
+0x0060f058,
+0x006c0395,
+0x00cf5d50,
+0x00185148,
+0x00f221f8,
+0x0007fff0,
+0x00fb9490,
+0x00023c70,
+0x00c1a1c3,
+0x00147503,
+0x0008d62b,
+0x00ddc993,
+0x0056a233,
+0x00fd2bf0,
+0x00054a20,
+0x00f6b500,
+0x001012a8,
+0x00e26390,
+0x004b56d0,
+0x0072f70d,
+0x00d45408,
+0x00157878,
+0x00f3cc50,
+0x00070c10,
+0x00fc1754,
+0x007f746f,
+0x00c7c91b,
+0x0012ea3b,
+0x0006309b,
+0x00e6e21b,
+0x0040ab93,
+0x00fdde98,
+0x00040178,
+0x00f8f1a0,
+0x000c31f8,
+0x00e9b5b8,
+0x00367598,
+0x00788dfd,
+0x00dbb070,
+0x001185c8,
+0x00f61488,
+0x0005bc08,
+0x00fcce9c,
+0x0068d11b,
+0x00d13c0b,
+0x00101e33,
+0x0003c6eb,
+0x00efdbfb,
+0x002a4a93,
+0x00a5ff43,
+0x0002a8ac,
+0x00fb4da0,
+0x00081d20,
+0x00f146b8,
+0x0022b568,
+0x007ca649,
+0x00e57730,
+0x000c8b38,
+0x00f8ede8,
+0x00041728,
+0x00fdb6d0,
+0x004b880b,
+0x00ddec9b,
+0x000c0373,
+0x0001b16b,
+0x00f855f3,
+0x0014740b,
+0x00d40cc3,
+0x00539323,
+0x00fdafb8,
+0x0003fef8,
+0x00f8cbc0,
+0x00107398,
+0x007f26c5,
+0x00f19bc0,
+0x0006a660,
+0x00fc4508,
+0x000228bc,
+0x00b2821b,
+0x00284343,
+0x00eda3d3,
+0x00069cf3,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00040002,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000003,
+0x00000020,
+0x003fffe0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x004b54e7,
+0x002866b7,
+0x0002526c,
+0x005d3e43,
+0x0002526c,
+0x002866b7,
+0x004b54e7,
+0x0090828c,
+0x00097262,
+0x00e8875a,
+0x0021f9ea,
+0x00e1aff2,
+0x000feece,
+0x000387fc,
+0x0079341b,
+0x0006f740,
+0x00045eec,
+0x0006f740,
+0x0079341b,
+0x000387fc,
+0x0090828c,
+0x00097262,
+0x00e8875a,
+0x0021f9ea,
+0x00e1aff2,
+0x000feece,
+0x007de295,
+0x00f821da,
+0x007de295,
+0x008431e5,
+0x0007dde2,
+0x0012f747,
+0x00c81d03,
+0x005f165b,
+0x0094600b,
+0x005f165b,
+0x00c81d03,
+0x0012f747,
+0x00aa0ab1,
+0x001057be,
+0x00d5b832,
+0x003b8bf6,
+0x00cfd2ca,
+0x00154066,
+0x0071cb9f,
+0x00fac2b8,
+0x0008ea18,
+0x00f5e900,
+0x0008ea18,
+0x00fac2b8,
+0x0071cb9f,
+0x00aa0ab1,
+0x001057be,
+0x00d5b832,
+0x003b8bf6,
+0x00cfd2ca,
+0x00154066,
+0x008e3ba9,
+0x000aaa6a,
+0x00f5559a,
+0x0071c459,
+0x00651dd9,
+0x00f5c6b6,
+0x000b0ede,
+0x00000020,
+0x003fffe0,
+0x00269ec3,
+0x000d0ff4,
+0x00051eba,
+0x00640001,
+0x0002f290,
+0x00fdd340,
+0x0002a810,
+0x0002a810,
+0x00fdd340,
+0x0002f290,
+0x0045a895,
+0x00f4a186,
+0x0018a312,
+0x00e445b2,
+0x0010419e,
+0x000b68e0,
+0x0021f7f0,
+0x0044471c,
+0x005c5e48,
+0x005c5e48,
+0x0044471c,
+0x0021f7f0,
+0x000b68e0,
+0x0020ff38,
+0x00b24b3d,
+0x00062d86,
+0x00f4f6ea,
+0x000d3f5a,
+0x00f2ea1a,
+0x00075f92,
+0x00c1248b,
+0x00fd1080,
+0x00faca4c,
+0x00fab048,
+0x00fdb0ac,
+0x00024f54,
+0x00054fb8,
+0x000535b4,
+0x0002ef80,
+0x003edb7b,
+0x001d92ec,
+0x00962b59,
+0x000bd422,
+0x00e48132,
+0x002dbdc2,
+0x00c7a94a,
+0x0033fbe6,
+0x00dd3502,
+0x000fea26,
+0x00c1248b,
+0x00fd1080,
+0x00faca4c,
+0x00fab048,
+0x00fdb0ac,
+0x00024f54,
+0x00054fb8,
+0x000535b4,
+0x0002ef80,
+0x003edb7b,
+0x001d92ec,
+0x00962b59,
+0x000bd422,
+0x00e48132,
+0x002dbdc2,
+0x00c7a94a,
+0x0033fbe6,
+0x00dd3502,
+0x000fea26,
+0x00400000,
+0x00100002,
+0x007f0001,
+0x00040002,
+0x00040002,
+0x00000020,
+0x003fffe0,
+0x00000020,
+0x003fffe0,
+0x0000e95b,
+0x00045e13,
+0x00e38bd3,
+0x0049a0eb,
+0x0086a523,
+0x00021a60,
+0x00b3b22b,
+0x00c008cb,
+0x0003ee58,
+0x00f98190,
+0x0007bebc,
+0x00f927cc,
+0x000369f8,
+0x000210a0,
+0x00f7d700,
+0x000cf630,
+0x00f0b350,
+0x000f00d8,
+0x00f45884,
+0x0004930c,
+0x000cca50,
+0x00d5b1a0,
+0x0036ee50,
+0x00c50200,
+0x00c1a4a3,
+0x005fc0f5,
+0x004f99c8,
+0x00026924,
+0x00ff83fb,
+0x0008de8b,
+0x00de91f3,
+0x0044c043,
+0x00a56883,
+0x0040eb8b,
+0x001e74a3,
+0x00fd21b0,
+0x000554e4,
+0x00f94c68,
+0x000647f4,
+0x00fc5390,
+0x00c48fa3,
+0x00067e44,
+0x00f4b078,
+0x000daa00,
+0x00f31630,
+0x00095c18,
+0x00fd153c,
+0x00f92d4c,
+0x00187260,
+0x00d118b0,
+0x002e0ce0,
+0x00dfc588,
+0x00d88710,
+0x005ade01,
+0x0069ab18,
+0x000581a8,
+0x00ff0f2b,
+0x000a2003,
+0x00e0f9b3,
+0x00341ca3,
+0x00d0769b,
+0x00f72c73,
+0x0079f1eb,
+0x00fbed28,
+0x0005aab8,
+0x00fa5660,
+0x0003b918,
+0x00028fb3,
+0x00fb129c,
+0x00098f30,
+0x00f3bff8,
+0x000bc1d8,
+0x00f7e048,
+0x000228e8,
+0x0005dda0,
+0x00f00dc0,
+0x001eb940,
+0x00d459f0,
+0x001db068,
+0x00fcb1e0,
+0x00bb70e0,
+0x00500125,
+0x00423c25,
+0x000cb760,
+0x00ff3a63,
+0x0008dcf3,
+0x00e89f33,
+0x001cf00b,
+0x00fdff03,
+0x00b7a13b,
+0x0002d9ac,
+0x00fb9038,
+0x0004ee8c,
+0x00fc6088,
+0x0025bba3,
+0x000396e8,
+0x00f82434,
+0x000abf70,
+0x00f51e3c,
+0x0007b174,
+0x0083c45b,
+0x00fadcd0,
+0x000d0158,
+0x00eaba28,
+0x001ef828,
+0x00de61d8,
+0x00091358,
+0x00172bd8,
+0x00aaa5f8,
+0x007f9968,
+0x004ead35,
+0x0016d358,
+0x00ff9df3,
+0x00063423,
+0x00f2bc93,
+0x0004db3b,
+0x002510d3,
+0x008d0163,
+0x00032dec,
+0x00fc0c14,
+0x00035394,
+0x00bfd6bb,
+0x00fd7bc4,
+0x000653e0,
+0x00f6c644,
+0x0009e92c,
+0x00f874d4,
+0x00025014,
+0x000466f8,
+0x00f4e050,
+0x00113910,
+0x00e9e9d8,
+0x0019a460,
+0x00ed06b8,
+0x00f3f088,
+0x002b3ea8,
+0x00a75d50,
+0x00573b88,
+0x0058acdd,
+0x00253e48,
+0x00ffe99b,
+0x00034623,
+0x00fca67b,
+0x00f0ade3,
+0x003f433b,
+0x00fdf30c,
+0x0002e438,
+0x00fd3880,
+0x004d26e3,
+0x006be023,
+0x00fafa08,
+0x0007c8c0,
+0x00f72900,
+0x000747f8,
+0x00fd12b4,
+0x00fcac44,
+0x0009b130,
+0x00f14b30,
+0x0011de10,
+0x00ed7168,
+0x00102888,
+0x00fd78fc,
+0x00e1dd38,
+0x003632e8,
+0x00b0f308,
+0x002ad4a0,
+0x005ec5d9,
+0x00385800,
+0x00fed5c7,
+0x0001d26f,
+0x00fa588b,
+0x000daca7,
+0x00e3d6d3,
+0x00339bc7,
+0x00a97e63,
+0x00021db8,
+0x00fcd778,
+0x00049f28,
+0x00f8fde8,
+0x000d23e8,
+0x007d7e59,
+0x00f89bb0,
+0x000259b4,
+0x00d1846b,
+0x0003ff83,
+0x000bf0f7,
+0x00f0e3cf,
+0x000ca4f7,
+0x00f77a0b,
+0x0004c883,
+0x00fdcf83,
+0x0000c0c7,
+0x00ff662f,
+0x0002ff27,
+0x00f6afb3,
+0x0016defb,
+0x00cfc55f,
+0x005b288f,
+0x00fd84f0,
+0x000411f4,
+0x00f99078,
+0x000a2044,
+0x00ef1978,
+0x0024d648,
+0x007aa5a5,
+0x00e7c3e8,
+0x000aa4ec,
+0x00fa6a80,
+0x000304e0,
+0x009a1a6f,
+0x0032b7db,
+0x00e8d6d7,
+0x000963f3,
+0x00fcc6cf,
+0x0000dc7b,
+0x00ffda2f,
+0x00ff1ed3,
+0x0004309f,
+0x00f31b9b,
+0x001faed3,
+0x00bcc34f,
+0x00020190,
+0x00fc755c,
+0x0005e8c8,
+0x00f675cc,
+0x000f6978,
+0x00e54b98,
+0x003efe58,
+0x007512ad,
+0x00daf028,
+0x001174bc,
+0x00f652f4,
+0x000589a8,
+0x00fce2b4,
+0x006b13b7,
+0x00ca4a77,
+0x00188ddf,
+0x00f61837,
+0x000357df,
+0x00ff2823,
+0x00fed6b7,
+0x00054b13,
+0x00efed7f,
+0x0027599b,
+0x00ac68e3,
+0x00028110,
+0x00fb8cf0,
+0x00077d74,
+0x00f3c420,
+0x00141628,
+0x00dc4340,
+0x005ac084,
+0x006d00dd,
+0x00d23fd0,
+0x00167f08,
+0x00f33398,
+0x00077ccc,
+0x00fbb300,
+0x00025c40,
+0x00b2862b,
+0x0024406f,
+0x00f10627,
+0x00052b3f,
+0x00feadf3,
+0x00fe9647,
+0x00062edf,
+0x00ed7c03,
+0x002d1867,
+0x00a04bef,
+0x0002df40,
+0x00fae088,
+0x0008acc0,
+0x00f1b5e8,
+0x0017c370,
+0x00d4b638,
+0x0077237c,
+0x0062c57d,
+0x00cd9f14,
+0x00199c28,
+0x00f12c50,
+0x0008c91c,
+0x00fae638,
+0x0002d380,
+0x00a270f7,
+0x002c1793,
+0x00edb29f,
+0x00065057,
+0x00fe69af,
+0x00fe678b,
+0x0006badb,
+0x00ec1c5f,
+0x00302fa7,
+0x0099df87,
+0x00031180,
+0x00fa8294,
+0x000957b0,
+0x00f07efc,
+0x001a1714,
+0x00cf5714,
+0x00498dbd,
+0x0056cb65,
+0x00cccae8,
+0x001ac64c,
+0x00f04854,
+0x0009661c,
+0x00fa8180,
+0x00030f60,
+0x009a52c3,
+0x00300017,
+0x00ec1ad7,
+0x0006cf1f,
+0x00fe552f,
+0x00fe552f,
+0x0006cf1f,
+0x00ec1ad7,
+0x00300017,
+0x009a52c3,
+0x00030f60,
+0x00fa8180,
+0x0009661c,
+0x00f04854,
+0x001ac64c,
+0x00cccae8,
+0x0056cb65,
+0x00498dbd,
+0x00cf5714,
+0x001a1714,
+0x00f07efc,
+0x000957b0,
+0x00fa8294,
+0x00031180,
+0x0099df87,
+0x00302fa7,
+0x00ec1c5f,
+0x0006badb,
+0x00fe678b,
+0x00fe69af,
+0x00065057,
+0x00edb29f,
+0x002c1793,
+0x00a270f7,
+0x0002d380,
+0x00fae638,
+0x0008c91c,
+0x00f12c50,
+0x00199c28,
+0x00cd9f14,
+0x0062c57d,
+0x0077237c,
+0x00d4b638,
+0x0017c370,
+0x00f1b5e8,
+0x0008acc0,
+0x00fae088,
+0x0002df40,
+0x00a04bef,
+0x002d1867,
+0x00ed7c03,
+0x00062edf,
+0x00fe9647,
+0x00feadf3,
+0x00052b3f,
+0x00f10627,
+0x0024406f,
+0x00b2862b,
+0x00025c40,
+0x00fbb300,
+0x00077ccc,
+0x00f33398,
+0x00167f08,
+0x00d23fd0,
+0x006d00dd,
+0x005ac084,
+0x00dc4340,
+0x00141628,
+0x00f3c420,
+0x00077d74,
+0x00fb8cf0,
+0x00028110,
+0x00ac68e3,
+0x0027599b,
+0x00efed7f,
+0x00054b13,
+0x00fed6b7,
+0x00ff2823,
+0x000357df,
+0x00f61837,
+0x00188ddf,
+0x00ca4a77,
+0x006b13b7,
+0x00fce2b4,
+0x000589a8,
+0x00f652f4,
+0x001174bc,
+0x00daf028,
+0x007512ad,
+0x003efe58,
+0x00e54b98,
+0x000f6978,
+0x00f675cc,
+0x0005e8c8,
+0x00fc755c,
+0x00020190,
+0x00bcc34f,
+0x001faed3,
+0x00f31b9b,
+0x0004309f,
+0x00ff1ed3,
+0x00ffda2f,
+0x0000dc7b,
+0x00fcc6cf,
+0x000963f3,
+0x00e8d6d7,
+0x0032b7db,
+0x009a1a6f,
+0x000304e0,
+0x00fa6a80,
+0x000aa4ec,
+0x00e7c3e8,
+0x007aa5a5,
+0x0024d648,
+0x00ef1978,
+0x000a2044,
+0x00f99078,
+0x000411f4,
+0x00fd84f0,
+0x005b288f,
+0x00cfc55f,
+0x0016defb,
+0x00f6afb3,
+0x0002ff27,
+0x00ff662f,
+0x0000c0c7,
+0x00fdcf83,
+0x0004c883,
+0x00f77a0b,
+0x000ca4f7,
+0x00f0e3cf,
+0x000bf0f7,
+0x0003ff83,
+0x00d1846b,
+0x000259b4,
+0x00f89bb0,
+0x007d7e59,
+0x000d23e8,
+0x00f8fde8,
+0x00049f28,
+0x00fcd778,
+0x00021db8,
+0x00a97e63,
+0x00339bc7,
+0x00e3d6d3,
+0x000daca7,
+0x00fa588b,
+0x0001d26f,
+0x00fed5c7,
+0x00000000,
+0x00040002,
+0x00000000,
+0x00040002,
+0x00020002,
+0x00f80002,
+0x001a88b7,
+0x003bed83,
+0x00789f93,
+0x000353c8,
+0x000558c0,
+0x0007faa0,
+0x000b314c,
+0x000edf48,
+0x0012cfec,
+0x0016b8f4,
+0x001a3f88,
+0x001d00ec,
+0x001e9df0,
+0x001ec7e4,
+0x001d4d44,
+0x001a2424,
+0x00157070,
+0x000f8484,
+0x0008db70,
+0x00020cec,
+0x00fbbc5c,
+0x00f684d0,
+0x00f2e4e0,
+0x00f12d44,
+0x00f174d8,
+0x00f3945c,
+0x00f72ab0,
+0x00fba984,
+0x001a22e3,
+0x0004bcfc,
+0x0008115c,
+0x0009fa78,
+0x000a45e0,
+0x0008fffc,
+0x00067070,
+0x00030d88,
+0x00da2f23,
+0x00fc1730,
+0x00f99a54,
+0x00f84c00,
+0x00f851a8,
+0x00f9982c,
+0x00fbd928,
+0x00aa16cf,
+0x0061c6c3,
+0x0003fa04,
+0x00059d78,
+0x0006357c,
+0x0005b618,
+0x0004437c,
+0x000229bc,
+0x00f3803f,
+0x00fd9c14,
+0x00fbf354,
+0x00fb16bc,
+0x00fb2258,
+0x00fc0838,
+0x00fd94b0,
+0x00de4c6f,
+0x0056ddab,
+0x0002e608,
+0x0003d744,
+0x00040c18,
+0x000384e8,
+0x000263b0,
+0x00391a1f,
+0x00d43a5f,
+0x00fdf2ec,
+0x00fd06bc,
+0x00fcb100,
+0x00fcf934,
+0x00fdc9dc,
+0x00bd738f,
+0x00106c83,
+0x005be09f,
+0x00024a04,
+0x0002ae04,
+0x00028fd4,
+0x007f0d8f,
+0x004529ff,
+0x00020d4b,
+0x00c2867f,
+0x00920a0f,
+0x00fde2b0,
+0x00fde758,
+0x0093e747,
+0x00c0cb77,
+0x00f754ab,
+0x002d163f,
+0x00585e1f,
+0x0071ef8b,
+0x00763257,
+0x0065a79f,
+0x00449a33,
+0x001a255f,
+0x00eec953,
+0x00cad5f7,
+0x00b4f72f,
+0x00b1226f,
+0x00c00eeb,
+0x00df46af,
+0x0009c1f7,
+0x0038e64f,
+0x0065b5ef,
+0x000227dc,
+0x00028480,
+0x0002a3a4,
+0x000285b0,
+0x00023398,
+0x006f1f67,
+0x004caed7,
+0x002a2af7,
+0x000b7d53,
+0x00f3677b,
+0x00e349ef,
+0x00db2ccf,
+0x00d9fec3,
+0x00ddf61b,
+0x00e4fe17,
+0x00ed1b4f,
+0x00f068f7,
+0x0084edbd,
+0x007b1245,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00762489,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00009494,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000010,
+0x00000000,
+0x00000000,
+0x000004fc,
+0x00000000,
+0x00000000,
+0x00000018,
+0x000004f4,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00a0000c,
+0x003c00a1,
+0x00000000,
+0x00000000,
+0x000005ba,
+0x00a2000c,
+0x003c00a3,
+0x00000000,
+0x00000000,
+0x000005ba,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0000000a,
+0x7fff7fff,
+0x7fff7fff,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003ffff0,
+0x00000000,
+0x00400000,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003ffff0,
+0x00000000,
+0x00400000,
+0x01f501e2,
+0x021b0208,
+0x0241022e,
+0x02670254,
+0x028d027a,
+0x02b302a0,
+0x02d902c6,
+0x02ff02ec,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003ffff0,
+0x00000000,
+0x00400000,
+0x03280316,
+0x034c033a,
+0x0370035e,
+0x03940382,
+0x03b803a6,
+0x03dc03ca,
+0x040003ee,
+0x04240412,
+0x00001400,
+0x000000ff,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0aa40c24,
+0x00000c34,
+0x0a940c04,
+0x00000c14,
+0x0e640bb4,
+0x00000ba4,
+0x0e540b94,
+0x00000b84,
+0x0a840be4,
+0x00000bf4,
+0x0a740bc4,
+0x00000bd4,
+0x0e440b34,
+0x00000b24,
+0x0e340b14,
+0x00000b04,
+0x0a640b64,
+0x00000b74,
+0x0a540b44,
+0x00000b54,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003ffff0,
+0x00000000,
+0x00400000,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003ffff0,
+0x00000000,
+0x00400000,
+0x0a740bc4,
+0x000010f4,
+0x0a840be4,
+0x00001104,
+0x11340b14,
+0x00000000,
+0x11540b94,
+0x00000000,
+0x00560014,
+0x00570003,
+0x005a0058,
+0x00000013,
+0x00560014,
+0x00570006,
+0x00610058,
+0x00000013,
+0x00560019,
+0x00570003,
+0x005a0058,
+0x033c0013,
+0x00560019,
+0x00570006,
+0x00610058,
+0x033c0013,
+0x00640014,
+0x0065010d,
+0x00680066,
+0x00000012,
+0x005b0015,
+0x005c0002,
+0x005f005d,
+0x00000013,
+0x005b0015,
+0x005c0005,
+0x0062005d,
+0x00000013,
+0x005b001a,
+0x005c0002,
+0x005f005d,
+0x038c0013,
+0x005b001a,
+0x005c0005,
+0x0062005d,
+0x038c0013,
+0x01050003,
+0x0001008e,
+0x00900001,
+0x00000000,
+0x01060003,
+0x0001008f,
+0x00910001,
+0x00000000,
+0x01070003,
+0x00010129,
+0x00900001,
+0x00000000,
+0x01070003,
+0x0001012a,
+0x00910001,
+0x00000000,
+0x00ab0003,
+0x0001008e,
+0x00900001,
+0x00000000,
+0x00ab0003,
+0x0001008f,
+0x00910001,
+0x00000000,
+0x0032000b,
+0x00710030,
+0x004e0072,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01100001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01110001,
+0x00000000,
+0x000d000a,
+0x000f000e,
+0x00110010,
+0x00000000,
+0x00280000,
+0x002b002a,
+0x002d002c,
+0x00000000,
+0x00240000,
+0x00790024,
+0x00920074,
+0x00000000,
+0x00030000,
+0x007a0003,
+0x009300ad,
+0x00000000,
+0x00240000,
+0x007b0024,
+0x00940077,
+0x00000000,
+0x00060000,
+0x007c0006,
+0x00950078,
+0x00000000,
+0x00290000,
+0x007d0105,
+0x00920073,
+0x00000000,
+0x008e0000,
+0x007e0060,
+0x00930075,
+0x00000000,
+0x00290000,
+0x007f0106,
+0x00940076,
+0x00000000,
+0x008f0000,
+0x00800063,
+0x00950078,
+0x00000000,
+0x01080000,
+0x00810108,
+0x00920074,
+0x00000000,
+0x010b0000,
+0x0082010b,
+0x00930075,
+0x00000000,
+0x01080000,
+0x00830108,
+0x00940077,
+0x00000000,
+0x010c0000,
+0x0084010c,
+0x00950078,
+0x00000000,
+0x00310000,
+0x00850107,
+0x00920073,
+0x00000000,
+0x01290000,
+0x00860109,
+0x00930075,
+0x00000000,
+0x00310000,
+0x00870107,
+0x00940076,
+0x00000000,
+0x012a0000,
+0x0088010a,
+0x00950078,
+0x00000000,
+0x00270000,
+0x008b00ab,
+0x00920073,
+0x00000000,
+0x008e0000,
+0x008c008d,
+0x00930075,
+0x00000000,
+0x00270000,
+0x008900ab,
+0x00940076,
+0x00000000,
+0x008f0000,
+0x008a008d,
+0x00950078,
+0x00000000,
+0x00310000,
+0x006f002f,
+0x004e0070,
+0x00000000,
+0x00300018,
+0x00980051,
+0x009700d0,
+0x00000000,
+0x002f0018,
+0x00960050,
+0x009700d2,
+0x00000000,
+0x002e0008,
+0x003c0031,
+0x00000017,
+0x00000000,
+0x00220008,
+0x003c0032,
+0x00000018,
+0x00000000,
+0x0137000c,
+0x00010001,
+0x01380001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00db0001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00dc0001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00dd0001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00de0001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00df0001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e00001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e10001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e20001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e30001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e40001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e50001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e60001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e70001,
+0x00000000,
+0x0001000d,
+0x00010001,
+0x00e80001,
+0x00000000,
+0x00fb000e,
+0x00010001,
+0x00fc0001,
+0x00000000,
+0x002f0005,
+0x001c0027,
+0x00000030,
+0x00000000,
+0x002a0005,
+0x001d002e,
+0x00000021,
+0x00000000,
+0x00080006,
+0x00260021,
+0x0000001a,
+0x00000000,
+0x00080006,
+0x00260022,
+0x0000001b,
+0x00000000,
+0x00080007,
+0x00260021,
+0x0000001a,
+0x00000000,
+0x00080007,
+0x00260022,
+0x0000001b,
+0x00000000,
+0x00080006,
+0x006a0069,
+0x0000001e,
+0x00000000,
+0x00080006,
+0x006a0029,
+0x0000001f,
+0x00000000,
+0x00080007,
+0x006a0029,
+0x0000001f,
+0x00000000,
+0x00c10001,
+0x00ca0052,
+0x0000011e,
+0x00000000,
+0x00030004,
+0x000c0024,
+0x00900001,
+0x00000000,
+0x00060004,
+0x000c0024,
+0x00910001,
+0x00000000,
+0x010b0004,
+0x000c0108,
+0x00900001,
+0x00000000,
+0x010c0004,
+0x000c0108,
+0x00910001,
+0x00000000,
+0x00300004,
+0x00fe0051,
+0x00fd0001,
+0x00000000,
+0x002f0004,
+0x00fe0050,
+0x00fd0001,
+0x00000000,
+0x00410002,
+0x00430042,
+0x00000016,
+0x00000000,
+0x00330002,
+0x00350034,
+0x00000013,
+0x00000000,
+0x00360002,
+0x00380037,
+0x00000014,
+0x00000000,
+0x00390002,
+0x003b003a,
+0x00000015,
+0x00000000,
+0x00690002,
+0x006c006b,
+0x00000019,
+0x00000000,
+0x01080002,
+0x0040003f,
+0x00000020,
+0x00000000,
+0x00080002,
+0x00470046,
+0x00000019,
+0x00000000,
+0x00cf0002,
+0x00c900c0,
+0x00000019,
+0x00000000,
+0x010d0002,
+0x010f010e,
+0x00000019,
+0x00000000,
+0x00270002,
+0x00450044,
+0x00000019,
+0x00000000,
+0x00010002,
+0x00010001,
+0x00000019,
+0x00000000,
+0x00010009,
+0x00010028,
+0x00530001,
+0x00000000,
+0x00010009,
+0x00010023,
+0x00540001,
+0x00000000,
+0x00c00011,
+0x00c200c1,
+0x00c700c3,
+0x00000000,
+0x00c80010,
+0x00cb00ca,
+0x00ce00cc,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01120001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01130001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01140001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01150001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01160001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01170001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01180001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01190001,
+0x00000000,
+0x0001000f,
+0x00010001,
+0x00010001,
+0x00000000,
+0x00490012,
+0x00d30041,
+0x00d600d4,
+0x00000000,
+0x004a0012,
+0x00d80033,
+0x00d700d5,
+0x00000000,
+0x004b0012,
+0x00d90036,
+0x00d700d5,
+0x00000000,
+0x004c0012,
+0x00da0039,
+0x00d700d5,
+0x00000000,
+0x011b0016,
+0x011c0001,
+0x011d0001,
+0x00000000,
+0x00010017,
+0x00010001,
+0x00000001,
+0x00000000,
+0x011f0014,
+0x0121010b,
+0x01240122,
+0x00000013,
+0x011f0014,
+0x0121010c,
+0x01250122,
+0x00000013,
+0x011f0019,
+0x0121010b,
+0x01240122,
+0x04040013,
+0x011f0019,
+0x0121010c,
+0x01250122,
+0x04040013,
+0x01260015,
+0x012d012b,
+0x0130012e,
+0x00000013,
+0x01260015,
+0x012d012c,
+0x0131012e,
+0x00000013,
+0x0126001a,
+0x012d012b,
+0x0130012e,
+0x02c40013,
+0x0126001a,
+0x012d012c,
+0x0131012e,
+0x02c40013,
+0x01290000,
+0x00860127,
+0x00930075,
+0x00000000,
+0x012a0000,
+0x00880128,
+0x00950078,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01320001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01330001,
+0x00000000,
+0x0003001b,
+0x01340024,
+0x01350001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01360001,
+0x00000000,
+0x010b001b,
+0x013a0108,
+0x01350001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01390001,
+0x00000000,
+0x00a7001c,
+0x004d0008,
+0x009e009c,
+0x00000000,
+0x00a9001c,
+0x00a80025,
+0x009f009d,
+0x00000000,
+0x00a7001d,
+0x004d0008,
+0x009e009c,
+0x00000000,
+0x00a9001d,
+0x00a80025,
+0x009f009d,
+0x00000000,
+0x00a7001e,
+0x004d0008,
+0x00ac009c,
+0x00000000,
+0x00a7001f,
+0x004d0008,
+0x00ac009c,
+0x00000000,
+0x00010020,
+0x00010001,
+0x00000001,
+0x00000000,
+0x00010021,
+0x00010001,
+0x00000001,
+0x00000000,
+0x00310022,
+0x013c0107,
+0x013d0001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x013e0001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x013f0001,
+0x00000000,
+0x00010013,
+0x00010001,
+0x01400001,
+0x00000000,
+0x00290022,
+0x01410105,
+0x013d0001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00003000,
+0x0041008a,
+0x003300d3,
+0x003600d8,
+0x003900d9,
+0x010500da,
+0x0105007d,
+0x0060007e,
+0x0060007e,
+0x010b007d,
+0x010b0082,
+0x01080081,
+0x01080082,
+0x00030081,
+0x00030134,
+0x00030079,
+0x0024007a,
+0x00240134,
+0x00240079,
+0x0107007a,
+0x0107013c,
+0x01090086,
+0x0109013c,
+0x002a0086,
+0x002f002b,
+0x0050006f,
+0x00300096,
+0x00510071,
+0x00ab0098,
+0x00ab008b,
+0x008d008c,
+0x008d008b,
+0x008d008c,
+0x00000000,
+0x0a7411f4,
+0x00000bd4,
+0x0a7411f4,
+0x000010f4,
+0x0a541234,
+0x00000b54,
+0x0443038f,
+0x03d5044e,
+0x006403df,
+0x004d0038,
+0x0481045c,
+0x03c00469,
+0x048e057f,
+0x00e905e0,
+0x01ed01c1,
+0x00d303a2,
+0x02020220,
+0x065e075a,
+0x022c03ea,
+0x040e0210,
+0x01ff0200,
+0x01fe0201,
+0x071706d4,
+0x00020422,
+0x010300f7,
+0x011e0112,
+0x0136012a,
+0x0154013d,
+0x0144014c,
+0x0176015b,
+0x0003019d,
+0x01bf01be,
+0x055e01c0,
+0x01a904a6,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00001580,
+0x00001580,
+0x00001580,
+0x0000193f,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00046f03,
+0x00000000,
+0x00047202,
+0x00000000,
+0x0006ba03,
+0x00000000,
+0x0004bc05,
+0x00000000,
+0x0004c104,
+0x00000000,
+0x0006b505,
+0x00000000,
+0x0001dc0c,
+0x00000000,
+0x0004c528,
+0x00000000,
+0x00051528,
+0x00000000,
+0x0006ef06,
+0x00000000,
+0x00028318,
+0x00000000,
+0x00019312,
+0x00000000,
+0x0001a512,
+0x00019000,
+0x0001b524,
+0x00019112,
+0x0001a312,
+0x00120024,
+0x0006dc00,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b50e,
+0x0001b80c,
+0x0001c304,
+0x0001b80c,
+0x0001c704,
+0x00000000,
+0x0001cb02,
+0x00000000,
+0x0001cd02,
+0x0001c40c,
+0x0001cf04,
+0x0001c40c,
+0x0001d304,
+0x0001d702,
+0x0001d702,
+0x00000000,
+0x0001e80c,
+0x00000000,
+0x0001f40c,
+0x00000000,
+0x0001d00c,
+0x00000000,
+0x0001c40c,
+0x00000000,
+0x0001b80c,
+0x0001c40c,
+0x0001d00c,
+0x00000000,
+0x0002000c,
+0x00000000,
+0x0002180c,
+0x00000000,
+0x0002240c,
+0x00000000,
+0x0002560c,
+0x00026209,
+0x00026209,
+0x00000000,
+0x0001d909,
+0x000b0009,
+0x00000000,
+0x00000000,
+0x00020c0c,
+0x00000000,
+0x0006bd0c,
+0x00000000,
+0x0006c90c,
+0x00000000,
+0x0006d50c,
+0x00000000,
+0x0006e10c,
+0x00000000,
+0x00029b0c,
+0x00028318,
+0x0002cb0c,
+0x00083900,
+0x0002d70c,
+0x00000000,
+0x0002a70c,
+0x00028300,
+0x0002e30c,
+0x00083900,
+0x0002ef0c,
+0x00000000,
+0x0002b30c,
+0x00028318,
+0x0002fb0c,
+0x00083900,
+0x0003070c,
+0x00083801,
+0x00083901,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00028318,
+0x0003130c,
+0x00083900,
+0x00031f0c,
+0x00000000,
+0x0002bf0c,
+0x00028318,
+0x00032b0c,
+0x00083900,
+0x0003370c,
+0x00028318,
+0x0003430c,
+0x00083900,
+0x00034f0c,
+0x00028318,
+0x00035b0c,
+0x00083900,
+0x0003670c,
+0x00000000,
+0x00037378,
+0x00000000,
+0x0003eb18,
+0x00000000,
+0x00040318,
+0x00000000,
+0x00041b18,
+0x00000000,
+0x00043318,
+0x00000000,
+0x0008c860,
+0x000b0019,
+0x00000000,
+0x000b0009,
+0x00000000,
+0x00000000,
+0x00047418,
+0x00000000,
+0x00048c18,
+0x00000000,
+0x0004a418,
+0x000b080c,
+0x00000000,
+0x000b0808,
+0x00000000,
+0x000b07f4,
+0x00000000,
+0x00000000,
+0x0004c528,
+0x0002ec13,
+0x0002ff13,
+0x0004c528,
+0x00031400,
+0x00031500,
+0x00020600,
+0x00590002,
+0x00038c00,
+0x00000000,
+0x0004ed28,
+0x0002ec13,
+0x0002ff13,
+0x0004ed28,
+0x00031200,
+0x00031300,
+0x00020e00,
+0x005e0002,
+0x00033c00,
+0x00000000,
+0x0004ed28,
+0x00590004,
+0x00038c00,
+0x005e0004,
+0x00033c00,
+0x00000000,
+0x0004ed28,
+0x00000000,
+0x00051528,
+0x00041212,
+0x00042412,
+0x00051528,
+0x00043600,
+0x00043700,
+0x00021e00,
+0x0067000c,
+0x00047c00,
+0x00000000,
+0x00053d0c,
+0x0002180c,
+0x0001b80c,
+0x00000000,
+0x0005490c,
+0x00083900,
+0x0005550c,
+0x00028318,
+0x0005610c,
+0x00083900,
+0x00056d0c,
+0x00059219,
+0x00059219,
+0x00000000,
+0x00046a19,
+0x00057919,
+0x00057919,
+0x00045119,
+0x00043819,
+0x00000000,
+0x0004a20d,
+0x00000000,
+0x0004af0d,
+0x00000000,
+0x0004bc07,
+0x00000000,
+0x0004830d,
+0x00000000,
+0x0004900d,
+0x00000000,
+0x00049d05,
+0x0005cf0d,
+0x0005cf0d,
+0x0005dc07,
+0x0005dc07,
+0x0005e30d,
+0x0005e30d,
+0x0005f005,
+0x0005f005,
+0x0005f50d,
+0x0005f50d,
+0x00060207,
+0x00060207,
+0x0006090d,
+0x0006090d,
+0x00061605,
+0x00061605,
+0x00061b0d,
+0x00061b0d,
+0x00062807,
+0x00062807,
+0x00062f0d,
+0x00062f0d,
+0x00063c05,
+0x00063c05,
+0x0006410d,
+0x0006410d,
+0x00064e07,
+0x00064e07,
+0x0006550d,
+0x0006550d,
+0x00066205,
+0x00066205,
+0x00067b0d,
+0x00067b0d,
+0x00068805,
+0x00068805,
+0x0006670d,
+0x0006670d,
+0x00067407,
+0x00067407,
+0x00000000,
+0x00068d28,
+0x00000000,
+0x0005c902,
+0x00000000,
+0x0005cb04,
+0x00000006,
+0x00000000,
+0x00000003,
+0x00000000,
+0x000b000d,
+0x00000000,
+0x00010007,
+0x00000000,
+0x000b000d,
+0x00000000,
+0x00030005,
+0x00000000,
+0x0005ab0f,
+0x0005ab0f,
+0x0000000f,
+0x00000000,
+0x0005ba0f,
+0x0005ba0f,
+0x00030007,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0005ba01,
+0x00000000,
+0x0005ba01,
+0x00140364,
+0x00000007,
+0x002803b4,
+0x00000007,
+0x00000000,
+0x0006da02,
+0x00000000,
+0x00098802,
+0x00000000,
+0x0006dc02,
+0x00000000,
+0x00098a02,
+0x0006de02,
+0x00098c01,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0008c860,
+0x00000000,
+0x0008c860,
+0x00000000,
+0x00092860,
+0x00000000,
+0x00092860,
+0x00050c01,
+0x00083918,
+0x00000000,
+0x0004630c,
+0x001406f0,
+0x00000007,
+0x00000000,
+0x00075907,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00098d01,
+0x00098d01,
+0x00000000,
+0x00072706,
+0x00028300,
+0x00074518,
+0x00075d0b,
+0x00075d0b,
+0x00000000,
+0x0004c90b,
+0x00019000,
+0x00072d18,
+0x00075d0b,
+0x00075d0b,
+0x00074518,
+0x00072706,
+0x00c4000b,
+0x0000c500,
+0x00000000,
+0x0006f506,
+0x00083900,
+0x0006f506,
+0x00028318,
+0x0006fc18,
+0x0004c504,
+0x0006fb00,
+0x00019000,
+0x00071400,
+0x00023100,
+0x00071512,
+0x00ea00cd,
+0x000026ff,
+0x00000000,
+0x0006ef06,
+0x0006ee00,
+0x0004d40f,
+0x00000000,
+0x00000000,
+0x0006ed00,
+0x0004d40f,
+0x00078013,
+0x00078013,
+0x00000000,
+0x0004e313,
+0x00000000,
+0x0004f613,
+0x00170013,
+0x00000000,
+0x00170013,
+0x00000000,
+0x00079313,
+0x00079313,
+0x0007a613,
+0x0007a613,
+0x0007b913,
+0x0007b913,
+0x00000274,
+0x00000000,
+0x0000029c,
+0x00000000,
+0x000002c4,
+0x00000000,
+0x000002ec,
+0x00000000,
+0x00000314,
+0x00000000,
+0x0000033c,
+0x00000000,
+0x00000364,
+0x00000000,
+0x0000038c,
+0x00000000,
+0x000003b4,
+0x00000000,
+0x000003dc,
+0x00000000,
+0x00000404,
+0x00000000,
+0x0000042c,
+0x00000000,
+0x00000454,
+0x00000000,
+0x0000047c,
+0x00000000,
+0x000004a4,
+0x00000000,
+0x000004cc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0001ac10,
+0x000f00eb,
+0x00000000,
+0x00000002,
+0x00000000,
+0x00000000,
+0x00019000,
+0x00000000,
+0x00019a0c,
+0x00000000,
+0x0007cc02,
+0x00000000,
+0x0007ce04,
+0x00000000,
+0x0007d206,
+0x00000000,
+0x0007d80c,
+0x00000000,
+0x0007e418,
+0x00000000,
+0x00044b0c,
+0x00000000,
+0x0004570c,
+0x00000000,
+0x0002300c,
+0x00000000,
+0x00023c0c,
+0x00000000,
+0x00024802,
+0x00000000,
+0x00024b04,
+0x00000000,
+0x00025002,
+0x00000000,
+0x00025204,
+0x00000000,
+0x0007fc0c,
+0x00028318,
+0x0008080c,
+0x00083900,
+0x0008140c,
+0x00000914,
+0x00000000,
+0x0000091c,
+0x00000000,
+0x00000924,
+0x00000000,
+0x0000092c,
+0x00000000,
+0x00000934,
+0x00000000,
+0x0000093c,
+0x00000000,
+0x00000944,
+0x00000000,
+0x0000094c,
+0x00000000,
+0x00000954,
+0x00000000,
+0x0000095c,
+0x00000000,
+0x00000000,
+0x00013d00,
+0x00000000,
+0x00056000,
+0x00013d00,
+0x00019000,
+0x00001940,
+0x00000000,
+0x00050c00,
+0x00050c01,
+0x00000000,
+0x00083a28,
+0x00000000,
+0x00083a28,
+0x0002ec13,
+0x0002ff13,
+0x00083a28,
+0x00051000,
+0x00051100,
+0x00025900,
+0x00230002,
+0x0002c401,
+0x00230004,
+0x0002c401,
+0x00000000,
+0x00086228,
+0x00000000,
+0x00086228,
+0x00000000,
+0x00086228,
+0x00000000,
+0x00088a02,
+0x00000000,
+0x00088c04,
+0x00000000,
+0x00024803,
+0x00000000,
+0x00024b05,
+0x0002ec13,
+0x0002ff13,
+0x00086228,
+0x00050e00,
+0x00050f00,
+0x00026100,
+0x002f0002,
+0x00040401,
+0x002f0004,
+0x00040401,
+0x000009a4,
+0x00000000,
+0x000009ac,
+0x00000000,
+0x000512a8,
+0x0008901c,
+0x0006001c,
+0x00000000,
+0x000009b4,
+0x00000000,
+0x00000000,
+0x00100020,
+0x001006f0,
+0x00000007,
+0x000009bc,
+0x00000000,
+0x000512a8,
+0x0008ac1c,
+0x000b0011,
+0x00000000,
+0x0006e079,
+0x00099f79,
+0x00060079,
+0x00000000,
+0x000012f4,
+0x00000000,
+0x000012fc,
+0x00000000,
+0x00001304,
+0x00000000,
+0x0006e079,
+0x000a2979,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000001,
+0x00000010,
+0x00000000,
+0x00000000,
+0x00400000,
+0x00400000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000001,
+0x00000001,
+0x00000001,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0000001b,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000008,
+0x00000000,
+0x00000008,
+0x00000000,
+0x00000008,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00e66666,
+0x00199999,
+0x00199999,
+0x00199999,
+0x00000000,
+0x00000000,
+0x00e66666,
+0x00e66666,
+0x00ffffff,
+0x00ffffff,
+0x00199999,
+0x00199999,
+0x00f33333,
+0x000ccccc,
+0x00f33333,
+0x00f33333,
+0x00199999,
+0x00e66666,
+0x00f33333,
+0x00f33333,
+0x00f33333,
+0x000ccccc,
+0x00199999,
+0x00199999,
+0x000ccccc,
+0x00162b95,
+0x00f33333,
+0x000ccccc,
+0x00e66666,
+0x00000000,
+0x00f33333,
+0x00f33333,
+0x000ccccc,
+0x00e9d46a,
+0x00199999,
+0x00e66666,
+0x000ccccc,
+0x00e9d46a,
+0x00f33333,
+0x00f33333,
+0x00e66666,
+0x00ffffff,
+0x00f33333,
+0x000ccccc,
+0x000ccccc,
+0x00162b95,
+0x00199999,
+0x00199999,
+0x00162b95,
+0x0018ba4a,
+0x000ccccc,
+0x00162b95,
+0x00000000,
+0x00121a18,
+0x00f33333,
+0x000ccccc,
+0x00e9d46a,
+0x0006a032,
+0x00e66666,
+0x00000000,
+0x00e9d46a,
+0x00f95fcd,
+0x00f33333,
+0x00f33333,
+0x00ffffff,
+0x00ede5e7,
+0x000ccccc,
+0x00e9d46a,
+0x00162b95,
+0x00e745b5,
+0x00199999,
+0x00e66666,
+0x00162b95,
+0x00e745b5,
+0x000ccccc,
+0x00e9d46a,
+0x00000000,
+0x00ede5e7,
+0x00f33333,
+0x00f33333,
+0x00e9d46a,
+0x00f95fcf,
+0x00e66666,
+0x00ffffff,
+0x00e9d46a,
+0x0006a032,
+0x00f33333,
+0x000ccccc,
+0x00ffffff,
+0x00121a18,
+0x000ccccc,
+0x00162b95,
+0x00162b95,
+0x0018ba4a,
+0x00199999,
+0x00199999,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x007fffff,
+0x00800000,
+0x001fffff,
+0x00e00000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x000049cc,
+0x000049cc,
+0x004fffff,
+0x00b00000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
diff --git a/sound/soc/omap/abe/abe_functionsid.h b/sound/soc/omap/abe/abe_functionsid.h
new file mode 100644
index 0000000..1c02770
--- /dev/null
+++ b/sound/soc/omap/abe/abe_functionsid.h
@@ -0,0 +1,122 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _ABE_FUNCTIONSID_H_
+#define _ABE_FUNCTIONSID_H_
+/*
+ * TASK function ID definitions
+ */
+#define C_ABE_FW_FUNCTION_IIR 0
+#define C_ABE_FW_FUNCTION_monoToStereoPack 1
+#define C_ABE_FW_FUNCTION_stereoToMonoSplit 2
+#define C_ABE_FW_FUNCTION_decimator 3
+#define C_ABE_FW_FUNCTION_OS0Fill 4
+#define C_ABE_FW_FUNCTION_mixer2 5
+#define C_ABE_FW_FUNCTION_mixer4 6
+#define C_ABE_FW_FUNCTION_mixer4_dual_mono 7
+#define C_ABE_FW_FUNCTION_inplaceGain 8
+#define C_ABE_FW_FUNCTION_StreamRouting 9
+#define C_ABE_FW_FUNCTION_gainConverge 10
+#define C_ABE_FW_FUNCTION_dualIir 11
+#define C_ABE_FW_FUNCTION_IO_DL_pp 12
+#define C_ABE_FW_FUNCTION_IO_generic 13
+#define C_ABE_FW_FUNCTION_irq_fifo_debug 14
+#define C_ABE_FW_FUNCTION_synchronize_pointers 15
+#define C_ABE_FW_FUNCTION_VIBRA2 16
+#define C_ABE_FW_FUNCTION_VIBRA1 17
+#define C_ABE_FW_FUNCTION_IIR_SRC_MIC 18
+#define C_ABE_FW_FUNCTION_wrappers 19
+#define C_ABE_FW_FUNCTION_ASRC_DL_wrapper 20
+#define C_ABE_FW_FUNCTION_ASRC_UL_wrapper 21
+#define C_ABE_FW_FUNCTION_mem_init 22
+#define C_ABE_FW_FUNCTION_debug_vx_asrc 23
+#define C_ABE_FW_FUNCTION_IIR_SRC2 24
+#define C_ABE_FW_FUNCTION_ASRC_DL_wrapper_sibling 25
+#define C_ABE_FW_FUNCTION_ASRC_UL_wrapper_sibling 26
+#define C_ABE_FW_FUNCTION_FIR6 27
+#define C_ABE_FW_FUNCTION_SRC44P1 28
+#define C_ABE_FW_FUNCTION_SRC44P1_1211 29
+#define C_ABE_FW_FUNCTION_SRC44P1_PP 30
+#define C_ABE_FW_FUNCTION_SRC44P1_1211_PP 31
+#define C_ABE_FW_FUNCTION_CHECK_IIR_LEFT 32
+#define C_ABE_FW_FUNCTION_CHECK_IIR_RIGHT 33
+#define C_ABE_FW_FUNCTION_FIR12_2 34
+/*
+ * COPY function ID definitions
+ */
+#define NULL_COPY_CFPID 0
+#define S2D_STEREO_16_16_CFPID 1
+#define S2D_MONO_MSB_CFPID 2
+#define S2D_STEREO_MSB_CFPID 3
+#define S2D_STEREO_RSHIFTED_16_CFPID 4
+#define S2D_MONO_RSHIFTED_16_CFPID 5
+#define D2S_STEREO_16_16_CFPID 6
+#define D2S_MONO_MSB_CFPID 7
+#define D2S_MONO_RSHIFTED_16_CFPID 8
+#define D2S_STEREO_RSHIFTED_16_CFPID 9
+#define D2S_STEREO_MSB_CFPID 10
+#define COPY_DMIC_CFPID 11
+#define COPY_MCPDM_DL_CFPID 12
+#define COPY_MM_UL_CFPID 13
+#define SPLIT_SMEM_CFPID 14
+#define MERGE_SMEM_CFPID 15
+#define SPLIT_TDM_CFPID 16
+#define MERGE_TDM_CFPID 17
+#define ROUTE_MM_UL_CFPID 18
+#define IO_IP_CFPID 19
+#define COPY_UNDERFLOW_CFPID 20
+#endif /* _ABE_FUNCTIONSID_H_ */
diff --git a/sound/soc/omap/abe/abe_fw.h b/sound/soc/omap/abe/abe_fw.h
new file mode 100644
index 0000000..a29dbb3
--- /dev/null
+++ b/sound/soc/omap/abe/abe_fw.h
@@ -0,0 +1,214 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_FW_H_
+#define _ABE_FW_H_
+
+#include "abe_cm_addr.h"
+#include "abe_sm_addr.h"
+#include "abe_dm_addr.h"
+#include "abe_typedef.h"
+/*
+ * GLOBAL DEFINITION
+ */
+/* one scheduler loop = 4kHz = 12 samples at 48kHz */
+#define FW_SCHED_LOOP_FREQ 4000
+/* one scheduler loop = 4kHz = 12 samples at 48kHz */
+#define FW_SCHED_LOOP_FREQ_DIV1000 (FW_SCHED_LOOP_FREQ/1000)
+#define EVENT_FREQUENCY 96000
+#define SLOTS_IN_SCHED_LOOP (96000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_8kHz (8000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_16kHz (16000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_24kHz (24000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_48kHz (48000/FW_SCHED_LOOP_FREQ)
+#define TASKS_IN_SLOT 8
+/*
+ * DMEM AREA - SCHEDULER
+ */
+#define dmem_mm_trace OMAP_ABE_D_DEBUG_FIFO_ADDR
+#define dmem_mm_trace_size ((OMAP_ABE_D_DEBUG_FIFO_SIZE)/4)
+#define ATC_SIZE 8 /* 8 bytes per descriptors */
+struct omap_abe_atc_desc {
+ unsigned rdpt:7; /* first 32bits word of the descriptor */
+ unsigned reserved0:1;
+ unsigned cbsize:7;
+ unsigned irqdest:1;
+ unsigned cberr:1;
+ unsigned reserved1:5;
+ unsigned cbdir:1;
+ unsigned nw:1;
+ unsigned wrpt:7;
+ unsigned reserved2:1;
+ unsigned badd:12; /* second 32bits word of the descriptor */
+ unsigned iter:7; /* iteration field overlaps 16-bit boundary */
+ unsigned srcid:6;
+ unsigned destid:6;
+ unsigned desen:1;
+};
+/*
+ * Infinite counter incremented on each sheduler periods (~250 us)
+ * uint16 dmem_debug_time_stamp
+ */
+#define dmem_debug_time_stamp OMAP_ABE_D_LOOPCOUNTER_ADDR
+/*
+ * ATC BUFFERS + IO TASKS SMEM buffers
+ */
+#define dmem_dmic OMAP_ABE_D_DMIC_UL_FIFO_ADDR
+#define dmem_dmic_size (OMAP_ABE_D_DMIC_UL_FIFO_SIZE/4)
+#define dmem_amic OMAP_ABE_D_MCPDM_UL_FIFO_ADDR
+#define dmem_amic_size (OMAP_ABE_D_MCPDM_UL_FIFO_SIZE/4)
+#define smem_amic AMIC_96_labelID
+#define dmem_mcpdm OMAP_ABE_D_MCPDM_DL_FIFO_ADDR
+#define dmem_mcpdm_size (OMAP_ABE_D_MCPDM_DL_FIFO_SIZE/4)
+#define dmem_mm_ul OMAP_ABE_D_MM_UL_FIFO_ADDR
+#define dmem_mm_ul_size (OMAP_ABE_D_MM_UL_FIFO_SIZE/4)
+/* managed directly by the router */
+#define smem_mm_ul MM_UL_labelID
+#define dmem_mm_ul2 OMAP_ABE_D_MM_UL2_FIFO_ADDR
+#define dmem_mm_ul2_size (OMAP_ABE_D_MM_UL2_FIFO_SIZE/4)
+/* managed directly by the router */
+#define smem_mm_ul2 MM_UL2_labelID
+#define dmem_mm_dl OMAP_ABE_D_MM_DL_FIFO_ADDR
+#define dmem_mm_dl_size (OMAP_ABE_D_MM_DL_FIFO_SIZE/4)
+#define smem_mm_dl MM_DL_labelID
+#define dmem_vx_dl OMAP_ABE_D_VX_DL_FIFO_ADDR
+#define dmem_vx_dl_size (OMAP_ABE_D_VX_DL_FIFO_SIZE/4)
+#define smem_vx_dl IO_VX_DL_ASRC_labelID /* Voice_16k_DL_labelID */
+#define dmem_vx_ul OMAP_ABE_D_VX_UL_FIFO_ADDR
+#define dmem_vx_ul_size (OMAP_ABE_D_VX_UL_FIFO_SIZE/4)
+#define smem_vx_ul Voice_8k_UL_labelID
+#define dmem_tones_dl OMAP_ABE_D_TONES_DL_FIFO_ADDR
+#define dmem_tones_dl_size (OMAP_ABE_D_TONES_DL_FIFO_SIZE/4)
+#define smem_tones_dl Tones_labelID
+#define dmem_vib_dl OMAP_ABE_D_VIB_DL_FIFO_ADDR
+#define dmem_vib_dl_size (OMAP_ABE_D_VIB_DL_FIFO_SIZE/4)
+#define smem_vib IO_VIBRA_DL_labelID
+#define dmem_mm_ext_out OMAP_ABE_D_MM_EXT_OUT_FIFO_ADDR
+#define dmem_mm_ext_out_size (OMAP_ABE_D_MM_EXT_OUT_FIFO_SIZE/4)
+#define smem_mm_ext_out DL1_GAIN_out_labelID
+#define dmem_mm_ext_in OMAP_ABE_D_MM_EXT_IN_FIFO_ADDR
+#define dmem_mm_ext_in_size (OMAP_ABE_D_MM_EXT_IN_FIFO_SIZE/4)
+/*IO_MM_EXT_IN_ASRC_labelID ASRC input buffer, size 40 */
+#define smem_mm_ext_in_opp100 IO_MM_EXT_IN_ASRC_labelID
+/* at OPP 50 without ASRC */
+#define smem_mm_ext_in_opp50 MM_EXT_IN_labelID
+#define dmem_bt_vx_dl OMAP_ABE_D_BT_DL_FIFO_ADDR
+#define dmem_bt_vx_dl_size (OMAP_ABE_D_BT_DL_FIFO_SIZE/4)
+#define smem_bt_vx_dl_opp50 BT_DL_8k_labelID
+/*BT_DL_8k_opp100_labelID ASRC output buffer, size 40 */
+#define smem_bt_vx_dl_opp100 BT_DL_8k_opp100_labelID
+#define dmem_bt_vx_ul OMAP_ABE_D_BT_UL_FIFO_ADDR
+#define dmem_bt_vx_ul_size (OMAP_ABE_D_BT_UL_FIFO_SIZE/4)
+#define smem_bt_vx_ul_opp50 BT_UL_8k_labelID
+/*IO_BT_UL_ASRC_labelID ASRC input buffer, size 40 */
+#define smem_bt_vx_ul_opp100 IO_BT_UL_ASRC_labelID
+/*
+ * SMEM AREA
+ */
+/*
+ * GAIN SMEM on PORT
+ * int32 smem_G0 [18] : desired gain on the ports
+ * format of G0 = 6 bits left shifted desired gain in linear 24bits format
+ * int24 stereo G0 [18] = G0
+ * int24 stereo GI [18] current value of the gain in the same format of G0
+ * List of smoothed gains :
+ * 6 DMIC 0 1 2 3 4 5
+ * 2 AMIC L R
+ * 4 PORT1/2_RX L R
+ * 2 MM_EXT L R
+ * 2 MM_VX_DL L R
+ * 2 IHF L R
+ * ---------------
+ * 18 = TOTAL
+ */
+/*
+ * COEFFICIENTS AREA
+ */
+/*
+ * delay coefficients used in the IIR-1 filters
+ * int24 cmem_gain_delay_iir1[9 x 2] (a, (1-a))
+ *
+ * 3 for 6 DMIC 0 1 2 3 4 5
+ * 1 for 2 AMIC L R
+ * 2 for 4 PORT1/2_RX L R
+ * 1 for 2 MM_EXT L R
+ * 1 for 2 MM_VX_DL L R
+ * 1 for 2 IHF L R
+ */
+/*
+ * gain controls
+ */
+#define GAIN_LEFT_OFFSET 0
+#define GAIN_RIGHT_OFFSET 1
+/* stereo gains */
+#define dmic1_gains_offset 0
+#define dmic2_gains_offset 2
+#define dmic3_gains_offset 4
+#define amic_gains_offset 6
+#define dl1_gains_offset 8
+#define dl2_gains_offset 10
+#define splitters_gains_offset 12
+#define mixer_dl1_offset 14
+#define mixer_dl2_offset 18
+#define mixer_echo_offset 22
+#define mixer_sdt_offset 24
+#define mixer_vxrec_offset 26
+#define mixer_audul_offset 30
+#define btul_gains_offset 34
+
+#endif/* _ABE_FW_H_ */
diff --git a/sound/soc/omap/abe/abe_gain.c b/sound/soc/omap/abe/abe_gain.c
new file mode 100644
index 0000000..9c148da
--- /dev/null
+++ b/sound/soc/omap/abe/abe_gain.c
@@ -0,0 +1,790 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dbg.h"
+#include "abe.h"
+#include "abe_gain.h"
+#include "abe_mem.h"
+
+/*
+ * ABE CONST AREA FOR PARAMETERS TRANSLATION
+ */
+#define min_mdb (-12000)
+#define max_mdb (3000)
+#define sizeof_db2lin_table (1 + ((max_mdb - min_mdb)/100))
+
+const u32 abe_db2lin_table[sizeof_db2lin_table] = {
+ 0x00000000, /* SMEM coding of -120 dB */
+ 0x00000000, /* SMEM coding of -119 dB */
+ 0x00000000, /* SMEM coding of -118 dB */
+ 0x00000000, /* SMEM coding of -117 dB */
+ 0x00000000, /* SMEM coding of -116 dB */
+ 0x00000000, /* SMEM coding of -115 dB */
+ 0x00000000, /* SMEM coding of -114 dB */
+ 0x00000000, /* SMEM coding of -113 dB */
+ 0x00000000, /* SMEM coding of -112 dB */
+ 0x00000000, /* SMEM coding of -111 dB */
+ 0x00000000, /* SMEM coding of -110 dB */
+ 0x00000000, /* SMEM coding of -109 dB */
+ 0x00000001, /* SMEM coding of -108 dB */
+ 0x00000001, /* SMEM coding of -107 dB */
+ 0x00000001, /* SMEM coding of -106 dB */
+ 0x00000001, /* SMEM coding of -105 dB */
+ 0x00000001, /* SMEM coding of -104 dB */
+ 0x00000001, /* SMEM coding of -103 dB */
+ 0x00000002, /* SMEM coding of -102 dB */
+ 0x00000002, /* SMEM coding of -101 dB */
+ 0x00000002, /* SMEM coding of -100 dB */
+ 0x00000002, /* SMEM coding of -99 dB */
+ 0x00000003, /* SMEM coding of -98 dB */
+ 0x00000003, /* SMEM coding of -97 dB */
+ 0x00000004, /* SMEM coding of -96 dB */
+ 0x00000004, /* SMEM coding of -95 dB */
+ 0x00000005, /* SMEM coding of -94 dB */
+ 0x00000005, /* SMEM coding of -93 dB */
+ 0x00000006, /* SMEM coding of -92 dB */
+ 0x00000007, /* SMEM coding of -91 dB */
+ 0x00000008, /* SMEM coding of -90 dB */
+ 0x00000009, /* SMEM coding of -89 dB */
+ 0x0000000A, /* SMEM coding of -88 dB */
+ 0x0000000B, /* SMEM coding of -87 dB */
+ 0x0000000D, /* SMEM coding of -86 dB */
+ 0x0000000E, /* SMEM coding of -85 dB */
+ 0x00000010, /* SMEM coding of -84 dB */
+ 0x00000012, /* SMEM coding of -83 dB */
+ 0x00000014, /* SMEM coding of -82 dB */
+ 0x00000017, /* SMEM coding of -81 dB */
+ 0x0000001A, /* SMEM coding of -80 dB */
+ 0x0000001D, /* SMEM coding of -79 dB */
+ 0x00000021, /* SMEM coding of -78 dB */
+ 0x00000025, /* SMEM coding of -77 dB */
+ 0x00000029, /* SMEM coding of -76 dB */
+ 0x0000002E, /* SMEM coding of -75 dB */
+ 0x00000034, /* SMEM coding of -74 dB */
+ 0x0000003A, /* SMEM coding of -73 dB */
+ 0x00000041, /* SMEM coding of -72 dB */
+ 0x00000049, /* SMEM coding of -71 dB */
+ 0x00000052, /* SMEM coding of -70 dB */
+ 0x0000005D, /* SMEM coding of -69 dB */
+ 0x00000068, /* SMEM coding of -68 dB */
+ 0x00000075, /* SMEM coding of -67 dB */
+ 0x00000083, /* SMEM coding of -66 dB */
+ 0x00000093, /* SMEM coding of -65 dB */
+ 0x000000A5, /* SMEM coding of -64 dB */
+ 0x000000B9, /* SMEM coding of -63 dB */
+ 0x000000D0, /* SMEM coding of -62 dB */
+ 0x000000E9, /* SMEM coding of -61 dB */
+ 0x00000106, /* SMEM coding of -60 dB */
+ 0x00000126, /* SMEM coding of -59 dB */
+ 0x0000014A, /* SMEM coding of -58 dB */
+ 0x00000172, /* SMEM coding of -57 dB */
+ 0x0000019F, /* SMEM coding of -56 dB */
+ 0x000001D2, /* SMEM coding of -55 dB */
+ 0x0000020B, /* SMEM coding of -54 dB */
+ 0x0000024A, /* SMEM coding of -53 dB */
+ 0x00000292, /* SMEM coding of -52 dB */
+ 0x000002E2, /* SMEM coding of -51 dB */
+ 0x0000033C, /* SMEM coding of -50 dB */
+ 0x000003A2, /* SMEM coding of -49 dB */
+ 0x00000413, /* SMEM coding of -48 dB */
+ 0x00000492, /* SMEM coding of -47 dB */
+ 0x00000521, /* SMEM coding of -46 dB */
+ 0x000005C2, /* SMEM coding of -45 dB */
+ 0x00000676, /* SMEM coding of -44 dB */
+ 0x0000073F, /* SMEM coding of -43 dB */
+ 0x00000822, /* SMEM coding of -42 dB */
+ 0x00000920, /* SMEM coding of -41 dB */
+ 0x00000A3D, /* SMEM coding of -40 dB */
+ 0x00000B7D, /* SMEM coding of -39 dB */
+ 0x00000CE4, /* SMEM coding of -38 dB */
+ 0x00000E76, /* SMEM coding of -37 dB */
+ 0x0000103A, /* SMEM coding of -36 dB */
+ 0x00001235, /* SMEM coding of -35 dB */
+ 0x0000146E, /* SMEM coding of -34 dB */
+ 0x000016EC, /* SMEM coding of -33 dB */
+ 0x000019B8, /* SMEM coding of -32 dB */
+ 0x00001CDC, /* SMEM coding of -31 dB */
+ 0x00002061, /* SMEM coding of -30 dB */
+ 0x00002455, /* SMEM coding of -29 dB */
+ 0x000028C4, /* SMEM coding of -28 dB */
+ 0x00002DBD, /* SMEM coding of -27 dB */
+ 0x00003352, /* SMEM coding of -26 dB */
+ 0x00003995, /* SMEM coding of -25 dB */
+ 0x0000409C, /* SMEM coding of -24 dB */
+ 0x0000487E, /* SMEM coding of -23 dB */
+ 0x00005156, /* SMEM coding of -22 dB */
+ 0x00005B43, /* SMEM coding of -21 dB */
+ 0x00006666, /* SMEM coding of -20 dB */
+ 0x000072E5, /* SMEM coding of -19 dB */
+ 0x000080E9, /* SMEM coding of -18 dB */
+ 0x000090A4, /* SMEM coding of -17 dB */
+ 0x0000A24B, /* SMEM coding of -16 dB */
+ 0x0000B618, /* SMEM coding of -15 dB */
+ 0x0000CC50, /* SMEM coding of -14 dB */
+ 0x0000E53E, /* SMEM coding of -13 dB */
+ 0x00010137, /* SMEM coding of -12 dB */
+ 0x0001209A, /* SMEM coding of -11 dB */
+ 0x000143D1, /* SMEM coding of -10 dB */
+ 0x00016B54, /* SMEM coding of -9 dB */
+ 0x000197A9, /* SMEM coding of -8 dB */
+ 0x0001C967, /* SMEM coding of -7 dB */
+ 0x00020137, /* SMEM coding of -6 dB */
+ 0x00023FD6, /* SMEM coding of -5 dB */
+ 0x00028619, /* SMEM coding of -4 dB */
+ 0x0002D4EF, /* SMEM coding of -3 dB */
+ 0x00032D64, /* SMEM coding of -2 dB */
+ 0x000390A4, /* SMEM coding of -1 dB */
+ 0x00040000, /* SMEM coding of 0 dB */
+ 0x00047CF2, /* SMEM coding of 1 dB */
+ 0x00050923, /* SMEM coding of 2 dB */
+ 0x0005A670, /* SMEM coding of 3 dB */
+ 0x000656EE, /* SMEM coding of 4 dB */
+ 0x00071CF5, /* SMEM coding of 5 dB */
+ 0x0007FB26, /* SMEM coding of 6 dB */
+ 0x0008F473, /* SMEM coding of 7 dB */
+ 0x000A0C2B, /* SMEM coding of 8 dB */
+ 0x000B4606, /* SMEM coding of 9 dB */
+ 0x000CA62C, /* SMEM coding of 10 dB */
+ 0x000E314A, /* SMEM coding of 11 dB */
+ 0x000FEC9E, /* SMEM coding of 12 dB */
+ 0x0011DE0A, /* SMEM coding of 13 dB */
+ 0x00140C28, /* SMEM coding of 14 dB */
+ 0x00167E60, /* SMEM coding of 15 dB */
+ 0x00193D00, /* SMEM coding of 16 dB */
+ 0x001C515D, /* SMEM coding of 17 dB */
+ 0x001FC5EB, /* SMEM coding of 18 dB */
+ 0x0023A668, /* SMEM coding of 19 dB */
+ 0x00280000, /* SMEM coding of 20 dB */
+ 0x002CE178, /* SMEM coding of 21 dB */
+ 0x00325B65, /* SMEM coding of 22 dB */
+ 0x00388062, /* SMEM coding of 23 dB */
+ 0x003F654E, /* SMEM coding of 24 dB */
+ 0x00472194, /* SMEM coding of 25 dB */
+ 0x004FCF7C, /* SMEM coding of 26 dB */
+ 0x00598C81, /* SMEM coding of 27 dB */
+ 0x006479B7, /* SMEM coding of 28 dB */
+ 0x0070BC3D, /* SMEM coding of 29 dB */
+ 0x007E7DB9, /* SMEM coding of 30 dB */
+};
+
+const u32 abe_1_alpha_iir[64] = {
+ 0x040002, 0x040002, 0x040002, 0x040002, /* 0 */
+ 0x50E955, 0x48CA65, 0x40E321, 0x72BE78, /* 1 [ms] */
+ 0x64BA68, 0x57DF14, 0x4C3D60, 0x41D690, /* 2 */
+ 0x38A084, 0x308974, 0x297B00, 0x235C7C, /* 4 */
+ 0x1E14B0, 0x198AF0, 0x15A800, 0x125660, /* 8 */
+ 0x0F82A0, 0x0D1B5C, 0x0B113C, 0x0956CC, /* 16 */
+ 0x07E054, 0x06A3B8, 0x059844, 0x04B680, /* 32 */
+ 0x03F80C, 0x035774, 0x02D018, 0x025E0C, /* 64 */
+ 0x7F8057, 0x6B482F, 0x5A4297, 0x4BEECB, /* 128 */
+ 0x3FE00B, 0x35BAA7, 0x2D3143, 0x2602AF, /* 256 */
+ 0x1FF803, 0x1AE2FB, 0x169C9F, 0x13042B, /* 512 */
+ 0x0FFE03, 0x0D72E7, 0x0B4F4F, 0x0982CB, /* 1.024 [s] */
+ 0x07FF83, 0x06B9CF, 0x05A7E7, 0x04C193, /* 2.048 */
+ 0x03FFE3, 0x035CFF, 0x02D403, 0x0260D7, /* 4.096 */
+ 0x01FFFB, 0x01AE87, 0x016A07, 0x01306F, /* 8.192 */
+ 0x00FFFF, 0x00D743, 0x00B503, 0x009837,
+};
+
+const u32 abe_alpha_iir[64] = {
+ 0x000000, 0x000000, 0x000000, 0x000000, /* 0 */
+ 0x5E2D58, 0x6E6B3C, 0x7E39C0, 0x46A0C5, /* 1 [ms] */
+ 0x4DA2CD, 0x541079, 0x59E151, 0x5F14B9, /* 2 */
+ 0x63AFC1, 0x67BB45, 0x6B4281, 0x6E51C1, /* 4 */
+ 0x70F5A9, 0x733A89, 0x752C01, 0x76D4D1, /* 8 */
+ 0x783EB1, 0x797251, 0x7A7761, 0x7B549D, /* 16 */
+ 0x7C0FD5, 0x7CAE25, 0x7D33DD, 0x7DA4C1, /* 32 */
+ 0x7E03FD, 0x7E5449, 0x7E97F5, 0x7ED0F9, /* 64 */
+ 0x7F0101, 0x7F2971, 0x7F4B7D, 0x7F6825, /* 128 */
+ 0x7F8041, 0x7F948D, 0x7FA59D, 0x7FB3FD, /* 256 */
+ 0x7FC011, 0x7FCA3D, 0x7FD2C9, 0x7FD9F9, /* 512 */
+ 0x7FE005, 0x7FE51D, 0x7FE961, 0x7FECFD, /* 1.024 [s] */
+ 0x7FF001, 0x7FF28D, 0x7FF4B1, 0x7FF67D, /* 2.048 */
+ 0x7FF801, 0x7FF949, 0x7FFA59, 0x7FFB41, /* 4.096 */
+ 0x7FFC01, 0x7FFCA5, 0x7FFD2D, 0x7FFDA1, /* 8.192 */
+ 0x7FFE01, 0x7FFE51, 0x7FFE95, 0x7FFED1,
+};
+
+/**
+ * abe_int_2_float
+ * returns a mantissa on 16 bits and the exponent
+ * 0x4000.0000 leads to M=0x4000 X=15
+ * 0x0004.0000 leads to M=0x4000 X=4
+ * 0x0000.0001 leads to M=0x4000 X=-14
+ *
+ */
+void abe_int_2_float16(u32 data, u32 *mantissa, u32 *exp)
+{
+ u32 i;
+ *exp = 0;
+ *mantissa = 0;
+ for (i = 0; i < 32; i++) {
+ if ((1 << i) > data)
+ break;
+ }
+ *exp = i - 15;
+ *mantissa = (*exp > 0) ? data >> (*exp) : data << (*exp);
+}
+
+/**
+ * abe_use_compensated_gain
+ * @on_off:
+ *
+ * Selects the automatic Mixer's gain management
+ * on_off = 1 allows the "abe_write_gain" to adjust the overall
+ * gains of the mixer to be tuned not to create saturation
+ */
+int omap_abe_use_compensated_gain(struct omap_abe *abe, int on_off)
+{
+ abe->compensated_mixer_gain = on_off;
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_use_compensated_gain);
+
+/**
+ * omap_abe_gain_offset
+ * returns the offset to firmware data structures
+ *
+ */
+void omap_abe_gain_offset(struct omap_abe *abe, u32 id, u32 *mixer_offset)
+{
+ switch (id) {
+ default:
+ case GAINS_DMIC1:
+ *mixer_offset = dmic1_gains_offset;
+ break;
+ case GAINS_DMIC2:
+ *mixer_offset = dmic2_gains_offset;
+ break;
+ case GAINS_DMIC3:
+ *mixer_offset = dmic3_gains_offset;
+ break;
+ case GAINS_AMIC:
+ *mixer_offset = amic_gains_offset;
+ break;
+ case GAINS_DL1:
+ *mixer_offset = dl1_gains_offset;
+ break;
+ case GAINS_DL2:
+ *mixer_offset = dl2_gains_offset;
+ break;
+ case GAINS_SPLIT:
+ *mixer_offset = splitters_gains_offset;
+ break;
+ case MIXDL1:
+ *mixer_offset = mixer_dl1_offset;
+ break;
+ case MIXDL2:
+ *mixer_offset = mixer_dl2_offset;
+ break;
+ case MIXECHO:
+ *mixer_offset = mixer_echo_offset;
+ break;
+ case MIXSDT:
+ *mixer_offset = mixer_sdt_offset;
+ break;
+ case MIXVXREC:
+ *mixer_offset = mixer_vxrec_offset;
+ break;
+ case MIXAUDUL:
+ *mixer_offset = mixer_audul_offset;
+ break;
+ case GAINS_BTUL:
+ *mixer_offset = btul_gains_offset;
+ break;
+ }
+}
+
+/**
+ * oamp_abe_write_equalizer
+ * @abe: Pointer on abe handle
+ * @id: name of the equalizer
+ * @param : equalizer coefficients
+ *
+ * Load the coefficients in CMEM.
+ */
+int omap_abe_write_equalizer(struct omap_abe *abe,
+ u32 id, struct omap_abe_equ *param)
+{
+ u32 eq_offset, length, *src, eq_mem, eq_mem_len;
+ _log(ABE_ID_WRITE_EQUALIZER, id, 0, 0);
+ switch (id) {
+ default:
+ case EQ1:
+ eq_offset = OMAP_ABE_C_DL1_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_DL1_M_EQ_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_DL1_M_EQ_DATA_SIZE;
+ break;
+ case EQ2L:
+ eq_offset = OMAP_ABE_C_DL2_L_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_DL2_M_LR_EQ_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_DL2_M_LR_EQ_DATA_SIZE;
+ break;
+ case EQ2R:
+ eq_offset = OMAP_ABE_C_DL2_R_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_DL2_M_LR_EQ_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_DL2_M_LR_EQ_DATA_SIZE;
+ break;
+ case EQSDT:
+ eq_offset = OMAP_ABE_C_SDT_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_SDT_F_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_SDT_F_DATA_SIZE;
+ break;
+ case EQAMIC:
+ eq_offset = OMAP_ABE_C_96_48_AMIC_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_AMIC_96_48_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_AMIC_96_48_DATA_SIZE;
+ break;
+ case EQDMIC:
+ eq_offset = OMAP_ABE_C_96_48_DMIC_COEFS_ADDR;
+ eq_mem = OMAP_ABE_S_DMIC0_96_48_DATA_ADDR;
+ eq_mem_len = OMAP_ABE_S_DMIC0_96_48_DATA_SIZE;
+ /* three DMIC are clear at the same time DMIC0 DMIC1 DMIC2 */
+ eq_mem_len *= 3;
+ break;
+ }
+ /* reset SMEM buffers before the coefficients are loaded */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM, eq_mem, eq_mem_len);
+
+ length = param->equ_length;
+ src = (u32 *) ((param->coef).type1);
+ /* translate in bytes */
+ length <<= 2;
+ omap_abe_mem_write(abe, OMAP_ABE_CMEM, eq_offset, src, length);
+
+ /* reset SMEM buffers after the coefficients are loaded */
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM, eq_mem, eq_mem_len);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_write_equalizer);
+
+/**
+ * omap_abe_disable_gain
+ * @abe: Pointer on abe handle
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+int omap_abe_disable_gain(struct omap_abe *abe, u32 id, u32 p)
+{
+ u32 mixer_offset, f_g, ramp;
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ /* save the input parameters for mute/unmute */
+ ramp = abe->desired_ramp_delay_ms[mixer_offset + p];
+ f_g = GAIN_MUTE;
+ if (!(abe->muted_gains_indicator[mixer_offset + p] &
+ OMAP_ABE_GAIN_DISABLED)) {
+ /* Check if we are in mute */
+ if (!(abe->muted_gains_indicator[mixer_offset + p] &
+ OMAP_ABE_GAIN_MUTED)) {
+ abe->muted_gains_decibel[mixer_offset + p] =
+ abe->desired_gains_decibel[mixer_offset + p];
+ /* mute the gain */
+ omap_abe_write_gain(abe, id, f_g, ramp, p);
+ }
+ abe->muted_gains_indicator[mixer_offset + p] |=
+ OMAP_ABE_GAIN_DISABLED;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_disable_gain);
+
+/**
+ * omap_abe_enable_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+int omap_abe_enable_gain(struct omap_abe *abe, u32 id, u32 p)
+{
+ u32 mixer_offset, f_g, ramp;
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ if ((abe->muted_gains_indicator[mixer_offset + p] &
+ OMAP_ABE_GAIN_DISABLED)) {
+ /* restore the input parameters for mute/unmute */
+ f_g = abe->muted_gains_decibel[mixer_offset + p];
+ ramp = abe->desired_ramp_delay_ms[mixer_offset + p];
+ abe->muted_gains_indicator[mixer_offset + p] &=
+ ~OMAP_ABE_GAIN_DISABLED;
+ /* unmute the gain */
+ omap_abe_write_gain(abe, id, f_g, ramp, p);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_enable_gain);
+/**
+ * omap_abe_mute_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+int omap_abe_mute_gain(struct omap_abe *abe, u32 id, u32 p)
+{
+ u32 mixer_offset, f_g, ramp;
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ /* save the input parameters for mute/unmute */
+ ramp = abe->desired_ramp_delay_ms[mixer_offset + p];
+ f_g = GAIN_MUTE;
+ if (!abe->muted_gains_indicator[mixer_offset + p]) {
+ abe->muted_gains_decibel[mixer_offset + p] =
+ abe->desired_gains_decibel[mixer_offset + p];
+ /* mute the gain */
+ omap_abe_write_gain(abe, id, f_g, ramp, p);
+ }
+ abe->muted_gains_indicator[mixer_offset + p] |= OMAP_ABE_GAIN_MUTED;
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_mute_gain);
+/**
+ * omap_abe_unmute_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+int omap_abe_unmute_gain(struct omap_abe *abe, u32 id, u32 p)
+{
+ u32 mixer_offset, f_g, ramp;
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ if ((abe->muted_gains_indicator[mixer_offset + p] &
+ OMAP_ABE_GAIN_MUTED)) {
+ /* restore the input parameters for mute/unmute */
+ f_g = abe->muted_gains_decibel[mixer_offset + p];
+ ramp = abe->desired_ramp_delay_ms[mixer_offset + p];
+ abe->muted_gains_indicator[mixer_offset + p] &=
+ ~OMAP_ABE_GAIN_MUTED;
+ /* unmute the gain */
+ omap_abe_write_gain(abe, id, f_g, ramp, p);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_unmute_gain);
+
+/**
+ * omap_abe_write_gain
+ * @id: gain name or mixer name
+ * @f_g: list of input gains of the mixer
+ * @ramp: gain ramp speed factor
+ * @p: list of ports corresponding to the above gains
+ *
+ * Loads the gain coefficients to FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's gain
+ * in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+int omap_abe_write_gain(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 ramp, u32 p)
+{
+ u32 lin_g, sum_g, mixer_target, mixer_offset, i, mean_gain, mean_exp;
+ u32 new_gain_linear[4];
+ s32 gain_index;
+ u32 alpha, beta;
+ u32 ramp_index;
+
+ _log(ABE_ID_WRITE_GAIN, id, f_g, p);
+ gain_index = ((f_g - min_mdb) / 100);
+ gain_index = maximum(gain_index, 0);
+ gain_index = minimum(gain_index, sizeof_db2lin_table);
+ lin_g = abe_db2lin_table[gain_index];
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ /* save the input parameters for mute/unmute */
+ abe->desired_gains_linear[mixer_offset + p] = lin_g;
+ abe->desired_gains_decibel[mixer_offset + p] = f_g;
+ abe->desired_ramp_delay_ms[mixer_offset + p] = ramp;
+ /* SMEM address in bytes */
+ mixer_target = OMAP_ABE_S_GTARGET1_ADDR;
+ mixer_target += (mixer_offset<<2);
+ mixer_target += (p<<2);
+
+ if (abe->compensated_mixer_gain) {
+ switch (id) {
+ case MIXDL1:
+ case MIXDL2:
+ case MIXVXREC:
+ case MIXAUDUL:
+ /* compute the sum of the gain of the mixer */
+ for (sum_g = i = 0; i < 4; i++)
+ sum_g += abe->desired_gains_linear[mixer_offset +
+ i];
+ /* lets avoid a division by 0 */
+ if (sum_g == 0)
+ break;
+ /* if the sum is OK with less than 1, then
+ do not weight the gains */
+ if (sum_g < 0x00040000) { /* REMOVE HARD CONST */
+ /* recompute all gains from original
+ desired values */
+ sum_g = 0x00040000;
+ }
+ /* translate it in Q16 format for the later division */
+ abe_int_2_float16(sum_g, &mean_gain, &mean_exp);
+ mean_exp = 10 - mean_exp;
+ for (i = 0; i < 4; i++) {
+ /* new gain = desired gain divided by sum of gains */
+ new_gain_linear[i] =
+ (abe->desired_gains_linear
+ [mixer_offset + i]
+ << 8) / mean_gain;
+ new_gain_linear[i] = (mean_exp > 0) ?
+ new_gain_linear[i] << mean_exp :
+ new_gain_linear[i] >> mean_exp;
+ }
+ /* load the whole adpated S_G_Target SMEM MIXER table */
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM,
+ mixer_target - (p << 2),
+ new_gain_linear, (4 * sizeof(lin_g)));
+ break;
+ default:
+ /* load the S_G_Target SMEM table */
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM,
+ mixer_target,
+ (u32 *) &lin_g, sizeof(lin_g));
+ break;
+ }
+ } else {
+ if (!abe->muted_gains_indicator[mixer_offset + p])
+ /* load the S_G_Target SMEM table */
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM,
+ mixer_target, (u32 *) &lin_g,
+ sizeof(lin_g));
+ else
+ /* update muted gain with new value */
+ abe->muted_gains_decibel[mixer_offset + p] = f_g;
+ }
+ ramp = maximum(minimum(RAMP_MAXLENGTH, ramp), RAMP_MINLENGTH);
+ /* ramp data should be interpolated in the table instead */
+ ramp_index = 3;
+ if ((RAMP_2MS <= ramp) && (ramp < RAMP_5MS))
+ ramp_index = 8;
+ if ((RAMP_5MS <= ramp) && (ramp < RAMP_50MS))
+ ramp_index = 24;
+ if ((RAMP_50MS <= ramp) && (ramp < RAMP_500MS))
+ ramp_index = 36;
+ if (ramp > RAMP_500MS)
+ ramp_index = 48;
+ beta = abe_alpha_iir[ramp_index];
+ alpha = abe_1_alpha_iir[ramp_index];
+ /* CMEM bytes address */
+ mixer_target = OMAP_ABE_C_1_ALPHA_ADDR;
+ /* a pair of gains is updated once in the firmware */
+ mixer_target += ((p + mixer_offset) >> 1) << 2;
+ /* load the ramp delay data */
+ omap_abe_mem_write(abe, OMAP_ABE_CMEM, mixer_target,
+ (u32 *) &alpha, sizeof(alpha));
+ /* CMEM bytes address */
+ mixer_target = OMAP_ABE_C_ALPHA_ADDR;
+ /* a pair of gains is updated once in the firmware */
+ mixer_target += ((p + mixer_offset) >> 1) << 2;
+ omap_abe_mem_write(abe, OMAP_ABE_CMEM, mixer_target,
+ (u32 *) &beta, sizeof(beta));
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_write_gain);
+/**
+ * omap_abe_write_mixer
+ * @id: name of the mixer
+ * @param: input gains and delay ramp of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+int omap_abe_write_mixer(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 f_ramp, u32 p)
+{
+ _log(ABE_ID_WRITE_MIXER, id, f_ramp, p);
+ omap_abe_write_gain(abe, id, f_g, f_ramp, p);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_write_mixer);
+
+/**
+ * omap_abe_read_gain
+ * @id: name of the mixer
+ * @param: list of input gains of the mixer
+ * @p: list of port corresponding to the above gains
+ *
+ */
+int omap_abe_read_gain(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p)
+{
+ u32 mixer_target, mixer_offset, i;
+ _log(ABE_ID_READ_GAIN, id, (u32) f_g, p);
+ omap_abe_gain_offset(abe, id, &mixer_offset);
+ /* SMEM bytes address */
+ mixer_target = OMAP_ABE_S_GTARGET1_ADDR;
+ mixer_target += (mixer_offset<<2);
+ mixer_target += (p<<2);
+ if (!abe->muted_gains_indicator[mixer_offset + p]) {
+ /* load the S_G_Target SMEM table */
+ omap_abe_mem_read(abe, OMAP_ABE_SMEM, mixer_target,
+ (u32 *) f_g, sizeof(*f_g));
+ for (i = 0; i < sizeof_db2lin_table; i++) {
+ if (abe_db2lin_table[i] == *f_g)
+ goto found;
+ }
+ *f_g = 0;
+ return -1;
+ found:
+ *f_g = (i * 100) + min_mdb;
+ } else {
+ /* update muted gain with new value */
+ *f_g = abe->muted_gains_decibel[mixer_offset + p];
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_read_gain);
+
+/**
+ * abe_read_mixer
+ * @id: name of the mixer
+ * @param: gains of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+int omap_abe_read_mixer(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p)
+{
+ _log(ABE_ID_READ_MIXER, id, 0, p);
+ omap_abe_read_gain(abe, id, f_g, p);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_read_mixer);
+
+/**
+ * abe_reset_gain_mixer
+ * @id: name of the mixer
+ * @p: list of port corresponding to the above gains
+ *
+ * restart the working gain value of the mixers when a port is enabled
+ */
+void omap_abe_reset_gain_mixer(struct omap_abe *abe, u32 id, u32 p)
+{
+ u32 lin_g, mixer_target, mixer_offset;
+ switch (id) {
+ default:
+ case GAINS_DMIC1:
+ mixer_offset = dmic1_gains_offset;
+ break;
+ case GAINS_DMIC2:
+ mixer_offset = dmic2_gains_offset;
+ break;
+ case GAINS_DMIC3:
+ mixer_offset = dmic3_gains_offset;
+ break;
+ case GAINS_AMIC:
+ mixer_offset = amic_gains_offset;
+ break;
+ case GAINS_DL1:
+ mixer_offset = dl1_gains_offset;
+ break;
+ case GAINS_DL2:
+ mixer_offset = dl2_gains_offset;
+ break;
+ case GAINS_SPLIT:
+ mixer_offset = splitters_gains_offset;
+ break;
+ case MIXDL1:
+ mixer_offset = mixer_dl1_offset;
+ break;
+ case MIXDL2:
+ mixer_offset = mixer_dl2_offset;
+ break;
+ case MIXECHO:
+ mixer_offset = mixer_echo_offset;
+ break;
+ case MIXSDT:
+ mixer_offset = mixer_sdt_offset;
+ break;
+ case MIXVXREC:
+ mixer_offset = mixer_vxrec_offset;
+ break;
+ case MIXAUDUL:
+ mixer_offset = mixer_audul_offset;
+ break;
+ case GAINS_BTUL:
+ mixer_offset = btul_gains_offset;
+ break;
+ }
+ /* SMEM bytes address for the CURRENT gain values */
+ mixer_target = OMAP_ABE_S_GCURRENT_ADDR;
+ mixer_target += (mixer_offset<<2);
+ mixer_target += (p<<2);
+ lin_g = 0;
+ /* load the S_G_Target SMEM table */
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, mixer_target,
+ (u32 *) &lin_g, sizeof(lin_g));
+}
diff --git a/sound/soc/omap/abe/abe_gain.h b/sound/soc/omap/abe/abe_gain.h
new file mode 100644
index 0000000..f332837
--- /dev/null
+++ b/sound/soc/omap/abe/abe_gain.h
@@ -0,0 +1,111 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_GAIN_H_
+#define _ABE_GAIN_H_
+
+#include "abe_typ.h"
+#include "abe_dm_addr.h"
+#include "abe_sm_addr.h"
+#include "abe_cm_addr.h"
+
+#define OMAP_ABE_GAIN_MUTED (0x0001<<0)
+#define OMAP_ABE_GAIN_DISABLED (0x0001<<1)
+
+#define OMAP_ABE_GAIN_DMIC1_LEFT 0
+#define OMAP_ABE_GAIN_DMIC1_RIGTH 1
+#define OMAP_ABE_GAIN_DMIC2_LEFT 2
+#define OMAP_ABE_GAIN_DMIC2_RIGTH 3
+#define OMAP_ABE_GAIN_DMIC3_LEFT 4
+#define OMAP_ABE_GAIN_DMIC3_RIGTH 5
+#define OMAP_ABE_GAIN_AMIC_LEFT 6
+#define OMAP_ABE_GAIN_AMIC_RIGTH 7
+#define OMAP_ABE_GAIN_DL1_LEFT 8
+#define OMAP_ABE_GAIN_DL1_RIGTH 9
+#define OMAP_ABE_GAIN_DL2_LEFT 10
+#define OMAP_ABE_GAIN_DL2_RIGTH 11
+#define OMAP_ABE_GAIN_SPLIT_LEFT 12
+#define OMAP_ABE_GAIN_SPLIT_RIGTH 13
+#define OMAP_ABE_MIXDL1_MM_DL 14
+#define OMAP_ABE_MIXDL1_MM_UL2 15
+#define OMAP_ABE_MIXDL1_VX_DL 16
+#define OMAP_ABE_MIXDL1_TONES 17
+#define OMAP_ABE_MIXDL2_MM_DL 18
+#define OMAP_ABE_MIXDL2_MM_UL2 19
+#define OMAP_ABE_MIXDL2_VX_DL 20
+#define OMAP_ABE_MIXDL2_TONES 21
+#define OMAP_ABE_MIXECHO_DL1 22
+#define OMAP_ABE_MIXECHO_DL2 23
+#define OMAP_ABE_MIXSDT_UL 24
+#define OMAP_ABE_MIXECHO_DL 25
+#define OMAP_ABE_MIXVXREC_MM_DL 26
+#define OMAP_ABE_MIXVXREC_TONES 27
+#define OMAP_ABE_MIXVXREC_VX_UL 28
+#define OMAP_ABE_MIXVXREC_VX_DL 29
+#define OMAP_ABE_MIXAUDUL_MM_DL 30
+#define OMAP_ABE_MIXAUDUL_TONES 31
+#define OMAP_ABE_MIXAUDUL_UPLINK 32
+#define OMAP_ABE_MIXAUDUL_VX_DL 33
+#define OMAP_ABE_GAIN_BTUL_LEFT 34
+#define OMAP_ABE_GAIN_BTUL_RIGTH 35
+
+void omap_abe_reset_gain_mixer(struct omap_abe *abe, u32 id, u32 p);
+
+void abe_int_2_float16(u32 data, u32 *mantissa, u32 *exp);
+
+#endif /* _ABE_GAIN_H_ */
diff --git a/sound/soc/omap/abe/abe_ini.c b/sound/soc/omap/abe/abe_ini.c
new file mode 100644
index 0000000..a126e23
--- /dev/null
+++ b/sound/soc/omap/abe/abe_ini.c
@@ -0,0 +1,455 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_dbg.h"
+#include "abe.h"
+#include "abe_aess.h"
+#include "abe_gain.h"
+#include "abe_mem.h"
+#include "abe_port.h"
+#include "abe_seq.h"
+
+#include "abe_taskid.h"
+
+
+#define ABE_TASK_ID(ID) (OMAP_ABE_D_TASKSLIST_ADDR + sizeof(ABE_STask)*(ID))
+void omap_abe_build_scheduler_table(struct omap_abe *abe);
+void omap_abe_reset_all_ports(struct omap_abe *abe);
+
+const u32 abe_firmware_array[ABE_FIRMWARE_MAX_SIZE] = {
+#include "abe_firmware.c"
+};
+
+
+/*
+ * initialize the default values for call-backs to subroutines
+ * - FIFO IRQ call-backs for sequenced tasks
+ * - FIFO IRQ call-backs for audio player/recorders (ping-pong protocols)
+ * - Remote debugger interface
+ * - Error monitoring
+ * - Activity Tracing
+ */
+
+/**
+ * abe_init_mem - Allocate Kernel space memory map for ABE
+ *
+ * Memory map of ABE memory space for PMEM/DMEM/SMEM/DMEM
+ */
+void abe_init_mem(void __iomem **_io_base)
+{
+ int i;
+
+ abe = kzalloc(sizeof(struct omap_abe), GFP_KERNEL);
+ if (abe == NULL)
+ printk(KERN_ERR "ABE Allocation ERROR ");
+
+ for (i = 0; i < 5; i++)
+ abe->io_base[i] = _io_base[i];
+
+ mutex_init(&abe->mutex);
+
+}
+EXPORT_SYMBOL(abe_init_mem);
+
+/**
+ * abe_load_fw_param - Load ABE Firmware memories
+ * @PMEM: Pointer of Program memory data
+ * @PMEM_SIZE: Size of PMEM data
+ * @CMEM: Pointer of Coeffients memory data
+ * @CMEM_SIZE: Size of CMEM data
+ * @SMEM: Pointer of Sample memory data
+ * @SMEM_SIZE: Size of SMEM data
+ * @DMEM: Pointer of Data memory data
+ * @DMEM_SIZE: Size of DMEM data
+ *
+ */
+int abe_load_fw_param(u32 *ABE_FW)
+{
+ u32 pmem_size, dmem_size, smem_size, cmem_size;
+ u32 *pmem_ptr, *dmem_ptr, *smem_ptr, *cmem_ptr, *fw_ptr;
+ /* fast counter timer set at 4096 * 250us = 1,024s */
+ u32 data = 0x10001000;
+
+ _log(ABE_ID_LOAD_FW_param, 0, 0, 0);
+#define ABE_FW_OFFSET 5
+ fw_ptr = ABE_FW;
+ abe->firmware_version_number = *fw_ptr++;
+ pmem_size = *fw_ptr++;
+ cmem_size = *fw_ptr++;
+ dmem_size = *fw_ptr++;
+ smem_size = *fw_ptr++;
+ pmem_ptr = fw_ptr;
+ cmem_ptr = pmem_ptr + (pmem_size >> 2);
+ dmem_ptr = cmem_ptr + (cmem_size >> 2);
+ smem_ptr = dmem_ptr + (dmem_size >> 2);
+ /* do not load PMEM */
+ if (abe->warm_boot) {
+ /* Stop the event Generator */
+ omap_abe_stop_event_generator(abe);
+
+ /* Now we are sure the firmware is stalled */
+ omap_abe_mem_write(abe, OMAP_ABE_CMEM, 0, cmem_ptr,
+ cmem_size);
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, 0, smem_ptr,
+ smem_size);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, 0, dmem_ptr,
+ dmem_size);
+
+ /* Restore the event Generator status */
+ omap_abe_start_event_generator(abe);
+ } else {
+ omap_abe_mem_write(abe, OMAP_ABE_PMEM, 0, pmem_ptr,
+ pmem_size);
+ omap_abe_mem_write(abe, OMAP_ABE_CMEM, 0, cmem_ptr,
+ cmem_size);
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, 0, smem_ptr,
+ smem_size);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, 0, dmem_ptr,
+ dmem_size);
+ }
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_FASTCOUNTER_ADDR,
+ &data,
+ OMAP_ABE_D_FASTCOUNTER_SIZE);
+
+ /* Update Saturation threshold */
+ data = 0x00700000;
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_SATURATION_EQ_ADDR,
+ &data, 4);
+ data = 0x00900000;
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_SATURATION_EQ_ADDR + 4,
+ &data, 4);
+
+ abe->warm_boot = 1;
+ return 0;
+}
+EXPORT_SYMBOL(abe_load_fw_param);
+
+/**
+ * omap_abe_load_fw - Load ABE Firmware and initialize memories
+ * @abe: Pointer on abe handle
+ *
+ */
+int omap_abe_load_fw(struct omap_abe *abe, u32 *firmware)
+{
+ _log(ABE_ID_LOAD_FW, 0, 0, 0);
+ abe_load_fw_param(firmware);
+ omap_abe_reset_all_ports(abe);
+ omap_abe_build_scheduler_table(abe);
+ omap_abe_reset_all_sequence(abe);
+ omap_abe_select_main_port(OMAP_ABE_PDM_DL_PORT);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_load_fw);
+
+/**
+ * abe_reload_fw - Reload ABE Firmware after OFF mode
+ */
+int omap_abe_reload_fw(struct omap_abe *abe, u32 *firmware)
+{
+ abe->warm_boot = 0;
+ abe_load_fw_param(firmware);
+ omap_abe_build_scheduler_table(abe);
+ omap_abe_dbg_reset(&abe->dbg);
+ /* IRQ circular read pointer in DMEM */
+ abe->irq_dbg_read_ptr = 0;
+ /* Restore Gains not managed by the drivers */
+ omap_abe_write_gain(abe, GAINS_SPLIT, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_SPLIT, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_reload_fw);
+
+/**
+ * omap_abe_get_default_fw
+ *
+ * Get default ABE firmware
+ */
+u32 *omap_abe_get_default_fw(struct omap_abe *abe)
+{
+ return (u32 *)abe_firmware_array;
+}
+
+/**
+ * abe_build_scheduler_table
+ *
+ */
+void omap_abe_build_scheduler_table(struct omap_abe *abe)
+{
+ u16 i, n;
+ u8 *ptr;
+ u16 aUplinkMuxing[NBROUTE_UL];
+
+ /* LOAD OF THE TASKS' MULTIFRAME */
+ /* WARNING ON THE LOCATION OF IO_MM_DL WHICH IS PATCHED
+ IN "abe_init_io_tasks" */
+ for (ptr = (u8 *) &(abe->MultiFrame[0][0]), i = 0;
+ i < sizeof(abe->MultiFrame); i++)
+ *ptr++ = 0;
+
+ abe->MultiFrame[0][2] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_VX_DL)*/;
+ abe->MultiFrame[0][3] = ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_DL_8);
+
+ abe->MultiFrame[1][3] = ABE_TASK_ID(C_ABE_FW_TASK_VX_DL_8_48_FIR);
+ abe->MultiFrame[1][6] = ABE_TASK_ID(C_ABE_FW_TASK_DL2Mixer);
+ abe->MultiFrame[1][7] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_VIB_DL)*/;
+
+ abe->MultiFrame[2][0] = ABE_TASK_ID(C_ABE_FW_TASK_DL1Mixer);
+ abe->MultiFrame[2][1] = ABE_TASK_ID(C_ABE_FW_TASK_SDTMixer);
+ abe->MultiFrame[2][5] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_DMIC)*/;
+
+ abe->MultiFrame[3][0] = ABE_TASK_ID(C_ABE_FW_TASK_DL1_GAIN);
+ abe->MultiFrame[3][6] = ABE_TASK_ID(C_ABE_FW_TASK_DL2_GAIN);
+ abe->MultiFrame[3][7] = ABE_TASK_ID(C_ABE_FW_TASK_DL2_EQ);
+
+ abe->MultiFrame[4][0] = ABE_TASK_ID(C_ABE_FW_TASK_DL1_EQ);
+ abe->MultiFrame[4][2] = ABE_TASK_ID(C_ABE_FW_TASK_VXRECMixer);
+ abe->MultiFrame[4][3] = ABE_TASK_ID(C_ABE_FW_TASK_VXREC_SPLIT);
+ abe->MultiFrame[4][6] = ABE_TASK_ID(C_ABE_FW_TASK_VIBRA1);
+ abe->MultiFrame[4][7] = ABE_TASK_ID(C_ABE_FW_TASK_VIBRA2);
+
+ abe->MultiFrame[5][0] = 0;
+ abe->MultiFrame[5][1] = ABE_TASK_ID(C_ABE_FW_TASK_EARP_48_96_LP);
+ abe->MultiFrame[5][2] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_UL)*/;
+ abe->MultiFrame[5][7] = ABE_TASK_ID(C_ABE_FW_TASK_VIBRA_SPLIT);
+
+ abe->MultiFrame[6][0] = ABE_TASK_ID(C_ABE_FW_TASK_EARP_48_96_LP);
+ abe->MultiFrame[6][4] = ABE_TASK_ID(C_ABE_FW_TASK_EchoMixer);
+ abe->MultiFrame[6][5] = ABE_TASK_ID(C_ABE_FW_TASK_BT_UL_SPLIT);
+
+ abe->MultiFrame[7][0] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_DL)*/;
+ abe->MultiFrame[7][3] = ABE_TASK_ID(C_ABE_FW_TASK_DBG_SYNC);
+ abe->MultiFrame[7][5] = ABE_TASK_ID(C_ABE_FW_TASK_ECHO_REF_SPLIT);
+
+ abe->MultiFrame[9][2] = ABE_TASK_ID(C_ABE_FW_TASK_CHECK_IIR_RIGHT);
+
+ abe->MultiFrame[9][6] = 0;
+ abe->MultiFrame[9][7] = ABE_TASK_ID(C_ABE_FW_TASK_IHF_48_96_LP);
+
+ abe->MultiFrame[10][7] = ABE_TASK_ID(C_ABE_FW_TASK_IHF_48_96_LP);
+
+ abe->MultiFrame[11][2] = ABE_TASK_ID(C_ABE_FW_TASK_AMIC_96_48_LP);
+ abe->MultiFrame[11][4] = ABE_TASK_ID(C_ABE_FW_TASK_AMIC_SPLIT);
+ abe->MultiFrame[11][7] = ABE_TASK_ID(C_ABE_FW_TASK_VIBRA_PACK);
+
+ abe->MultiFrame[12][3] = ABE_TASK_ID(C_ABE_FW_TASK_VX_UL_ROUTING);
+ abe->MultiFrame[12][4] = ABE_TASK_ID(C_ABE_FW_TASK_ULMixer);
+ abe->MultiFrame[12][5] = ABE_TASK_ID(C_ABE_FW_TASK_VX_UL_48_8);
+
+ abe->MultiFrame[13][2] = ABE_TASK_ID(C_ABE_FW_TASK_MM_UL2_ROUTING);
+ abe->MultiFrame[13][3] = ABE_TASK_ID(C_ABE_FW_TASK_SideTone);
+ abe->MultiFrame[13][5] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_BT_VX_DL)*/;
+
+ abe->MultiFrame[14][3] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_DMIC)*/;
+ abe->MultiFrame[14][4] = ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_8_FIR);
+
+ abe->MultiFrame[15][0] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_EXT_OUT)*/;
+ abe->MultiFrame[15][3] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_BT_VX_UL)*/;
+ abe->MultiFrame[15][6] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_UL_8)*/;
+
+ abe->MultiFrame[16][2] = ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_UL_8);
+ abe->MultiFrame[16][3] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_VX_UL)*/;
+
+ abe->MultiFrame[17][2] = ABE_TASK_ID(C_ABE_FW_TASK_BT_UL_8_48);
+ abe->MultiFrame[17][3] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_UL2)*/;
+
+ abe->MultiFrame[18][0] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_DL)*/;
+ abe->MultiFrame[18][6] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_DL_8)*/;
+
+ abe->MultiFrame[19][0] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_DL)*/;
+
+ /* MM_UL is moved to OPP 100% */
+ abe->MultiFrame[19][6] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_UL)*/;
+
+ abe->MultiFrame[20][0] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_TONES_DL)*/;
+ abe->MultiFrame[20][6] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_ASRC_MM_EXT_IN)*/;
+
+ abe->MultiFrame[21][1] = ABE_TASK_ID(C_ABE_FW_TASK_DEBUGTRACE_VX_ASRCs);
+ abe->MultiFrame[21][3] = 0/*ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_EXT_IN)*/;
+ /* MUST STAY ON SLOT 22 */
+ abe->MultiFrame[22][0] = ABE_TASK_ID(C_ABE_FW_TASK_DEBUG_IRQFIFO);
+ abe->MultiFrame[22][1] = ABE_TASK_ID(C_ABE_FW_TASK_INIT_FW_MEMORY);
+ abe->MultiFrame[22][2] = 0;
+ /* MM_EXT_IN_SPLIT task must be after IO_MM_EXT_IN and before
+ ASRC_MM_EXT_IN in order to manage OPP50 <-> transitions */
+ abe->MultiFrame[22][4] = ABE_TASK_ID(C_ABE_FW_TASK_MM_EXT_IN_SPLIT);
+
+ abe->MultiFrame[23][0] = ABE_TASK_ID(C_ABE_FW_TASK_GAIN_UPDATE);
+ abe->MultiFrame[23][2] = ABE_TASK_ID(C_ABE_FW_TASK_CHECK_IIR_LEFT);
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_MULTIFRAME_ADDR,
+ (u32 *) abe->MultiFrame, sizeof(abe->MultiFrame));
+ /* reset the uplink router */
+ n = (OMAP_ABE_D_AUPLINKROUTING_SIZE) >> 1;
+ for (i = 0; i < n; i++)
+ aUplinkMuxing[i] = ZERO_labelID;
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_AUPLINKROUTING_ADDR,
+ (u32 *) aUplinkMuxing, sizeof(aUplinkMuxing));
+}
+
+/**
+ * omap_abe_reset_port
+ * @id: ABE port ID
+ *
+ * stop the port activity and reload default parameters on the associated
+ * processing features.
+ * Clears the internal AE buffers.
+ */
+int omap_abe_reset_port(u32 id)
+{
+ _log(ABE_ID_RESET_PORT, id, 0, 0);
+ abe_port[id] = ((abe_port_t *) abe_port_init)[id];
+ return 0;
+}
+
+/**
+ * abe_reset_all_ports
+ *
+ * load default configuration for all features
+ */
+void omap_abe_reset_all_ports(struct omap_abe *abe)
+{
+ u16 i;
+ for (i = 0; i < LAST_PORT_ID; i++)
+ omap_abe_reset_port(i);
+ /* mixers' configuration */
+ omap_abe_write_mixer(abe, MIXDL1, MUTE_GAIN,
+ RAMP_2MS, MIX_DL1_INPUT_MM_DL);
+ omap_abe_write_mixer(abe, MIXDL1, MUTE_GAIN,
+ RAMP_2MS, MIX_DL1_INPUT_MM_UL2);
+ omap_abe_write_mixer(abe, MIXDL1, MUTE_GAIN,
+ RAMP_2MS, MIX_DL1_INPUT_VX_DL);
+ omap_abe_write_mixer(abe, MIXDL1, MUTE_GAIN,
+ RAMP_2MS, MIX_DL1_INPUT_TONES);
+ omap_abe_write_mixer(abe, MIXDL2, MUTE_GAIN,
+ RAMP_2MS, MIX_DL2_INPUT_TONES);
+ omap_abe_write_mixer(abe, MIXDL2, MUTE_GAIN,
+ RAMP_2MS, MIX_DL2_INPUT_VX_DL);
+ omap_abe_write_mixer(abe, MIXDL2, MUTE_GAIN,
+ RAMP_2MS, MIX_DL2_INPUT_MM_DL);
+ omap_abe_write_mixer(abe, MIXDL2, MUTE_GAIN,
+ RAMP_2MS, MIX_DL2_INPUT_MM_UL2);
+ omap_abe_write_mixer(abe, MIXSDT, MUTE_GAIN,
+ RAMP_2MS, MIX_SDT_INPUT_UP_MIXER);
+ omap_abe_write_mixer(abe, MIXSDT, GAIN_0dB,
+ RAMP_2MS, MIX_SDT_INPUT_DL1_MIXER);
+ omap_abe_write_mixer(abe, MIXECHO, MUTE_GAIN,
+ RAMP_2MS, MIX_ECHO_DL1);
+ omap_abe_write_mixer(abe, MIXECHO, MUTE_GAIN,
+ RAMP_2MS, MIX_ECHO_DL2);
+ omap_abe_write_mixer(abe, MIXAUDUL, MUTE_GAIN,
+ RAMP_2MS, MIX_AUDUL_INPUT_MM_DL);
+ omap_abe_write_mixer(abe, MIXAUDUL, MUTE_GAIN,
+ RAMP_2MS, MIX_AUDUL_INPUT_TONES);
+ omap_abe_write_mixer(abe, MIXAUDUL, GAIN_0dB,
+ RAMP_2MS, MIX_AUDUL_INPUT_UPLINK);
+ omap_abe_write_mixer(abe, MIXAUDUL, MUTE_GAIN,
+ RAMP_2MS, MIX_AUDUL_INPUT_VX_DL);
+ omap_abe_write_mixer(abe, MIXVXREC, MUTE_GAIN,
+ RAMP_2MS, MIX_VXREC_INPUT_TONES);
+ omap_abe_write_mixer(abe, MIXVXREC, MUTE_GAIN,
+ RAMP_2MS, MIX_VXREC_INPUT_VX_DL);
+ omap_abe_write_mixer(abe, MIXVXREC, MUTE_GAIN,
+ RAMP_2MS, MIX_VXREC_INPUT_MM_DL);
+ omap_abe_write_mixer(abe, MIXVXREC, MUTE_GAIN,
+ RAMP_2MS, MIX_VXREC_INPUT_VX_UL);
+ omap_abe_write_gain(abe, GAINS_DMIC1, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DMIC1, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DMIC2, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DMIC2, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DMIC3, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DMIC3, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_AMIC, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_AMIC, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_SPLIT, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_SPLIT, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DL1, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DL1, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DL2, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_DL2, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_BTUL, GAIN_0dB,
+ RAMP_2MS, GAIN_LEFT_OFFSET);
+ omap_abe_write_gain(abe, GAINS_BTUL, GAIN_0dB,
+ RAMP_2MS, GAIN_RIGHT_OFFSET);
+}
diff --git a/sound/soc/omap/abe/abe_initxxx_labels.h b/sound/soc/omap/abe/abe_initxxx_labels.h
new file mode 100644
index 0000000..823f2f3
--- /dev/null
+++ b/sound/soc/omap/abe/abe_initxxx_labels.h
@@ -0,0 +1,460 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _ABE_INITXXX_LABELS_H_
+#define _ABE_INITXXX_LABELS_H_
+#define Dummy_Regs_labelID 0
+#define Dummy_AM_labelID 1
+#define Voice_8k_UL_labelID 2
+#define Voice_8k_DL_labelID 3
+#define ECHO_REF_8K_labelID 4
+#define Voice_16k_UL_labelID 5
+#define Voice_16k_DL_labelID 6
+#define ECHO_REF_16K_labelID 7
+#define MM_DL_labelID 8
+#define IO_VX_DL_ASRC_labelID 9
+#define IO_MM_EXT_IN_ASRC_labelID 10
+#define IO_VIBRA_DL_labelID 11
+#define ZERO_labelID 12
+#define GTarget_labelID 13
+#define GCurrent_labelID 14
+#define Gr_1_labelID 15
+#define Gr_2_labelID 16
+#define Gr_Regs_labelID 17
+#define DMIC0_Gain_labelID 18
+#define DMIC1_Gain_labelID 19
+#define DMIC2_Gain_labelID 20
+#define DMIC3_Gain_labelID 21
+#define AMIC_Gain_labelID 22
+#define MIXDL1_Gain_labelID 23
+#define MIXDL2_Gain_labelID 24
+#define DEFAULT_Gain_labelID 25
+#define DL1_M_G_Tones_labelID 26
+#define DL2_M_G_Tones_labelID 27
+#define Echo_M_G_labelID 28
+#define SDT_M_G_labelID 29
+#define VXREC_M_G_VX_DL_labelID 30
+#define UL_M_G_VX_DL_labelID 31
+#define BTUL_Gain_labelID 32
+#define DL1_M_labelID 33
+#define DL2_M_labelID 34
+#define MM_UL2_labelID 35
+#define VX_DL_labelID 36
+#define Tones_labelID 37
+#define DL_M_MM_UL2_VX_DL_labelID 38
+#define Echo_M_labelID 39
+#define VX_UL_labelID 40
+#define VX_UL_M_labelID 41
+#define SDT_F_labelID 42
+#define SDT_F_data_labelID 43
+#define SDT_Coef_labelID 44
+#define SDT_Regs_labelID 45
+#define SDT_M_labelID 46
+#define DL1_EQ_labelID 47
+#define DL2_EQ_labelID 48
+#define DL1_GAIN_out_labelID 49
+#define DL2_GAIN_out_labelID 50
+#define DMIC1_labelID 51
+#define DMIC1_L_labelID 52
+#define DMIC1_R_labelID 53
+#define DMIC2_labelID 54
+#define DMIC2_L_labelID 55
+#define DMIC2_R_labelID 56
+#define DMIC3_labelID 57
+#define DMIC3_L_labelID 58
+#define DMIC3_R_labelID 59
+#define SaturationMinMax_labelID 60
+#define TEMPORARY0_labelID 61
+#define TEMPORARY1_labelID 62
+#define BT_UL_L_labelID 63
+#define BT_UL_R_labelID 64
+#define AMIC_labelID 65
+#define AMIC_L_labelID 66
+#define AMIC_R_labelID 67
+#define EchoRef_L_labelID 68
+#define EchoRef_R_labelID 69
+#define MM_DL_L_labelID 70
+#define MM_DL_R_labelID 71
+#define MM_UL_labelID 72
+#define AMIC_96_labelID 73
+#define DMIC0_96_labelID 74
+#define DMIC1_96_labelID 75
+#define DMIC2_96_labelID 76
+#define MM_DL_44P1_WPTR_labelID 77
+#define EQ_DL_48K_labelID 78
+#define EQ_48K_labelID 79
+#define McPDM_Out1_labelID 80
+#define McPDM_Out2_labelID 81
+#define McPDM_Out3_labelID 82
+#define VX_UL_MUX_labelID 83
+#define MM_UL2_MUX_labelID 84
+#define MM_UL_MUX_labelID 85
+#define XinASRC_DL_VX_labelID 86
+#define ASRC_DL_VX_Coefs_labelID 87
+#define ASRC_DL_VX_Alpha_labelID 88
+#define ASRC_DL_VX_VarsBeta_labelID 89
+#define ASRC_DL_VX_8k_Regs_labelID 90
+#define XinASRC_UL_VX_labelID 91
+#define ASRC_UL_VX_Coefs_labelID 92
+#define ASRC_UL_VX_Alpha_labelID 93
+#define ASRC_UL_VX_VarsBeta_labelID 94
+#define ASRC_UL_VX_8k_Regs_labelID 95
+#define UL_48_8_DEC_labelID 96
+#define ASRC_DL_VX_16k_Regs_labelID 97
+#define ASRC_UL_VX_16k_Regs_labelID 98
+#define UL_48_16_DEC_labelID 99
+#define XinASRC_MM_EXT_IN_labelID 100
+#define ASRC_MM_EXT_IN_Coefs_labelID 101
+#define ASRC_MM_EXT_IN_Alpha_labelID 102
+#define ASRC_MM_EXT_IN_VarsBeta_labelID 103
+#define ASRC_MM_EXT_IN_Regs_labelID 104
+#define VX_REC_labelID 105
+#define VXREC_UL_M_Tones_VX_UL_labelID 106
+#define VX_REC_L_labelID 107
+#define VX_REC_R_labelID 108
+#define DL2_M_L_labelID 109
+#define DL2_M_R_labelID 110
+#define DL1_M_data_labelID 111
+#define DL1_M_Coefs_labelID 112
+#define DL2_M_LR_data_labelID 113
+#define DL2_M_LR_Coefs_labelID 114
+#define SRC_6_LP_COEFS_labelID 115
+#define SRC_6_LP_GAIN_COEFS_labelID 116
+#define SRC_6_HP_COEFS_labelID 117
+#define SRC_3_LP_COEFS_labelID 118
+#define SRC_3_LP_GAIN_COEFS_labelID 119
+#define SRC_3_HP_COEFS_labelID 120
+#define VX_DL_8_48_LP_DATA_labelID 121
+#define VX_DL_8_48_HP_DATA_labelID 122
+#define VX_DL_16_48_LP_DATA_labelID 123
+#define VX_DL_16_48_HP_DATA_labelID 124
+#define VX_UL_48_8_LP_DATA_labelID 125
+#define VX_UL_48_8_HP_DATA_labelID 126
+#define VX_UL_48_16_LP_DATA_labelID 127
+#define VX_UL_48_16_HP_DATA_labelID 128
+#define BT_UL_8_48_LP_DATA_labelID 129
+#define BT_UL_8_48_HP_DATA_labelID 130
+#define BT_UL_16_48_LP_DATA_labelID 131
+#define BT_UL_16_48_HP_DATA_labelID 132
+#define BT_DL_48_8_LP_DATA_labelID 133
+#define BT_DL_48_8_HP_DATA_labelID 134
+#define BT_DL_48_16_LP_DATA_labelID 135
+#define BT_DL_48_16_HP_DATA_labelID 136
+#define ECHO_REF_48_16_LP_DATA_labelID 137
+#define ECHO_REF_48_16_HP_DATA_labelID 138
+#define ECHO_REF_48_8_LP_DATA_labelID 139
+#define ECHO_REF_48_8_HP_DATA_labelID 140
+#define ECHO_REF_DEC_labelID 141
+#define VX_UL_8_TEMP_labelID 142
+#define VX_UL_16_TEMP_labelID 143
+#define UP_DOWN_8_48_labelID 144
+#define UP_DOWN_16_48_labelID 145
+#define SRC_6_LP_48k_labelID 146
+#define SRC_6_HP_labelID 147
+#define SRC_3_LP_48k_labelID 148
+#define SRC_3_HP_labelID 149
+#define EARP_48_96_LP_DATA_labelID 150
+#define SRC_48_96_LP_labelID 151
+#define IHF_48_96_LP_DATA_labelID 152
+#define EQ_VX_UL_16K_labelID 153
+#define AB0_labelID 154
+#define AC0_labelID 155
+#define MM_DL_C_labelID 156
+#define TONES_C_labelID 157
+#define MM_DL_44P1_REGS_labelID 158
+#define TONES_44P1_REGS_labelID 159
+#define MM_DL_44P1_DRIFT_labelID 160
+#define MM_DL_44P1_XK_labelID 161
+#define TONES_44P1_DRIFT_labelID 162
+#define TONES_44P1_XK_labelID 163
+#define SRC_44P1_MULFAC1_2_labelID 164
+#define A00_labelID 165
+#define MM_DL_44P1_WPTR1_labelID 166
+#define MM_DL_44P1_RPTR_labelID 167
+#define TONES_44P1_WPTR_labelID 168
+#define TONES_44P1_RPTR_labelID 169
+#define C_0DB_SAT_labelID 170
+#define UL_MIC_48K_labelID 171
+#define MM_DL_44P1_PP_REGS_labelID 172
+#define SRC_6_HP_NEW_COEFS_labelID 173
+#define AF_labelID 174
+#define AG_labelID 175
+#define AH_labelID 176
+#define AI_labelID 177
+#define AJ_labelID 178
+#define AK_labelID 179
+#define AL_labelID 180
+#define AM_labelID 181
+#define AN_labelID 182
+#define AO_labelID 183
+#define AP_labelID 184
+#define AQ_labelID 185
+#define AR_labelID 186
+#define AS_labelID 187
+#define AT_labelID 188
+#define AU_labelID 189
+#define AV_labelID 190
+#define SaturationMinMaxEQ_labelID 191
+#define pVIBRA1_p0_labelID 192
+#define pVIBRA1_p1_labelID 193
+#define pVIBRA1_p23_labelID 194
+#define pVIBRA1_p45_labelID 195
+#define pVibra1_pR1_labelID 196
+#define pVibra1_pR2_labelID 197
+#define pVibra1_pR3_labelID 198
+#define pVIBRA1_r_labelID 199
+#define pVIBRA2_p0_0_labelID 200
+#define pVIBRA2_p0_labelID 201
+#define pVIBRA2_p1_labelID 202
+#define pVIBRA2_p23_labelID 203
+#define pVIBRA2_p45_labelID 204
+#define pCtrl_p67_labelID 205
+#define pVIBRA2_r_labelID 206
+#define VIBRA_labelID 207
+#define UP_48_96_LP_COEFS_DC_HF_labelID 208
+#define AX_labelID 209
+#define UP_48_96_LP_COEFS_DC_HS_labelID 210
+#define AMIC_96_48_data_labelID 211
+#define DOWN_96_48_AMIC_Coefs_labelID 212
+#define DOWN_96_48_DMIC_Coefs_labelID 213
+#define DOWN_96_48_AMIC_Regs_labelID 214
+#define DOWN_96_48_DMIC_Regs_labelID 215
+#define DMIC0_96_48_data_labelID 216
+#define DMIC1_96_48_data_labelID 217
+#define DMIC2_96_48_data_labelID 218
+#define SIO_DMIC_labelID 219
+#define SIO_PDM_UL_labelID 220
+#define SIO_BT_VX_UL_labelID 221
+#define SIO_MM_UL_labelID 222
+#define SIO_MM_UL2_labelID 223
+#define SIO_VX_UL_labelID 224
+#define SIO_MM_DL_labelID 225
+#define SIO_VX_DL_labelID 226
+#define SIO_TONES_DL_labelID 227
+#define SIO_VIB_DL_labelID 228
+#define SIO_BT_VX_DL_labelID 229
+#define SIO_PDM_DL_labelID 230
+#define SIO_MM_EXT_OUT_labelID 231
+#define SIO_MM_EXT_IN_labelID 232
+#define SIO_TDM_OUT_labelID 233
+#define SIO_TDM_IN_labelID 234
+#define DMIC_ATC_PTR_labelID 235
+#define MCPDM_UL_ATC_PTR_labelID 236
+#define BT_VX_UL_ATC_PTR_labelID 237
+#define MM_UL_ATC_PTR_labelID 238
+#define MM_UL2_ATC_PTR_labelID 239
+#define VX_UL_ATC_PTR_labelID 240
+#define MM_DL_ATC_PTR_labelID 241
+#define VX_DL_ATC_PTR_labelID 242
+#define TONES_DL_ATC_PTR_labelID 243
+#define VIB_DL_ATC_PTR_labelID 244
+#define BT_VX_DL_ATC_PTR_labelID 245
+#define PDM_DL_ATC_PTR_labelID 246
+#define MM_EXT_OUT_ATC_PTR_labelID 247
+#define MM_EXT_IN_ATC_PTR_labelID 248
+#define TDM_OUT_ATC_PTR_labelID 249
+#define TDM_IN_ATC_PTR_labelID 250
+#define MCU_IRQ_FIFO_ptr_labelID 251
+#define DEBUG_IRQ_FIFO_reg_labelID 252
+#define UP_DOWN_48_96_labelID 253
+#define OSR96_2_labelID 254
+#define DEBUG_GAINS_labelID 255
+#define DBG_8K_PATTERN_labelID 256
+#define DBG_16K_PATTERN_labelID 257
+#define DBG_24K_PATTERN_labelID 258
+#define DBG_48K_PATTERN_labelID 259
+#define DBG_96K_PATTERN_labelID 260
+#define UL_VX_UL_48_8K_labelID 261
+#define UL_VX_UL_48_16K_labelID 262
+#define BT_DL_labelID 263
+#define BT_UL_labelID 264
+#define BT_DL_8k_labelID 265
+#define BT_DL_16k_labelID 266
+#define BT_UL_8k_labelID 267
+#define BT_UL_16k_labelID 268
+#define MM_EXT_IN_labelID 269
+#define MM_EXT_IN_L_labelID 270
+#define MM_EXT_IN_R_labelID 271
+#define ECHO_REF_48_16_WRAP_labelID 272
+#define ECHO_REF_48_8_WRAP_labelID 273
+#define BT_UL_16_48_WRAP_labelID 274
+#define BT_UL_8_48_WRAP_labelID 275
+#define BT_DL_48_16_WRAP_labelID 276
+#define BT_DL_48_8_WRAP_labelID 277
+#define VX_DL_16_48_WRAP_labelID 278
+#define VX_DL_8_48_WRAP_labelID 279
+#define VX_UL_48_16_WRAP_labelID 280
+#define VX_UL_48_8_WRAP_labelID 281
+#define ATC_NULL_BUFFER_labelID 282
+#define MEM_INIT_hal_mem_labelID 283
+#define MEM_INIT_write_mem_labelID 284
+#define MEM_INIT_regs_labelID 285
+#define GAIN_0DB_labelID 286
+#define XinASRC_BT_UL_labelID 287
+#define IO_BT_UL_ASRC_labelID 288
+#define ASRC_BT_UL_Coefs_labelID 289
+#define ASRC_BT_UL_Alpha_labelID 290
+#define ASRC_BT_UL_VarsBeta_labelID 291
+#define ASRC_BT_UL_8k_Regs_labelID 292
+#define ASRC_BT_UL_16k_Regs_labelID 293
+#define XinASRC_BT_DL_labelID 294
+#define DL_48_8_DEC_labelID 295
+#define DL_48_16_DEC_labelID 296
+#define BT_DL_8k_TEMP_labelID 297
+#define BT_DL_16k_TEMP_labelID 298
+#define BT_DL_8k_opp100_labelID 299
+#define BT_DL_16k_opp100_labelID 300
+#define ASRC_BT_DL_Coefs_labelID 301
+#define ASRC_BT_DL_Alpha_labelID 302
+#define ASRC_BT_DL_VarsBeta_labelID 303
+#define ASRC_BT_DL_8k_Regs_labelID 304
+#define ASRC_BT_DL_16k_Regs_labelID 305
+#define BT_DL_48_8_OPP100_WRAP_labelID 306
+#define BT_DL_48_16_OPP100_WRAP_labelID 307
+#define VX_DL_8_48_OSR_LP_labelID 308
+#define SRC_FIR6_OSR_LP_labelID 309
+#define VX_DL_8_48_FIR_WRAP_labelID 310
+#define PING_labelID 311
+#define PING_Regs_labelID 312
+#define BT_UL_8_48_FIR_WRAP_labelID 313
+#define BT_UL_8_48_OSR_LP_labelID 314
+#define SRC_6_LP_NEW_48k_labelID 315
+#define BT_DL_8_48_OSR_LP_labelID 316
+#define SRC_FIR12_OSR_LP_labelID 317
+#define BT_DL_48_8_FIR_WRAP_labelID 318
+#define BT_DL_48_8_FIR_OPP100_WRAP_labelID 319
+#define VX_UL_48_8_FIR_WRAP_labelID 320
+#define VX_UL_8_48_OSR_LP_labelID 321
+#define Dummy_322_labelID 322
+#define Dummy_323_labelID 323
+#define Dummy_324_labelID 324
+#define Dummy_325_labelID 325
+#define Dummy_326_labelID 326
+#define Dummy_327_labelID 327
+#define Dummy_328_labelID 328
+#define Dummy_329_labelID 329
+#define Dummy_330_labelID 330
+#define Dummy_331_labelID 331
+#define Dummy_332_labelID 332
+#define Dummy_333_labelID 333
+#define Dummy_334_labelID 334
+#define Dummy_335_labelID 335
+#define Dummy_336_labelID 336
+#define Dummy_337_labelID 337
+#define Dummy_338_labelID 338
+#define Dummy_339_labelID 339
+#define Dummy_340_labelID 340
+#define Dummy_341_labelID 341
+#define Dummy_342_labelID 342
+#define Dummy_343_labelID 343
+#define Dummy_344_labelID 344
+#define Dummy_345_labelID 345
+#define Dummy_346_labelID 346
+#define Dummy_347_labelID 347
+#define Dummy_348_labelID 348
+#define Dummy_349_labelID 349
+#define Dummy_350_labelID 350
+#define Dummy_351_labelID 351
+#define Dummy_352_labelID 352
+#define Dummy_353_labelID 353
+#define Dummy_354_labelID 354
+#define Dummy_355_labelID 355
+#define Dummy_356_labelID 356
+#define Dummy_357_labelID 357
+#define Dummy_358_labelID 358
+#define Dummy_359_labelID 359
+#define Dummy_360_labelID 360
+#define Dummy_361_labelID 361
+#define Dummy_362_labelID 362
+#define Dummy_363_labelID 363
+#define Dummy_364_labelID 364
+#define Dummy_365_labelID 365
+#define Dummy_366_labelID 366
+#define Dummy_367_labelID 367
+#define Dummy_368_labelID 368
+#define Dummy_369_labelID 369
+#define Dummy_370_labelID 370
+#define Dummy_371_labelID 371
+#define Dummy_372_labelID 372
+#define Dummy_373_labelID 373
+#define Dummy_374_labelID 374
+#define Dummy_375_labelID 375
+#define Dummy_376_labelID 376
+#define Dummy_377_labelID 377
+#define Dummy_378_labelID 378
+#define Dummy_379_labelID 379
+#define Dummy_380_labelID 380
+#define Dummy_381_labelID 381
+#define Dummy_382_labelID 382
+#define Dummy_383_labelID 383
+#define Dummy_384_labelID 384
+#define Dummy_385_labelID 385
+#define Dummy_386_labelID 386
+#define Dummy_387_labelID 387
+#define Dummy_388_labelID 388
+#define Dummy_389_labelID 389
+#define Dummy_390_labelID 390
+#define Dummy_391_labelID 391
+#define Dummy_392_labelID 392
+#define Dummy_393_labelID 393
+#define Dummy_394_labelID 394
+#define Dummy_395_labelID 395
+#define Dummy_396_labelID 396
+#define Dummy_397_labelID 397
+#define Dummy_398_labelID 398
+#define Dummy_399_labelID 399
+#endif /* _ABE_INITXXXX_LABELS_H_ */
diff --git a/sound/soc/omap/abe/abe_irq.c b/sound/soc/omap/abe/abe_irq.c
new file mode 100644
index 0000000..7749d46
--- /dev/null
+++ b/sound/soc/omap/abe/abe_irq.c
@@ -0,0 +1,113 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "abe_legacy.h"
+
+extern u32 abe_irq_pingpong_player_id;
+
+/*
+ * initialize the default values for call-backs to subroutines
+ * - FIFO IRQ call-backs for sequenced tasks
+ * - FIFO IRQ call-backs for audio player/recorders (ping-pong protocols)
+ * - Remote debugger interface
+ * - Error monitoring
+ * - Activity Tracing
+ */
+/**
+ * abe_irq_ping_pong
+ *
+ * Call the respective subroutine depending on the IRQ FIFO content:
+ * APS interrupts : IRQ_FIFO[31:28] = IRQtag_APS,
+ * IRQ_FIFO[27:16] = APS_IRQs, IRQ_FIFO[15:0] = loopCounter
+ * SEQ interrupts : IRQ_FIFO[31:28] = IRQtag_COUNT,
+ * IRQ_FIFO[27:16] = Count_IRQs, IRQ_FIFO[15:0] = loopCounter
+ * Ping-Pong Interrupts : IRQ_FIFO[31:28] = IRQtag_PP,
+ * IRQ_FIFO[27:16] = PP_MCU_IRQ, IRQ_FIFO[15:0] = loopCounter
+ */
+void abe_irq_ping_pong(void)
+{
+ /* first IRQ doesn't represent a buffer transference completion */
+ if (abe->pp_first_irq)
+ abe->pp_first_irq = 0;
+ else
+ abe->pp_buf_id = (abe->pp_buf_id + 1) & 0x03;
+
+ abe_call_subroutine(abe_irq_pingpong_player_id, NOPARAMETER,
+ NOPARAMETER, NOPARAMETER, NOPARAMETER);
+}
+/**
+ * abe_irq_check_for_sequences
+* @i: sequence ID
+ *
+ * check the active sequence list
+ *
+ */
+void abe_irq_check_for_sequences(u32 i)
+{
+}
+/**
+ * abe_irq_aps
+ *
+ * call the application subroutines that updates
+ * the acoustics protection filters
+ */
+void abe_irq_aps(u32 aps_info)
+{
+ abe_call_subroutine(abe_irq_aps_adaptation_id, NOPARAMETER, NOPARAMETER,
+ NOPARAMETER, NOPARAMETER);
+}
diff --git a/sound/soc/omap/abe/abe_legacy.h b/sound/soc/omap/abe/abe_legacy.h
new file mode 100644
index 0000000..ca73dc2
--- /dev/null
+++ b/sound/soc/omap/abe/abe_legacy.h
@@ -0,0 +1,98 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_MAIN_H_
+#define _ABE_MAIN_H_
+
+#include <linux/io.h>
+
+#include "abe_dm_addr.h"
+#include "abe_sm_addr.h"
+#include "abe_cm_addr.h"
+#include "abe_define.h"
+#include "abe_fw.h"
+#include "abe_def.h"
+#include "abe_typ.h"
+#include "abe_ext.h"
+#include "abe_dbg.h"
+#include "abe_ref.h"
+#include "abe_api.h"
+#include "abe_typedef.h"
+#include "abe_functionsid.h"
+#include "abe_taskid.h"
+#include "abe_initxxx_labels.h"
+#include "abe_fw.h"
+
+/* pipe connection to the TARGET simulator */
+#define ABE_DEBUG_CHECKERS 0
+/* simulator data extracted from a text-file */
+#define ABE_DEBUG_HWFILE 0
+/* low-level log files */
+#define ABE_DEBUG_LL_LOG 0
+
+extern struct omap_abe *abe;
+
+void omap_abe_dbg_log(struct omap_abe *abe, u32 x, u32 y, u32 z, u32 t);
+void omap_abe_dbg_error(struct omap_abe *abe, int level, int error);
+
+/*
+ * MACROS
+ */
+#define _log(x, y, z, t) { if (x & abe->dbg.mask) omap_abe_dbg_log(abe, x, y, z, t); }
+
+#endif /* _ABE_MAIN_H_ */
diff --git a/sound/soc/omap/abe/abe_main.c b/sound/soc/omap/abe/abe_main.c
new file mode 100644
index 0000000..4f35e7f
--- /dev/null
+++ b/sound/soc/omap/abe/abe_main.c
@@ -0,0 +1,847 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "abe_legacy.h"
+#include "abe_dbg.h"
+#include "abe_port.h"
+
+
+struct omap_abe_equ {
+ /* type of filter */
+ u32 equ_type;
+ /* filter length */
+ u32 equ_length;
+ union {
+ /* parameters are the direct and recursive coefficients in */
+ /* Q6.26 integer fixed-point format. */
+ s32 type1[NBEQ1];
+ struct {
+ /* center frequency of the band [Hz] */
+ s32 freq[NBEQ2];
+ /* gain of each band. [dB] */
+ s32 gain[NBEQ2];
+ /* Q factor of this band [dB] */
+ s32 q[NBEQ2];
+ } type2;
+ } coef;
+ s32 equ_param3;
+};
+
+#include "abe_gain.h"
+#include "abe_aess.h"
+#include "abe_seq.h"
+
+
+int omap_abe_connect_debug_trace(struct omap_abe *abe,
+ struct omap_abe_dma *dma2);
+
+int omap_abe_reset_hal(struct omap_abe *abe);
+int omap_abe_load_fw(struct omap_abe *abe, u32 *firmware);
+int omap_abe_reload_fw(struct omap_abe *abe, u32 *firmware);
+u32* omap_abe_get_default_fw(struct omap_abe *abe);
+int omap_abe_wakeup(struct omap_abe *abe);
+int omap_abe_irq_processing(struct omap_abe *abe);
+int omap_abe_clear_irq(struct omap_abe *abe);
+int omap_abe_disable_irq(struct omap_abe *abe);
+int omap_abe_set_debug_trace(struct omap_abe_dbg *dbg, int debug);
+int omap_abe_set_ping_pong_buffer(struct omap_abe *abe,
+ u32 port, u32 n_bytes);
+int omap_abe_read_next_ping_pong_buffer(struct omap_abe *abe,
+ u32 port, u32 *p, u32 *n);
+int omap_abe_init_ping_pong_buffer(struct omap_abe *abe,
+ u32 id, u32 size_bytes, u32 n_buffers,
+ u32 *p);
+int omap_abe_read_offset_from_ping_buffer(struct omap_abe *abe,
+ u32 id, u32 *n);
+int omap_abe_set_router_configuration(struct omap_abe *abe,
+ u32 id, u32 k, u32 *param);
+int omap_abe_set_opp_processing(struct omap_abe *abe, u32 opp);
+int omap_abe_disable_data_transfer(struct omap_abe *abe, u32 id);
+int omap_abe_enable_data_transfer(struct omap_abe *abe, u32 id);
+int omap_abe_connect_cbpr_dmareq_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 d,
+ abe_dma_t *returned_dma_t);
+int omap_abe_connect_irq_ping_pong_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 subroutine_id, u32 size,
+ u32 *sink, u32 dsp_mcu_flag);
+int omap_abe_connect_serial_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 mcbsp_id);
+int omap_abe_read_port_address(struct omap_abe *abe,
+ u32 port, abe_dma_t *dma2);
+int omap_abe_check_activity(struct omap_abe *abe);
+
+int omap_abe_use_compensated_gain(struct omap_abe *abe, int on_off);
+int omap_abe_write_equalizer(struct omap_abe *abe,
+ u32 id, struct omap_abe_equ *param);
+
+int omap_abe_disable_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_enable_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_mute_gain(struct omap_abe *abe, u32 id, u32 p);
+int omap_abe_unmute_gain(struct omap_abe *abe, u32 id, u32 p);
+
+int omap_abe_write_gain(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 ramp, u32 p);
+int omap_abe_write_mixer(struct omap_abe *abe,
+ u32 id, s32 f_g, u32 f_ramp, u32 p);
+int omap_abe_read_gain(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p);
+int omap_abe_read_mixer(struct omap_abe *abe,
+ u32 id, u32 *f_g, u32 p);
+int omap_abe_mono_mixer(struct omap_abe *abe, u32 id, u32 on_off);
+
+int omap_abe_reset_vx_ul_src_filters(struct omap_abe *abe);
+int omap_abe_reset_mic_ul_src_filters(struct omap_abe *abe);
+int omap_abe_reset_vx_dl_src_filters(struct omap_abe *abe);
+int omap_abe_reset_dl1_src_filters(struct omap_abe *abe);
+int omap_abe_reset_dl2_src_filters(struct omap_abe *abe);
+int omap_abe_reset_bt_dl_src_filters(struct omap_abe *abe);
+void omap_abe_src_filters_saturation_monitoring(struct omap_abe *abe);
+
+extern struct omap_abe *abe;
+
+#if 0
+/**
+ * abe_init_mem - Allocate Kernel space memory map for ABE
+ *
+ * Memory map of ABE memory space for PMEM/DMEM/SMEM/DMEM
+ */
+void abe_init_mem(void __iomem *_io_base)
+{
+ omap_abe_init_mem(abe, _io_base);
+}
+EXPORT_SYMBOL(abe_init_mem);
+
+struct omap_abe* abe_probe_aess(void)
+{
+ return omap_abe_probe_aess(abe);
+}
+EXPORT_SYMBOL(abe_probe_aess);
+
+void abe_remove_aess(void)
+{
+ omap_abe_remove_aess(abe);
+}
+EXPORT_SYMBOL(abe_remove_aess);
+
+void abe_add_subroutine(u32 *id, abe_subroutine2 f,
+ u32 nparam, u32 *params)
+{
+ omap_abe_add_subroutine(abe, id, f, nparam, params);
+}
+EXPORT_SYMBOL(abe_add_subroutine);
+
+#endif
+
+/**
+ * abe_reset_hal - reset the ABE/HAL
+ * @rdev: regulator source
+ * @constraints: constraints to apply
+ *
+ * Operations : reset the HAL by reloading the static variables and
+ * default AESS registers.
+ * Called after a PRCM cold-start reset of ABE
+ */
+u32 abe_reset_hal(void)
+{
+ omap_abe_reset_hal(abe);
+ return 0;
+}
+EXPORT_SYMBOL(abe_reset_hal);
+
+/**
+ * abe_load_fw - Load ABE Firmware and initialize memories
+ *
+ */
+u32 abe_load_fw(u32 *firmware)
+{
+ omap_abe_load_fw(abe, firmware);
+ return 0;
+}
+EXPORT_SYMBOL(abe_load_fw);
+
+/**
+ * abe_reload_fw - Reload ABE Firmware and initialize memories
+ *
+ */
+u32 abe_reload_fw(u32 *firmware)
+{
+ omap_abe_reload_fw(abe, firmware);
+ return 0;
+}
+EXPORT_SYMBOL(abe_reload_fw);
+
+u32* abe_get_default_fw(void)
+{
+ return omap_abe_get_default_fw(abe);
+}
+EXPORT_SYMBOL(abe_get_default_fw);
+
+/**
+ * abe_wakeup - Wakeup ABE
+ *
+ * Wakeup ABE in case of retention
+ */
+u32 abe_wakeup(void)
+{
+ omap_abe_wakeup(abe);
+ return 0;
+}
+EXPORT_SYMBOL(abe_wakeup);
+
+/**
+ * abe_irq_processing - Process ABE interrupt
+ *
+ * This subroutine is call upon reception of "MA_IRQ_99 ABE_MPU_IRQ" Audio
+ * back-end interrupt. This subroutine will check the ATC Hrdware, the
+ * IRQ_FIFO from the AE and act accordingly. Some IRQ source are originated
+ * for the delivery of "end of time sequenced tasks" notifications, some are
+ * originated from the Ping-Pong protocols, some are generated from
+ * the embedded debugger when the firmware stops on programmable break-points,
+ * etc ...
+ */
+u32 abe_irq_processing(void)
+{
+ omap_abe_irq_processing(abe);
+ return 0;
+}
+EXPORT_SYMBOL(abe_irq_processing);
+
+/**
+ * abe_clear_irq - clear ABE interrupt
+ *
+ * This subroutine is call to clear MCU Irq
+ */
+u32 abe_clear_irq(void)
+{
+ omap_abe_clear_irq(abe);
+ return 0;
+}
+EXPORT_SYMBOL(abe_clear_irq);
+
+/**
+ * abe_disable_irq - disable MCU/DSP ABE interrupt
+ *
+ * This subroutine is disabling ABE MCU/DSP Irq
+ */
+u32 abe_disable_irq(void)
+{
+ omap_abe_disable_irq(abe);
+
+ return 0;
+}
+EXPORT_SYMBOL(abe_disable_irq);
+
+/**
+ * abe_write_event_generator - Selects event generator source
+ * @e: Event Generation Counter, McPDM, DMIC or default.
+ *
+ * Loads the AESS event generator hardware source.
+ * Loads the firmware parameters accordingly.
+ * Indicates to the FW which data stream is the most important to preserve
+ * in case all the streams are asynchronous.
+ * If the parameter is "default", then HAL decides which Event source
+ * is the best appropriate based on the opened ports.
+ *
+ * When neither the DMIC and the McPDM are activated, the AE will have
+ * its EVENT generator programmed with the EVENT_COUNTER.
+ * The event counter will be tuned in order to deliver a pulse frequency higher
+ * than 96 kHz.
+ * The DPLL output at 100% OPP is MCLK = (32768kHz x6000) = 196.608kHz
+ * The ratio is (MCLK/96000)+(1<<1) = 2050
+ * (1<<1) in order to have the same speed at 50% and 100% OPP
+ * (only 15 MSB bits are used at OPP50%)
+ */
+u32 abe_write_event_generator(u32 e) // should integarte abe as parameter
+{
+ omap_abe_write_event_generator(abe, e);
+ return 0;
+}
+EXPORT_SYMBOL(abe_write_event_generator);
+
+/**
+ * abe_start_event_generator - Starts event generator source
+ *
+ * Start the event genrator of AESS. No more event will be send to AESS engine.
+ * Upper layer must wait 1/96kHz to be sure that engine reaches
+ * the IDLE instruction.
+ */
+u32 abe_stop_event_generator(void)
+{
+ omap_abe_stop_event_generator(abe);
+ return 0;
+}
+EXPORT_SYMBOL(abe_stop_event_generator);
+
+/**
+ * abe_connect_debug_trace
+ * @dma2:pointer to the DMEM trace buffer
+ *
+ * returns the address and size of the real-time debug trace buffer,
+ * the content of which will vary from one firmware release to another
+ */
+u32 abe_connect_debug_trace(abe_dma_t *dma2)
+{
+ omap_abe_connect_debug_trace(abe, (struct omap_abe_dma *)dma2);
+ return 0;
+}
+EXPORT_SYMBOL(abe_connect_debug_trace);
+
+/**
+ * abe_set_debug_trace
+ * @debug: debug ID from a list to be defined
+ *
+ * loads a mask which filters the debug trace to dedicated types of data
+ */
+u32 abe_set_debug_trace(abe_dbg_t debug)
+{
+ omap_abe_set_debug_trace(&abe->dbg, (int)(debug));
+ return 0;
+}
+EXPORT_SYMBOL(abe_set_debug_trace);
+
+/**
+ * abe_set_ping_pong_buffer
+ * @port: ABE port ID
+ * @n_bytes: Size of Ping/Pong buffer
+ *
+ * Updates the next ping-pong buffer with "size" bytes copied from the
+ * host processor. This API notifies the FW that the data transfer is done.
+ */
+u32 abe_set_ping_pong_buffer(u32 port, u32 n_bytes)
+{
+ omap_abe_set_ping_pong_buffer(abe, port, n_bytes);
+ return 0;
+}
+EXPORT_SYMBOL(abe_set_ping_pong_buffer);
+
+/**
+ * abe_read_next_ping_pong_buffer
+ * @port: ABE portID
+ * @p: Next buffer address (pointer)
+ * @n: Next buffer size (pointer)
+ *
+ * Tell the next base address of the next ping_pong Buffer and its size
+ */
+u32 abe_read_next_ping_pong_buffer(u32 port, u32 *p, u32 *n)
+{
+ omap_abe_read_next_ping_pong_buffer(abe, port, p, n);
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_next_ping_pong_buffer);
+
+/**
+ * abe_init_ping_pong_buffer
+ * @id: ABE port ID
+ * @size_bytes:size of the ping pong
+ * @n_buffers:number of buffers (2 = ping/pong)
+ * @p:returned address of the ping-pong list of base addresses
+ * (byte offset from DMEM start)
+ *
+ * Computes the base address of the ping_pong buffers
+ */
+u32 abe_init_ping_pong_buffer(u32 id, u32 size_bytes, u32 n_buffers,
+ u32 *p)
+{
+ omap_abe_init_ping_pong_buffer(abe, id, size_bytes, n_buffers, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_init_ping_pong_buffer);
+
+/**
+ * abe_read_offset_from_ping_buffer
+ * @id: ABE port ID
+ * @n: returned address of the offset
+ * from the ping buffer start address (in samples)
+ *
+ * Computes the current firmware ping pong read pointer location,
+ * expressed in samples, as the offset from the start address of ping buffer.
+ */
+u32 abe_read_offset_from_ping_buffer(u32 id, u32 *n)
+{
+ omap_abe_read_offset_from_ping_buffer(abe, id, n);
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_offset_from_ping_buffer);
+
+/**
+ * abe_write_equalizer
+ * @id: name of the equalizer
+ * @param : equalizer coefficients
+ *
+ * Load the coefficients in CMEM.
+ */
+u32 abe_write_equalizer(u32 id, abe_equ_t *param)
+{
+ omap_abe_write_equalizer(abe, id, (struct omap_abe_equ *)param);
+ return 0;
+}
+EXPORT_SYMBOL(abe_write_equalizer);
+/**
+ * abe_disable_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+u32 abe_disable_gain(u32 id, u32 p)
+{
+ omap_abe_disable_gain(abe, id, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_disable_gain);
+/**
+ * abe_enable_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+u32 abe_enable_gain(u32 id, u32 p)
+{
+ omap_abe_enable_gain(abe, id, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_enable_gain);
+
+/**
+ * abe_mute_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+u32 abe_mute_gain(u32 id, u32 p)
+{
+ omap_abe_mute_gain(abe, id, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_mute_gain);
+
+/**
+ * abe_unmute_gain
+ * Parameters:
+ * mixer id
+ * sub-port id
+ *
+ */
+u32 abe_unmute_gain(u32 id, u32 p)
+{
+ omap_abe_unmute_gain(abe, id, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_unmute_gain);
+
+/**
+ * abe_write_gain
+ * @id: gain name or mixer name
+ * @f_g: list of input gains of the mixer
+ * @ramp: gain ramp speed factor
+ * @p: list of ports corresponding to the above gains
+ *
+ * Loads the gain coefficients to FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's gain
+ * in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+u32 abe_write_gain(u32 id, s32 f_g, u32 ramp, u32 p)
+{
+ omap_abe_write_gain(abe, id, f_g, ramp, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_write_gain);
+
+/**
+ * abe_write_mixer
+ * @id: name of the mixer
+ * @param: input gains and delay ramp of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+u32 abe_write_mixer(u32 id, s32 f_g, u32 f_ramp, u32 p)
+{
+ omap_abe_write_gain(abe, id, f_g, f_ramp, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_write_mixer);
+
+/**
+ * abe_read_gain
+ * @id: name of the mixer
+ * @param: list of input gains of the mixer
+ * @p: list of port corresponding to the above gains
+ *
+ */
+u32 abe_read_gain(u32 id, u32 *f_g, u32 p)
+{
+ omap_abe_read_gain(abe, id, f_g, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_gain);
+
+/**
+ * abe_read_mixer
+ * @id: name of the mixer
+ * @param: gains of the mixer
+ * @p: port corresponding to the above gains
+ *
+ * Load the gain coefficients in FW memory. This API can be called when
+ * the corresponding MIXER is not activated. After reloading the firmware
+ * the default coefficients corresponds to "all input and output mixer's
+ * gain in mute state". A mixer is disabled with a network reconfiguration
+ * corresponding to an OPP value.
+ */
+u32 abe_read_mixer(u32 id, u32 *f_g, u32 p)
+{
+ omap_abe_read_gain(abe, id, f_g, p);
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_mixer);
+
+/**
+ * abe_set_router_configuration
+ * @Id: name of the router
+ * @Conf: id of the configuration
+ * @param: list of output index of the route
+ *
+ * The uplink router takes its input from DMIC (6 samples), AMIC (2 samples)
+ * and PORT1/2 (2 stereo ports). Each sample will be individually stored in
+ * an intermediate table of 10 elements.
+ *
+ * Example of router table parameter for voice uplink with phoenix microphones
+ *
+ * indexes 0 .. 9 = MM_UL description (digital MICs and MMEXTIN)
+ * DMIC1_L_labelID, DMIC1_R_labelID, DMIC2_L_labelID, DMIC2_R_labelID,
+ * MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID, ZERO_labelID, ZERO_labelID,
+ * ZERO_labelID, ZERO_labelID,
+ * indexes 10 .. 11 = MM_UL2 description (recording on DMIC3)
+ * DMIC3_L_labelID, DMIC3_R_labelID,
+ * indexes 12 .. 13 = VX_UL description (VXUL based on PDMUL data)
+ * AMIC_L_labelID, AMIC_R_labelID,
+ * indexes 14 .. 15 = RESERVED (NULL)
+ * ZERO_labelID, ZERO_labelID,
+ */
+u32 abe_set_router_configuration(u32 id, u32 k, u32 *param)
+{
+ omap_abe_set_router_configuration(abe, id, k, param);
+ return 0;
+}
+EXPORT_SYMBOL(abe_set_router_configuration);
+
+/**
+ * abe_set_opp_processing - Set OPP mode for ABE Firmware
+ * @opp: OOPP mode
+ *
+ * New processing network and OPP:
+ * 0: Ultra Lowest power consumption audio player (no post-processing, no mixer)
+ * 1: OPP 25% (simple multimedia features, including low-power player)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% ( multimedia complex use-cases)
+ *
+ * Rearranges the FW task network to the corresponding OPP list of features.
+ * The corresponding AE ports are supposed to be set/reset accordingly before
+ * this switch.
+ *
+ */
+u32 abe_set_opp_processing(u32 opp)
+{
+ omap_abe_set_opp_processing(abe, opp);
+ return 0;
+}
+EXPORT_SYMBOL(abe_set_opp_processing);
+
+/**
+ * abe_disable_data_transfer
+ * @id: ABE port id
+ *
+ * disables the ATC descriptor and stop IO/port activities
+ * disable the IO task (@f = 0)
+ * clear ATC DMEM buffer, ATC enabled
+ */
+u32 abe_disable_data_transfer(u32 id)
+{
+ omap_abe_disable_data_transfer(abe, id);
+ return 0;
+}
+EXPORT_SYMBOL(abe_disable_data_transfer);
+
+/**
+ * abe_enable_data_transfer
+ * @ip: ABE port id
+ *
+ * enables the ATC descriptor
+ * reset ATC pointers
+ * enable the IO task (@f <> 0)
+ */
+u32 abe_enable_data_transfer(u32 id)
+{
+ omap_abe_enable_data_transfer(abe, id);
+ return 0;
+}
+EXPORT_SYMBOL(abe_enable_data_transfer);
+
+/**
+ * abe_connect_cbpr_dmareq_port
+ * @id: port name
+ * @f: desired data format
+ * @d: desired dma_request line (0..7)
+ * @a: returned pointer to the base address of the CBPr register and number of
+ * samples to exchange during a DMA_request.
+ *
+ * enables the data echange between a DMA and the ABE through the
+ * CBPr registers of AESS.
+ */
+u32 abe_connect_cbpr_dmareq_port(u32 id, abe_data_format_t *f, u32 d,
+ abe_dma_t *returned_dma_t)
+{
+ omap_abe_connect_cbpr_dmareq_port(abe, id, f, d, returned_dma_t);
+ return 0;
+}
+EXPORT_SYMBOL(abe_connect_cbpr_dmareq_port);
+
+/**
+ * abe_connect_irq_ping_pong_port
+ * @id: port name
+ * @f: desired data format
+ * @I: index of the call-back subroutine to call
+ * @s: half-buffer (ping) size
+ * @p: returned base address of the first (ping) buffer)
+ *
+ * enables the data echanges between a direct access to the DMEM
+ * memory of ABE using cache flush. On each IRQ activation a subroutine
+ * registered with "abe_plug_subroutine" will be called. This subroutine
+ * will generate an amount of samples, send them to DMEM memory and call
+ * "abe_set_ping_pong_buffer" to notify the new amount of samples in the
+ * pong buffer.
+ */
+u32 abe_connect_irq_ping_pong_port(u32 id, abe_data_format_t *f,
+ u32 subroutine_id, u32 size,
+ u32 *sink, u32 dsp_mcu_flag)
+{
+ omap_abe_connect_irq_ping_pong_port(abe, id, f, subroutine_id, size,
+ sink, dsp_mcu_flag);
+ return 0;
+}
+EXPORT_SYMBOL(abe_connect_irq_ping_pong_port);
+
+/**
+ * abe_connect_serial_port()
+ * @id: port name
+ * @f: data format
+ * @i: peripheral ID (McBSP #1, #2, #3)
+ *
+ * Operations : enables the data echanges between a McBSP and an ATC buffer in
+ * DMEM. This API is used connect 48kHz McBSP streams to MM_DL and 8/16kHz
+ * voice streams to VX_UL, VX_DL, BT_VX_UL, BT_VX_DL. It abstracts the
+ * abe_write_port API.
+ */
+u32 abe_connect_serial_port(u32 id, abe_data_format_t *f,
+ u32 mcbsp_id)
+{
+ omap_abe_connect_serial_port(abe, id, f, mcbsp_id);
+ return 0;
+}
+EXPORT_SYMBOL(abe_connect_serial_port);
+
+/**
+ * abe_read_port_address
+ * @dma: output pointer to the DMA iteration and data destination pointer
+ *
+ * This API returns the address of the DMA register used on this audio port.
+ * Depending on the protocol being used, adds the base address offset L3
+ * (DMA) or MPU (ARM)
+ */
+u32 abe_read_port_address(u32 port, abe_dma_t *dma2)
+{
+ omap_abe_read_port_address(abe, port, dma2);
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_port_address);
+
+/**
+ * abe_check_activity - Check if some ABE activity.
+ *
+ * Check if any ABE ports are running.
+ * return 1: still activity on ABE
+ * return 0: no more activity on ABE. Event generator can be stopped
+ *
+ */
+u32 abe_check_activity(void)
+{
+ return (u32)omap_abe_check_activity(abe);
+}
+EXPORT_SYMBOL(abe_check_activity);
+/**
+ * abe_use_compensated_gain
+ * @on_off:
+ *
+ * Selects the automatic Mixer's gain management
+ * on_off = 1 allows the "abe_write_gain" to adjust the overall
+ * gains of the mixer to be tuned not to create saturation
+ */
+abehal_status abe_use_compensated_gain(u32 on_off)
+{
+ omap_abe_use_compensated_gain(abe, (int)(on_off));
+ return 0;
+}
+
+/**
+ * abe_mono_mixer
+ * @id: name of the mixer (MIXDL1, MIXDL2, MIXAUDUL)
+ * on_off: enable\disable flag
+ *
+ * This API Programs DL1Mixer or DL2Mixer to output mono data
+ * on both left and right data paths.
+ */
+int abe_mono_mixer(u32 id, u32 on_off)
+{
+ return omap_abe_mono_mixer(abe, id, on_off);
+}
+EXPORT_SYMBOL(abe_mono_mixer);
+
+EXPORT_SYMBOL(abe_use_compensated_gain);
+
+/**
+* abe_reset_vx_ul_src_filters - reset VX UL path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_vx_ul_src_filters(void)
+{
+ return (u32)omap_abe_reset_vx_ul_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_vx_ul_src_filters);
+
+/**
+* abe_reset_mic_ul_src_filters - reset mic path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_mic_ul_src_filters(void)
+{
+ return (u32)omap_abe_reset_mic_ul_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_mic_ul_src_filters);
+
+/**
+* abe_reset_vx_dl_src_filters - reset VX DL path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_vx_dl_src_filters(void)
+{
+ return (u32)omap_abe_reset_vx_dl_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_vx_dl_src_filters);
+
+/**
+* abe_reset_dl1_src_filters - reset DL1 path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_dl1_src_filters(void)
+{
+ return (u32)omap_abe_reset_dl1_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_dl1_src_filters);
+
+/**
+* abe_reset_dl2_src_filters - reset DL2 path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_dl2_src_filters(void)
+{
+ return (u32)omap_abe_reset_dl2_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_dl2_src_filters);
+
+/**
+* abe_reset_bt_dl_src_filters - reset BT DL path filters
+*
+* it is assumed that filters are located in SMEM
+*/
+u32 abe_reset_bt_dl_src_filters(void)
+{
+ return (u32)omap_abe_reset_bt_dl_src_filters(abe);
+}
+EXPORT_SYMBOL(abe_reset_bt_dl_src_filters);
+
+/**
+* abe_src_ilters_saturation_monitoring - monitor for saturation
+* in abe filters
+*/
+void abe_src_filters_saturation_monitoring(void)
+{
+ omap_abe_src_filters_saturation_monitoring(abe);
+}
+EXPORT_SYMBOL(abe_src_filters_saturation_monitoring);
diff --git a/sound/soc/omap/abe/abe_main.h b/sound/soc/omap/abe/abe_main.h
new file mode 100644
index 0000000..e019541
--- /dev/null
+++ b/sound/soc/omap/abe/abe_main.h
@@ -0,0 +1,676 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_MAIN_H_
+#define _ABE_MAIN_H_
+
+#include <linux/io.h>
+
+#include "abe_initxxx_labels.h"
+
+#define D_DEBUG_FIFO_ADDR 8160
+#define D_DEBUG_FIFO_ADDR_END 8255
+
+#define SUB_0_PARAM 0
+#define SUB_1_PARAM 1
+
+#define ABE_DEFAULT_BASE_ADDRESS_L3 0x49000000L
+#define ABE_DMEM_BASE_ADDRESS_MPU 0x40180000L
+#define ABE_DMEM_BASE_OFFSET_MPU 0x00080000L
+#define ABE_DMEM_BASE_ADDRESS_L3 (ABE_DEFAULT_BASE_ADDRESS_L3 + \
+ ABE_DMEM_BASE_OFFSET_MPU)
+
+/*
+ * HARDWARE AND PERIPHERAL DEFINITIONS
+ */
+/* MM_DL */
+#define ABE_CBPR0_IDX 0
+/* VX_DL */
+#define ABE_CBPR1_IDX 1
+/* VX_UL */
+#define ABE_CBPR2_IDX 2
+/* MM_UL */
+#define ABE_CBPR3_IDX 3
+/* MM_UL2 */
+#define ABE_CBPR4_IDX 4
+/* TONES */
+#define ABE_CBPR5_IDX 5
+/* VIB */
+#define ABE_CBPR6_IDX 6
+/* DEBUG/CTL */
+#define ABE_CBPR7_IDX 7
+
+/*
+ * OPP TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (multimedia complex use-cases)
+ */
+#define ABE_OPP0 0
+#define ABE_OPP25 1
+#define ABE_OPP50 2
+#define ABE_OPP100 3
+/*
+ * SAMPLES TYPE
+ *
+ * mono 16 bit sample LSB aligned, 16 MSB bits are unused;
+ * mono right shifted to 16bits LSBs on a 32bits DMEM FIFO for McBSP
+ * TX purpose;
+ * mono sample MSB aligned (16/24/32bits);
+ * two successive mono samples in one 32bits container;
+ * Two L/R 16bits samples in a 32bits container;
+ * Two channels defined with two MSB aligned samples;
+ * Three channels defined with three MSB aligned samples (MIC);
+ * Four channels defined with four MSB aligned samples (MIC);
+ * . . .
+ * Eight channels defined with eight MSB aligned samples (MIC);
+ */
+#define MONO_MSB 1
+#define MONO_RSHIFTED_16 2
+#define STEREO_RSHIFTED_16 3
+#define STEREO_16_16 4
+#define STEREO_MSB 5
+#define THREE_MSB 6
+#define FOUR_MSB 7
+#define FIVE_MSB 8
+#define SIX_MSB 9
+#define SEVEN_MSB 10
+#define EIGHT_MSB 11
+#define NINE_MSB 12
+#define TEN_MSB 13
+/*
+ * PORT PROTOCOL TYPE - abe_port_protocol_switch_id
+ */
+#define SLIMBUS_PORT_PROT 1
+#define SERIAL_PORT_PROT 2
+#define TDM_SERIAL_PORT_PROT 3
+#define DMIC_PORT_PROT 4
+#define MCPDMDL_PORT_PROT 5
+#define MCPDMUL_PORT_PROT 6
+#define PINGPONG_PORT_PROT 7
+#define DMAREQ_PORT_PROT 8
+/*
+ * PORT IDs, this list is aligned with the FW data mapping
+ */
+#define DMIC_PORT 0
+#define PDM_UL_PORT 1
+#define BT_VX_UL_PORT 2
+#define MM_UL_PORT 3
+#define MM_UL2_PORT 4
+#define VX_UL_PORT 5
+#define MM_DL_PORT 6
+#define VX_DL_PORT 7
+#define TONES_DL_PORT 8
+#define VIB_DL_PORT 9
+#define BT_VX_DL_PORT 10
+#define PDM_DL_PORT 11
+#define MM_EXT_OUT_PORT 12
+#define MM_EXT_IN_PORT 13
+#define TDM_DL_PORT 14
+#define TDM_UL_PORT 15
+#define DEBUG_PORT 16
+#define LAST_PORT_ID 17
+/* definitions for the compatibility with HAL05xx */
+#define PDM_DL1_PORT 18
+#define PDM_DL2_PORT 19
+#define PDM_VIB_PORT 20
+/* There is only one DMIC port, always used with 6 samples
+ per 96kHz periods */
+#define DMIC_PORT1 DMIC_PORT
+#define DMIC_PORT2 DMIC_PORT
+#define DMIC_PORT3 DMIC_PORT
+/*
+ * Signal processing module names - EQ APS MIX ROUT
+ */
+/* equalizer downlink path headset + earphone */
+#define FEAT_EQ1 1
+/* equalizer downlink path integrated handsfree LEFT */
+#define FEAT_EQ2L (FEAT_EQ1+1)
+/* equalizer downlink path integrated handsfree RIGHT */
+#define FEAT_EQ2R (FEAT_EQ2L+1)
+/* equalizer downlink path side-tone */
+#define FEAT_EQSDT (FEAT_EQ2R+1)
+/* equalizer uplink path AMIC */
+#define FEAT_EQAMIC (FEAT_EQSDT+1)
+/* equalizer uplink path DMIC */
+#define FEAT_EQDMIC (FEAT_EQAMIC+1)
+/* Acoustic protection for headset */
+#define FEAT_APS1 (FEAT_EQDMIC+1)
+/* acoustic protection high-pass filter for handsfree "Left" */
+#define FEAT_APS2 (FEAT_APS1+1)
+/* acoustic protection high-pass filter for handsfree "Right" */
+#define FEAT_APS3 (FEAT_APS2+1)
+/* asynchronous sample-rate-converter for the downlink voice path */
+#define FEAT_ASRC1 (FEAT_APS3+1)
+/* asynchronous sample-rate-converter for the uplink voice path */
+#define FEAT_ASRC2 (FEAT_ASRC1+1)
+/* asynchronous sample-rate-converter for the multimedia player */
+#define FEAT_ASRC3 (FEAT_ASRC2+1)
+/* asynchronous sample-rate-converter for the echo reference */
+#define FEAT_ASRC4 (FEAT_ASRC3+1)
+/* mixer of the headset and earphone path */
+#define FEAT_MIXDL1 (FEAT_ASRC4+1)
+/* mixer of the hands-free path */
+#define FEAT_MIXDL2 (FEAT_MIXDL1+1)
+/* mixer for audio being sent on the voice_ul path */
+#define FEAT_MIXAUDUL (FEAT_MIXDL2+1)
+/* mixer for voice communication recording */
+#define FEAT_MIXVXREC (FEAT_MIXAUDUL+1)
+/* mixer for side-tone */
+#define FEAT_MIXSDT (FEAT_MIXVXREC+1)
+/* mixer for echo reference */
+#define FEAT_MIXECHO (FEAT_MIXSDT+1)
+/* router of the uplink path */
+#define FEAT_UPROUTE (FEAT_MIXECHO+1)
+/* all gains */
+#define FEAT_GAINS (FEAT_UPROUTE+1)
+#define FEAT_GAINS_DMIC1 (FEAT_GAINS+1)
+#define FEAT_GAINS_DMIC2 (FEAT_GAINS_DMIC1+1)
+#define FEAT_GAINS_DMIC3 (FEAT_GAINS_DMIC2+1)
+#define FEAT_GAINS_AMIC (FEAT_GAINS_DMIC3+1)
+#define FEAT_GAINS_SPLIT (FEAT_GAINS_AMIC+1)
+#define FEAT_GAINS_DL1 (FEAT_GAINS_SPLIT+1)
+#define FEAT_GAINS_DL2 (FEAT_GAINS_DL1+1)
+#define FEAT_GAIN_BTUL (FEAT_GAINS_DL2+1)
+/* sequencing queue of micro tasks */
+#define FEAT_SEQ (FEAT_GAIN_BTUL+1)
+/* Phoenix control queue through McPDM */
+#define FEAT_CTL (FEAT_SEQ+1)
+/* list of features of the firmware -------------------------------*/
+#define MAXNBFEATURE FEAT_CTL
+/* abe_equ_id */
+/* equalizer downlink path headset + earphone */
+#define EQ1 FEAT_EQ1
+/* equalizer downlink path integrated handsfree LEFT */
+#define EQ2L FEAT_EQ2L
+#define EQ2R FEAT_EQ2R
+/* equalizer downlink path side-tone */
+#define EQSDT FEAT_EQSDT
+#define EQAMIC FEAT_EQAMIC
+#define EQDMIC FEAT_EQDMIC
+/* abe_aps_id */
+/* Acoustic protection for headset */
+#define APS1 FEAT_APS1
+#define APS2L FEAT_APS2
+#define APS2R FEAT_APS3
+/* abe_asrc_id */
+/* asynchronous sample-rate-converter for the downlink voice path */
+#define ASRC1 FEAT_ASRC1
+/* asynchronous sample-rate-converter for the uplink voice path */
+#define ASRC2 FEAT_ASRC2
+/* asynchronous sample-rate-converter for the multimedia player */
+#define ASRC3 FEAT_ASRC3
+/* asynchronous sample-rate-converter for the voice uplink echo_reference */
+#define ASRC4 FEAT_ASRC4
+/* abe_mixer_id */
+#define MIXDL1 FEAT_MIXDL1
+#define MIXDL2 FEAT_MIXDL2
+#define MIXSDT FEAT_MIXSDT
+#define MIXECHO FEAT_MIXECHO
+#define MIXAUDUL FEAT_MIXAUDUL
+#define MIXVXREC FEAT_MIXVXREC
+/* abe_router_id */
+/* there is only one router up to now */
+#define UPROUTE FEAT_UPROUTE
+/*
+ * gain controls
+ */
+#define GAIN_LEFT_OFFSET 0
+#define GAIN_RIGHT_OFFSET 1
+/*
+ * GAIN IDs
+ */
+#define GAINS_DMIC1 FEAT_GAINS_DMIC1
+#define GAINS_DMIC2 FEAT_GAINS_DMIC2
+#define GAINS_DMIC3 FEAT_GAINS_DMIC3
+#define GAINS_AMIC FEAT_GAINS_AMIC
+#define GAINS_SPLIT FEAT_GAINS_SPLIT
+#define GAINS_DL1 FEAT_GAINS_DL1
+#define GAINS_DL2 FEAT_GAINS_DL2
+#define GAINS_BTUL FEAT_GAIN_BTUL
+/*
+ * ABE CONST AREA FOR PARAMETERS TRANSLATION
+ */
+#define sizeof_alpha_iir_table 61
+#define sizeof_beta_iir_table 61
+#define GAIN_MAXIMUM 3000L
+#define GAIN_24dB 2400L
+#define GAIN_18dB 1800L
+#define GAIN_12dB 1200L
+#define GAIN_6dB 600L
+/* default gain = 1 */
+#define GAIN_0dB 0L
+#define GAIN_M1dB -100L
+#define GAIN_M6dB -600L
+#define GAIN_M7dB -700L
+#define GAIN_M8dB -800L
+#define GAIN_M12dB -1200L
+#define GAIN_M18dB -1800L
+#define GAIN_M24dB -2400L
+#define GAIN_M30dB -3000L
+#define GAIN_M40dB -4000L
+#define GAIN_M50dB -5000L
+/* muted gain = -120 decibels */
+#define MUTE_GAIN -12000L
+#define GAIN_TOOLOW -13000L
+#define GAIN_MUTE MUTE_GAIN
+#define RAMP_MINLENGTH 3L
+/* ramp_t is in milli- seconds */
+#define RAMP_0MS 0L
+#define RAMP_1MS 1L
+#define RAMP_2MS 2L
+#define RAMP_5MS 5L
+#define RAMP_10MS 10L
+#define RAMP_20MS 20L
+#define RAMP_50MS 50L
+#define RAMP_100MS 100L
+#define RAMP_200MS 200L
+#define RAMP_500MS 500L
+#define RAMP_1000MS 1000L
+#define RAMP_MAXLENGTH 10000L
+/* for abe_translate_gain_format */
+#define LINABE_TO_DECIBELS 1
+#define DECIBELS_TO_LINABE 2
+/* for abe_translate_ramp_format */
+#define IIRABE_TO_MICROS 1
+#define MICROS_TO_IIABE 2
+/*
+ * EVENT GENERATORS - abe_event_id
+ */
+#define EVENT_TIMER 0
+#define EVENT_44100 1
+/*
+ * DMA requests
+ */
+/*Internal connection doesn't connect at ABE boundary */
+#define External_DMA_0 0
+/*Transmit request digital microphone */
+#define DMIC_DMA_REQ 1
+/*Multichannel PDM downlink */
+#define McPDM_DMA_DL 2
+/*Multichannel PDM uplink */
+#define McPDM_DMA_UP 3
+/*MCBSP module 1 - transmit request */
+#define MCBSP1_DMA_TX 4
+/*MCBSP module 1 - receive request */
+#define MCBSP1_DMA_RX 5
+/*MCBSP module 2 - transmit request */
+#define MCBSP2_DMA_TX 6
+/*MCBSP module 2 - receive request */
+#define MCBSP2_DMA_RX 7
+/*MCBSP module 3 - transmit request */
+#define MCBSP3_DMA_TX 8
+/*MCBSP module 3 - receive request */
+#define MCBSP3_DMA_RX 9
+/*
+ * SERIAL PORTS IDs - abe_mcbsp_id
+ */
+#define MCBSP1_TX MCBSP1_DMA_TX
+#define MCBSP1_RX MCBSP1_DMA_RX
+#define MCBSP2_TX MCBSP2_DMA_TX
+#define MCBSP2_RX MCBSP2_DMA_RX
+#define MCBSP3_TX MCBSP3_DMA_TX
+#define MCBSP3_RX MCBSP3_DMA_RX
+
+#define PING_PONG_WITH_MCU_IRQ 1
+#define PING_PONG_WITH_DSP_IRQ 2
+
+/*
+ Mixer ID Input port ID Comments
+ DL1_MIXER 0 MMDL path
+ 1 MMUL2 path
+ 2 VXDL path
+ 3 TONES path
+ SDT_MIXER 0 Uplink path
+ 1 Downlink path
+ ECHO_MIXER 0 DL1_MIXER path
+ 1 DL2_MIXER path
+ AUDUL_MIXER 0 TONES_DL path
+ 1 Uplink path
+ 2 MM_DL path
+ VXREC_MIXER 0 TONES_DL path
+ 1 VX_DL path
+ 2 MM_DL path
+ 3 VX_UL path
+*/
+#define MIX_VXUL_INPUT_MM_DL 0
+#define MIX_VXUL_INPUT_TONES 1
+#define MIX_VXUL_INPUT_VX_UL 2
+#define MIX_VXUL_INPUT_VX_DL 3
+#define MIX_DL1_INPUT_MM_DL 0
+#define MIX_DL1_INPUT_MM_UL2 1
+#define MIX_DL1_INPUT_VX_DL 2
+#define MIX_DL1_INPUT_TONES 3
+#define MIX_DL2_INPUT_MM_DL 0
+#define MIX_DL2_INPUT_MM_UL2 1
+#define MIX_DL2_INPUT_VX_DL 2
+#define MIX_DL2_INPUT_TONES 3
+#define MIX_SDT_INPUT_UP_MIXER 0
+#define MIX_SDT_INPUT_DL1_MIXER 1
+#define MIX_AUDUL_INPUT_MM_DL 0
+#define MIX_AUDUL_INPUT_TONES 1
+#define MIX_AUDUL_INPUT_UPLINK 2
+#define MIX_AUDUL_INPUT_VX_DL 3
+#define MIX_VXREC_INPUT_MM_DL 0
+#define MIX_VXREC_INPUT_TONES 1
+#define MIX_VXREC_INPUT_VX_UL 2
+#define MIX_VXREC_INPUT_VX_DL 3
+#define MIX_ECHO_DL1 0
+#define MIX_ECHO_DL2 1
+/* nb of samples to route */
+#define NBROUTE_UL 16
+/* 10 routing tables max */
+#define NBROUTE_CONFIG_MAX 10
+/* 5 pre-computed routing tables */
+#define NBROUTE_CONFIG 6
+/* AMIC on VX_UL */
+#define UPROUTE_CONFIG_AMIC 0
+/* DMIC first pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC1 1
+/* DMIC second pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC2 2
+/* DMIC last pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC3 3
+/* BT_UL on VX_UL */
+#define UPROUTE_CONFIG_BT 4
+/* ECHO_REF on MM_UL2 */
+#define UPROUTE_ECHO_MMUL2 5
+
+/*
+ * DMA_T
+ *
+ * dma structure for easing programming
+ */
+typedef struct {
+ /* OCP L3 pointer to the first address of the */
+ void *data;
+ /* destination buffer (either DMA or Ping-Pong read/write pointers). */
+ /* address L3 when addressing the DMEM buffer instead of CBPr */
+ void *l3_dmem;
+ /* address L3 translated to L4 the ARM memory space */
+ void *l4_dmem;
+ /* number of iterations for the DMA data moves. */
+ u32 iter;
+} abe_dma_t;
+typedef u32 abe_dbg_t;
+/*
+ * ROUTER_T
+ *
+ * table of indexes in unsigned bytes
+ */
+typedef u16 abe_router_t;
+/*
+ * DATA_FORMAT_T
+ *
+ * used in port declaration
+ */
+typedef struct {
+ /* Sampling frequency of the stream */
+ u32 f;
+ /* Sample format type */
+ u32 samp_format;
+} abe_data_format_t;
+/*
+ * PORT_PROTOCOL_T
+ *
+ * port declaration
+ */
+typedef struct {
+ /* Direction=0 means input from AESS point of view */
+ u32 direction;
+ /* Protocol type (switch) during the data transfers */
+ u32 protocol_switch;
+ union {
+ /* Slimbus peripheral connected to ATC */
+ struct {
+ /* Address of ATC Slimbus descriptor's index */
+ u32 desc_addr1;
+ /* DMEM address 1 in bytes */
+ u32 buf_addr1;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ /* Second ATC index for SlimBus reception (or NULL) */
+ u32 desc_addr2;
+ /* DMEM address 2 in bytes */
+ u32 buf_addr2;
+ } prot_slimbus;
+ /* McBSP/McASP peripheral connected to ATC */
+ struct {
+ u32 desc_addr;
+ /* Address of ATC McBSP/McASP descriptor's in bytes */
+ u32 buf_addr;
+ /* DMEM address in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ } prot_serial;
+ /* DMIC peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* Number of activated DMIC */
+ u32 nbchan;
+ } prot_dmic;
+ /* McPDMDL peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes */
+ u32 buf_size;
+ /* Control allowed on McPDM DL */
+ u32 control;
+ } prot_mcpdmdl;
+ /* McPDMUL peripheral connected to ATC */
+ struct {
+ /* DMEM address size in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ } prot_mcpdmul;
+ /* Ping-Pong interface to the Host using cache-flush */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes for each ping and pong buffers */
+ u32 buf_size;
+ /* IRQ address (either DMA (0) MCU (1) or DSP(2)) */
+ u32 irq_addr;
+ /* IRQ data content loaded in the AESS IRQ register */
+ u32 irq_data;
+ /* Call-back function upon IRQ reception */
+ u32 callback;
+ } prot_pingpong;
+ /* DMAreq line to CBPr */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } prot_dmareq;
+ /* Circular buffer - direct addressing to DMEM */
+ struct {
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } prot_circular_buffer;
+ } p;
+} abe_port_protocol_t;
+
+/*
+ * EQU_T
+ *
+ * coefficients of the equalizer
+ */
+/* 24 Q6.26 coefficients */
+#define NBEQ1 25
+/* 2x12 Q6.26 coefficients */
+#define NBEQ2 13
+
+typedef struct {
+ /* type of filter */
+ u32 equ_type;
+ /* filter length */
+ u32 equ_length;
+ union {
+ /* parameters are the direct and recursive coefficients in */
+ /* Q6.26 integer fixed-point format. */
+ s32 type1[NBEQ1];
+ struct {
+ /* center frequency of the band [Hz] */
+ s32 freq[NBEQ2];
+ /* gain of each band. [dB] */
+ s32 gain[NBEQ2];
+ /* Q factor of this band [dB] */
+ s32 q[NBEQ2];
+ } type2;
+ } coef;
+ s32 equ_param3;
+} abe_equ_t;
+
+
+/* subroutine with no parameter */
+typedef void (*abe_subroutine0) (void);
+/* subroutine with one parameter */
+typedef void (*abe_subroutine1) (u32);
+typedef void (*abe_subroutine2) (u32, u32);
+typedef void (*abe_subroutine3) (u32, u32, u32);
+typedef void (*abe_subroutine4) (u32, u32, u32, u32);
+
+
+extern u32 abe_irq_pingpong_player_id;
+
+
+void abe_init_mem(void __iomem **_io_base);
+u32 abe_reset_hal(void);
+int abe_load_fw(u32 *firmware);
+int abe_reload_fw(u32 *firmware);
+u32 *abe_get_default_fw(void);
+u32 abe_wakeup(void);
+u32 abe_irq_processing(void);
+u32 abe_clear_irq(void);
+u32 abe_disable_irq(void);
+u32 abe_write_event_generator(u32 e);
+u32 abe_stop_event_generator(void);
+u32 abe_connect_debug_trace(abe_dma_t *dma2);
+u32 abe_set_debug_trace(abe_dbg_t debug);
+u32 abe_set_ping_pong_buffer(u32 port, u32 n_bytes);
+u32 abe_read_next_ping_pong_buffer(u32 port, u32 *p, u32 *n);
+u32 abe_init_ping_pong_buffer(u32 id, u32 size_bytes, u32 n_buffers,
+ u32 *p);
+u32 abe_read_offset_from_ping_buffer(u32 id, u32 *n);
+u32 abe_write_equalizer(u32 id, abe_equ_t *param);
+u32 abe_disable_gain(u32 id, u32 p);
+u32 abe_enable_gain(u32 id, u32 p);
+u32 abe_mute_gain(u32 id, u32 p);
+u32 abe_unmute_gain(u32 id, u32 p);
+u32 abe_write_gain(u32 id, s32 f_g, u32 ramp, u32 p);
+u32 abe_write_mixer(u32 id, s32 f_g, u32 f_ramp, u32 p);
+u32 abe_read_gain(u32 id, u32 *f_g, u32 p);
+u32 abe_read_mixer(u32 id, u32 *f_g, u32 p);
+int abe_mono_mixer(u32 id, u32 on_off);
+u32 abe_set_router_configuration(u32 id, u32 k, u32 *param);
+u32 abe_set_opp_processing(u32 opp);
+u32 abe_disable_data_transfer(u32 id);
+u32 abe_enable_data_transfer(u32 id);
+u32 abe_connect_cbpr_dmareq_port(u32 id, abe_data_format_t *f, u32 d,
+ abe_dma_t *returned_dma_t);
+u32 abe_connect_irq_ping_pong_port(u32 id, abe_data_format_t *f,
+ u32 subroutine_id, u32 size,
+ u32 *sink, u32 dsp_mcu_flag);
+u32 abe_connect_serial_port(u32 id, abe_data_format_t *f,
+ u32 mcbsp_id);
+u32 abe_read_port_address(u32 port, abe_dma_t *dma2);
+void abe_add_subroutine(u32 *id, abe_subroutine2 f, u32 nparam, u32 *params);
+u32 abe_read_next_ping_pong_buffer(u32 port, u32 *p, u32 *n);
+void abe_write_pdmdl_offset(u32 path, u32 offset_left, u32 offset_right);
+u32 abe_reset_vx_ul_src_filters(void);
+u32 abe_reset_mic_ul_src_filters(void);
+u32 abe_reset_vx_dl_src_filters(void);
+u32 abe_reset_dl1_src_filters(void);
+u32 abe_reset_dl2_src_filters(void);
+u32 abe_reset_bt_dl_src_filters(void);
+void abe_src_filters_saturation_monitoring(void);
+u32 abe_check_activity(void);
+void abe_add_subroutine(u32 *id, abe_subroutine2 f,
+ u32 nparam, u32 *params);
+
+u32 abe_plug_subroutine(u32 *id, abe_subroutine2 f, u32 n,
+ u32 *params);
+
+#endif /* _ABE_MAIN_H_ */
diff --git a/sound/soc/omap/abe/abe_mem.h b/sound/soc/omap/abe/abe_mem.h
new file mode 100644
index 0000000..683968e
--- /dev/null
+++ b/sound/soc/omap/abe/abe_mem.h
@@ -0,0 +1,99 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_MEM_H_
+#define _ABE_MEM_H_
+
+#define OMAP_ABE_DMEM 0
+#define OMAP_ABE_CMEM 1
+#define OMAP_ABE_SMEM 2
+#define OMAP_ABE_PMEM 3
+#define OMAP_ABE_AESS 4
+
+/* Distinction between Read and Write from/to ABE memory
+ * is useful for simulation tool */
+static inline void omap_abe_mem_write(struct omap_abe *abe, int bank,
+ u32 offset, u32 *src, size_t bytes)
+{
+ memcpy((abe->io_base[bank] + offset), src, bytes);
+}
+
+static inline void omap_abe_mem_read(struct omap_abe *abe, int bank,
+ u32 offset, u32 *dest, size_t bytes)
+{
+ memcpy(dest, (abe->io_base[bank] + offset), bytes);
+}
+
+static inline u32 omap_abe_reg_readl(struct omap_abe *abe, u32 offset)
+{
+ return __raw_readl(abe->io_base[OMAP_ABE_AESS] + offset);
+}
+
+static inline void omap_abe_reg_writel(struct omap_abe *abe,
+ u32 offset, u32 val)
+{
+ __raw_writel(val, (abe->io_base[OMAP_ABE_AESS] + offset));
+}
+
+static inline void *omap_abe_reset_mem(struct omap_abe *abe, int bank,
+ u32 offset, size_t bytes)
+{
+ return memset(abe->io_base[bank] + offset, 0, bytes);
+}
+
+#endif /*_ABE_MEM_H_*/
diff --git a/sound/soc/omap/abe/abe_port.c b/sound/soc/omap/abe/abe_port.c
new file mode 100644
index 0000000..724dabd
--- /dev/null
+++ b/sound/soc/omap/abe/abe_port.c
@@ -0,0 +1,1774 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "abe_legacy.h"
+#include "abe_port.h"
+#include "abe_dbg.h"
+#include "abe_mem.h"
+#include "abe_gain.h"
+
+/**
+ * abe_clean_temporay buffers
+ *
+ * clear temporary buffers
+ */
+void omap_abe_clean_temporary_buffers(struct omap_abe *abe, u32 id)
+{
+ switch (id) {
+ case OMAP_ABE_DMIC_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_DMIC_UL_FIFO_ADDR,
+ OMAP_ABE_D_DMIC_UL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC0_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC0_96_48_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC1_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC1_96_48_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DMIC2_96_48_DATA_ADDR,
+ OMAP_ABE_S_DMIC2_96_48_DATA_SIZE);
+ /* reset working values of the gain, target gain is preserved */
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_PDM_UL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MCPDM_UL_FIFO_ADDR,
+ OMAP_ABE_D_MCPDM_UL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_AMIC_96_48_DATA_ADDR,
+ OMAP_ABE_S_AMIC_96_48_DATA_SIZE);
+ /* reset working values of the gain, target gain is preserved */
+ omap_abe_reset_gain_mixer(abe, GAINS_AMIC, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_BT_VX_UL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_BT_UL_FIFO_ADDR,
+ OMAP_ABE_D_BT_UL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_ADDR,
+ OMAP_ABE_S_BT_UL_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_8_48_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_8_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_8_48_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_8_48_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_16_48_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_16_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_UL_16_48_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_UL_16_48_LP_DATA_SIZE);
+ /* reset working values of the gain, target gain is preserved */
+ omap_abe_reset_gain_mixer(abe, GAINS_BTUL, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_BTUL, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_MM_UL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MM_UL_FIFO_ADDR,
+ OMAP_ABE_D_MM_UL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_MM_UL_ADDR,
+ OMAP_ABE_S_MM_UL_SIZE);
+ break;
+ case OMAP_ABE_MM_UL2_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MM_UL2_FIFO_ADDR,
+ OMAP_ABE_D_MM_UL2_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_MM_UL2_ADDR,
+ OMAP_ABE_S_MM_UL2_SIZE);
+ break;
+ case OMAP_ABE_VX_UL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_VX_UL_FIFO_ADDR,
+ OMAP_ABE_D_VX_UL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_ADDR,
+ OMAP_ABE_S_VX_UL_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_8_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_8_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_8_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_8_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_16_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_16_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_UL_48_16_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_UL_48_16_LP_DATA_SIZE);
+ omap_abe_reset_gain_mixer(abe, MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ break;
+ case OMAP_ABE_MM_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MM_DL_FIFO_ADDR,
+ OMAP_ABE_D_MM_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_MM_DL_ADDR,
+ OMAP_ABE_S_MM_DL_SIZE);
+ omap_abe_reset_gain_mixer(abe, MIXDL1, MIX_DL1_INPUT_MM_DL);
+ omap_abe_reset_gain_mixer(abe, MIXDL2, MIX_DL2_INPUT_MM_DL);
+ break;
+ case OMAP_ABE_VX_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_VX_DL_FIFO_ADDR,
+ OMAP_ABE_D_VX_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_ADDR,
+ OMAP_ABE_S_VX_DL_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_8_48_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_8_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_8_48_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_8_48_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_8_48_OSR_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_8_48_OSR_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_16_48_HP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_16_48_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VX_DL_16_48_LP_DATA_ADDR,
+ OMAP_ABE_S_VX_DL_16_48_LP_DATA_SIZE);
+ omap_abe_reset_gain_mixer(abe, MIXDL1, MIX_DL1_INPUT_VX_DL);
+ omap_abe_reset_gain_mixer(abe, MIXDL2, MIX_DL2_INPUT_VX_DL);
+ break;
+ case OMAP_ABE_TONES_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_TONES_DL_FIFO_ADDR,
+ OMAP_ABE_D_TONES_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_TONES_ADDR,
+ OMAP_ABE_S_TONES_SIZE);
+ omap_abe_reset_gain_mixer(abe, MIXDL1, MIX_DL1_INPUT_TONES);
+ omap_abe_reset_gain_mixer(abe, MIXDL2, MIX_DL2_INPUT_TONES);
+ break;
+ case OMAP_ABE_VIB_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_VIB_DL_FIFO_ADDR,
+ OMAP_ABE_D_VIB_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_VIBRA_ADDR,
+ OMAP_ABE_S_VIBRA_SIZE);
+ break;
+ case OMAP_ABE_BT_VX_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_BT_DL_FIFO_ADDR,
+ OMAP_ABE_D_BT_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_ADDR,
+ OMAP_ABE_S_BT_DL_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_8_48_OSR_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_8_48_OSR_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_8_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_8_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_8_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_8_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_16_HP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_16_HP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_BT_DL_48_16_LP_DATA_ADDR,
+ OMAP_ABE_S_BT_DL_48_16_LP_DATA_SIZE);
+ break;
+ case OMAP_ABE_PDM_DL_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MCPDM_DL_FIFO_ADDR,
+ OMAP_ABE_D_MCPDM_DL_FIFO_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DL2_M_LR_EQ_DATA_ADDR,
+ OMAP_ABE_S_DL2_M_LR_EQ_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_DL1_M_EQ_DATA_ADDR,
+ OMAP_ABE_S_DL1_M_EQ_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_EARP_48_96_LP_DATA_ADDR,
+ OMAP_ABE_S_EARP_48_96_LP_DATA_SIZE);
+ omap_abe_reset_mem(abe, OMAP_ABE_SMEM,
+ OMAP_ABE_S_IHF_48_96_LP_DATA_ADDR,
+ OMAP_ABE_S_IHF_48_96_LP_DATA_SIZE);
+ omap_abe_reset_gain_mixer(abe, GAINS_DL1, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DL1, GAIN_RIGHT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DL2, GAIN_LEFT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, GAINS_DL2, GAIN_RIGHT_OFFSET);
+ omap_abe_reset_gain_mixer(abe, MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ omap_abe_reset_gain_mixer(abe, MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ break;
+ case OMAP_ABE_MM_EXT_OUT_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MM_EXT_OUT_FIFO_ADDR,
+ OMAP_ABE_D_MM_EXT_OUT_FIFO_SIZE);
+ break;
+ case OMAP_ABE_MM_EXT_IN_PORT:
+ omap_abe_reset_mem(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MM_EXT_IN_FIFO_ADDR,
+ OMAP_ABE_D_MM_EXT_IN_FIFO_SIZE);
+ break;
+ }
+}
+
+/**
+ * omap_abe_disable_enable_dma_request
+ * Parameter:
+ * Operations:
+ * Return value:
+ */
+void omap_abe_disable_enable_dma_request(struct omap_abe *abe, u32 id,
+ u32 on_off)
+{
+ u8 desc_third_word[4], irq_dmareq_field;
+ u32 sio_desc_address;
+ u32 struct_offset;
+ struct ABE_SIODescriptor sio_desc;
+ struct ABE_SPingPongDescriptor desc_pp;
+
+ if (abe_port[id].protocol.protocol_switch == PINGPONG_PORT_PROT) {
+ irq_dmareq_field =
+ (u8) (on_off *
+ abe_port[id].protocol.p.prot_pingpong.irq_data);
+ sio_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR;
+ struct_offset = (u32) &(desc_pp.data_size) - (u32) &(desc_pp);
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ sio_desc_address + struct_offset,
+ (u32 *) desc_third_word, 4);
+ desc_third_word[2] = irq_dmareq_field;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ sio_desc_address + struct_offset,
+ (u32 *) desc_third_word, 4);
+ } else {
+ /* serial interface: sync ATC with Firmware activity */
+ sio_desc_address =
+ OMAP_ABE_D_IODESCR_ADDR +
+ (id * sizeof(struct ABE_SIODescriptor));
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ sio_desc_address, (u32 *) &sio_desc,
+ sizeof(sio_desc));
+ if (on_off) {
+ if (abe_port[id].protocol.protocol_switch != SERIAL_PORT_PROT)
+ sio_desc.atc_irq_data =
+ (u8) abe_port[id].protocol.p.prot_dmareq.
+ dma_data;
+ sio_desc.on_off = 0x80;
+ } else {
+ sio_desc.atc_irq_data = 0;
+ sio_desc.on_off = 0;
+ }
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ sio_desc_address, (u32 *) &sio_desc,
+ sizeof(sio_desc));
+ }
+
+}
+
+/**
+ * omap_abe_enable_dma_request
+ *
+ * Parameter:
+ * Operations:
+ * Return value:
+ *
+ */
+void omap_abe_enable_dma_request(struct omap_abe *abe, u32 id)
+{
+ omap_abe_disable_enable_dma_request(abe, id, 1);
+}
+
+/**
+ * omap_abe_disable_dma_request
+ *
+ * Parameter:
+ * Operations:
+ * Return value:
+ *
+ */
+void omap_abe_disable_dma_request(struct omap_abe *abe, u32 id)
+{
+ omap_abe_disable_enable_dma_request(abe, id, 0);
+}
+
+/**
+ * abe_init_atc
+ * @id: ABE port ID
+ *
+ * load the DMEM ATC/AESS descriptors
+ */
+void omap_abe_init_atc(struct omap_abe *abe, u32 id)
+{
+ u8 iter;
+ s32 datasize;
+ struct omap_abe_atc_desc atc_desc;
+
+#define JITTER_MARGIN 4
+ /* load default values of the descriptor */
+ atc_desc.rdpt = 0;
+ atc_desc.wrpt = 0;
+ atc_desc.irqdest = 0;
+ atc_desc.cberr = 0;
+ atc_desc.desen = 0;
+ atc_desc.nw = 0;
+ atc_desc.reserved0 = 0;
+ atc_desc.reserved1 = 0;
+ atc_desc.reserved2 = 0;
+ atc_desc.srcid = 0;
+ atc_desc.destid = 0;
+ atc_desc.badd = 0;
+ atc_desc.iter = 0;
+ atc_desc.cbsize = 0;
+ datasize = abe_dma_port_iter_factor(&((abe_port[id]).format));
+ iter = (u8) abe_dma_port_iteration(&((abe_port[id]).format));
+ /* if the ATC FIFO is too small there will be two ABE firmware
+ utasks to do the copy this happems on DMIC and MCPDMDL */
+ /* VXDL_8kMono = 4 = 2 + 2x1 */
+ /* VXDL_16kstereo = 12 = 8 + 2x2 */
+ /* MM_DL_1616 = 14 = 12 + 2x1 */
+ /* DMIC = 84 = 72 + 2x6 */
+ /* VXUL_8kMono = 2 */
+ /* VXUL_16kstereo = 4 */
+ /* MM_UL2_Stereo = 4 */
+ /* PDMDL = 12 */
+ /* IN from AESS point of view */
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN)
+ if (iter + 2 * datasize > 126)
+ atc_desc.wrpt = (iter >> 1) +
+ ((JITTER_MARGIN-1) * datasize);
+ else
+ atc_desc.wrpt = iter + ((JITTER_MARGIN-1) * datasize);
+ else
+ atc_desc.wrpt = 0 + ((JITTER_MARGIN+1) * datasize);
+ switch ((abe_port[id]).protocol.protocol_switch) {
+ case SLIMBUS_PORT_PROT:
+ atc_desc.cbdir = (abe_port[id]).protocol.direction;
+ atc_desc.cbsize =
+ (abe_port[id]).protocol.p.prot_slimbus.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_slimbus.buf_addr1) >> 4;
+ atc_desc.iter = (abe_port[id]).protocol.p.prot_slimbus.iter;
+ atc_desc.srcid =
+ abe_atc_srcid[(abe_port[id]).protocol.p.prot_slimbus.
+ desc_addr1 >> 3];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_slimbus.
+ desc_addr1, (u32 *) &atc_desc, sizeof(atc_desc));
+ atc_desc.badd =
+ (abe_port[id]).protocol.p.prot_slimbus.buf_addr2;
+ atc_desc.srcid =
+ abe_atc_srcid[(abe_port[id]).protocol.p.prot_slimbus.
+ desc_addr2 >> 3];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_slimbus.
+ desc_addr2, (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ case SERIAL_PORT_PROT:
+ atc_desc.cbdir = (abe_port[id]).protocol.direction;
+ atc_desc.cbsize =
+ (abe_port[id]).protocol.p.prot_serial.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_serial.buf_addr) >> 4;
+ atc_desc.iter = (abe_port[id]).protocol.p.prot_serial.iter;
+ atc_desc.srcid =
+ abe_atc_srcid[(abe_port[id]).protocol.p.prot_serial.
+ desc_addr >> 3];
+ atc_desc.destid =
+ abe_atc_dstid[(abe_port[id]).protocol.p.prot_serial.
+ desc_addr >> 3];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_serial.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ case DMIC_PORT_PROT:
+ atc_desc.cbdir = ABE_ATC_DIRECTION_IN;
+ atc_desc.cbsize = (abe_port[id]).protocol.p.prot_dmic.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_dmic.buf_addr) >> 4;
+ atc_desc.iter = DMIC_ITER;
+ atc_desc.srcid = abe_atc_srcid[ABE_ATC_DMIC_DMA_REQ];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (ABE_ATC_DMIC_DMA_REQ*ATC_SIZE),
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ case MCPDMDL_PORT_PROT:
+ atc_desc.cbdir = ABE_ATC_DIRECTION_OUT;
+ atc_desc.cbsize =
+ (abe_port[id]).protocol.p.prot_mcpdmdl.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_mcpdmdl.buf_addr) >> 4;
+ atc_desc.iter = MCPDM_DL_ITER;
+ atc_desc.destid = abe_atc_dstid[ABE_ATC_MCPDMDL_DMA_REQ];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (ABE_ATC_MCPDMDL_DMA_REQ*ATC_SIZE),
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ case MCPDMUL_PORT_PROT:
+ atc_desc.cbdir = ABE_ATC_DIRECTION_IN;
+ atc_desc.cbsize =
+ (abe_port[id]).protocol.p.prot_mcpdmul.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_mcpdmul.buf_addr) >> 4;
+ atc_desc.iter = MCPDM_UL_ITER;
+ atc_desc.srcid = abe_atc_srcid[ABE_ATC_MCPDMUL_DMA_REQ];
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (ABE_ATC_MCPDMUL_DMA_REQ*ATC_SIZE),
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ case PINGPONG_PORT_PROT:
+ /* software protocol, nothing to do on ATC */
+ break;
+ case DMAREQ_PORT_PROT:
+ atc_desc.cbdir = (abe_port[id]).protocol.direction;
+ atc_desc.cbsize =
+ (abe_port[id]).protocol.p.prot_dmareq.buf_size;
+ atc_desc.badd =
+ ((abe_port[id]).protocol.p.prot_dmareq.buf_addr) >> 4;
+ /* CBPr needs ITER=1.
+ It is the job of eDMA to do the iterations */
+ atc_desc.iter = 1;
+ /* input from ABE point of view */
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN) {
+ /* atc_atc_desc.rdpt = 127; */
+ /* atc_atc_desc.wrpt = 0; */
+ atc_desc.srcid = abe_atc_srcid
+ [(abe_port[id]).protocol.p.prot_dmareq.
+ desc_addr >> 3];
+ } else {
+ /* atc_atc_desc.rdpt = 0; */
+ /* atc_atc_desc.wrpt = 127; */
+ atc_desc.destid = abe_atc_dstid
+ [(abe_port[id]).protocol.p.prot_dmareq.
+ desc_addr >> 3];
+ }
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_dmareq.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ break;
+ }
+}
+
+/**
+ * omap_abe_enable_pp_io_task
+ * @id: port_id
+ *
+ *
+ */
+void omap_abe_enable_pp_io_task(struct omap_abe *abe, u32 id)
+{
+ if (OMAP_ABE_MM_DL_PORT == id) {
+ /* MM_DL managed in ping-pong */
+ abe->MultiFrame[TASK_IO_MM_DL_SLT][TASK_IO_MM_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_IO_PING_PONG);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MULTIFRAME_ADDR, (u32 *) abe->MultiFrame,
+ sizeof(abe->MultiFrame));
+ } else {
+ /* ping_pong is only supported on MM_DL */
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+}
+/**
+ * omap_abe_disable_pp_io_task
+ * @id: port_id
+ *
+ *
+ */
+void omap_abe_disable_pp_io_task(struct omap_abe *abe, u32 id)
+{
+ if (OMAP_ABE_MM_DL_PORT == id) {
+ /* MM_DL managed in ping-pong */
+ abe->MultiFrame[TASK_IO_MM_DL_SLT][TASK_IO_MM_DL_IDX] = 0;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MULTIFRAME_ADDR, (u32 *) abe->MultiFrame,
+ sizeof(abe->MultiFrame));
+ } else {
+ /* ping_pong is only supported on MM_DL */
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+}
+
+/**
+ * omap_abe_disable_data_transfer
+ * @id: ABE port id
+ *
+ * disables the ATC descriptor and stop IO/port activities
+ * disable the IO task (@f = 0)
+ * clear ATC DMEM buffer, ATC enabled
+ */
+int omap_abe_disable_data_transfer(struct omap_abe *abe, u32 id)
+{
+
+ _log(ABE_ID_DISABLE_DATA_TRANSFER, id, 0, 0);
+
+ /* MM_DL managed in ping-pong */
+ if (id == OMAP_ABE_MM_DL_PORT) {
+ if (abe_port[OMAP_ABE_MM_DL_PORT].protocol.protocol_switch == PINGPONG_PORT_PROT)
+ omap_abe_disable_pp_io_task(abe, OMAP_ABE_MM_DL_PORT);
+ }
+ /* local host variable status= "port is running" */
+ abe_port[id].status = OMAP_ABE_PORT_ACTIVITY_IDLE;
+ /* disable DMA requests */
+ omap_abe_disable_dma_request(abe, id);
+ /* disable ATC transfers */
+ omap_abe_init_atc(abe, id);
+ omap_abe_clean_temporary_buffers(abe, id);
+ /* select the main port based on the desactivation of this port */
+ abe_decide_main_port();
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_disable_data_transfer);
+
+/**
+ * omap_abe_enable_data_transfer
+ * @ip: ABE port id
+ *
+ * enables the ATC descriptor
+ * reset ATC pointers
+ * enable the IO task (@f <> 0)
+ */
+int omap_abe_enable_data_transfer(struct omap_abe *abe, u32 id)
+{
+ abe_port_protocol_t *protocol;
+ abe_data_format_t format;
+
+ _log(ABE_ID_ENABLE_DATA_TRANSFER, id, 0, 0);
+ omap_abe_clean_temporary_buffers(abe, id);
+
+ switch (id) {
+ case OMAP_ABE_PDM_UL_PORT:
+ case OMAP_ABE_PDM_DL_PORT:
+ case OMAP_ABE_DMIC_PORT:
+ /* initializes the ABE ATC descriptors in DMEM for BE ports */
+ protocol = &(abe_port[id].protocol);
+ format = abe_port[id].format;
+ omap_abe_init_atc(abe, id);
+ abe_init_io_tasks(id, &format, protocol);
+ break;
+
+ case OMAP_ABE_MM_DL_PORT:
+ protocol = &(abe_port[OMAP_ABE_MM_DL_PORT].protocol);
+ if (protocol->protocol_switch == PINGPONG_PORT_PROT)
+ abe->MultiFrame[TASK_IO_MM_DL_SLT][TASK_IO_MM_DL_IDX] = ABE_TASK_ID(C_ABE_FW_TASK_IO_PING_PONG);
+ else
+ abe->MultiFrame[TASK_IO_MM_DL_SLT][TASK_IO_MM_DL_IDX] = ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_DL);
+ break;
+ case OMAP_ABE_VX_UL_PORT:
+ break;
+ case OMAP_ABE_VX_DL_PORT:
+ break;
+ case OMAP_ABE_MM_UL2_PORT:
+ abe->MultiFrame[17][3] = ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_UL2);
+ break;
+ case OMAP_ABE_TONES_DL_PORT:
+ abe->MultiFrame[20][0] = ABE_TASK_ID(C_ABE_FW_TASK_IO_TONES_DL);
+ break;
+ case OMAP_ABE_MM_UL_PORT:
+ abe->MultiFrame[19][6] = ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_UL);
+ break;
+ case OMAP_ABE_BT_VX_DL_PORT:
+ abe->MultiFrame[13][5] = ABE_TASK_ID(C_ABE_FW_TASK_IO_BT_VX_DL);
+ break;
+ case OMAP_ABE_BT_VX_UL_PORT:
+ abe->MultiFrame[15][3] = ABE_TASK_ID(C_ABE_FW_TASK_IO_BT_VX_UL);
+ break;
+ case OMAP_ABE_MM_EXT_IN_PORT:
+ abe->MultiFrame[21][3] = ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_EXT_IN);
+ break;
+ case OMAP_ABE_MM_EXT_OUT_PORT:
+ abe->MultiFrame[15][0] = ABE_TASK_ID(C_ABE_FW_TASK_IO_MM_EXT_OUT);
+ break;
+ default:
+ break;
+ }
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_MULTIFRAME_ADDR,
+ (u32 *) abe->MultiFrame, sizeof(abe->MultiFrame));
+
+ /* local host variable status= "port is running" */
+ abe_port[id].status = OMAP_ABE_PORT_ACTIVITY_RUNNING;
+ /* enable DMA requests */
+ omap_abe_enable_dma_request(abe, id);
+ /* select the main port based on the activation of this new port */
+ abe_decide_main_port();
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_enable_data_transfer);
+
+/**
+ * omap_abe_connect_cbpr_dmareq_port
+ * @id: port name
+ * @f: desired data format
+ * @d: desired dma_request line (0..7)
+ * @a: returned pointer to the base address of the CBPr register and number of
+ * samples to exchange during a DMA_request.
+ *
+ * enables the data echange between a DMA and the ABE through the
+ * CBPr registers of AESS.
+ */
+int omap_abe_connect_cbpr_dmareq_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 d,
+ abe_dma_t *returned_dma_t)
+{
+ _log(ABE_ID_CONNECT_CBPR_DMAREQ_PORT, id, f->f, f->samp_format);
+
+ abe_port[id] = ((abe_port_t *) abe_port_init)[id];
+ (abe_port[id]).format = (*f);
+ abe_port[id].protocol.protocol_switch = DMAREQ_PORT_PROT;
+ abe_port[id].protocol.p.prot_dmareq.iter = abe_dma_port_iteration(f);
+ abe_port[id].protocol.p.prot_dmareq.dma_addr = ABE_DMASTATUS_RAW;
+ abe_port[id].protocol.p.prot_dmareq.dma_data = (1 << d);
+ /* load the dma_t with physical information from AE memory mapping */
+ abe_init_dma_t(id, &((abe_port[id]).protocol));
+
+ /* load the ATC descriptors - disabled */
+ omap_abe_init_atc(abe, id);
+
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port[id]).format),
+ &((abe_port[id]).protocol));
+ abe_port[id].status = OMAP_ABE_PORT_INITIALIZED;
+
+ /* return the dma pointer address */
+ abe_read_port_address(id, returned_dma_t);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_connect_cbpr_dmareq_port);
+
+/**
+ * omap_abe_connect_irq_ping_pong_port
+ * @id: port name
+ * @f: desired data format
+ * @I: index of the call-back subroutine to call
+ * @s: half-buffer (ping) size
+ * @p: returned base address of the first (ping) buffer)
+ *
+ * enables the data echanges between a direct access to the DMEM
+ * memory of ABE using cache flush. On each IRQ activation a subroutine
+ * registered with "abe_plug_subroutine" will be called. This subroutine
+ * will generate an amount of samples, send them to DMEM memory and call
+ * "abe_set_ping_pong_buffer" to notify the new amount of samples in the
+ * pong buffer.
+ */
+int omap_abe_connect_irq_ping_pong_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 subroutine_id, u32 size,
+ u32 *sink, u32 dsp_mcu_flag)
+{
+ _log(ABE_ID_CONNECT_IRQ_PING_PONG_PORT, id, f->f, f->samp_format);
+
+ /* ping_pong is only supported on MM_DL */
+ if (id != OMAP_ABE_MM_DL_PORT) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+ abe_port[id] = ((abe_port_t *) abe_port_init)[id];
+ (abe_port[id]).format = (*f);
+ (abe_port[id]).protocol.protocol_switch = PINGPONG_PORT_PROT;
+ (abe_port[id]).protocol.p.prot_pingpong.buf_addr =
+ OMAP_ABE_D_PING_ADDR;
+ (abe_port[id]).protocol.p.prot_pingpong.buf_size = size;
+ (abe_port[id]).protocol.p.prot_pingpong.irq_data = (1);
+ abe_init_ping_pong_buffer(OMAP_ABE_MM_DL_PORT, size, 2, sink);
+ if (dsp_mcu_flag == PING_PONG_WITH_MCU_IRQ)
+ (abe_port[id]).protocol.p.prot_pingpong.irq_addr =
+ ABE_MCU_IRQSTATUS_RAW;
+ if (dsp_mcu_flag == PING_PONG_WITH_DSP_IRQ)
+ (abe_port[id]).protocol.p.prot_pingpong.irq_addr =
+ ABE_DSP_IRQSTATUS_RAW;
+ abe_port[id].status = OMAP_ABE_PORT_INITIALIZED;
+
+ /* load the ATC descriptors - disabled */
+ omap_abe_init_atc(abe, id);
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port[id]).format),
+ &((abe_port[id]).protocol));
+
+ *sink = (abe_port[id]).protocol.p.prot_pingpong.buf_addr;
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_connect_irq_ping_pong_port);
+
+/**
+ * omap_abe_connect_serial_port()
+ * @id: port name
+ * @f: data format
+ * @i: peripheral ID (McBSP #1, #2, #3)
+ *
+ * Operations : enables the data echanges between a McBSP and an ATC buffer in
+ * DMEM. This API is used connect 48kHz McBSP streams to MM_DL and 8/16kHz
+ * voice streams to VX_UL, VX_DL, BT_VX_UL, BT_VX_DL. It abstracts the
+ * abe_write_port API.
+ */
+int omap_abe_connect_serial_port(struct omap_abe *abe,
+ u32 id, abe_data_format_t *f,
+ u32 mcbsp_id)
+{
+ _log(ABE_ID_CONNECT_SERIAL_PORT, id, f->samp_format, mcbsp_id);
+
+ abe_port[id] = ((abe_port_t *) abe_port_init)[id];
+ (abe_port[id]).format = (*f);
+ (abe_port[id]).protocol.protocol_switch = SERIAL_PORT_PROT;
+ /* McBSP peripheral connected to ATC */
+ (abe_port[id]).protocol.p.prot_serial.desc_addr = mcbsp_id*ATC_SIZE;
+ /* check the iteration of ATC */
+ (abe_port[id]).protocol.p.prot_serial.iter =
+ abe_dma_port_iter_factor(f);
+
+ /* load the ATC descriptors - disabled */
+ omap_abe_init_atc(abe, id);
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port[id]).format),
+ &((abe_port[id]).protocol));
+ abe_port[id].status = OMAP_ABE_PORT_INITIALIZED;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_connect_serial_port);
+
+/**
+ * omap_abe_read_port_address
+ * @dma: output pointer to the DMA iteration and data destination pointer
+ *
+ * This API returns the address of the DMA register used on this audio port.
+ * Depending on the protocol being used, adds the base address offset L3
+ * (DMA) or MPU (ARM)
+ */
+int omap_abe_read_port_address(struct omap_abe *abe,
+ u32 port, abe_dma_t *dma2)
+{
+ abe_dma_t_offset dma1;
+ u32 protocol_switch;
+
+ _log(ABE_ID_READ_PORT_ADDRESS, port, 0, 0);
+
+ dma1 = (abe_port[port]).dma;
+ protocol_switch = abe_port[port].protocol.protocol_switch;
+ switch (protocol_switch) {
+ case PINGPONG_PORT_PROT:
+ /* return the base address of the buffer in L3 and L4 spaces */
+ (*dma2).data = (void *)(dma1.data +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).l3_dmem = (void *)(dma1.data +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).l4_dmem = (void *)(dma1.data +
+ ABE_DEFAULT_BASE_ADDRESS_L4 + ABE_DMEM_BASE_OFFSET_MPU);
+ break;
+ case DMAREQ_PORT_PROT:
+ /* return the CBPr(L3), DMEM(L3), DMEM(L4) address */
+ (*dma2).data = (void *)(dma1.data +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_ATC_BASE_OFFSET_MPU);
+ (*dma2).l3_dmem =
+ (void *)((abe_port[port]).protocol.p.prot_dmareq.buf_addr +
+ ABE_DEFAULT_BASE_ADDRESS_L3 + ABE_DMEM_BASE_OFFSET_MPU);
+ (*dma2).l4_dmem =
+ (void *)((abe_port[port]).protocol.p.prot_dmareq.buf_addr +
+ ABE_DEFAULT_BASE_ADDRESS_L4 + ABE_DMEM_BASE_OFFSET_MPU);
+ break;
+ default:
+ break;
+ }
+ (*dma2).iter = (dma1.iter);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_read_port_address);
+
+/**
+ * abe_init_dma_t
+ * @ id: ABE port ID
+ * @ prot: protocol being used
+ *
+ * load the dma_t with physical information from AE memory mapping
+ */
+void abe_init_dma_t(u32 id, abe_port_protocol_t *prot)
+{
+ abe_dma_t_offset dma;
+ u32 idx;
+ /* default dma_t points to address 0000... */
+ dma.data = 0;
+ dma.iter = 0;
+ switch (prot->protocol_switch) {
+ case PINGPONG_PORT_PROT:
+ for (idx = 0; idx < 32; idx++) {
+ if (((prot->p).prot_pingpong.irq_data) ==
+ (u32) (1 << idx))
+ break;
+ }
+ (prot->p).prot_dmareq.desc_addr =
+ ((CBPr_DMA_RTX0 + idx)*ATC_SIZE);
+ /* translate byte address/size in DMEM words */
+ dma.data = (prot->p).prot_pingpong.buf_addr >> 2;
+ dma.iter = (prot->p).prot_pingpong.buf_size >> 2;
+ break;
+ case DMAREQ_PORT_PROT:
+ for (idx = 0; idx < 32; idx++) {
+ if (((prot->p).prot_dmareq.dma_data) ==
+ (u32) (1 << idx))
+ break;
+ }
+ dma.data = (CIRCULAR_BUFFER_PERIPHERAL_R__0 + (idx << 2));
+ dma.iter = (prot->p).prot_dmareq.iter;
+ (prot->p).prot_dmareq.desc_addr =
+ ((CBPr_DMA_RTX0 + idx)*ATC_SIZE);
+ break;
+ case SLIMBUS_PORT_PROT:
+ case SERIAL_PORT_PROT:
+ case DMIC_PORT_PROT:
+ case MCPDMDL_PORT_PROT:
+ case MCPDMUL_PORT_PROT:
+ default:
+ break;
+ }
+ /* upload the dma type */
+ abe_port[id].dma = dma;
+}
+
+/**
+ * abe_enable_atc
+ * Parameter:
+ * Operations:
+ * Return value:
+ */
+void abe_enable_atc(u32 id)
+{
+ struct omap_abe_atc_desc atc_desc;
+
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_dmareq.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ atc_desc.desen = 1;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_dmareq.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+
+}
+/**
+ * abe_disable_atc
+ * Parameter:
+ * Operations:
+ * Return value:
+ */
+void abe_disable_atc(u32 id)
+{
+ struct omap_abe_atc_desc atc_desc;
+
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_dmareq.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+ atc_desc.desen = 0;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ (abe_port[id]).protocol.p.prot_dmareq.desc_addr,
+ (u32 *) &atc_desc, sizeof(atc_desc));
+
+}
+/**
+ * abe_init_io_tasks
+ * @prot : protocol being used
+ *
+ * load the micro-task parameters doing to DMEM <==> SMEM data moves
+ *
+ * I/O descriptors input parameters :
+ * For Read from DMEM usually THR1/THR2 = X+1/X-1
+ * For Write to DMEM usually THR1/THR2 = 2/0
+ * UP_1/2 =X+1/X-1
+ */
+void abe_init_io_tasks(u32 id, abe_data_format_t *format,
+ abe_port_protocol_t *prot)
+{
+ u32 x_io, direction, iter_samples, smem1, smem2, smem3, io_sub_id,
+ io_flag;
+ u32 copy_func_index, before_func_index, after_func_index;
+ u32 dmareq_addr, dmareq_field;
+ u32 sio_desc_address, datasize, iter, nsamp, datasize2, dOppMode32;
+ u32 atc_ptr_saved, atc_ptr_saved2, copy_func_index1;
+ u32 copy_func_index2, atc_desc_address1, atc_desc_address2;
+ struct ABE_SPingPongDescriptor desc_pp;
+ struct ABE_SIODescriptor sio_desc;
+
+ if (prot->protocol_switch == PINGPONG_PORT_PROT) {
+ /* ping_pong is only supported on MM_DL */
+ if (OMAP_ABE_MM_DL_PORT != id) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_PARAMETER_ERROR);
+ }
+ smem1 = smem_mm_dl;
+ copy_func_index = (u8) abe_dma_port_copy_subroutine_id(id);
+ dmareq_addr = abe_port[id].protocol.p.prot_pingpong.irq_addr;
+ dmareq_field = abe_port[id].protocol.p.prot_pingpong.irq_data;
+ datasize = abe_dma_port_iter_factor(format);
+ /* number of "samples" either mono or stereo */
+ iter = abe_dma_port_iteration(format);
+ iter_samples = (iter / datasize);
+ /* load the IO descriptor */
+ /* no drift */
+ desc_pp.drift_ASRC = 0;
+ /* no drift */
+ desc_pp.drift_io = 0;
+ desc_pp.hw_ctrl_addr = (u16) dmareq_addr;
+ desc_pp.copy_func_index = (u8) copy_func_index;
+ desc_pp.smem_addr = (u8) smem1;
+ /* DMA req 0 is used for CBPr0 */
+ desc_pp.atc_irq_data = (u8) dmareq_field;
+ /* size of block transfer */
+ desc_pp.x_io = (u8) iter_samples;
+ desc_pp.data_size = (u8) datasize;
+ /* address comunicated in Bytes */
+ desc_pp.workbuff_BaseAddr =
+ (u16) (abe_base_address_pingpong[1]);
+ /* size comunicated in XIO sample */
+ desc_pp.workbuff_Samples = 0;
+ desc_pp.nextbuff0_BaseAddr =
+ (u16) (abe_base_address_pingpong[0]);
+ desc_pp.nextbuff1_BaseAddr =
+ (u16) (abe_base_address_pingpong[1]);
+ if (dmareq_addr == ABE_DMASTATUS_RAW) {
+ desc_pp.nextbuff0_Samples =
+ (u16) ((abe_size_pingpong >> 2) / datasize);
+ desc_pp.nextbuff1_Samples =
+ (u16) ((abe_size_pingpong >> 2) / datasize);
+ } else {
+ desc_pp.nextbuff0_Samples = 0;
+ desc_pp.nextbuff1_Samples = 0;
+ }
+ /* next buffer to send is B1, first IRQ fills B0 */
+ desc_pp.counter = 0;
+ /* send a DMA req to fill B0 with N samples
+ abe_block_copy (COPY_FROM_HOST_TO_ABE,
+ ABE_ATC,
+ ABE_DMASTATUS_RAW,
+ &(abe_port[id].protocol.p.prot_pingpong.irq_data),
+ 4); */
+ sio_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ sio_desc_address, (u32 *) &desc_pp,
+ sizeof(desc_pp));
+ } else {
+ io_sub_id = dmareq_addr = ABE_DMASTATUS_RAW;
+ dmareq_field = 0;
+ atc_desc_address1 = atc_desc_address2 = 0;
+ /* default: repeat of the last downlink samples in case of
+ DMA errors, (disable=0x00) */
+ io_flag = 0xFF;
+ datasize2 = datasize = abe_dma_port_iter_factor(format);
+ x_io = (u8) abe_dma_port_iteration(format);
+ nsamp = (x_io / datasize);
+ atc_ptr_saved2 = atc_ptr_saved = DMIC_ATC_PTR_labelID + id;
+ smem1 = abe_port[id].smem_buffer1;
+ smem3 = smem2 = abe_port[id].smem_buffer2;
+ copy_func_index1 = (u8) abe_dma_port_copy_subroutine_id(id);
+ before_func_index = after_func_index =
+ copy_func_index2 = NULL_COPY_CFPID;
+ switch (prot->protocol_switch) {
+ case DMIC_PORT_PROT:
+ /* DMIC port is read in two steps */
+ x_io = x_io >> 1;
+ nsamp = nsamp >> 1;
+ atc_desc_address1 = (ABE_ATC_DMIC_DMA_REQ*ATC_SIZE);
+ io_sub_id = IO_IP_CFPID;
+ break;
+ case MCPDMDL_PORT_PROT:
+ /* PDMDL port is written to in two steps */
+ x_io = x_io >> 1;
+ atc_desc_address1 =
+ (ABE_ATC_MCPDMDL_DMA_REQ*ATC_SIZE);
+ io_sub_id = IO_IP_CFPID;
+ break;
+ case MCPDMUL_PORT_PROT:
+ atc_desc_address1 =
+ (ABE_ATC_MCPDMUL_DMA_REQ*ATC_SIZE);
+ io_sub_id = IO_IP_CFPID;
+ break;
+ case SLIMBUS_PORT_PROT:
+ atc_desc_address1 =
+ abe_port[id].protocol.p.prot_slimbus.desc_addr1;
+ atc_desc_address2 =
+ abe_port[id].protocol.p.prot_slimbus.desc_addr2;
+ copy_func_index2 = NULL_COPY_CFPID;
+ /* @@@@@@
+ #define SPLIT_SMEM_CFPID 9
+ #define MERGE_SMEM_CFPID 10
+ #define SPLIT_TDM_12_CFPID 11
+ #define MERGE_TDM_12_CFPID 12
+ */
+ io_sub_id = IO_IP_CFPID;
+ break;
+ case SERIAL_PORT_PROT: /* McBSP/McASP */
+ atc_desc_address1 =
+ (s16) abe_port[id].protocol.p.prot_serial.
+ desc_addr;
+ io_sub_id = IO_IP_CFPID;
+ break;
+ case DMAREQ_PORT_PROT: /* DMA w/wo CBPr */
+ dmareq_addr =
+ abe_port[id].protocol.p.prot_dmareq.dma_addr;
+ dmareq_field = 0;
+ atc_desc_address1 =
+ abe_port[id].protocol.p.prot_dmareq.desc_addr;
+ io_sub_id = IO_IP_CFPID;
+ break;
+ }
+ /* special situation of the PING_PONG protocol which
+ has its own SIO descriptor format */
+ /*
+ Sequence of operations on ping-pong buffers B0/B1
+ -------------- time ---------------------------->>>>
+ Host Application is ready to send data from DDR to B0
+ SDMA is initialized from "abe_connect_irq_ping_pong_port" to B0
+ FIRMWARE starts with #12 B1 data,
+ sends IRQ/DMAreq, sends #pong B1 data,
+ sends IRQ/DMAreq, sends #ping B0,
+ sends B1 samples
+ ARM / SDMA | fills B0 | fills B1 ... | fills B0 ...
+ Counter 0 1 2 3
+ */
+ switch (id) {
+ case OMAP_ABE_PDM_DL_PORT:
+ abe->MultiFrame[7][0] = ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_DL);
+ abe->MultiFrame[19][0] = ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_DL);
+ break;
+ case OMAP_ABE_TONES_DL_PORT:
+ break;
+ case OMAP_ABE_PDM_UL_PORT:
+ abe->MultiFrame[5][2] = ABE_TASK_ID(C_ABE_FW_TASK_IO_PDM_UL);
+ break;
+ case OMAP_ABE_DMIC_PORT:
+ abe->MultiFrame[2][5] = ABE_TASK_ID(C_ABE_FW_TASK_IO_DMIC);
+ abe->MultiFrame[14][3] = ABE_TASK_ID(C_ABE_FW_TASK_IO_DMIC);
+ break;
+ case OMAP_ABE_MM_UL_PORT:
+ copy_func_index1 = COPY_MM_UL_CFPID;
+ before_func_index = ROUTE_MM_UL_CFPID;
+ break;
+ case OMAP_ABE_MM_UL2_PORT:
+ break;
+ case OMAP_ABE_VX_DL_PORT:
+ abe->MultiFrame[0][2] = ABE_TASK_ID(C_ABE_FW_TASK_IO_VX_DL);
+ /* check for 8kHz/16kHz */
+ if (abe_port[id].format.f == 8000) {
+ abe->MultiFrame[TASK_VX_DL_SLT][TASK_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_VX_DL_8_48_FIR);
+ /*Voice_8k_DL_labelID */
+ smem1 = IO_VX_DL_ASRC_labelID;
+
+ if ((abe_port[OMAP_ABE_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is VX_DL_PORT
+ * both VX_UL ASRC and VX_DL ASRC will add/remove sample
+ * referring to VX_DL flow_counter */
+ abe->MultiFrame[TASK_ASRC_VX_DL_SLT][TASK_ASRC_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_DL_8);
+ abe->MultiFrame[TASK_ASRC_VX_UL_SLT][TASK_ASRC_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_UL_8_SIB);
+ /* Init VX_UL ASRC & VX_DL ASRC and enable its adaptation */
+ abe_init_asrc_vx_ul(-250);
+ abe_init_asrc_vx_dl(250);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+ } else {
+ abe->MultiFrame[TASK_VX_DL_SLT][TASK_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_VX_DL_16_48);
+ /* Voice_16k_DL_labelID */
+ smem1 = IO_VX_DL_ASRC_labelID;
+
+ if ((abe_port[OMAP_ABE_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is VX_DL_PORT
+ * both VX_UL ASRC and VX_DL ASRC will add/remove sample
+ * referring to VX_DL flow_counter */
+ abe->MultiFrame[TASK_ASRC_VX_DL_SLT][TASK_ASRC_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_DL_16);
+ abe->MultiFrame[TASK_ASRC_VX_UL_SLT][TASK_ASRC_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_UL_16_SIB);
+ /* Init VX_UL ASRC & VX_DL ASRC and enable its adaptation */
+ abe_init_asrc_vx_ul(-250);
+ abe_init_asrc_vx_dl(250);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+ }
+ break;
+ case OMAP_ABE_VX_UL_PORT:
+ abe->MultiFrame[16][3] = ABE_TASK_ID(C_ABE_FW_TASK_IO_VX_UL);
+ /* check for 8kHz/16kHz */
+ if (abe_port[id].format.f == 8000) {
+ abe->MultiFrame[TASK_VX_UL_SLT][TASK_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_VX_UL_48_8);
+ /* MultiFrame[TASK_ECHO_SLT][TASK_ECHO_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ECHO_REF_48_8); */
+ smem1 = Voice_8k_UL_labelID;
+
+ if ((abe_port[OMAP_ABE_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is VX_UL_PORT
+ * both VX_UL ASRC and VX_DL ASRC will add/remove sample
+ * referring to VX_UL flow_counter */
+ abe->MultiFrame[TASK_ASRC_VX_DL_SLT][TASK_ASRC_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_DL_8_SIB);
+ abe->MultiFrame[TASK_ASRC_VX_UL_SLT][TASK_ASRC_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_UL_8);
+ /* Init VX_UL ASRC & VX_DL ASRC and enable its adaptation */
+ abe_init_asrc_vx_ul(-250);
+ abe_init_asrc_vx_dl(250);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+ } else {
+ abe->MultiFrame[TASK_VX_UL_SLT][TASK_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_VX_UL_48_16);
+ /* MultiFrame[TASK_ECHO_SLT][TASK_ECHO_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ECHO_REF_48_16); */
+ smem1 = Voice_16k_UL_labelID;
+
+ if ((abe_port[OMAP_ABE_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is VX_UL_PORT
+ * both VX_UL ASRC and VX_DL ASRC will add/remove sample
+ * referring to VX_UL flow_counter */
+ abe->MultiFrame[TASK_ASRC_VX_DL_SLT][TASK_ASRC_VX_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_DL_16_SIB);
+ abe->MultiFrame[TASK_ASRC_VX_UL_SLT][TASK_ASRC_VX_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_VX_UL_16);
+ /* Init VX_UL ASRC & VX_DL ASRC and enable its adaptation */
+ abe_init_asrc_vx_ul(-250);
+ abe_init_asrc_vx_dl(250);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+ }
+ break;
+ case OMAP_ABE_BT_VX_DL_PORT:
+ /* check for 8kHz/16kHz */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MAXTASKBYTESINSLOT_ADDR, &dOppMode32,
+ sizeof(u32));
+
+ /* Disable BT ASRC */
+ dOppMode32 = DOPPMODE32_OPP50;
+
+ if (abe_port[id].format.f == 8000) {
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_8_FIR_OPP100);
+ smem1 = BT_DL_8k_opp100_labelID;
+ } else {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_8_FIR);
+ smem1 = BT_DL_8k_labelID;
+ }
+#if 0
+ if ((abe_port[OMAP_ABE_BT_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_BT_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is BT_VX_DL_PORT
+ * both BT_VX_DL ASRC and BT_VX_UL ASRC will add/remove sample
+ * referring to BT_VX_DL flow_counter */
+ abe->MultiFrame[TASK_ASRC_BT_DL_SLT][TASK_ASRC_BT_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_DL_8);
+ abe->MultiFrame[TASK_ASRC_BT_UL_SLT][TASK_ASRC_BT_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_UL_8_SIB);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+#endif
+ } else {
+ if (dOppMode32 == DOPPMODE32_OPP100) {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_16_OPP100);
+ smem1 = BT_DL_16k_opp100_labelID;
+ } else {
+ abe->MultiFrame[TASK_BT_DL_48_8_SLT][TASK_BT_DL_48_8_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_DL_48_16);
+ smem1 = BT_DL_16k_labelID;
+ }
+#if 0
+ if ((abe_port[OMAP_ABE_BT_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_BT_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is BT_VX_DL_PORT
+ * both BT_VX_DL ASRC and BT_VX_UL ASRC will add/remove sample
+ * referring to BT_VX_DL flow_counter */
+ abe->MultiFrame[TASK_ASRC_BT_DL_SLT][TASK_ASRC_BT_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_DL_16);
+ abe->MultiFrame[TASK_ASRC_BT_UL_SLT][TASK_ASRC_BT_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_UL_16_SIB);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+#endif
+ }
+ break;
+ case OMAP_ABE_BT_VX_UL_PORT:
+ /* check for 8kHz/16kHz */
+ /* set the SMEM buffer -- programming sequence */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MAXTASKBYTESINSLOT_ADDR, &dOppMode32,
+ sizeof(u32));
+
+ /* Disable BT ASRC */
+ dOppMode32 = DOPPMODE32_OPP50;
+
+ if (abe_port[id].format.f == 8000) {
+ abe->MultiFrame[TASK_BT_UL_8_48_SLT][TASK_BT_UL_8_48_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_UL_8_48);
+ if (dOppMode32 == DOPPMODE32_OPP100)
+ /* ASRC input buffer, size 40 */
+ smem1 = smem_bt_vx_ul_opp100;
+ else
+ /* at OPP 50 without ASRC */
+ smem1 = BT_UL_8k_labelID;
+#if 0
+ if ((abe_port[OMAP_ABE_BT_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_BT_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is BT_VX_UL_PORT */
+ /* both BT_VX_UL ASRC and BT_VX_DL ASRC will add/remove sample
+ referring to BT_VX_UL flow_counter */
+ abe->MultiFrame[TASK_ASRC_BT_UL_SLT][TASK_ASRC_BT_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_UL_8);
+ abe->MultiFrame[TASK_ASRC_BT_DL_SLT][TASK_ASRC_BT_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_DL_8_SIB);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+#endif
+ } else {
+ abe->MultiFrame[TASK_BT_UL_8_48_SLT][TASK_BT_UL_8_48_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_BT_UL_16_48);
+ if (dOppMode32 == DOPPMODE32_OPP100)
+ /* ASRC input buffer, size 40 */
+ smem1 = smem_bt_vx_ul_opp100;
+ else
+ /* at OPP 50 without ASRC */
+ smem1 = BT_UL_16k_labelID;
+#if 0
+ if ((abe_port[OMAP_ABE_BT_VX_UL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE) &&
+ (abe_port[OMAP_ABE_BT_VX_DL_PORT].status ==
+ OMAP_ABE_PORT_ACTIVITY_IDLE)) {
+ /* the 1st opened port is BT_VX_UL_PORT */
+ /* both BT_VX_UL ASRC and BT_VX_DL ASRC will add/remove sample
+ referring to BT_VX_UL flow_counter */
+ abe->MultiFrame[TASK_ASRC_BT_UL_SLT][TASK_ASRC_BT_UL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_UL_16);
+ abe->MultiFrame[TASK_ASRC_BT_DL_SLT][TASK_ASRC_BT_DL_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ASRC_BT_DL_16_SIB);
+ } else {
+ /* Do nothing, Scheduling Table has already been patched */
+ }
+#endif
+ }
+ break;
+ case OMAP_ABE_MM_DL_PORT:
+ /* check for CBPr / serial_port / Ping-pong access */
+ smem1 = smem_mm_dl;
+ break;
+ case OMAP_ABE_MM_EXT_IN_PORT:
+ /* set the SMEM buffer -- programming sequence */
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MAXTASKBYTESINSLOT_ADDR, &dOppMode32,
+ sizeof(u32));
+
+ /* Disable MM EXT ASRC */
+ dOppMode32 = DOPPMODE32_OPP50;
+
+ if (dOppMode32 == DOPPMODE32_OPP100)
+ /* ASRC input buffer, size 40 */
+ smem1 = smem_mm_ext_in_opp100;
+ else
+ /* at OPP 50 without ASRC */
+ smem1 = smem_mm_ext_in_opp50;
+
+ break;
+ case OMAP_ABE_MM_EXT_OUT_PORT:
+ break;
+ default:
+ break;
+ }
+
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN)
+ direction = 0;
+ else
+ /* offset of the write pointer in the ATC descriptor */
+ direction = 3;
+
+ sio_desc.drift_ASRC = 0;
+ sio_desc.drift_io = 0;
+ sio_desc.io_type_idx = (u8) io_sub_id;
+ sio_desc.samp_size = (u8) datasize;
+ sio_desc.hw_ctrl_addr = (u16) (dmareq_addr << 2);
+ sio_desc.atc_irq_data = (u8) dmareq_field;
+ sio_desc.flow_counter = (u16) 0;
+ sio_desc.direction_rw = (u8) direction;
+ sio_desc.repeat_last_samp = (u8) io_flag;
+ sio_desc.nsamp = (u8) nsamp;
+ sio_desc.x_io = (u8) x_io;
+ /* set ATC ON */
+ sio_desc.on_off = 0x80;
+ sio_desc.split_addr1 = (u16) smem1;
+ sio_desc.split_addr2 = (u16) smem2;
+ sio_desc.split_addr3 = (u16) smem3;
+ sio_desc.before_f_index = (u8) before_func_index;
+ sio_desc.after_f_index = (u8) after_func_index;
+ sio_desc.smem_addr1 = (u16) smem1;
+ sio_desc.atc_address1 = (u16) atc_desc_address1;
+ sio_desc.atc_pointer_saved1 = (u16) atc_ptr_saved;
+ sio_desc.data_size1 = (u8) datasize;
+ sio_desc.copy_f_index1 = (u8) copy_func_index1;
+ sio_desc.smem_addr2 = (u16) smem2;
+ sio_desc.atc_address2 = (u16) atc_desc_address2;
+ sio_desc.atc_pointer_saved2 = (u16) atc_ptr_saved2;
+ sio_desc.data_size2 = (u8) datasize2;
+ sio_desc.copy_f_index2 = (u8) copy_func_index2;
+ sio_desc_address = OMAP_ABE_D_IODESCR_ADDR + (id *
+ sizeof(struct ABE_SIODescriptor));
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ sio_desc_address, (u32 *) &sio_desc,
+ sizeof(sio_desc));
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM,
+ OMAP_ABE_D_MULTIFRAME_ADDR, (u32 *) abe->MultiFrame,
+ sizeof(abe->MultiFrame));
+ }
+
+}
+
+/**
+ * omap_abe_select_main_port - Select stynchronization port for Event generator.
+ * @id: audio port name
+ *
+ * tells the FW which is the reference stream for adjusting
+ * the processing on 23/24/25 slots
+ */
+int omap_abe_select_main_port(u32 id)
+{
+ u32 selection;
+
+ _log(ABE_ID_SELECT_MAIN_PORT, id, 0, 0);
+
+ /* flow control */
+ selection = OMAP_ABE_D_IODESCR_ADDR + id * sizeof(struct ABE_SIODescriptor) +
+ flow_counter_;
+ /* when the main port is a sink port from AESS point of view
+ the sign the firmware task analysis must be changed */
+ selection &= 0xFFFFL;
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN)
+ selection |= 0x80000;
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_SLOT23_CTRL_ADDR,
+ &selection, 4);
+ return 0;
+}
+/**
+ * abe_decide_main_port - Select stynchronization port for Event generator.
+ * @id: audio port name
+ *
+ * tells the FW which is the reference stream for adjusting
+ * the processing on 23/24/25 slots
+ *
+ * takes the first port in a list which is slave on the data interface
+ */
+u32 abe_valid_port_for_synchro(u32 id)
+{
+ if ((abe_port[id].protocol.protocol_switch ==
+ DMAREQ_PORT_PROT) ||
+ (abe_port[id].protocol.protocol_switch ==
+ PINGPONG_PORT_PROT) ||
+ (abe_port[id].status != OMAP_ABE_PORT_ACTIVITY_RUNNING))
+ return 0;
+ else
+ return 1;
+}
+void abe_decide_main_port(void)
+{
+ u32 id, id_not_found;
+ id_not_found = 1;
+ for (id = 0; id < LAST_PORT_ID - 1; id++) {
+ if (abe_valid_port_for_synchro(abe_port_priority[id])) {
+ id_not_found = 0;
+ break;
+ }
+ }
+ /* if no port is currently activated, the default one is PDM_DL */
+ if (id_not_found)
+ omap_abe_select_main_port(OMAP_ABE_PDM_DL_PORT);
+ else
+ omap_abe_select_main_port(abe_port_priority[id]);
+}
+/**
+ * abe_format_switch
+ * @f: port format
+ * @iter: port iteration
+ * @mulfac: multiplication factor
+ *
+ * translates the sampling and data length to ITER number for the DMA
+ * and the multiplier factor to apply during data move with DMEM
+ *
+ */
+void abe_format_switch(abe_data_format_t *f, u32 *iter, u32 *mulfac)
+{
+ u32 n_freq;
+#if FW_SCHED_LOOP_FREQ == 4000
+ switch (f->f) {
+ /* nb of samples processed by scheduling loop */
+ case 8000:
+ n_freq = 2;
+ break;
+ case 16000:
+ n_freq = 4;
+ break;
+ case 24000:
+ n_freq = 6;
+ break;
+ case 44100:
+ n_freq = 12;
+ break;
+ case 96000:
+ n_freq = 24;
+ break;
+ default/*case 48000 */ :
+ n_freq = 12;
+ break;
+ }
+#else
+ /* erroneous cases */
+ n_freq = 0;
+#endif
+ switch (f->samp_format) {
+ case MONO_MSB:
+ case MONO_RSHIFTED_16:
+ case STEREO_16_16:
+ *mulfac = 1;
+ break;
+ case STEREO_MSB:
+ case STEREO_RSHIFTED_16:
+ *mulfac = 2;
+ break;
+ case THREE_MSB:
+ *mulfac = 3;
+ break;
+ case FOUR_MSB:
+ *mulfac = 4;
+ break;
+ case FIVE_MSB:
+ *mulfac = 5;
+ break;
+ case SIX_MSB:
+ *mulfac = 6;
+ break;
+ case SEVEN_MSB:
+ *mulfac = 7;
+ break;
+ case EIGHT_MSB:
+ *mulfac = 8;
+ break;
+ case NINE_MSB:
+ *mulfac = 9;
+ break;
+ default:
+ *mulfac = 1;
+ break;
+ }
+ *iter = (n_freq * (*mulfac));
+}
+/**
+ * abe_dma_port_iteration
+ * @f: port format
+ *
+ * translates the sampling and data length to ITER number for the DMA
+ */
+u32 abe_dma_port_iteration(abe_data_format_t *f)
+{
+ u32 iter, mulfac;
+ abe_format_switch(f, &iter, &mulfac);
+ return iter;
+}
+/**
+ * abe_dma_port_iter_factor
+ * @f: port format
+ *
+ * returns the multiplier factor to apply during data move with DMEM
+ */
+u32 abe_dma_port_iter_factor(abe_data_format_t *f)
+{
+ u32 iter, mulfac;
+ abe_format_switch(f, &iter, &mulfac);
+ return mulfac;
+}
+/**
+ * omap_abe_dma_port_iter_factor
+ * @f: port format
+ *
+ * returns the multiplier factor to apply during data move with DMEM
+ */
+u32 omap_abe_dma_port_iter_factor(struct omap_abe_data_format *f)
+{
+ u32 iter, mulfac;
+ abe_format_switch((abe_data_format_t *)f, &iter, &mulfac);
+ return mulfac;
+}
+/**
+ * abe_dma_port_copy_subroutine_id
+ *
+ * @port_id: ABE port ID
+ *
+ * returns the index of the function doing the copy in I/O tasks
+ */
+u32 abe_dma_port_copy_subroutine_id(u32 port_id)
+{
+ u32 sub_id;
+ if (abe_port[port_id].protocol.direction == ABE_ATC_DIRECTION_IN) {
+ switch (abe_port[port_id].format.samp_format) {
+ case MONO_MSB:
+ sub_id = D2S_MONO_MSB_CFPID;
+ break;
+ case MONO_RSHIFTED_16:
+ sub_id = D2S_MONO_RSHIFTED_16_CFPID;
+ break;
+ case STEREO_RSHIFTED_16:
+ sub_id = D2S_STEREO_RSHIFTED_16_CFPID;
+ break;
+ case STEREO_16_16:
+ sub_id = D2S_STEREO_16_16_CFPID;
+ break;
+ case STEREO_MSB:
+ sub_id = D2S_STEREO_MSB_CFPID;
+ break;
+ case SIX_MSB:
+ if (port_id == OMAP_ABE_DMIC_PORT) {
+ sub_id = COPY_DMIC_CFPID;
+ break;
+ }
+ default:
+ sub_id = NULL_COPY_CFPID;
+ break;
+ }
+ } else {
+ switch (abe_port[port_id].format.samp_format) {
+ case MONO_MSB:
+ sub_id = S2D_MONO_MSB_CFPID;
+ break;
+ case MONO_RSHIFTED_16:
+ sub_id = S2D_MONO_RSHIFTED_16_CFPID;
+ break;
+ case STEREO_RSHIFTED_16:
+ sub_id = S2D_STEREO_RSHIFTED_16_CFPID;
+ break;
+ case STEREO_16_16:
+ sub_id = S2D_STEREO_16_16_CFPID;
+ break;
+ case STEREO_MSB:
+ sub_id = S2D_STEREO_MSB_CFPID;
+ break;
+ case SIX_MSB:
+ if (port_id == OMAP_ABE_PDM_DL_PORT) {
+ sub_id = COPY_MCPDM_DL_CFPID;
+ break;
+ }
+ if (port_id == OMAP_ABE_MM_UL_PORT) {
+ sub_id = COPY_MM_UL_CFPID;
+ break;
+ }
+ case THREE_MSB:
+ case FOUR_MSB:
+ case FIVE_MSB:
+ case SEVEN_MSB:
+ case EIGHT_MSB:
+ case NINE_MSB:
+ sub_id = COPY_MM_UL_CFPID;
+ break;
+ default:
+ sub_id = NULL_COPY_CFPID;
+ break;
+ }
+ }
+ return sub_id;
+}
+
+/**
+ * abe_read_remaining_data
+ * @id: ABE port_ID
+ * @n: size pointer to the remaining number of 32bits words
+ *
+ * computes the remaining amount of data in the buffer.
+ */
+abehal_status abe_read_remaining_data(u32 port, u32 *n)
+{
+ u32 sio_pp_desc_address;
+ struct ABE_SPingPongDescriptor desc_pp;
+
+ _log(ABE_ID_READ_REMAINING_DATA, port, 0, 0);
+
+ /*
+ * read the port SIO descriptor and extract the
+ * current pointer address after reading the counter
+ */
+ sio_pp_desc_address = OMAP_ABE_D_PINGPONGDESC_ADDR;
+ omap_abe_mem_read(abe, OMAP_ABE_DMEM, sio_pp_desc_address,
+ (u32 *) &desc_pp, sizeof(struct ABE_SPingPongDescriptor));
+ *n = desc_pp.workbuff_Samples;
+
+ return 0;
+}
+EXPORT_SYMBOL(abe_read_remaining_data);
+
+/**
+ * omap_abe_mono_mixer
+ * @id: name of the mixer (MIXDL1, MIXDL2 or MIXAUDUL)
+ * on_off: enable\disable flag
+ *
+ * This API Programs DL1Mixer or DL2Mixer to output mono data
+ * on both left and right data paths.
+ */
+int omap_abe_mono_mixer(struct omap_abe *abe, u32 id, u32 on_off)
+{
+ switch (id) {
+ case MIXDL1:
+ if (on_off)
+ abe->MultiFrame[TASK_DL1Mixer_SLT][TASK_DL1Mixer_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_DL1Mixer_dual_mono);
+ else
+ abe->MultiFrame[TASK_DL1Mixer_SLT][TASK_DL1Mixer_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_DL1Mixer);
+ break;
+ case MIXDL2:
+ if (on_off)
+ abe->MultiFrame[TASK_DL2Mixer_SLT][TASK_DL2Mixer_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_DL2Mixer_dual_mono);
+ else
+ abe->MultiFrame[TASK_DL2Mixer_SLT][TASK_DL2Mixer_IDX] =
+ ABE_TASK_ID(C_ABE_FW_TASK_DL2Mixer);
+ break;
+ case MIXAUDUL:
+ if (on_off)
+ abe->MultiFrame[12][4] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ULMixer_dual_mono);
+ else
+ abe->MultiFrame[12][4] =
+ ABE_TASK_ID(C_ABE_FW_TASK_ULMixer);
+ break;
+ default:
+ break;
+ }
+
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_MULTIFRAME_ADDR,
+ (u32 *) abe->MultiFrame, sizeof(abe->MultiFrame));
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_mono_mixer);
+/**
+ * abe_write_pdmdl_offset - write the desired offset on the DL1/DL2 paths
+ *
+ * Parameters:
+ * path: 1 for the DL1 ABE path, 2 for the DL2 ABE path
+ * offset_left: integer value that will be added on all PDM left samples
+ * offset_right: integer value that will be added on all PDM right samples
+ *
+ */
+void abe_write_pdmdl_offset(u32 path, u32 offset_left, u32 offset_right)
+{
+ switch (path) {
+ case 1:
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, OMAP_ABE_S_DC_HS_ADDR + 4,
+ &offset_left, sizeof(u32));
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, OMAP_ABE_S_DC_HS_ADDR,
+ &offset_right, sizeof(u32));
+ break;
+ case 2:
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, OMAP_ABE_S_DC_HF_ADDR + 4,
+ &offset_left, sizeof(u32));
+ omap_abe_mem_write(abe, OMAP_ABE_SMEM, OMAP_ABE_S_DC_HF_ADDR,
+ &offset_right, sizeof(u32));
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(abe_write_pdmdl_offset);
+
diff --git a/sound/soc/omap/abe/abe_port.h b/sound/soc/omap/abe/abe_port.h
new file mode 100644
index 0000000..290f8b5
--- /dev/null
+++ b/sound/soc/omap/abe/abe_port.h
@@ -0,0 +1,161 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_PORT_H_
+#define _ABE_PORT_H_
+
+struct omap_abe_data_format {
+ /* Sampling frequency of the stream */
+ u32 f;
+ /* Sample format type */
+ u32 samp_format;
+};
+
+struct omap_abe_port_protocol {
+ /* Direction=0 means input from AESS point of view */
+ u32 direction;
+ /* Protocol type (switch) during the data transfers */
+ u32 protocol_switch;
+ union {
+ /* McBSP/McASP peripheral connected to ATC */
+ struct {
+ u32 desc_addr;
+ /* Address of ATC McBSP/McASP descriptor's in bytes */
+ u32 buf_addr;
+ /* DMEM address in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ } serial;
+ /* DMIC peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* Number of activated DMIC */
+ u32 nbchan;
+ } dmic;
+ /* McPDMDL peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes */
+ u32 buf_size;
+ /* Control allowed on McPDM DL */
+ u32 control;
+ } mcpdmdl;
+ /* McPDMUL peripheral connected to ATC */
+ struct {
+ /* DMEM address size in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ } mcpdmul;
+ /* Ping-Pong interface to the Host using cache-flush */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes for each ping and pong buffers */
+ u32 buf_size;
+ /* IRQ address (either DMA (0) MCU (1) or DSP(2)) */
+ u32 irq_addr;
+ /* IRQ data content loaded in the AESS IRQ register */
+ u32 irq_data;
+ /* Call-back function upon IRQ reception */
+ u32 callback;
+ } pingpong;
+ /* DMAreq line to CBPr */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } dmareq;
+ /* Circular buffer - direct addressing to DMEM */
+ struct {
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } circular_buffer;
+ } port;
+};
+
+extern const abe_port_t abe_port_init[];
+extern abe_port_t abe_port[];
+extern const u32 abe_port_priority[];
+
+int omap_abe_select_main_port(u32 id);
+u32 omap_abe_dma_port_iter_factor(struct omap_abe_data_format *f);
+
+#endif/* _ABE_PORT_H_ */
diff --git a/sound/soc/omap/abe/abe_ref.h b/sound/soc/omap/abe/abe_ref.h
new file mode 100644
index 0000000..4c8a9bb
--- /dev/null
+++ b/sound/soc/omap/abe/abe_ref.h
@@ -0,0 +1,152 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_REF_H_
+#define _ABE_REF_H_
+
+#include "abe_api.h"
+
+/*
+ * 'ABE_PRO.H' all non-API prototypes for INI, IRQ, SEQ ...
+ */
+/*
+ * HAL EXTERNAL AP
+ */
+/*
+ * HAL INTERNAL AP
+ */
+void abe_decide_main_port(void);
+void abe_reset_all_ports(void);
+void abe_reset_all_fifo(void);
+void abe_reset_all_sequence(void);
+u32 abe_dma_port_iteration(abe_data_format_t *format);
+void abe_read_sys_clock(u32 *time);
+void abe_enable_atc(u32 id);
+void abe_disable_atc(u32 id);
+void abe_init_io_tasks(u32 id, abe_data_format_t *format,
+ abe_port_protocol_t *prot);
+void abe_init_dma_t(u32 id, abe_port_protocol_t *prot);
+u32 abe_dma_port_iter_factor(abe_data_format_t *f);
+u32 abe_dma_port_copy_subroutine_id(u32 i);
+void abe_call_subroutine(u32 idx, u32 p1, u32 p2, u32 p3, u32 p4);
+void abe_monitoring(void);
+void abe_add_subroutine(u32 *id, abe_subroutine2 f, u32 nparam, u32 *params);
+abehal_status abe_read_next_ping_pong_buffer(u32 port, u32 *p, u32 *n);
+void abe_irq_ping_pong(void);
+void abe_irq_check_for_sequences(u32 seq_info);
+void abe_default_irq_pingpong_player(void);
+void abe_default_irq_pingpong_player_32bits(void);
+void abe_rshifted16_irq_pingpong_player_32bits(void);
+void abe_1616_irq_pingpong_player_1616bits(void);
+void abe_default_irq_aps_adaptation(void);
+void abe_irq_aps(u32 aps_info);
+void abe_dbg_error_log(u32 x);
+void abe_init_asrc_vx_dl(s32 dppm);
+void abe_init_asrc_vx_ul(s32 dppm);
+void abe_init_asrc_mm_ext_in(s32 dppm);
+void abe_init_asrc_bt_ul(s32 dppm);
+void abe_init_asrc_bt_dl(s32 dppm);
+
+void omap_abe_hw_configuration(struct omap_abe *abe);
+void omap_abe_gain_offset(struct omap_abe *abe, u32 id, u32 *mixer_offset);
+int omap_abe_use_compensated_gain(struct omap_abe *abe, int on_off);
+
+/*
+ * HAL INTERNAL DATA
+ */
+extern const u32 abe_port_priority[LAST_PORT_ID - 1];
+extern const u32 abe_firmware_array[ABE_FIRMWARE_MAX_SIZE];
+extern const u32 abe_atc_srcid[];
+extern const u32 abe_atc_dstid[];
+extern const abe_port_t abe_port_init[];
+extern const abe_seq_t all_sequence_init[];
+extern const abe_router_t abe_router_ul_table_preset
+ [NBROUTE_CONFIG][NBROUTE_UL];
+extern const abe_sequence_t seq_null;
+
+extern abe_port_t abe_port[];
+extern abe_seq_t all_sequence[];
+extern abe_router_t abe_router_ul_table[NBROUTE_CONFIG_MAX][NBROUTE_UL];
+/* table of new subroutines called in the sequence */
+extern abe_subroutine2 abe_all_subsubroutine[MAXNBSUBROUTINE];
+/* number of parameters per calls */
+extern u32 abe_all_subsubroutine_nparam[MAXNBSUBROUTINE];
+extern u32 abe_subroutine_id[MAXNBSUBROUTINE];
+extern u32 *abe_all_subroutine_params[MAXNBSUBROUTINE];
+extern u32 abe_subroutine_write_pointer;
+extern abe_sequence_t abe_all_sequence[MAXNBSEQUENCE];
+extern u32 abe_sequence_write_pointer;
+/* current number of pending sequences (avoids to look in the table) */
+extern u32 abe_nb_pending_sequences;
+/* pending sequences due to ressource collision */
+extern u32 abe_pending_sequences[MAXNBSEQUENCE];
+/* mask of unsharable ressources among other sequences */
+extern u32 abe_global_sequence_mask;
+/* table of active sequences */
+extern abe_seq_t abe_active_sequence[MAXACTIVESEQUENCE][MAXSEQUENCESTEPS];
+/* index of the plugged subroutine doing ping-pong cache-flush
+ DMEM accesses */
+extern u32 abe_irq_aps_adaptation_id;
+/* base addresses of the ping pong buffers */
+extern u32 abe_base_address_pingpong[MAX_PINGPONG_BUFFERS];
+/* size of each ping/pong buffers */
+extern u32 abe_size_pingpong;
+/* number of ping/pong buffer being used */
+extern u32 abe_nb_pingpong;
+
+#endif/* _ABE_REF_H_ */
diff --git a/sound/soc/omap/abe/abe_seq.c b/sound/soc/omap/abe/abe_seq.c
new file mode 100644
index 0000000..6ae2aa5
--- /dev/null
+++ b/sound/soc/omap/abe/abe_seq.c
@@ -0,0 +1,308 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "abe_legacy.h"
+
+#include "abe_mem.h"
+
+extern struct omap_abe *abe;
+extern u32 abe_irq_pingpong_player_id;
+
+/**
+ * abe_null_subroutine
+ *
+ */
+void abe_null_subroutine_0(void)
+{
+}
+void abe_null_subroutine_2(u32 a, u32 b)
+{
+}
+void abe_null_subroutine_4(u32 a, u32 b, u32 c, u32 d)
+{
+}
+/**
+ * abe_init_subroutine_table - initializes the default table of pointers
+ * to subroutines
+ *
+ * initializes the default table of pointers to subroutines
+ *
+ */
+void abe_init_subroutine_table(void)
+{
+ u32 id;
+ /* reset the table's pointers */
+ abe_subroutine_write_pointer = 0;
+ /* the first index is the NULL task */
+ abe_add_subroutine(&id, (abe_subroutine2) abe_null_subroutine_2,
+ SUB_0_PARAM, (u32 *) 0);
+ /* write mixer has 4 parameters */
+ abe_add_subroutine(&(abe_subroutine_id[SUB_WRITE_MIXER]),
+ (abe_subroutine2) abe_write_mixer, SUB_4_PARAM,
+ (u32 *) 0);
+ /* ping-pong player IRQ */
+ abe_add_subroutine(&abe_irq_pingpong_player_id,
+ (abe_subroutine2) abe_null_subroutine_0, SUB_0_PARAM,
+ (u32 *) 0);
+}
+/**
+ * abe_add_subroutine
+ * @id: ABE port id
+ * @f: pointer to the subroutines
+ * @nparam: number of parameters
+ * @params: pointer to the psrameters
+ *
+ * add one function pointer more and returns the index to it
+ */
+void abe_add_subroutine(u32 *id, abe_subroutine2 f, u32 nparam, u32 *params)
+{
+ u32 i, i_found;
+ if ((abe_subroutine_write_pointer >= MAXNBSUBROUTINE) ||
+ ((u32) f == 0)) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_SEQ,
+ ABE_PARAMETER_OVERFLOW);
+ } else {
+ /* search if this subroutine address was not already
+ * declared, then return the previous index
+ */
+ for (i_found = abe_subroutine_write_pointer, i = 0;
+ i < abe_subroutine_write_pointer; i++) {
+ if (f == abe_all_subsubroutine[i])
+ i_found = i;
+ }
+ if (i_found == abe_subroutine_write_pointer) {
+ *id = abe_subroutine_write_pointer;
+ abe_all_subsubroutine
+ [abe_subroutine_write_pointer] = (f);
+ abe_all_subroutine_params
+ [abe_subroutine_write_pointer] = params;
+ abe_all_subsubroutine_nparam
+ [abe_subroutine_write_pointer] = nparam;
+ abe_subroutine_write_pointer++;
+ } else {
+ abe_all_subroutine_params[i_found] = params;
+ *id = i_found;
+ }
+ }
+}
+/**
+ * abe_add_sequence
+ * @id: returned sequence index after pluging a new sequence
+ * (index in the tables)
+ * @s: sequence to be inserted
+ *
+ * Load a time-sequenced operations.
+ */
+void abe_add_sequence(u32 *id, abe_sequence_t *s)
+{
+ abe_seq_t *seq_src, *seq_dst;
+ u32 i, no_end_of_sequence_found;
+ seq_src = &(s->seq1);
+ seq_dst = &((abe_all_sequence[abe_sequence_write_pointer]).seq1);
+ if ((abe_sequence_write_pointer >= MAXNBSEQUENCE) || ((u32) s == 0)) {
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_SEQ,
+ ABE_PARAMETER_OVERFLOW);
+ } else {
+ *id = abe_subroutine_write_pointer;
+ /* copy the mask */
+ (abe_all_sequence[abe_sequence_write_pointer]).mask = s->mask;
+ for (no_end_of_sequence_found = 1, i = 0; i < MAXSEQUENCESTEPS;
+ i++, seq_src++, seq_dst++) {
+ /* sequence copied line by line */
+ (*seq_dst) = (*seq_src);
+ /* stop when the line start with time=(-1) */
+ if ((*(s32 *) seq_src) == (-1)) {
+ /* stop when the line start with time=(-1) */
+ no_end_of_sequence_found = 0;
+ break;
+ }
+ }
+ abe_subroutine_write_pointer++;
+ if (no_end_of_sequence_found)
+ omap_abe_dbg_error(abe, OMAP_ABE_ERR_API,
+ ABE_SEQTOOLONG);
+ }
+}
+/**
+ * abe_reset_one_sequence
+ * @id: sequence ID
+ *
+ * load default configuration for that sequence
+ * kill running activities
+ */
+void abe_reset_one_sequence(u32 id)
+{
+}
+/**
+ * abe_reset_all_sequence
+ *
+ * load default configuration for all sequences
+ * kill any running activities
+ */
+void omap_abe_reset_all_sequence(struct omap_abe *abe)
+{
+ u32 i;
+ abe_init_subroutine_table();
+ /* arrange to have the first sequence index=0 to the NULL operation
+ sequence */
+ abe_add_sequence(&i, (abe_sequence_t *) &seq_null);
+ /* reset the the collision protection mask */
+ abe_global_sequence_mask = 0;
+ /* reset the pending sequences list */
+ for (abe_nb_pending_sequences = i = 0; i < MAXNBSEQUENCE; i++)
+ abe_pending_sequences[i] = 0;
+}
+/**
+ * abe_call_subroutine
+ * @idx: index to the table of all registered Call-backs and subroutines
+ *
+ * run and log a subroutine
+ */
+void abe_call_subroutine(u32 idx, u32 p1, u32 p2, u32 p3, u32 p4)
+{
+ abe_subroutine0 f0;
+ abe_subroutine1 f1;
+ abe_subroutine2 f2;
+ abe_subroutine3 f3;
+ abe_subroutine4 f4;
+ u32 *params;
+ if (idx > MAXNBSUBROUTINE)
+ return;
+ switch (idx) {
+ /* call the subroutines defined at compilation time
+ (const .. sequences) */
+#if 0
+ case SUB_WRITE_MIXER_DL1:
+ abe_write_mixer_dl1(p1, p2, p3)
+ abe_fprintf("write_mixer");
+ break;
+#endif
+ /* call the subroutines defined at execution time
+ (dynamic sequences) */
+ default:
+ switch (abe_all_subsubroutine_nparam[idx]) {
+ case SUB_0_PARAM:
+ f0 = (abe_subroutine0) abe_all_subsubroutine[idx];
+ (*f0) ();
+ break;
+ case SUB_1_PARAM:
+ f1 = (abe_subroutine1) abe_all_subsubroutine[idx];
+ params = abe_all_subroutine_params
+ [abe_irq_pingpong_player_id];
+ if (params != (u32 *) 0)
+ p1 = params[0];
+ (*f1) (p1);
+ break;
+ case SUB_2_PARAM:
+ f2 = abe_all_subsubroutine[idx];
+ params = abe_all_subroutine_params
+ [abe_irq_pingpong_player_id];
+ if (params != (u32 *) 0) {
+ p1 = params[0];
+ p2 = params[1];
+ }
+ (*f2) (p1, p2);
+ break;
+ case SUB_3_PARAM:
+ f3 = (abe_subroutine3) abe_all_subsubroutine[idx];
+ params = abe_all_subroutine_params
+ [abe_irq_pingpong_player_id];
+ if (params != (u32 *) 0) {
+ p1 = params[0];
+ p2 = params[1];
+ p3 = params[2];
+ }
+ (*f3) (p1, p2, p3);
+ break;
+ case SUB_4_PARAM:
+ f4 = (abe_subroutine4) abe_all_subsubroutine[idx];
+ params = abe_all_subroutine_params
+ [abe_irq_pingpong_player_id];
+ if (params != (u32 *) 0) {
+ p1 = params[0];
+ p2 = params[1];
+ p3 = params[2];
+ p4 = params[3];
+ }
+ (*f4) (p1, p2, p3, p4);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * abe_set_sequence_time_accuracy
+ * @fast: fast counter
+ * @slow: slow counter
+ *
+ */
+abehal_status abe_set_sequence_time_accuracy(u32 fast, u32 slow)
+{
+ u32 data;
+ _log(ABE_ID_SET_SEQUENCE_TIME_ACCURACY, fast, slow, 0);
+ data = minimum(MAX_UINT16, fast / FW_SCHED_LOOP_FREQ_DIV1000);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_FASTCOUNTER_ADDR,
+ &data, sizeof(data));
+ data = minimum(MAX_UINT16, slow / FW_SCHED_LOOP_FREQ_DIV1000);
+ omap_abe_mem_write(abe, OMAP_ABE_DMEM, OMAP_ABE_D_SLOWCOUNTER_ADDR,
+ &data, sizeof(data));
+ return 0;
+}
+EXPORT_SYMBOL(abe_set_sequence_time_accuracy);
diff --git a/sound/soc/omap/abe/abe_seq.h b/sound/soc/omap/abe/abe_seq.h
new file mode 100644
index 0000000..e5047ad
--- /dev/null
+++ b/sound/soc/omap/abe/abe_seq.h
@@ -0,0 +1,64 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_SEQ_H_
+#define _ABE_SEQ_H_
+
+void omap_abe_reset_all_sequence(struct omap_abe *abe);
+
+#endif /* _ABE_SEQ_H_ */
diff --git a/sound/soc/omap/abe/abe_sm_addr.h b/sound/soc/omap/abe/abe_sm_addr.h
new file mode 100644
index 0000000..514ed0c
--- /dev/null
+++ b/sound/soc/omap/abe/abe_sm_addr.h
@@ -0,0 +1,363 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define OMAP_ABE_INIT_SM_ADDR 0x0
+#define OMAP_ABE_INIT_SM_SIZE 0xC80
+#define OMAP_ABE_S_DATA0_ADDR 0xC80
+#define OMAP_ABE_S_DATA0_SIZE 0x8
+#define OMAP_ABE_S_TEMP_ADDR 0xC88
+#define OMAP_ABE_S_TEMP_SIZE 0x8
+#define OMAP_ABE_S_PHOENIXOFFSET_ADDR 0xC90
+#define OMAP_ABE_S_PHOENIXOFFSET_SIZE 0x8
+#define OMAP_ABE_S_GTARGET1_ADDR 0xC98
+#define OMAP_ABE_S_GTARGET1_SIZE 0x38
+#define OMAP_ABE_S_GTARGET_DL1_ADDR 0xCD0
+#define OMAP_ABE_S_GTARGET_DL1_SIZE 0x10
+#define OMAP_ABE_S_GTARGET_DL2_ADDR 0xCE0
+#define OMAP_ABE_S_GTARGET_DL2_SIZE 0x10
+#define OMAP_ABE_S_GTARGET_ECHO_ADDR 0xCF0
+#define OMAP_ABE_S_GTARGET_ECHO_SIZE 0x8
+#define OMAP_ABE_S_GTARGET_SDT_ADDR 0xCF8
+#define OMAP_ABE_S_GTARGET_SDT_SIZE 0x8
+#define OMAP_ABE_S_GTARGET_VXREC_ADDR 0xD00
+#define OMAP_ABE_S_GTARGET_VXREC_SIZE 0x10
+#define OMAP_ABE_S_GTARGET_UL_ADDR 0xD10
+#define OMAP_ABE_S_GTARGET_UL_SIZE 0x10
+#define OMAP_ABE_S_GTARGET_BTUL_ADDR 0xD20
+#define OMAP_ABE_S_GTARGET_BTUL_SIZE 0x8
+#define OMAP_ABE_S_GCURRENT_ADDR 0xD28
+#define OMAP_ABE_S_GCURRENT_SIZE 0x90
+#define OMAP_ABE_S_GAIN_ONE_ADDR 0xDB8
+#define OMAP_ABE_S_GAIN_ONE_SIZE 0x8
+#define OMAP_ABE_S_TONES_ADDR 0xDC0
+#define OMAP_ABE_S_TONES_SIZE 0x60
+#define OMAP_ABE_S_VX_DL_ADDR 0xE20
+#define OMAP_ABE_S_VX_DL_SIZE 0x60
+#define OMAP_ABE_S_MM_UL2_ADDR 0xE80
+#define OMAP_ABE_S_MM_UL2_SIZE 0x60
+#define OMAP_ABE_S_MM_DL_ADDR 0xEE0
+#define OMAP_ABE_S_MM_DL_SIZE 0x60
+#define OMAP_ABE_S_DL1_M_OUT_ADDR 0xF40
+#define OMAP_ABE_S_DL1_M_OUT_SIZE 0x60
+#define OMAP_ABE_S_DL2_M_OUT_ADDR 0xFA0
+#define OMAP_ABE_S_DL2_M_OUT_SIZE 0x60
+#define OMAP_ABE_S_ECHO_M_OUT_ADDR 0x1000
+#define OMAP_ABE_S_ECHO_M_OUT_SIZE 0x60
+#define OMAP_ABE_S_SDT_M_OUT_ADDR 0x1060
+#define OMAP_ABE_S_SDT_M_OUT_SIZE 0x60
+#define OMAP_ABE_S_VX_UL_ADDR 0x10C0
+#define OMAP_ABE_S_VX_UL_SIZE 0x60
+#define OMAP_ABE_S_VX_UL_M_ADDR 0x1120
+#define OMAP_ABE_S_VX_UL_M_SIZE 0x60
+#define OMAP_ABE_S_BT_DL_ADDR 0x1180
+#define OMAP_ABE_S_BT_DL_SIZE 0x60
+#define OMAP_ABE_S_BT_UL_ADDR 0x11E0
+#define OMAP_ABE_S_BT_UL_SIZE 0x60
+#define OMAP_ABE_S_BT_DL_8K_ADDR 0x1240
+#define OMAP_ABE_S_BT_DL_8K_SIZE 0x18
+#define OMAP_ABE_S_BT_DL_16K_ADDR 0x1258
+#define OMAP_ABE_S_BT_DL_16K_SIZE 0x28
+#define OMAP_ABE_S_BT_UL_8K_ADDR 0x1280
+#define OMAP_ABE_S_BT_UL_8K_SIZE 0x10
+#define OMAP_ABE_S_BT_UL_16K_ADDR 0x1290
+#define OMAP_ABE_S_BT_UL_16K_SIZE 0x20
+#define OMAP_ABE_S_SDT_F_ADDR 0x12B0
+#define OMAP_ABE_S_SDT_F_SIZE 0x60
+#define OMAP_ABE_S_SDT_F_DATA_ADDR 0x1310
+#define OMAP_ABE_S_SDT_F_DATA_SIZE 0x48
+#define OMAP_ABE_S_MM_DL_OSR_ADDR 0x1358
+#define OMAP_ABE_S_MM_DL_OSR_SIZE 0xC0
+#define OMAP_ABE_S_24_ZEROS_ADDR 0x1418
+#define OMAP_ABE_S_24_ZEROS_SIZE 0xC0
+#define OMAP_ABE_S_DMIC1_ADDR 0x14D8
+#define OMAP_ABE_S_DMIC1_SIZE 0x60
+#define OMAP_ABE_S_DMIC2_ADDR 0x1538
+#define OMAP_ABE_S_DMIC2_SIZE 0x60
+#define OMAP_ABE_S_DMIC3_ADDR 0x1598
+#define OMAP_ABE_S_DMIC3_SIZE 0x60
+#define OMAP_ABE_S_AMIC_ADDR 0x15F8
+#define OMAP_ABE_S_AMIC_SIZE 0x60
+#define OMAP_ABE_S_DMIC1_L_ADDR 0x1658
+#define OMAP_ABE_S_DMIC1_L_SIZE 0x60
+#define OMAP_ABE_S_DMIC1_R_ADDR 0x16B8
+#define OMAP_ABE_S_DMIC1_R_SIZE 0x60
+#define OMAP_ABE_S_DMIC2_L_ADDR 0x1718
+#define OMAP_ABE_S_DMIC2_L_SIZE 0x60
+#define OMAP_ABE_S_DMIC2_R_ADDR 0x1778
+#define OMAP_ABE_S_DMIC2_R_SIZE 0x60
+#define OMAP_ABE_S_DMIC3_L_ADDR 0x17D8
+#define OMAP_ABE_S_DMIC3_L_SIZE 0x60
+#define OMAP_ABE_S_DMIC3_R_ADDR 0x1838
+#define OMAP_ABE_S_DMIC3_R_SIZE 0x60
+#define OMAP_ABE_S_BT_UL_L_ADDR 0x1898
+#define OMAP_ABE_S_BT_UL_L_SIZE 0x60
+#define OMAP_ABE_S_BT_UL_R_ADDR 0x18F8
+#define OMAP_ABE_S_BT_UL_R_SIZE 0x60
+#define OMAP_ABE_S_AMIC_L_ADDR 0x1958
+#define OMAP_ABE_S_AMIC_L_SIZE 0x60
+#define OMAP_ABE_S_AMIC_R_ADDR 0x19B8
+#define OMAP_ABE_S_AMIC_R_SIZE 0x60
+#define OMAP_ABE_S_ECHOREF_L_ADDR 0x1A18
+#define OMAP_ABE_S_ECHOREF_L_SIZE 0x60
+#define OMAP_ABE_S_ECHOREF_R_ADDR 0x1A78
+#define OMAP_ABE_S_ECHOREF_R_SIZE 0x60
+#define OMAP_ABE_S_MM_DL_L_ADDR 0x1AD8
+#define OMAP_ABE_S_MM_DL_L_SIZE 0x60
+#define OMAP_ABE_S_MM_DL_R_ADDR 0x1B38
+#define OMAP_ABE_S_MM_DL_R_SIZE 0x60
+#define OMAP_ABE_S_MM_UL_ADDR 0x1B98
+#define OMAP_ABE_S_MM_UL_SIZE 0x3C0
+#define OMAP_ABE_S_AMIC_96K_ADDR 0x1F58
+#define OMAP_ABE_S_AMIC_96K_SIZE 0xC0
+#define OMAP_ABE_S_DMIC0_96K_ADDR 0x2018
+#define OMAP_ABE_S_DMIC0_96K_SIZE 0xC0
+#define OMAP_ABE_S_DMIC1_96K_ADDR 0x20D8
+#define OMAP_ABE_S_DMIC1_96K_SIZE 0xC0
+#define OMAP_ABE_S_DMIC2_96K_ADDR 0x2198
+#define OMAP_ABE_S_DMIC2_96K_SIZE 0xC0
+#define OMAP_ABE_S_UL_VX_UL_48_8K_ADDR 0x2258
+#define OMAP_ABE_S_UL_VX_UL_48_8K_SIZE 0x60
+#define OMAP_ABE_S_UL_VX_UL_48_16K_ADDR 0x22B8
+#define OMAP_ABE_S_UL_VX_UL_48_16K_SIZE 0x60
+#define OMAP_ABE_S_UL_MIC_48K_ADDR 0x2318
+#define OMAP_ABE_S_UL_MIC_48K_SIZE 0x60
+#define OMAP_ABE_S_VOICE_8K_UL_ADDR 0x2378
+#define OMAP_ABE_S_VOICE_8K_UL_SIZE 0x18
+#define OMAP_ABE_S_VOICE_8K_DL_ADDR 0x2390
+#define OMAP_ABE_S_VOICE_8K_DL_SIZE 0x10
+#define OMAP_ABE_S_MCPDM_OUT1_ADDR 0x23A0
+#define OMAP_ABE_S_MCPDM_OUT1_SIZE 0xC0
+#define OMAP_ABE_S_MCPDM_OUT2_ADDR 0x2460
+#define OMAP_ABE_S_MCPDM_OUT2_SIZE 0xC0
+#define OMAP_ABE_S_MCPDM_OUT3_ADDR 0x2520
+#define OMAP_ABE_S_MCPDM_OUT3_SIZE 0xC0
+#define OMAP_ABE_S_VOICE_16K_UL_ADDR 0x25E0
+#define OMAP_ABE_S_VOICE_16K_UL_SIZE 0x28
+#define OMAP_ABE_S_VOICE_16K_DL_ADDR 0x2608
+#define OMAP_ABE_S_VOICE_16K_DL_SIZE 0x20
+#define OMAP_ABE_S_XINASRC_DL_VX_ADDR 0x2628
+#define OMAP_ABE_S_XINASRC_DL_VX_SIZE 0x140
+#define OMAP_ABE_S_XINASRC_UL_VX_ADDR 0x2768
+#define OMAP_ABE_S_XINASRC_UL_VX_SIZE 0x140
+#define OMAP_ABE_S_XINASRC_MM_EXT_IN_ADDR 0x28A8
+#define OMAP_ABE_S_XINASRC_MM_EXT_IN_SIZE 0x140
+#define OMAP_ABE_S_VX_REC_ADDR 0x29E8
+#define OMAP_ABE_S_VX_REC_SIZE 0x60
+#define OMAP_ABE_S_VX_REC_L_ADDR 0x2A48
+#define OMAP_ABE_S_VX_REC_L_SIZE 0x60
+#define OMAP_ABE_S_VX_REC_R_ADDR 0x2AA8
+#define OMAP_ABE_S_VX_REC_R_SIZE 0x60
+#define OMAP_ABE_S_DL2_M_L_ADDR 0x2B08
+#define OMAP_ABE_S_DL2_M_L_SIZE 0x60
+#define OMAP_ABE_S_DL2_M_R_ADDR 0x2B68
+#define OMAP_ABE_S_DL2_M_R_SIZE 0x60
+#define OMAP_ABE_S_DL2_M_LR_EQ_DATA_ADDR 0x2BC8
+#define OMAP_ABE_S_DL2_M_LR_EQ_DATA_SIZE 0xC8
+#define OMAP_ABE_S_DL1_M_EQ_DATA_ADDR 0x2C90
+#define OMAP_ABE_S_DL1_M_EQ_DATA_SIZE 0xC8
+#define OMAP_ABE_S_EARP_48_96_LP_DATA_ADDR 0x2D58
+#define OMAP_ABE_S_EARP_48_96_LP_DATA_SIZE 0x78
+#define OMAP_ABE_S_IHF_48_96_LP_DATA_ADDR 0x2DD0
+#define OMAP_ABE_S_IHF_48_96_LP_DATA_SIZE 0x78
+#define OMAP_ABE_S_VX_UL_8_TEMP_ADDR 0x2E48
+#define OMAP_ABE_S_VX_UL_8_TEMP_SIZE 0x10
+#define OMAP_ABE_S_VX_UL_16_TEMP_ADDR 0x2E58
+#define OMAP_ABE_S_VX_UL_16_TEMP_SIZE 0x20
+#define OMAP_ABE_S_VX_DL_8_48_LP_DATA_ADDR 0x2E78
+#define OMAP_ABE_S_VX_DL_8_48_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_VX_DL_8_48_HP_DATA_ADDR 0x2EE0
+#define OMAP_ABE_S_VX_DL_8_48_HP_DATA_SIZE 0x38
+#define OMAP_ABE_S_VX_DL_16_48_LP_DATA_ADDR 0x2F18
+#define OMAP_ABE_S_VX_DL_16_48_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_VX_DL_16_48_HP_DATA_ADDR 0x2F80
+#define OMAP_ABE_S_VX_DL_16_48_HP_DATA_SIZE 0x28
+#define OMAP_ABE_S_VX_UL_48_8_LP_DATA_ADDR 0x2FA8
+#define OMAP_ABE_S_VX_UL_48_8_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_VX_UL_48_8_HP_DATA_ADDR 0x3010
+#define OMAP_ABE_S_VX_UL_48_8_HP_DATA_SIZE 0x38
+#define OMAP_ABE_S_VX_UL_48_16_LP_DATA_ADDR 0x3048
+#define OMAP_ABE_S_VX_UL_48_16_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_VX_UL_48_16_HP_DATA_ADDR 0x30B0
+#define OMAP_ABE_S_VX_UL_48_16_HP_DATA_SIZE 0x28
+#define OMAP_ABE_S_BT_UL_8_48_LP_DATA_ADDR 0x30D8
+#define OMAP_ABE_S_BT_UL_8_48_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_BT_UL_8_48_HP_DATA_ADDR 0x3140
+#define OMAP_ABE_S_BT_UL_8_48_HP_DATA_SIZE 0x38
+#define OMAP_ABE_S_BT_UL_16_48_LP_DATA_ADDR 0x3178
+#define OMAP_ABE_S_BT_UL_16_48_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_BT_UL_16_48_HP_DATA_ADDR 0x31E0
+#define OMAP_ABE_S_BT_UL_16_48_HP_DATA_SIZE 0x28
+#define OMAP_ABE_S_BT_DL_48_8_LP_DATA_ADDR 0x3208
+#define OMAP_ABE_S_BT_DL_48_8_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_BT_DL_48_8_HP_DATA_ADDR 0x3270
+#define OMAP_ABE_S_BT_DL_48_8_HP_DATA_SIZE 0x38
+#define OMAP_ABE_S_BT_DL_48_16_LP_DATA_ADDR 0x32A8
+#define OMAP_ABE_S_BT_DL_48_16_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_BT_DL_48_16_HP_DATA_ADDR 0x3310
+#define OMAP_ABE_S_BT_DL_48_16_HP_DATA_SIZE 0x28
+#define OMAP_ABE_S_ECHO_REF_48_8_LP_DATA_ADDR 0x3338
+#define OMAP_ABE_S_ECHO_REF_48_8_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_ECHO_REF_48_8_HP_DATA_ADDR 0x33A0
+#define OMAP_ABE_S_ECHO_REF_48_8_HP_DATA_SIZE 0x38
+#define OMAP_ABE_S_ECHO_REF_48_16_LP_DATA_ADDR 0x33D8
+#define OMAP_ABE_S_ECHO_REF_48_16_LP_DATA_SIZE 0x68
+#define OMAP_ABE_S_ECHO_REF_48_16_HP_DATA_ADDR 0x3440
+#define OMAP_ABE_S_ECHO_REF_48_16_HP_DATA_SIZE 0x28
+#define OMAP_ABE_S_XINASRC_ECHO_REF_ADDR 0x3468
+#define OMAP_ABE_S_XINASRC_ECHO_REF_SIZE 0x140
+#define OMAP_ABE_S_ECHO_REF_16K_ADDR 0x35A8
+#define OMAP_ABE_S_ECHO_REF_16K_SIZE 0x28
+#define OMAP_ABE_S_ECHO_REF_8K_ADDR 0x35D0
+#define OMAP_ABE_S_ECHO_REF_8K_SIZE 0x18
+#define OMAP_ABE_S_DL1_EQ_ADDR 0x35E8
+#define OMAP_ABE_S_DL1_EQ_SIZE 0x60
+#define OMAP_ABE_S_DL2_EQ_ADDR 0x3648
+#define OMAP_ABE_S_DL2_EQ_SIZE 0x60
+#define OMAP_ABE_S_DL1_GAIN_OUT_ADDR 0x36A8
+#define OMAP_ABE_S_DL1_GAIN_OUT_SIZE 0x60
+#define OMAP_ABE_S_DL2_GAIN_OUT_ADDR 0x3708
+#define OMAP_ABE_S_DL2_GAIN_OUT_SIZE 0x60
+#define OMAP_ABE_S_DC_HS_ADDR 0x3768
+#define OMAP_ABE_S_DC_HS_SIZE 0x8
+#define OMAP_ABE_S_DC_HF_ADDR 0x3770
+#define OMAP_ABE_S_DC_HF_SIZE 0x8
+#define OMAP_ABE_S_VIBRA_ADDR 0x3778
+#define OMAP_ABE_S_VIBRA_SIZE 0x30
+#define OMAP_ABE_S_VIBRA2_IN_ADDR 0x37A8
+#define OMAP_ABE_S_VIBRA2_IN_SIZE 0x30
+#define OMAP_ABE_S_VIBRA2_ADDR_ADDR 0x37D8
+#define OMAP_ABE_S_VIBRA2_ADDR_SIZE 0x8
+#define OMAP_ABE_S_VIBRACTRL_FORRIGHTSM_ADDR 0x37E0
+#define OMAP_ABE_S_VIBRACTRL_FORRIGHTSM_SIZE 0xC0
+#define OMAP_ABE_S_RNOISE_MEM_ADDR 0x38A0
+#define OMAP_ABE_S_RNOISE_MEM_SIZE 0x8
+#define OMAP_ABE_S_CTRL_ADDR 0x38A8
+#define OMAP_ABE_S_CTRL_SIZE 0x90
+#define OMAP_ABE_S_VIBRA1_IN_ADDR 0x3938
+#define OMAP_ABE_S_VIBRA1_IN_SIZE 0x30
+#define OMAP_ABE_S_VIBRA1_TEMP_ADDR 0x3968
+#define OMAP_ABE_S_VIBRA1_TEMP_SIZE 0xC0
+#define OMAP_ABE_S_VIBRACTRL_FORLEFTSM_ADDR 0x3A28
+#define OMAP_ABE_S_VIBRACTRL_FORLEFTSM_SIZE 0xC0
+#define OMAP_ABE_S_VIBRA1_MEM_ADDR 0x3AE8
+#define OMAP_ABE_S_VIBRA1_MEM_SIZE 0x58
+#define OMAP_ABE_S_VIBRACTRL_STEREO_ADDR 0x3B40
+#define OMAP_ABE_S_VIBRACTRL_STEREO_SIZE 0xC0
+#define OMAP_ABE_S_AMIC_96_48_DATA_ADDR 0x3C00
+#define OMAP_ABE_S_AMIC_96_48_DATA_SIZE 0x98
+#define OMAP_ABE_S_DMIC0_96_48_DATA_ADDR 0x3C98
+#define OMAP_ABE_S_DMIC0_96_48_DATA_SIZE 0x98
+#define OMAP_ABE_S_DMIC1_96_48_DATA_ADDR 0x3D30
+#define OMAP_ABE_S_DMIC1_96_48_DATA_SIZE 0x98
+#define OMAP_ABE_S_DMIC2_96_48_DATA_ADDR 0x3DC8
+#define OMAP_ABE_S_DMIC2_96_48_DATA_SIZE 0x98
+#define OMAP_ABE_S_DBG_8K_PATTERN_ADDR 0x3E60
+#define OMAP_ABE_S_DBG_8K_PATTERN_SIZE 0x10
+#define OMAP_ABE_S_DBG_16K_PATTERN_ADDR 0x3E70
+#define OMAP_ABE_S_DBG_16K_PATTERN_SIZE 0x20
+#define OMAP_ABE_S_DBG_24K_PATTERN_ADDR 0x3E90
+#define OMAP_ABE_S_DBG_24K_PATTERN_SIZE 0x30
+#define OMAP_ABE_S_DBG_48K_PATTERN_ADDR 0x3EC0
+#define OMAP_ABE_S_DBG_48K_PATTERN_SIZE 0x60
+#define OMAP_ABE_S_DBG_96K_PATTERN_ADDR 0x3F20
+#define OMAP_ABE_S_DBG_96K_PATTERN_SIZE 0xC0
+#define OMAP_ABE_S_MM_EXT_IN_ADDR 0x3FE0
+#define OMAP_ABE_S_MM_EXT_IN_SIZE 0x60
+#define OMAP_ABE_S_MM_EXT_IN_L_ADDR 0x4040
+#define OMAP_ABE_S_MM_EXT_IN_L_SIZE 0x60
+#define OMAP_ABE_S_MM_EXT_IN_R_ADDR 0x40A0
+#define OMAP_ABE_S_MM_EXT_IN_R_SIZE 0x60
+#define OMAP_ABE_S_MIC4_ADDR 0x4100
+#define OMAP_ABE_S_MIC4_SIZE 0x60
+#define OMAP_ABE_S_MIC4_L_ADDR 0x4160
+#define OMAP_ABE_S_MIC4_L_SIZE 0x60
+#define OMAP_ABE_S_SATURATION_7FFF_ADDR 0x41C0
+#define OMAP_ABE_S_SATURATION_7FFF_SIZE 0x8
+#define OMAP_ABE_S_SATURATION_ADDR 0x41C8
+#define OMAP_ABE_S_SATURATION_SIZE 0x8
+#define OMAP_ABE_S_XINASRC_BT_UL_ADDR 0x41D0
+#define OMAP_ABE_S_XINASRC_BT_UL_SIZE 0x140
+#define OMAP_ABE_S_XINASRC_BT_DL_ADDR 0x4310
+#define OMAP_ABE_S_XINASRC_BT_DL_SIZE 0x140
+#define OMAP_ABE_S_BT_DL_8K_TEMP_ADDR 0x4450
+#define OMAP_ABE_S_BT_DL_8K_TEMP_SIZE 0x10
+#define OMAP_ABE_S_BT_DL_16K_TEMP_ADDR 0x4460
+#define OMAP_ABE_S_BT_DL_16K_TEMP_SIZE 0x20
+#define OMAP_ABE_S_VX_DL_8_48_OSR_LP_DATA_ADDR 0x4480
+#define OMAP_ABE_S_VX_DL_8_48_OSR_LP_DATA_SIZE 0xE0
+#define OMAP_ABE_S_BT_UL_8_48_OSR_LP_DATA_ADDR 0x4560
+#define OMAP_ABE_S_BT_UL_8_48_OSR_LP_DATA_SIZE 0xE0
+#define OMAP_ABE_S_MM_DL_44P1_ADDR 0x4640
+#define OMAP_ABE_S_MM_DL_44P1_SIZE 0x300
+#define OMAP_ABE_S_TONES_44P1_ADDR 0x4940
+#define OMAP_ABE_S_TONES_44P1_SIZE 0x300
+#define OMAP_ABE_S_MM_DL_44P1_XK_ADDR 0x4C40
+#define OMAP_ABE_S_MM_DL_44P1_XK_SIZE 0x10
+#define OMAP_ABE_S_TONES_44P1_XK_ADDR 0x4C50
+#define OMAP_ABE_S_TONES_44P1_XK_SIZE 0x10
+#define OMAP_ABE_S_SRC_44P1_MULFAC1_ADDR 0x4C60
+#define OMAP_ABE_S_SRC_44P1_MULFAC1_SIZE 0x8
+#define OMAP_ABE_S_SATURATION_EQ_ADDR 0x4C68
+#define OMAP_ABE_S_SATURATION_EQ_SIZE 0x8
+#define OMAP_ABE_S_BT_DL_48_8_LP_NEW_DATA_ADDR 0x4C70
+#define OMAP_ABE_S_BT_DL_48_8_LP_NEW_DATA_SIZE 0x88
+#define OMAP_ABE_S_BT_DL_8_48_OSR_LP_DATA_ADDR 0x4CF8
+#define OMAP_ABE_S_BT_DL_8_48_OSR_LP_DATA_SIZE 0x3C8
+#define OMAP_ABE_S_VX_UL_48_8_LP_NEW_DATA_ADDR 0x50C0
+#define OMAP_ABE_S_VX_UL_48_8_LP_NEW_DATA_SIZE 0x88
+#define OMAP_ABE_S_VX_UL_8_48_OSR_LP_DATA_ADDR 0x5148
+#define OMAP_ABE_S_VX_UL_8_48_OSR_LP_DATA_SIZE 0x3C8
diff --git a/sound/soc/omap/abe/abe_taskid.h b/sound/soc/omap/abe/abe_taskid.h
new file mode 100644
index 0000000..abf31f3
--- /dev/null
+++ b/sound/soc/omap/abe/abe_taskid.h
@@ -0,0 +1,196 @@
+/*
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _ABE_TASKID_H_
+#define _ABE_TASKID_H_
+#define C_ABE_FW_TASK_ASRC_VX_DL_8 0
+#define C_ABE_FW_TASK_ASRC_VX_DL_16 1
+#define C_ABE_FW_TASK_ASRC_VX_DL_8_SIB 2
+#define C_ABE_FW_TASK_ASRC_VX_DL_16_SIB 3
+#define C_ABE_FW_TASK_ASRC_MM_EXT_IN 4
+#define C_ABE_FW_TASK_ASRC_VX_UL_8 5
+#define C_ABE_FW_TASK_ASRC_VX_UL_16 6
+#define C_ABE_FW_TASK_ASRC_VX_UL_8_SIB 7
+#define C_ABE_FW_TASK_ASRC_VX_UL_16_SIB 8
+#define C_ABE_FW_TASK_VX_UL_48_8_DEC 9
+#define C_ABE_FW_TASK_VX_UL_48_16_DEC 10
+#define C_ABE_FW_TASK_BT_DL_48_8_DEC 11
+#define C_ABE_FW_TASK_BT_DL_48_16_DEC 12
+#define C_ABE_FW_TASK_ECHO_REF_48_8_DEC 13
+#define C_ABE_FW_TASK_ECHO_REF_48_16_DEC 14
+#define C_ABE_FW_TASK_DL2_EQ 15
+#define C_ABE_FW_TASK_ECHO_REF_48_16 16
+#define C_ABE_FW_TASK_ECHO_REF_48_8 17
+#define C_ABE_FW_TASK_GAIN_UPDATE 18
+#define C_ABE_FW_TASK_SideTone 19
+#define C_ABE_FW_TASK_VX_DL_8_48_LP 20
+#define C_ABE_FW_TASK_VX_DL_8_48_HP 21
+#define C_ABE_FW_TASK_VX_DL_16_48_LP 22
+#define C_ABE_FW_TASK_VX_DL_16_48_HP 23
+#define C_ABE_FW_TASK_VX_UL_48_8_LP 24
+#define C_ABE_FW_TASK_VX_UL_48_8_HP 25
+#define C_ABE_FW_TASK_VX_UL_48_16_LP 26
+#define C_ABE_FW_TASK_VX_UL_48_16_HP 27
+#define C_ABE_FW_TASK_BT_UL_8_48_LP 28
+#define C_ABE_FW_TASK_BT_UL_8_48_HP 29
+#define C_ABE_FW_TASK_BT_UL_16_48_LP 30
+#define C_ABE_FW_TASK_BT_UL_16_48_HP 31
+#define C_ABE_FW_TASK_BT_DL_48_8_LP 32
+#define C_ABE_FW_TASK_BT_DL_48_8_HP 33
+#define C_ABE_FW_TASK_BT_DL_48_16_LP 34
+#define C_ABE_FW_TASK_BT_DL_48_16_HP 35
+#define C_ABE_FW_TASK_ECHO_REF_48_8_LP 36
+#define C_ABE_FW_TASK_ECHO_REF_48_8_HP 37
+#define C_ABE_FW_TASK_ECHO_REF_48_16_LP 38
+#define C_ABE_FW_TASK_ECHO_REF_48_16_HP 39
+#define C_ABE_FW_TASK_DL1_EQ 40
+#define C_ABE_FW_TASK_IHF_48_96_LP 41
+#define C_ABE_FW_TASK_EARP_48_96_LP 42
+#define C_ABE_FW_TASK_DL1_GAIN 43
+#define C_ABE_FW_TASK_DL2_GAIN 44
+#define C_ABE_FW_TASK_IO_PING_PONG 45
+#define C_ABE_FW_TASK_IO_DMIC 46
+#define C_ABE_FW_TASK_IO_PDM_UL 47
+#define C_ABE_FW_TASK_IO_BT_VX_UL 48
+#define C_ABE_FW_TASK_IO_MM_UL 49
+#define C_ABE_FW_TASK_IO_MM_UL2 50
+#define C_ABE_FW_TASK_IO_VX_UL 51
+#define C_ABE_FW_TASK_IO_MM_DL 52
+#define C_ABE_FW_TASK_IO_VX_DL 53
+#define C_ABE_FW_TASK_IO_TONES_DL 54
+#define C_ABE_FW_TASK_IO_VIB_DL 55
+#define C_ABE_FW_TASK_IO_BT_VX_DL 56
+#define C_ABE_FW_TASK_IO_PDM_DL 57
+#define C_ABE_FW_TASK_IO_MM_EXT_OUT 58
+#define C_ABE_FW_TASK_IO_MM_EXT_IN 59
+#define C_ABE_FW_TASK_DEBUG_IRQFIFO 60
+#define C_ABE_FW_TASK_EchoMixer 61
+#define C_ABE_FW_TASK_SDTMixer 62
+#define C_ABE_FW_TASK_DL1Mixer 63
+#define C_ABE_FW_TASK_DL2Mixer 64
+#define C_ABE_FW_TASK_DL1Mixer_dual_mono 65
+#define C_ABE_FW_TASK_DL2Mixer_dual_mono 66
+#define C_ABE_FW_TASK_VXRECMixer 67
+#define C_ABE_FW_TASK_ULMixer 68
+#define C_ABE_FW_TASK_ULMixer_dual_mono 69
+#define C_ABE_FW_TASK_VIBRA_PACK 70
+#define C_ABE_FW_TASK_VX_DL_8_48_0SR 71
+#define C_ABE_FW_TASK_VX_DL_16_48_0SR 72
+#define C_ABE_FW_TASK_BT_UL_8_48_0SR 73
+#define C_ABE_FW_TASK_BT_UL_16_48_0SR 74
+#define C_ABE_FW_TASK_IHF_48_96_0SR 75
+#define C_ABE_FW_TASK_EARP_48_96_0SR 76
+#define C_ABE_FW_TASK_AMIC_SPLIT 77
+#define C_ABE_FW_TASK_DMIC1_SPLIT 78
+#define C_ABE_FW_TASK_DMIC2_SPLIT 79
+#define C_ABE_FW_TASK_DMIC3_SPLIT 80
+#define C_ABE_FW_TASK_VXREC_SPLIT 81
+#define C_ABE_FW_TASK_BT_UL_SPLIT 82
+#define C_ABE_FW_TASK_MM_SPLIT 83
+#define C_ABE_FW_TASK_VIBRA_SPLIT 84
+#define C_ABE_FW_TASK_MM_EXT_IN_SPLIT 85
+#define C_ABE_FW_TASK_ECHO_REF_SPLIT 86
+#define C_ABE_FW_TASK_UNUSED_1 87
+#define C_ABE_FW_TASK_VX_UL_ROUTING 88
+#define C_ABE_FW_TASK_MM_UL2_ROUTING 89
+#define C_ABE_FW_TASK_VIBRA1 90
+#define C_ABE_FW_TASK_VIBRA2 91
+#define C_ABE_FW_TASK_BT_UL_16_48 92
+#define C_ABE_FW_TASK_BT_UL_8_48 93
+#define C_ABE_FW_TASK_BT_DL_48_16 94
+#define C_ABE_FW_TASK_BT_DL_48_8 95
+#define C_ABE_FW_TASK_VX_DL_16_48 96
+#define C_ABE_FW_TASK_VX_DL_8_48 97
+#define C_ABE_FW_TASK_VX_UL_48_16 98
+#define C_ABE_FW_TASK_VX_UL_48_8 99
+#define C_ABE_FW_TASK_DBG_SYNC 100
+#define C_ABE_FW_TASK_AMIC_96_48_LP 101
+#define C_ABE_FW_TASK_DMIC1_96_48_LP 102
+#define C_ABE_FW_TASK_DMIC2_96_48_LP 103
+#define C_ABE_FW_TASK_DMIC3_96_48_LP 104
+#define C_ABE_FW_TASK_INIT_FW_MEMORY 105
+#define C_ABE_FW_TASK_DEBUGTRACE_VX_ASRCs 106
+#define C_ABE_FW_TASK_ASRC_BT_UL_8 107
+#define C_ABE_FW_TASK_ASRC_BT_UL_16 108
+#define C_ABE_FW_TASK_ASRC_BT_UL_8_SIB 109
+#define C_ABE_FW_TASK_ASRC_BT_UL_16_SIB 110
+#define C_ABE_FW_TASK_ASRC_BT_DL_8 111
+#define C_ABE_FW_TASK_ASRC_BT_DL_16 112
+#define C_ABE_FW_TASK_ASRC_BT_DL_8_SIB 113
+#define C_ABE_FW_TASK_ASRC_BT_DL_16_SIB 114
+#define C_ABE_FW_TASK_BT_DL_48_8_HP_OPP100 115
+#define C_ABE_FW_TASK_BT_DL_48_16_HP_OPP100 116
+#define C_ABE_FW_TASK_BT_DL_48_8_OPP100 117
+#define C_ABE_FW_TASK_BT_DL_48_16_OPP100 118
+#define C_ABE_FW_TASK_VX_DL_8_48_OSR_LP 119
+#define C_ABE_FW_TASK_VX_DL_8_48_FIR 120
+#define C_ABE_FW_TASK_BT_UL_8_48_OSR_LP 121
+#define C_ABE_FW_TASK_BT_UL_8_48_FIR 122
+#define C_ABE_FW_TASK_SRC44P1_MMDL 123
+#define C_ABE_FW_TASK_SRC44P1_TONES 124
+#define C_ABE_FW_TASK_SRC44P1_MMDL_1211 125
+#define C_ABE_FW_TASK_SRC44P1_TONES_1211 126
+#define C_ABE_FW_TASK_SRC44P1_MMDL_PP 127
+#define C_ABE_FW_TASK_SRC44P1_MMDL_1211_PP 128
+#define C_ABE_FW_TASK_CHECK_IIR_LEFT 129
+#define C_ABE_FW_TASK_CHECK_IIR_RIGHT 130
+#define C_ABE_FW_TASK_BT_DL_48_8_LP_FIR 131
+#define C_ABE_FW_TASK_BT_DL_48_8_FIR 132
+#define C_ABE_FW_TASK_BT_DL_48_8_FIR_OPP100 133
+#define C_ABE_FW_TASK_VX_UL_48_8_FIR 134
+#define C_ABE_FW_TASK_VX_UL_48_8_LP_FIR 135
+#endif /* _ABE_TASKID_H_ */
diff --git a/sound/soc/omap/abe/abe_typ.h b/sound/soc/omap/abe/abe_typ.h
new file mode 100644
index 0000000..650d043
--- /dev/null
+++ b/sound/soc/omap/abe/abe_typ.h
@@ -0,0 +1,654 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "abe_def.h"
+#include "abe_initxxx_labels.h"
+
+#ifndef _ABE_TYP_H_
+#define _ABE_TYP_H_
+/*
+ * BASIC TYPES
+ */
+#define MAX_UINT8 ((((1L << 7) - 1) << 1) + 1)
+#define MAX_UINT16 ((((1L << 15) - 1) << 1) + 1)
+#define MAX_UINT32 ((((1L << 31) - 1) << 1) + 1)
+#define s8 char
+#define u8 unsigned char
+#define s16 short
+#define u16 unsigned short
+#define s32 int
+#define u32 unsigned int
+/* returned status from HAL APIs */
+#define abehal_status u32
+/* 4 bytes Bit field indicating the type of informations to be traced */
+typedef u32 abe_dbg_mask_t;
+/* scheduling task loops (250us / 272us with respectively 48kHz /
+ 44.1kHz on Phoenix). */
+typedef u32 abe_dbg_t;
+/* Index to the table of sequences */
+typedef u32 abe_seq_code_t;
+/* Index to the table of subroutines called in the sequence */
+typedef u32 abe_sub_code_t;
+/* subroutine with no parameter */
+typedef void (*abe_subroutine0) (void);
+/* subroutine with one parameter */
+typedef void (*abe_subroutine1) (u32);
+typedef void (*abe_subroutine2) (u32, u32);
+typedef void (*abe_subroutine3) (u32, u32, u32);
+typedef void (*abe_subroutine4) (u32, u32, u32, u32);
+/*
+ * CODE PORTABILITY - FUTURE PATCHES
+ *
+ * 32bits field for having the code compatible with future revisions of
+ * the hardware (audio integration) or evolution of the software
+ * partitionning. Used for the highest level APIs (launch_sequences)
+ */
+typedef u32 abe_patch_rev;
+/*
+ * ENUMS
+ */
+/*
+ * MEMORY CONFIG TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (multimedia complex use-cases)
+ */
+#define ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE 1
+#define ABE_DRIFT_MANAGEMENT_FOR_AUDIO_PLAYER 2
+#define ABE_DRIFT_MANAGEMENT_FOR_VOICE_CALL 3
+#define ABE_VOICE_CALL_ON_HEADSET_OR_EARPHONE_OR_BT 4
+#define ABE_MULTIMEDIA_AUDIO_RECORDER 5
+#define ABE_VIBRATOR_OR_HAPTICS 6
+#define ABE_VOICE_CALL_ON_HANDS_FREE_SPEAKER 7
+#define ABE_RINGER_TONES 8
+#define ABE_VOICE_CALL_WITH_EARPHONE_ACTIVE_NOISE_CANCELLER 9
+#define ABE_LAST_USE_CASE 10
+/*
+ * OPP TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (multimedia complex use-cases)
+ */
+#define ABE_OPP0 0
+#define ABE_OPP25 1
+#define ABE_OPP50 2
+#define ABE_OPP100 3
+/*
+ * DMIC DECIMATION RATIO
+ *
+ */
+#define ABE_DEC16 16
+#define ABE_DEC25 25
+#define ABE_DEC32 32
+#define ABE_DEC40 40
+/*
+ * SAMPLES TYPE
+ *
+ * mono 16 bit sample LSB aligned, 16 MSB bits are unused;
+ * mono right shifted to 16bits LSBs on a 32bits DMEM FIFO for McBSP
+ * TX purpose;
+ * mono sample MSB aligned (16/24/32bits);
+ * two successive mono samples in one 32bits container;
+ * Two L/R 16bits samples in a 32bits container;
+ * Two channels defined with two MSB aligned samples;
+ * Three channels defined with three MSB aligned samples (MIC);
+ * Four channels defined with four MSB aligned samples (MIC);
+ * . . .
+ * Eight channels defined with eight MSB aligned samples (MIC);
+ */
+#define MONO_MSB 1
+#define MONO_RSHIFTED_16 2
+#define STEREO_RSHIFTED_16 3
+#define STEREO_16_16 4
+#define STEREO_MSB 5
+#define THREE_MSB 6
+#define FOUR_MSB 7
+#define FIVE_MSB 8
+#define SIX_MSB 9
+#define SEVEN_MSB 10
+#define EIGHT_MSB 11
+#define NINE_MSB 12
+#define TEN_MSB 13
+/*
+ * PORT PROTOCOL TYPE - abe_port_protocol_switch_id
+ */
+#define SLIMBUS_PORT_PROT 1
+#define SERIAL_PORT_PROT 2
+#define TDM_SERIAL_PORT_PROT 3
+#define DMIC_PORT_PROT 4
+#define MCPDMDL_PORT_PROT 5
+#define MCPDMUL_PORT_PROT 6
+#define PINGPONG_PORT_PROT 7
+#define DMAREQ_PORT_PROT 8
+/*
+ * PORT IDs, this list is aligned with the FW data mapping
+ */
+#define OMAP_ABE_DMIC_PORT 0
+#define OMAP_ABE_PDM_UL_PORT 1
+#define OMAP_ABE_BT_VX_UL_PORT 2
+#define OMAP_ABE_MM_UL_PORT 3
+#define OMAP_ABE_MM_UL2_PORT 4
+#define OMAP_ABE_VX_UL_PORT 5
+#define OMAP_ABE_MM_DL_PORT 6
+#define OMAP_ABE_VX_DL_PORT 7
+#define OMAP_ABE_TONES_DL_PORT 8
+#define OMAP_ABE_VIB_DL_PORT 9
+#define OMAP_ABE_BT_VX_DL_PORT 10
+#define OMAP_ABE_PDM_DL_PORT 11
+#define OMAP_ABE_MM_EXT_OUT_PORT 12
+#define OMAP_ABE_MM_EXT_IN_PORT 13
+#define TDM_DL_PORT 14
+#define TDM_UL_PORT 15
+#define DEBUG_PORT 16
+#define LAST_PORT_ID 17
+/* definitions for the compatibility with HAL05xx */
+#define PDM_DL1_PORT 18
+#define PDM_DL2_PORT 19
+#define PDM_VIB_PORT 20
+/* There is only one DMIC port, always used with 6 samples
+ per 96kHz periods */
+#define DMIC_PORT1 DMIC_PORT
+#define DMIC_PORT2 DMIC_PORT
+#define DMIC_PORT3 DMIC_PORT
+/*
+ * ABE_DL_SRC_ID source of samples
+ */
+#define SRC_DL1_MIXER_OUTPUT DL1_M_labelID
+#define SRC_SDT_MIXER_OUTPUT SDT_M_labelID
+#define SRC_DL1_GAIN_OUTPUT DL1_GAIN_out_labelID
+#define SRC_DL1_EQ_OUTPUT DL1_EQ_labelID
+#define SRC_DL2_GAIN_OUTPUT DL2_GAIN_out_labelID
+#define SRC_DL2_EQ_OUTPUT DL2_EQ_labelID
+#define SRC_MM_DL MM_DL_labelID
+#define SRC_TONES_DL Tones_labelID
+#define SRC_VX_DL VX_DL_labelID
+#define SRC_VX_UL VX_UL_labelID
+#define SRC_MM_UL2 MM_UL2_labelID
+#define SRC_MM_UL MM_UL_labelID
+/*
+ * abe_patched_pattern_id
+ * selection of the audio engine signal to
+ * replace by a precomputed pattern
+ */
+#define DBG_PATCH_AMIC 1
+#define DBG_PATCH_DMIC1 2
+#define DBG_PATCH_DMIC2 3
+#define DBG_PATCH_DMIC3 4
+#define DBG_PATCH_VX_REC 5
+#define DBG_PATCH_BT_UL 6
+#define DBG_PATCH_MM_DL 7
+#define DBG_PATCH_DL2_EQ 8
+#define DBG_PATCH_VIBRA 9
+#define DBG_PATCH_MM_EXT_IN 10
+#define DBG_PATCH_EANC_FBK_Out 11
+#define DBG_PATCH_MIC4 12
+#define DBG_PATCH_MM_DL_MIXDL1 13
+#define DBG_PATCH_MM_DL_MIXDL2 14
+/*
+ * Signal processing module names - EQ APS MIX ROUT
+ */
+/* equalizer downlink path headset + earphone */
+#define FEAT_EQ1 1
+/* equalizer downlink path integrated handsfree LEFT */
+#define FEAT_EQ2L (FEAT_EQ1+1)
+/* equalizer downlink path integrated handsfree RIGHT */
+#define FEAT_EQ2R (FEAT_EQ2L+1)
+/* equalizer downlink path side-tone */
+#define FEAT_EQSDT (FEAT_EQ2R+1)
+/* equalizer uplink path AMIC */
+#define FEAT_EQAMIC (FEAT_EQSDT+1)
+/* equalizer uplink path DMIC */
+#define FEAT_EQDMIC (FEAT_EQAMIC+1)
+/* Acoustic protection for headset */
+#define FEAT_APS1 (FEAT_EQDMIC+1)
+/* acoustic protection high-pass filter for handsfree "Left" */
+#define FEAT_APS2 (FEAT_APS1+1)
+/* acoustic protection high-pass filter for handsfree "Right" */
+#define FEAT_APS3 (FEAT_APS2+1)
+/* asynchronous sample-rate-converter for the downlink voice path */
+#define FEAT_ASRC1 (FEAT_APS3+1)
+/* asynchronous sample-rate-converter for the uplink voice path */
+#define FEAT_ASRC2 (FEAT_ASRC1+1)
+/* asynchronous sample-rate-converter for the multimedia player */
+#define FEAT_ASRC3 (FEAT_ASRC2+1)
+/* asynchronous sample-rate-converter for the echo reference */
+#define FEAT_ASRC4 (FEAT_ASRC3+1)
+/* mixer of the headset and earphone path */
+#define FEAT_MIXDL1 (FEAT_ASRC4+1)
+/* mixer of the hands-free path */
+#define FEAT_MIXDL2 (FEAT_MIXDL1+1)
+/* mixer for audio being sent on the voice_ul path */
+#define FEAT_MIXAUDUL (FEAT_MIXDL2+1)
+/* mixer for voice communication recording */
+#define FEAT_MIXVXREC (FEAT_MIXAUDUL+1)
+/* mixer for side-tone */
+#define FEAT_MIXSDT (FEAT_MIXVXREC+1)
+/* mixer for echo reference */
+#define FEAT_MIXECHO (FEAT_MIXSDT+1)
+/* router of the uplink path */
+#define FEAT_UPROUTE (FEAT_MIXECHO+1)
+/* all gains */
+#define FEAT_GAINS (FEAT_UPROUTE+1)
+#define FEAT_GAINS_DMIC1 (FEAT_GAINS+1)
+#define FEAT_GAINS_DMIC2 (FEAT_GAINS_DMIC1+1)
+#define FEAT_GAINS_DMIC3 (FEAT_GAINS_DMIC2+1)
+#define FEAT_GAINS_AMIC (FEAT_GAINS_DMIC3+1)
+#define FEAT_GAINS_SPLIT (FEAT_GAINS_AMIC+1)
+#define FEAT_GAINS_DL1 (FEAT_GAINS_SPLIT+1)
+#define FEAT_GAINS_DL2 (FEAT_GAINS_DL1+1)
+#define FEAT_GAIN_BTUL (FEAT_GAINS_DL2+1)
+/* sequencing queue of micro tasks */
+#define FEAT_SEQ (FEAT_GAIN_BTUL+1)
+/* Phoenix control queue through McPDM */
+#define FEAT_CTL (FEAT_SEQ+1)
+/* list of features of the firmware -------------------------------*/
+#define MAXNBFEATURE FEAT_CTL
+/* abe_equ_id */
+/* equalizer downlink path headset + earphone */
+#define EQ1 FEAT_EQ1
+/* equalizer downlink path integrated handsfree LEFT */
+#define EQ2L FEAT_EQ2L
+#define EQ2R FEAT_EQ2R
+/* equalizer downlink path side-tone */
+#define EQSDT FEAT_EQSDT
+#define EQAMIC FEAT_EQAMIC
+#define EQDMIC FEAT_EQDMIC
+/* abe_aps_id */
+/* Acoustic protection for headset */
+#define APS1 FEAT_APS1
+#define APS2L FEAT_APS2
+#define APS2R FEAT_APS3
+/* abe_asrc_id */
+/* asynchronous sample-rate-converter for the downlink voice path */
+#define ASRC1 FEAT_ASRC1
+/* asynchronous sample-rate-converter for the uplink voice path */
+#define ASRC2 FEAT_ASRC2
+/* asynchronous sample-rate-converter for the multimedia player */
+#define ASRC3 FEAT_ASRC3
+/* asynchronous sample-rate-converter for the voice uplink echo_reference */
+#define ASRC4 FEAT_ASRC4
+/* abe_mixer_id */
+#define MIXDL1 FEAT_MIXDL1
+#define MIXDL2 FEAT_MIXDL2
+#define MIXSDT FEAT_MIXSDT
+#define MIXECHO FEAT_MIXECHO
+#define MIXAUDUL FEAT_MIXAUDUL
+#define MIXVXREC FEAT_MIXVXREC
+/* abe_router_id */
+/* there is only one router up to now */
+#define UPROUTE FEAT_UPROUTE
+/*
+ * GAIN IDs
+ */
+#define GAINS_DMIC1 FEAT_GAINS_DMIC1
+#define GAINS_DMIC2 FEAT_GAINS_DMIC2
+#define GAINS_DMIC3 FEAT_GAINS_DMIC3
+#define GAINS_AMIC FEAT_GAINS_AMIC
+#define GAINS_SPLIT FEAT_GAINS_SPLIT
+#define GAINS_DL1 FEAT_GAINS_DL1
+#define GAINS_DL2 FEAT_GAINS_DL2
+#define GAINS_BTUL FEAT_GAIN_BTUL
+/*
+ * EVENT GENERATORS - abe_event_id
+ */
+#define EVENT_TIMER 0
+#define EVENT_44100 1
+/*
+ * SERIAL PORTS IDs - abe_mcbsp_id
+ */
+#define MCBSP1_TX MCBSP1_DMA_TX
+#define MCBSP1_RX MCBSP1_DMA_RX
+#define MCBSP2_TX MCBSP2_DMA_TX
+#define MCBSP2_RX MCBSP2_DMA_RX
+#define MCBSP3_TX MCBSP3_DMA_TX
+#define MCBSP3_RX MCBSP3_DMA_RX
+/*
+ * SERIAL PORTS IDs - abe_slimbus_id;
+ */
+#define SLIMBUS1_TX0 SLIMBUS1_DMA_TX0
+#define SLIMBUS1_TX1 SLIMBUS1_DMA_TX1
+#define SLIMBUS1_TX2 SLIMBUS1_DMA_TX2
+#define SLIMBUS1_TX3 SLIMBUS1_DMA_TX3
+#define SLIMBUS1_TX4 SLIMBUS1_DMA_TX4
+#define SLIMBUS1_TX5 SLIMBUS1_DMA_TX5
+#define SLIMBUS1_TX6 SLIMBUS1_DMA_TX6
+#define SLIMBUS1_TX7 SLIMBUS1_DMA_TX7
+#define SLIMBUS1_RX0 SLIMBUS1_DMA_RX0
+#define SLIMBUS1_RX1 SLIMBUS1_DMA_RX1
+#define SLIMBUS1_RX2 SLIMBUS1_DMA_RX2
+#define SLIMBUS1_RX3 SLIMBUS1_DMA_RX3
+#define SLIMBUS1_RX4 SLIMBUS1_DMA_RX4
+#define SLIMBUS1_RX5 SLIMBUS1_DMA_RX5
+#define SLIMBUS1_RX6 SLIMBUS1_DMA_RX6
+#define SLIMBUS1_RX7 SLIMBUS1_DMA_RX7
+#define SLIMBUS_UNUSED _DUMMY_FIFO_
+/*
+ * ----------------- TYPES USED FOR APIS ---------------
+ */
+
+/*
+ * EQU_T
+ *
+ * coefficients of the equalizer
+ */
+typedef struct {
+ /* type of filter */
+ u32 equ_type;
+ /* filter length */
+ u32 equ_length;
+ union {
+ /* parameters are the direct and recursive coefficients in */
+ /* Q6.26 integer fixed-point format. */
+ s32 type1[NBEQ1];
+ struct {
+ /* center frequency of the band [Hz] */
+ s32 freq[NBEQ2];
+ /* gain of each band. [dB] */
+ s32 gain[NBEQ2];
+ /* Q factor of this band [dB] */
+ s32 q[NBEQ2];
+ } type2;
+ } coef;
+ s32 equ_param3;
+} abe_equ_t;
+
+/*
+ * APS_T
+ *
+ * coefficients of the Acoustics Protection and Safety
+ */
+struct abe_aps_t {
+ s32 coef1[NBAPS1];
+ s32 coef2[NBAPS2];
+};
+
+struct abe_aps_energy_t {
+ /* structure of two energy_t estimation for coil and membrane */
+ u32 e1;
+ u32 e2;
+};
+/*
+ * ROUTER_T
+ *
+ * table of indexes in unsigned bytes
+ */
+typedef u16 abe_router_t;
+/*
+ * DATA_FORMAT_T
+ *
+ * used in port declaration
+ */
+typedef struct {
+ /* Sampling frequency of the stream */
+ u32 f;
+ /* Sample format type */
+ u32 samp_format;
+} abe_data_format_t;
+/*
+ * PORT_PROTOCOL_T
+ *
+ * port declaration
+ */
+typedef struct {
+ /* Direction=0 means input from AESS point of view */
+ u32 direction;
+ /* Protocol type (switch) during the data transfers */
+ u32 protocol_switch;
+ union {
+ /* Slimbus peripheral connected to ATC */
+ struct {
+ /* Address of ATC Slimbus descriptor's index */
+ u32 desc_addr1;
+ /* DMEM address 1 in bytes */
+ u32 buf_addr1;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ /* Second ATC index for SlimBus reception (or NULL) */
+ u32 desc_addr2;
+ /* DMEM address 2 in bytes */
+ u32 buf_addr2;
+ } prot_slimbus;
+ /* McBSP/McASP peripheral connected to ATC */
+ struct {
+ u32 desc_addr;
+ /* Address of ATC McBSP/McASP descriptor's in bytes */
+ u32 buf_addr;
+ /* DMEM address in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ } prot_serial;
+ /* DMIC peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* Number of activated DMIC */
+ u32 nbchan;
+ } prot_dmic;
+ /* McPDMDL peripheral connected to ATC */
+ struct {
+ /* DMEM address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes */
+ u32 buf_size;
+ /* Control allowed on McPDM DL */
+ u32 control;
+ } prot_mcpdmdl;
+ /* McPDMUL peripheral connected to ATC */
+ struct {
+ /* DMEM address size in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ } prot_mcpdmul;
+ /* Ping-Pong interface to the Host using cache-flush */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM size in bytes for each ping and pong buffers */
+ u32 buf_size;
+ /* IRQ address (either DMA (0) MCU (1) or DSP(2)) */
+ u32 irq_addr;
+ /* IRQ data content loaded in the AESS IRQ register */
+ u32 irq_data;
+ /* Call-back function upon IRQ reception */
+ u32 callback;
+ } prot_pingpong;
+ /* DMAreq line to CBPr */
+ struct {
+ /* Address of ATC descriptor's */
+ u32 desc_addr;
+ /* DMEM buffer address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size size in bytes */
+ u32 buf_size;
+ /* ITERation on each DMAreq signals */
+ u32 iter;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } prot_dmareq;
+ /* Circular buffer - direct addressing to DMEM */
+ struct {
+ /* DMEM buffer base address in bytes */
+ u32 buf_addr;
+ /* DMEM buffer size in bytes */
+ u32 buf_size;
+ /* DMAreq address */
+ u32 dma_addr;
+ /* DMA/AESS = 1 << #DMA */
+ u32 dma_data;
+ } prot_circular_buffer;
+ } p;
+} abe_port_protocol_t;
+/*
+ * DMA_T
+ *
+ * dma structure for easing programming
+ */
+typedef struct {
+ /* OCP L3 pointer to the first address of the */
+ void *data;
+ /* destination buffer (either DMA or Ping-Pong read/write pointers). */
+ /* address L3 when addressing the DMEM buffer instead of CBPr */
+ void *l3_dmem;
+ /* address L3 translated to L4 the ARM memory space */
+ void *l4_dmem;
+ /* number of iterations for the DMA data moves. */
+ u32 iter;
+} abe_dma_t;
+
+typedef struct {
+ /* Offset to the first address of the */
+ u32 data;
+ /* number of iterations for the DMA data moves. */
+ u32 iter;
+} abe_dma_t_offset;
+/*
+ * SEQ_T
+ *
+ * struct {
+ * micros_t time; Waiting time before executing next line
+ * seq_code_t code Subroutine index interpreted in the HAL
+ * and translated to FW subroutine codes
+ * in case of ABE tasks
+ * int32 param[2] Two parameters
+ * } seq_t
+ *
+ */
+typedef struct {
+ u32 delta_time;
+ u32 code;
+ u32 param[4];
+ u8 tag;
+} abe_seq_t;
+
+typedef struct {
+ u32 mask;
+ abe_seq_t seq1;
+ abe_seq_t seq2;
+} abe_sequence_t;
+/*
+ * DRIFT_T abe_drift_t = s32
+ *
+ * ASRC drift parameter in [ppm] value
+ */
+/*
+ * -------------------- INTERNAL DATA TYPES ---------------------
+ */
+/*
+ * ABE_IRQ_DATA_T
+ *
+ * IRQ FIFO content declaration
+ * APS interrupts : IRQ_FIFO[31:28] = IRQtag_APS,
+ * IRQ_FIFO[27:16] = APS_IRQs, IRQ_FIFO[15:0] = loopCounter
+ * SEQ interrupts : IRQ_FIFO[31:28] IRQtag_COUNT,
+ * IRQ_FIFO[27:16] = Count_IRQs, IRQ_FIFO[15:0] = loopCounter
+ * Ping-Pong Interrupts : IRQ_FIFO[31:28] = IRQtag_PP,
+ * IRQ_FIFO[27:16] = PP_MCU_IRQ, IRQ_FIFO[15:0] = loopCounter
+ */
+typedef struct {
+ unsigned int counter:16;
+ unsigned int data:12;
+ unsigned int tag:4;
+} abe_irq_data_t;
+/*
+ * ABE_PORT_T status / format / sampling / protocol(call_back) /
+ * features / gain / name ..
+ *
+ */
+typedef struct {
+ /* running / idled */
+ u16 status;
+ /* Sample format type */
+ abe_data_format_t format;
+ /* API : for ASRC */
+ s32 drift;
+ /* optionnal call-back index for errors and ack */
+ u16 callback;
+ /* IO tasks buffers */
+ u16 smem_buffer1;
+ u16 smem_buffer2;
+ abe_port_protocol_t protocol;
+ /* pointer and iteration counter of the xDMA */
+ abe_dma_t_offset dma;
+ /* list of features associated to a port (EQ, APS, ... , ends with 0) */
+ u16 feature_index[MAXFEATUREPORT];
+ char name[NBCHARPORTNAME];
+} abe_port_t;
+/*
+ * ABE_SUBROUTINE_T
+ *
+ */
+typedef struct {
+ u32 sub_id;
+ s32 param[4];
+} abe_subroutine_t;
+
+#endif/* ifndef _ABE_TYP_H_ */
diff --git a/sound/soc/omap/abe/abe_typedef.h b/sound/soc/omap/abe/abe_typedef.h
new file mode 100644
index 0000000..943968e
--- /dev/null
+++ b/sound/soc/omap/abe/abe_typedef.h
@@ -0,0 +1,240 @@
+/*
+
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ BSD LICENSE
+
+ Copyright(c) 2010-2011 Texas Instruments Incorporated,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef _ABE_TYPEDEF_H_
+#define _ABE_TYPEDEF_H_
+
+#include "abe_define.h"
+#include "abe_typ.h"
+
+/*
+ * Basic types definition
+ */
+/*
+ * Commonly used structures
+ */
+typedef struct abetaskTag {
+ /* 0 ... Index of called function */
+ u16 iF;
+ /* 2 ... for INITPTR of A0 */
+ u16 A0;
+ /* 4 ... for INITPTR of A1 */
+ u16 A1;
+ /* 6 ... for INITPTR of A2 & A3 */
+ u16 A2_3;
+ /* 8 ... for INITPTR of A4 & A5 */
+ u16 A4_5;
+ /* 10 ... for INITREG of R0, R1, R2, R3 */
+ u16 R;
+ /* 12 */
+ u16 misc0;
+ /* 14 */
+ u16 misc1;
+} ABE_STask;
+typedef ABE_STask *pABE_STask;
+typedef ABE_STask **ppABE_STask;
+
+struct ABE_SIODescriptor {
+ /* 0 */
+ u16 drift_ASRC;
+ /* 2 */
+ u16 drift_io;
+ /* 4 "Function index" of XLS sheet "Functions" */
+ u8 io_type_idx;
+ /* 5 1 = MONO or Stereo1616, 2= STEREO, ... */
+ u8 samp_size;
+ /* 6 drift "issues" for ASRC */
+ s16 flow_counter;
+ /* 8 address for IRQ or DMArequests */
+ u16 hw_ctrl_addr;
+ /* 10 DMA request bit-field or IRQ (DSP/MCU) */
+ u8 atc_irq_data;
+ /* 11 0 = Read, 3 = Write */
+ u8 direction_rw;
+ /* 12 */
+ u8 repeat_last_samp;
+ /* 13 12 at 48kHz, ... */
+ u8 nsamp;
+ /* 14 nsamp x samp_size */
+ u8 x_io;
+ /* 15 ON = 0x80, OFF = 0x00 */
+ u8 on_off;
+ /* 16 For Slimbus and TDM purpose */
+ u16 split_addr1;
+ /* 18 */
+ u16 split_addr2;
+ /* 20 */
+ u16 split_addr3;
+ /* 22 */
+ u8 before_f_index;
+ /* 23 */
+ u8 after_f_index;
+ /* 24 SM/CM INITPTR field */
+ u16 smem_addr1;
+ /* 26 in bytes */
+ u16 atc_address1;
+ /* 28 DMIC_ATC_PTR, MCPDM_UL_ATC_PTR, ... */
+ u16 atc_pointer_saved1;
+ /* 30 samp_size (except in TDM or Slimbus) */
+ u8 data_size1;
+ /* 31 "Function index" of XLS sheet "Functions" */
+ u8 copy_f_index1;
+ /* 32 For Slimbus and TDM purpose */
+ u16 smem_addr2;
+ /* 34 */
+ u16 atc_address2;
+ /* 36 */
+ u16 atc_pointer_saved2;
+ /* 38 */
+ u8 data_size2;
+ /* 39 */
+ u8 copy_f_index2;
+};
+
+/* [w] asrc output used for the next asrc call (+/- 1 / 0) */
+#define drift_asrc_ 0
+/* [w] asrc output used for controlling the number of samples to be
+ exchanged (+/- 1 / 0) */
+#define drift_io_ 2
+/* address of the IO subroutine */
+#define io_type_idx_ 4
+#define samp_size_ 5
+/* flow error counter */
+#define flow_counter_ 6
+/* dmareq address or host irq buffer address (atc address) */
+#define hw_ctrl_addr_ 8
+/* data content to be loaded to "hw_ctrl_addr" */
+#define atc_irq_data_ 10
+/* read dmem =0, write dmem =3 (atc offset of the access pointer) */
+#define direction_rw_ 11
+/* flag set to allow repeating the last sample on downlink paths */
+#define repeat_last_samp_ 12
+/* number of samples (either mono stereo...) */
+#define nsamp_ 13
+/* x number of raw DMEM data moved */
+#define x_io_ 14
+#define on_off_ 15
+/* internal smem buffer initptr pointer index */
+#define split_addr1_ 16
+/* internal smem buffer initptr pointer index */
+#define split_addr2_ 18
+/* internal smem buffer initptr pointer index */
+#define split_addr3_ 20
+/* index of the copy subroutine */
+#define before_f_index_ 22
+/* index of the copy subroutine */
+#define after_f_index_ 23
+#define minidesc1_ 24
+/* internal smem buffer initptr pointer index */
+#define rel_smem_ 0
+/* atc descriptor address (byte address x4) */
+#define rel_atc_ 2
+/* location of the saved ATC pointer (+debug info) */
+#define rel_atc_saved 4
+/* size of each sample (1:mono/1616 2:stereo ... ) */
+#define rel_size_ 6
+/* index of the copy subroutine */
+#define rel_f_ 7
+#define s_mem_mm_ul 24
+#define s_mm_ul_size 30
+#define minidesc2_ 32
+#define Struct_Size 40
+
+struct ABE_SPingPongDescriptor {
+ /* 0: [W] asrc output used for the next ASRC call (+/- 1 / 0) */
+ u16 drift_ASRC;
+ /* 2: [W] asrc output used for controlling the number of
+ samples to be exchanged (+/- 1 / 0) */
+ u16 drift_io;
+ /* 4: DMAReq address or HOST IRQ buffer address (ATC ADDRESS) */
+ u16 hw_ctrl_addr;
+ /* 6: index of the copy subroutine */
+ u8 copy_func_index;
+ /* 7: X number of SMEM samples to move */
+ u8 x_io;
+ /* 8: 0 for mono data, 1 for stereo data */
+ u8 data_size;
+ /* 9: internal SMEM buffer INITPTR pointer index */
+ u8 smem_addr;
+ /* 10: data content to be loaded to "hw_ctrl_addr" */
+ u8 atc_irq_data;
+ /* 11: ping/pong buffer flag */
+ u8 counter;
+ /* 12: reseved */
+ u16 dummy1;
+ /* 14: reseved */
+ u16 dummy2;
+ /* 16 For 12/11 in case of 44.1 mode (same address as SIO desc)*/
+ u16 split_addr1;
+ /* 18: reseved */
+ u16 dummy3;
+ /* 20: current Base address of the working buffer */
+ u16 workbuff_BaseAddr;
+ /* 14: samples left in the working buffer */
+ u16 workbuff_Samples;
+ /* 16: Base address of the ping/pong buffer 0 */
+ u16 nextbuff0_BaseAddr;
+ /* 18: samples available in the ping/pong buffer 0 */
+ u16 nextbuff0_Samples;
+ /* 20: Base address of the ping/pong buffer 1 */
+ u16 nextbuff1_BaseAddr;
+ /* 22: samples available in the ping/pong buffer 1 */
+ u16 nextbuff1_Samples;
+};
+
+#endif/* _ABE_TYPEDEF_H_ */
diff --git a/sound/soc/omap/abe/port_mgr.c b/sound/soc/omap/abe/port_mgr.c
new file mode 100644
index 0000000..ef9d7a6
--- /dev/null
+++ b/sound/soc/omap/abe/port_mgr.c
@@ -0,0 +1,345 @@
+/*
+ * ALSA SoC OMAP ABE port manager
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+//#define DEBUG
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include "port_mgr.h"
+#include "abe_main.h"
+
+#ifdef CONFIG_DEBUG_FS
+/* this must match logical ID numbers in port_mgr.h */
+static const char *lport_name[] = {
+ "dmic0", "dmic1", "dmic2", "pdmdl1", "pdmdl2", "pdmvib",
+ "pdmul1", "bt_vx_dl", "bt_vx_ul", "mm_ext_ul", "mm_ext_dl",
+ "mm_dl1", "mm_ul1", "mm_ul2", "vx_dl", "vx_ul", "vib", "tones"
+};
+#endif
+
+static DEFINE_MUTEX(port_mgr_mutex);
+static struct abe *the_abe = NULL;
+static int users = 0;
+
+/*
+ * Get the Physical port ID based on the logical port ID
+ *
+ * FE and BE ports have unique ID's within the driver but share
+ * ID's within the ABE. This maps a driver port ID to an ABE port ID.
+ */
+static int get_physical_id(int logical_id)
+{
+ switch (logical_id) {
+ /* backend ports */
+ case OMAP_ABE_BE_PORT_DMIC0:
+ case OMAP_ABE_BE_PORT_DMIC1:
+ case OMAP_ABE_BE_PORT_DMIC2:
+ return DMIC_PORT;
+ case OMAP_ABE_BE_PORT_PDM_DL1:
+ case OMAP_ABE_BE_PORT_PDM_DL2:
+ return PDM_DL_PORT;
+ case OMAP_ABE_BE_PORT_PDM_VIB:
+ return VIB_DL_PORT;
+ case OMAP_ABE_BE_PORT_PDM_UL1:
+ return PDM_UL_PORT;
+ case OMAP_ABE_BE_PORT_BT_VX_DL:
+ return BT_VX_DL_PORT;
+ case OMAP_ABE_BE_PORT_BT_VX_UL:
+ return BT_VX_UL_PORT;
+ case OMAP_ABE_BE_PORT_MM_EXT_UL:
+ return MM_EXT_OUT_PORT;
+ case OMAP_ABE_BE_PORT_MM_EXT_DL:
+ return MM_EXT_IN_PORT;
+ /* front end ports */
+ case OMAP_ABE_FE_PORT_MM_DL1:
+ return MM_DL_PORT;
+ case OMAP_ABE_FE_PORT_MM_UL1:
+ return MM_UL_PORT;
+ case OMAP_ABE_FE_PORT_MM_UL2:
+ return MM_UL2_PORT;
+ case OMAP_ABE_FE_PORT_VX_DL:
+ return VX_DL_PORT;
+ case OMAP_ABE_FE_PORT_VX_UL:
+ return VX_UL_PORT;
+ case OMAP_ABE_FE_PORT_VIB:
+ return VIB_DL_PORT;
+ case OMAP_ABE_FE_PORT_TONES:
+ return TONES_DL_PORT;
+ }
+ return -EINVAL;
+}
+
+/*
+ * Get the number of enabled users of the physical port shared by this client.
+ * Locks held by callers.
+ */
+static int port_get_num_users(struct abe *abe, struct omap_abe_port *port)
+{
+ struct omap_abe_port *p;
+ int users = 0;
+
+ list_for_each_entry(p, &abe->ports, list) {
+ if (p->physical_id == port->physical_id && p->state == PORT_ENABLED)
+ users++;
+ }
+ return users;
+}
+
+static int port_is_open(struct abe *abe, int phy_port)
+{
+ struct omap_abe_port *p;
+
+ list_for_each_entry(p, &abe->ports, list) {
+ if (p->physical_id == phy_port && p->state == PORT_ENABLED)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check whether the physical port is enabled for this PHY port ID.
+ * Locks held by callers.
+ */
+int omap_abe_port_is_enabled(struct abe *abe, struct omap_abe_port *port)
+{
+ struct omap_abe_port *p;
+ unsigned long flags;
+
+ spin_lock_irqsave(&abe->lock, flags);
+
+ list_for_each_entry(p, &abe->ports, list) {
+ if (p->physical_id == port->physical_id && p->state == PORT_ENABLED) {
+ spin_unlock_irqrestore(&abe->lock, flags);
+ return 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&abe->lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_port_is_enabled);
+
+/*
+ * omap_abe_port_enable - enable ABE logical port
+ *
+ * @abe - ABE.
+ * @port - logical ABE port ID to be enabled.
+ */
+int omap_abe_port_enable(struct abe *abe, struct omap_abe_port *port)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ /* only enable the physical port iff it is disabled */
+ pr_debug("port %s increment count %d\n",
+ lport_name[port->logical_id], port->users);
+
+ spin_lock_irqsave(&abe->lock, flags);
+ if (port->users == 0 && port_get_num_users(abe, port) == 0) {
+
+ /* enable the physical port */
+ pr_debug("port %s phy port %d enabled\n",
+ lport_name[port->logical_id], port->physical_id);
+ abe_enable_data_transfer(port->physical_id);
+ }
+
+ port->state = PORT_ENABLED;
+ port->users++;
+ spin_unlock_irqrestore(&abe->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(omap_abe_port_enable);
+
+/*
+ * omap_abe_port_disable - disable ABE logical port
+ *
+ * @abe - ABE.
+ * @port - logical ABE port ID to be disabled.
+ */
+int omap_abe_port_disable(struct abe *abe, struct omap_abe_port *port)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ /* only disable the port iff no other users are using it */
+ pr_debug("port %s decrement count %d\n",
+ lport_name[port->logical_id], port->users);
+
+ spin_lock_irqsave(&abe->lock, flags);
+
+ WARN(!port->users, "port %s phy port %d is already disabled\n",
+ lport_name[port->logical_id], port->physical_id);
+
+ if (port->users == 1 && port_get_num_users(abe, port) == 1) {
+ /* disable the physical port */
+ pr_debug("port %s phy port %d disabled\n",
+ lport_name[port->logical_id], port->physical_id);
+
+ abe_disable_data_transfer(port->physical_id);
+ }
+
+ port->state = PORT_DISABLED;
+ port->users--;
+ spin_unlock_irqrestore(&abe->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(omap_abe_port_disable);
+
+/*
+ * omap_abe_port_open - open ABE logical port
+ *
+ * @abe - ABE.
+ * @logical_id - logical ABE port ID to be opened.
+ */
+struct omap_abe_port *omap_abe_port_open(struct abe *abe, int logical_id)
+{
+ struct omap_abe_port *port;
+ unsigned long flags;
+
+#ifdef CONFIG_DEBUG_FS
+ char debug_fs_name[32];
+#endif
+
+ if (logical_id < 0 || logical_id > OMAP_ABE_MAX_PORT_ID)
+ return NULL;
+
+ if (port_is_open(abe, logical_id))
+ return NULL;
+
+ port = kzalloc(sizeof(struct omap_abe_port), GFP_KERNEL);
+ if (port == NULL)
+ return NULL;
+
+ port->logical_id = logical_id;
+ port->physical_id = get_physical_id(logical_id);
+ port->state = PORT_DISABLED;
+ port->abe = abe;
+
+ spin_lock_irqsave(&abe->lock, flags);
+ list_add(&port->list, &abe->ports);
+ spin_unlock_irqrestore(&abe->lock, flags);
+ port->physical_users = port_get_num_users(abe, port);
+
+#ifdef CONFIG_DEBUG_FS
+ sprintf(debug_fs_name, "%s_state", lport_name[logical_id]);
+ port->debugfs_lstate = debugfs_create_u32(debug_fs_name, 0644,
+ abe->debugfs_root, &port->state);
+ sprintf(debug_fs_name, "%s_phy", lport_name[logical_id]);
+ port->debugfs_lphy = debugfs_create_u32(debug_fs_name, 0644,
+ abe->debugfs_root, &port->physical_id);
+ sprintf(debug_fs_name, "%s_users", lport_name[logical_id]);
+ port->debugfs_lusers = debugfs_create_u32(debug_fs_name, 0644,
+ abe->debugfs_root, &port->users);
+#endif
+
+ pr_debug("opened port %s\n", lport_name[logical_id]);
+ return port;
+}
+EXPORT_SYMBOL(omap_abe_port_open);
+
+/*
+ * omap_abe_port_close - close ABE logical port
+ *
+ * @port - logical ABE port to be closed (and disabled).
+ */
+void omap_abe_port_close(struct abe *abe, struct omap_abe_port *port)
+{
+ unsigned long flags;
+
+ /* disable the port */
+ omap_abe_port_disable(abe, port);
+
+ spin_lock_irqsave(&abe->lock, flags);
+ list_del(&port->list);
+ spin_unlock_irqrestore(&abe->lock, flags);
+
+ pr_debug("closed port %s\n", lport_name[port->logical_id]);
+ kfree(port);
+}
+EXPORT_SYMBOL(omap_abe_port_close);
+
+static struct abe *omap_abe_port_mgr_init(void)
+{
+ struct abe *abe;
+
+ abe = kzalloc(sizeof(struct abe), GFP_KERNEL);
+ if (abe == NULL)
+ return NULL;
+
+ spin_lock_init(&abe->lock);
+
+ INIT_LIST_HEAD(&abe->ports);
+ the_abe = abe;
+
+#ifdef CONFIG_DEBUG_FS
+ abe->debugfs_root = debugfs_create_dir("abe_port", NULL);
+ if (!abe->debugfs_root) {
+ pr_debug( "Failed to create port manager debugfs directory\n");
+ }
+#endif
+ return abe;
+}
+
+static void omap_abe_port_mgr_free(struct abe *abe)
+{
+ debugfs_remove_recursive(abe->debugfs_root);
+ kfree(abe);
+ the_abe = NULL;
+}
+
+struct abe *omap_abe_port_mgr_get(void)
+{
+ struct abe * abe;
+
+ mutex_lock(&port_mgr_mutex);
+
+ if (the_abe)
+ abe = the_abe;
+ else
+ abe = omap_abe_port_mgr_init();
+
+ users++;
+ mutex_unlock(&port_mgr_mutex);
+ return abe;
+}
+EXPORT_SYMBOL(omap_abe_port_mgr_get);
+
+void omap_abe_port_mgr_put(struct abe *abe)
+{
+ mutex_lock(&port_mgr_mutex);
+
+ if (users == 0)
+ goto out;
+
+ if (--users == 0)
+ omap_abe_port_mgr_free(abe);
+
+out:
+ mutex_unlock(&port_mgr_mutex);
+}
+EXPORT_SYMBOL(omap_abe_port_mgr_put);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/abe/port_mgr.h b/sound/soc/omap/abe/port_mgr.h
new file mode 100644
index 0000000..a65b0d3
--- /dev/null
+++ b/sound/soc/omap/abe/port_mgr.h
@@ -0,0 +1,98 @@
+/*
+ * ABE Port manager
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_SOC_OMAP_PORT_MGR_H
+#define __LINUX_SND_SOC_OMAP_PORT_MGR_H
+
+#include <linux/debugfs.h>
+
+/*
+ * TODO: These structures, enums and port ID macros should be moved to the
+ * new public ABE API header.
+ */
+
+/* Logical PORT IDs - Backend */
+#define OMAP_ABE_BE_PORT_DMIC0 0
+#define OMAP_ABE_BE_PORT_DMIC1 1
+#define OMAP_ABE_BE_PORT_DMIC2 2
+#define OMAP_ABE_BE_PORT_PDM_DL1 3
+#define OMAP_ABE_BE_PORT_PDM_DL2 4
+#define OMAP_ABE_BE_PORT_PDM_VIB 5
+#define OMAP_ABE_BE_PORT_PDM_UL1 6
+#define OMAP_ABE_BE_PORT_BT_VX_DL 7
+#define OMAP_ABE_BE_PORT_BT_VX_UL 8
+#define OMAP_ABE_BE_PORT_MM_EXT_UL 9
+#define OMAP_ABE_BE_PORT_MM_EXT_DL 10
+
+/* Logical PORT IDs - Frontend */
+#define OMAP_ABE_FE_PORT_MM_DL1 11
+#define OMAP_ABE_FE_PORT_MM_UL1 12
+#define OMAP_ABE_FE_PORT_MM_UL2 13
+#define OMAP_ABE_FE_PORT_VX_DL 14
+#define OMAP_ABE_FE_PORT_VX_UL 15
+#define OMAP_ABE_FE_PORT_VIB 16
+#define OMAP_ABE_FE_PORT_TONES 17
+
+#define OMAP_ABE_MAX_PORT_ID OMAP_ABE_FE_PORT_TONES
+
+/* ports can either be enabled or disabled */
+enum port_state {
+ PORT_DISABLED = 0,
+ PORT_ENABLED,
+};
+
+/* structure used for client port info */
+struct omap_abe_port {
+
+ /* logical and physical port IDs that correspond this port */
+ int logical_id;
+ int physical_id;
+ int physical_users;
+
+ /* enabled or disabled */
+ enum port_state state;
+
+ /* logical port ref count */
+ int users;
+
+ struct list_head list;
+ struct abe *abe;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_lstate;
+ struct dentry *debugfs_lphy;
+ struct dentry *debugfs_lusers;
+#endif
+};
+
+/* main ABE structure */
+struct abe {
+
+ /* List of open ABE logical ports */
+ struct list_head ports;
+
+ /* spinlock */
+ spinlock_t lock;
+
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_root;
+#endif
+};
+
+struct omap_abe_port *omap_abe_port_open(struct abe *abe, int logical_id);
+void omap_abe_port_close(struct abe *abe, struct omap_abe_port *port);
+int omap_abe_port_enable(struct abe *abe, struct omap_abe_port *port);
+int omap_abe_port_disable(struct abe *abe, struct omap_abe_port *port);
+int omap_abe_port_is_enabled(struct abe *abe, struct omap_abe_port *port);
+struct abe *omap_abe_port_mgr_get(void);
+void omap_abe_port_mgr_put(struct abe *abe);
+
+#endif /* __LINUX_SND_SOC_OMAP_PORT_MGR_H */
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
deleted file mode 100644
index 928f037..0000000
--- a/sound/soc/omap/mcpdm.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * mcpdm.c -- McPDM interface driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- * Copyright (C) 2009 - Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include "mcpdm.h"
-
-static struct omap_mcpdm *mcpdm;
-
-static inline void omap_mcpdm_write(u16 reg, u32 val)
-{
- __raw_writel(val, mcpdm->io_base + reg);
-}
-
-static inline int omap_mcpdm_read(u16 reg)
-{
- return __raw_readl(mcpdm->io_base + reg);
-}
-
-static void omap_mcpdm_reg_dump(void)
-{
- dev_dbg(mcpdm->dev, "***********************\n");
- dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
- dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQSTATUS));
- dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQENABLE_SET));
- dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
- dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQWAKE_EN));
- dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAENABLE_SET));
- dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
- dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAWAKEEN));
- dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
- omap_mcpdm_read(MCPDM_CTRL));
- dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DN_DATA));
- dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
- omap_mcpdm_read(MCPDM_UP_DATA));
- dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
- dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
- omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
- dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DN_OFFSET));
- dev_dbg(mcpdm->dev, "***********************\n");
-}
-
-/*
- * Takes the McPDM module in and out of reset state.
- * Uplink and downlink can be reset individually.
- */
-static void omap_mcpdm_reset_capture(int reset)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (reset)
- ctrl |= SW_UP_RST;
- else
- ctrl &= ~SW_UP_RST;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-static void omap_mcpdm_reset_playback(int reset)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (reset)
- ctrl |= SW_DN_RST;
- else
- ctrl &= ~SW_DN_RST;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Enables the transfer through the PDM interface to/from the Phoenix
- * codec by enabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_start(int stream)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (stream)
- ctrl |= mcpdm->up_channels;
- else
- ctrl |= mcpdm->dn_channels;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Disables the transfer through the PDM interface to/from the Phoenix
- * codec by disabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_stop(int stream)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (stream)
- ctrl &= ~mcpdm->up_channels;
- else
- ctrl &= ~mcpdm->dn_channels;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Configures McPDM uplink for audio recording.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
-{
- int irq_mask = 0;
- int ctrl;
-
- if (!uplink)
- return -EINVAL;
-
- mcpdm->uplink = uplink;
-
- /* Enable irq request generation */
- irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
- /* Configure uplink threshold */
- if (uplink->threshold > UP_THRES_MAX)
- uplink->threshold = UP_THRES_MAX;
-
- omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
-
- /* Configure DMA controller */
- omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
-
- /* Set pdm out format */
- ctrl = omap_mcpdm_read(MCPDM_CTRL);
- ctrl &= ~PDMOUTFORMAT;
- ctrl |= uplink->format & PDMOUTFORMAT;
-
- /* Uplink channels */
- mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
- return 0;
-}
-
-/*
- * Configures McPDM downlink for audio playback.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
-{
- int irq_mask = 0;
- int ctrl;
-
- if (!downlink)
- return -EINVAL;
-
- mcpdm->downlink = downlink;
-
- /* Enable irq request generation */
- irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
- /* Configure uplink threshold */
- if (downlink->threshold > DN_THRES_MAX)
- downlink->threshold = DN_THRES_MAX;
-
- omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
-
- /* Enable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
-
- /* Set pdm out format */
- ctrl = omap_mcpdm_read(MCPDM_CTRL);
- ctrl &= ~PDMOUTFORMAT;
- ctrl |= downlink->format & PDMOUTFORMAT;
-
- /* Downlink channels */
- mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
- return 0;
-}
-
-/*
- * Cleans McPDM uplink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
-{
- int irq_mask = 0;
-
- if (!uplink)
- return -EINVAL;
-
- /* Disable irq request generation */
- irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
- /* Disable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
-
- /* Clear Downlink channels */
- mcpdm->up_channels = 0;
-
- mcpdm->uplink = NULL;
-
- return 0;
-}
-
-/*
- * Cleans McPDM downlink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
-{
- int irq_mask = 0;
-
- if (!downlink)
- return -EINVAL;
-
- /* Disable irq request generation */
- irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
- /* Disable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
-
- /* clear Downlink channels */
- mcpdm->dn_channels = 0;
-
- mcpdm->downlink = NULL;
-
- return 0;
-}
-
-static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
-{
- struct omap_mcpdm *mcpdm_irq = dev_id;
- int irq_status;
-
- irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
-
- /* Acknowledge irq event */
- omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
-
- if (irq & MCPDM_DN_IRQ_FULL) {
- dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
- omap_mcpdm_reset_playback(1);
- omap_mcpdm_playback_open(mcpdm_irq->downlink);
- omap_mcpdm_reset_playback(0);
- }
-
- if (irq & MCPDM_DN_IRQ_EMPTY) {
- dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
- omap_mcpdm_reset_playback(1);
- omap_mcpdm_playback_open(mcpdm_irq->downlink);
- omap_mcpdm_reset_playback(0);
- }
-
- if (irq & MCPDM_DN_IRQ) {
- dev_dbg(mcpdm_irq->dev, "DN write request\n");
- }
-
- if (irq & MCPDM_UP_IRQ_FULL) {
- dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
- omap_mcpdm_reset_capture(1);
- omap_mcpdm_capture_open(mcpdm_irq->uplink);
- omap_mcpdm_reset_capture(0);
- }
-
- if (irq & MCPDM_UP_IRQ_EMPTY) {
- dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
- omap_mcpdm_reset_capture(1);
- omap_mcpdm_capture_open(mcpdm_irq->uplink);
- omap_mcpdm_reset_capture(0);
- }
-
- if (irq & MCPDM_UP_IRQ) {
- dev_dbg(mcpdm_irq->dev, "UP write request\n");
- }
-
- return IRQ_HANDLED;
-}
-
-int omap_mcpdm_request(void)
-{
- int ret;
-
- clk_enable(mcpdm->clk);
-
- spin_lock(&mcpdm->lock);
-
- if (!mcpdm->free) {
- dev_err(mcpdm->dev, "McPDM interface is in use\n");
- spin_unlock(&mcpdm->lock);
- ret = -EBUSY;
- goto err;
- }
- mcpdm->free = 0;
-
- spin_unlock(&mcpdm->lock);
-
- /* Disable lines while request is ongoing */
- omap_mcpdm_write(MCPDM_CTRL, 0x00);
-
- ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
- 0, "McPDM", (void *)mcpdm);
- if (ret) {
- dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
- goto err;
- }
-
- return 0;
-
-err:
- clk_disable(mcpdm->clk);
- return ret;
-}
-
-void omap_mcpdm_free(void)
-{
- spin_lock(&mcpdm->lock);
- if (mcpdm->free) {
- dev_err(mcpdm->dev, "McPDM interface is already free\n");
- spin_unlock(&mcpdm->lock);
- return;
- }
- mcpdm->free = 1;
- spin_unlock(&mcpdm->lock);
-
- clk_disable(mcpdm->clk);
-
- free_irq(mcpdm->irq, (void *)mcpdm);
-}
-
-/* Enable/disable DC offset cancelation for the analog
- * headset path (PDM channels 1 and 2).
- */
-int omap_mcpdm_set_offset(int offset1, int offset2)
-{
- int offset;
-
- if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
- return -EINVAL;
-
- offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
-
- /* offset cancellation for channel 1 */
- if (offset1)
- offset |= DN_OFST_RX1_EN;
- else
- offset &= ~DN_OFST_RX1_EN;
-
- /* offset cancellation for channel 2 */
- if (offset2)
- offset |= DN_OFST_RX2_EN;
- else
- offset &= ~DN_OFST_RX2_EN;
-
- omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
-
- return 0;
-}
-
-int __devinit omap_mcpdm_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int ret = 0;
-
- mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
- if (!mcpdm) {
- ret = -ENOMEM;
- goto exit;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no resource\n");
- goto err_resource;
- }
-
- spin_lock_init(&mcpdm->lock);
- mcpdm->free = 1;
- mcpdm->io_base = ioremap(res->start, resource_size(res));
- if (!mcpdm->io_base) {
- ret = -ENOMEM;
- goto err_resource;
- }
-
- mcpdm->irq = platform_get_irq(pdev, 0);
-
- mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
- if (IS_ERR(mcpdm->clk)) {
- ret = PTR_ERR(mcpdm->clk);
- dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
- goto err_clk;
- }
-
- mcpdm->dev = &pdev->dev;
- platform_set_drvdata(pdev, mcpdm);
-
- return 0;
-
-err_clk:
- iounmap(mcpdm->io_base);
-err_resource:
- kfree(mcpdm);
-exit:
- return ret;
-}
-
-int __devexit omap_mcpdm_remove(struct platform_device *pdev)
-{
- struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- clk_put(mcpdm_ptr->clk);
-
- iounmap(mcpdm_ptr->io_base);
-
- mcpdm_ptr->clk = NULL;
- mcpdm_ptr->free = 0;
- mcpdm_ptr->dev = NULL;
-
- kfree(mcpdm_ptr);
-
- return 0;
-}
-
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
deleted file mode 100644
index df3e16f..0000000
--- a/sound/soc/omap/mcpdm.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * mcpdm.h -- Defines for McPDM driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/* McPDM registers */
-
-#define MCPDM_REVISION 0x00
-#define MCPDM_SYSCONFIG 0x10
-#define MCPDM_IRQSTATUS_RAW 0x24
-#define MCPDM_IRQSTATUS 0x28
-#define MCPDM_IRQENABLE_SET 0x2C
-#define MCPDM_IRQENABLE_CLR 0x30
-#define MCPDM_IRQWAKE_EN 0x34
-#define MCPDM_DMAENABLE_SET 0x38
-#define MCPDM_DMAENABLE_CLR 0x3C
-#define MCPDM_DMAWAKEEN 0x40
-#define MCPDM_CTRL 0x44
-#define MCPDM_DN_DATA 0x48
-#define MCPDM_UP_DATA 0x4C
-#define MCPDM_FIFO_CTRL_DN 0x50
-#define MCPDM_FIFO_CTRL_UP 0x54
-#define MCPDM_DN_OFFSET 0x58
-
-/*
- * MCPDM_IRQ bit fields
- * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
- */
-
-#define MCPDM_DN_IRQ (1 << 0)
-#define MCPDM_DN_IRQ_EMPTY (1 << 1)
-#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2)
-#define MCPDM_DN_IRQ_FULL (1 << 3)
-
-#define MCPDM_UP_IRQ (1 << 8)
-#define MCPDM_UP_IRQ_EMPTY (1 << 9)
-#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10)
-#define MCPDM_UP_IRQ_FULL (1 << 11)
-
-#define MCPDM_DOWNLINK_IRQ_MASK 0x00F
-#define MCPDM_UPLINK_IRQ_MASK 0xF00
-
-/*
- * MCPDM_DMAENABLE bit fields
- */
-
-#define DMA_DN_ENABLE 0x1
-#define DMA_UP_ENABLE 0x2
-
-/*
- * MCPDM_CTRL bit fields
- */
-
-#define PDM_UP1_EN 0x0001
-#define PDM_UP2_EN 0x0002
-#define PDM_UP3_EN 0x0004
-#define PDM_DN1_EN 0x0008
-#define PDM_DN2_EN 0x0010
-#define PDM_DN3_EN 0x0020
-#define PDM_DN4_EN 0x0040
-#define PDM_DN5_EN 0x0080
-#define PDMOUTFORMAT 0x0100
-#define CMD_INT 0x0200
-#define STATUS_INT 0x0400
-#define SW_UP_RST 0x0800
-#define SW_DN_RST 0x1000
-#define PDM_UP_MASK 0x007
-#define PDM_DN_MASK 0x0F8
-#define PDM_CMD_MASK 0x200
-#define PDM_STATUS_MASK 0x400
-
-
-#define PDMOUTFORMAT_LJUST (0 << 8)
-#define PDMOUTFORMAT_RJUST (1 << 8)
-
-/*
- * MCPDM_FIFO_CTRL bit fields
- */
-
-#define UP_THRES_MAX 0xF
-#define DN_THRES_MAX 0xF
-
-/*
- * MCPDM_DN_OFFSET bit fields
- */
-
-#define DN_OFST_RX1_EN 0x0001
-#define DN_OFST_RX2_EN 0x0100
-
-#define DN_OFST_RX1 1
-#define DN_OFST_RX2 9
-#define DN_OFST_MAX 0x1F
-
-#define MCPDM_UPLINK 1
-#define MCPDM_DOWNLINK 2
-
-struct omap_mcpdm_link {
- int irq_mask;
- int threshold;
- int format;
- int channels;
-};
-
-struct omap_mcpdm_platform_data {
- unsigned long phys_base;
- u16 irq;
-};
-
-struct omap_mcpdm {
- struct device *dev;
- unsigned long phys_base;
- void __iomem *io_base;
- u8 free;
- int irq;
-
- spinlock_t lock;
- struct omap_mcpdm_platform_data *pdata;
- struct clk *clk;
- struct omap_mcpdm_link *downlink;
- struct omap_mcpdm_link *uplink;
- struct completion irq_completion;
-
- int dn_channels;
- int up_channels;
-};
-
-extern void omap_mcpdm_start(int stream);
-extern void omap_mcpdm_stop(int stream);
-extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_request(void);
-extern void omap_mcpdm_free(void);
-extern int omap_mcpdm_set_offset(int offset1, int offset2);
-int __devinit omap_mcpdm_probe(struct platform_device *pdev);
-int __devexit omap_mcpdm_remove(struct platform_device *pdev);
diff --git a/sound/soc/omap/omap-abe-dsp.c b/sound/soc/omap/omap-abe-dsp.c
new file mode 100644
index 0000000..b66db25
--- /dev/null
+++ b/sound/soc/omap/omap-abe-dsp.c
@@ -0,0 +1,2876 @@
+/*
+ * omap-abe-dsp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Authors: Liam Girdwood <lrg@ti.com>
+ * Misael Lopez Cruz <misael.lopez@ti.com>
+ * Sebastien Guiriec <s-guiriec@ti.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/twl.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/wait.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/opp.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/dma.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/omap-abe-dsp.h>
+
+#include "omap-abe-dsp.h"
+#include "omap-abe.h"
+#include "abe/abe_main.h"
+#include "abe/port_mgr.h"
+
+#define OMAP_ABE_HS_DC_OFFSET_STEP (1800 / 8)
+#define OMAP_ABE_HF_DC_OFFSET_STEP (4600 / 8)
+
+static const char *abe_memory_bank[5] = {
+ "dmem",
+ "cmem",
+ "smem",
+ "pmem",
+ "mpu"
+};
+
+
+/*
+ * ABE loadable coefficients.
+ * The coefficient and their mixer configurations are loaded with the firmware
+ * blob duing probe().
+ */
+
+struct coeff_config {
+ char name[ABE_COEFF_NAME_SIZE];
+ u32 count;
+ u32 coeff;
+ char texts[ABE_COEFF_NUM_TEXTS][ABE_COEFF_TEXT_SIZE];
+};
+
+/*
+ * ABE Firmware Header.
+ * The ABE firmware blob has a header that describes each data section. This
+ * way we can store coefficients etc in the firmware.
+ */
+struct fw_header {
+ u32 magic; /* magic number */
+ u32 crc; /* optional crc */
+ u32 firmware_size; /* payload size */
+ u32 coeff_size; /* payload size */
+ u32 coeff_version; /* coefficent version */
+ u32 firmware_version; /* min version of ABE firmware required */
+ u32 num_equ; /* number of equalizers */
+};
+
+struct abe_opp_req {
+ struct device *dev;
+ struct list_head node;
+ int opp;
+};
+
+/*
+ * ABE private data.
+ */
+struct abe_data {
+ struct omap4_abe_dsp_pdata *abe_pdata;
+ struct device *dev;
+ struct snd_soc_platform *platform;
+ struct delayed_work delayed_work;
+ struct mutex mutex;
+ struct mutex opp_mutex;
+ struct mutex opp_req_mutex;
+ struct clk *clk;
+ void __iomem *io_base[5];
+ int irq;
+ int opp;
+ unsigned long opp_freqs[OMAP_ABE_OPP_COUNT];
+
+ /* DC offset cancellation */
+ int power_mode;
+ u32 dc_hsl;
+ u32 dc_hsr;
+ u32 dc_hfl;
+ u32 dc_hfr;
+
+ int active;
+
+ /* coefficients */
+ struct fw_header hdr;
+ u32 *firmware;
+ s32 *equ[ABE_MAX_EQU];
+ int equ_profile[ABE_MAX_EQU];
+ struct soc_enum equalizer_enum[ABE_MAX_EQU];
+ struct snd_kcontrol_new equalizer_control[ABE_MAX_EQU];
+ struct coeff_config *equ_texts;
+
+ int mono_mix[ABE_NUM_MONO_MIXERS];
+
+ /* DAPM mixer config - TODO: some of this can be replaced with HAL update */
+ u32 widget_opp[ABE_NUM_DAPM_REG + 1];
+
+ struct list_head opp_req;
+ int opp_req_count;
+
+ u16 router[16];
+
+ struct snd_pcm_substream *ping_pong_substream;
+ int first_irq;
+
+ struct snd_pcm_substream *psubs;
+
+#ifdef CONFIG_DEBUG_FS
+ /* ABE runtime debug config */
+
+ /* its intended we can switch on/off individual debug items */
+ u32 dbg_format1; /* TODO: match flag names here to debug format flags */
+ u32 dbg_format2;
+ u32 dbg_format3;
+
+ u32 dbg_buffer_bytes;
+ u32 dbg_circular;
+ u32 dbg_buffer_msecs; /* size of buffer in secs */
+ u32 dbg_elem_bytes;
+ dma_addr_t dbg_buffer_addr;
+ wait_queue_head_t wait;
+ int dbg_reader_offset;
+ int dbg_dma_offset;
+ int dbg_complete;
+ struct dentry *debugfs_root;
+ struct dentry *debugfs_fmt1;
+ struct dentry *debugfs_fmt2;
+ struct dentry *debugfs_fmt3;
+ struct dentry *debugfs_size;
+ struct dentry *debugfs_data;
+ struct dentry *debugfs_circ;
+ struct dentry *debugfs_elem_bytes;
+ struct dentry *debugfs_opp_level;
+ char *dbg_buffer;
+ struct omap_pcm_dma_data *dma_data;
+ int dma_ch;
+ int dma_req;
+#endif
+};
+
+static struct abe_data *the_abe;
+
+static int aess_set_runtime_opp_level(struct abe_data *abe);
+
+// TODO: map to the new version of HAL
+static unsigned int abe_dsp_read(struct snd_soc_platform *platform,
+ unsigned int reg)
+{
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+
+ BUG_ON(reg > ABE_NUM_DAPM_REG);
+ return abe->widget_opp[reg];
+}
+
+static int abe_dsp_write(struct snd_soc_platform *platform, unsigned int reg,
+ unsigned int val)
+{
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+
+ BUG_ON(reg > ABE_NUM_DAPM_REG);
+ abe->widget_opp[reg] = val;
+ return 0;
+}
+
+static void abe_irq_pingpong_subroutine(u32 *data)
+{
+ u32 dst, n_bytes;
+
+ abe_read_next_ping_pong_buffer(MM_DL_PORT, &dst, &n_bytes);
+ abe_set_ping_pong_buffer(MM_DL_PORT, n_bytes);
+
+ /* Do not call ALSA function for first IRQ */
+ if (the_abe->first_irq) {
+ the_abe->first_irq = 0;
+ } else {
+ if (the_abe->ping_pong_substream)
+ snd_pcm_period_elapsed(the_abe->ping_pong_substream);
+ }
+}
+
+static irqreturn_t abe_irq_handler(int irq, void *dev_id)
+{
+ struct abe_data *abe = dev_id;
+
+ /* TODO: handle underruns/overruns/errors */
+ pm_runtime_get_sync(abe->dev);
+ abe_clear_irq(); // TODO: why is IRQ not cleared after processing ?
+ abe_irq_processing();
+ pm_runtime_put_sync_suspend(abe->dev);
+ return IRQ_HANDLED;
+}
+
+// TODO: these should really be called internally since we will know the McPDM state
+void abe_dsp_pm_get(void)
+{
+ pm_runtime_get_sync(the_abe->dev);
+}
+EXPORT_SYMBOL_GPL(abe_dsp_pm_get);
+
+void abe_dsp_pm_put(void)
+{
+ pm_runtime_put_sync(the_abe->dev);
+}
+EXPORT_SYMBOL_GPL(abe_dsp_pm_put);
+
+void abe_dsp_shutdown(void)
+{
+ struct omap4_abe_dsp_pdata *pdata = the_abe->abe_pdata;
+ int ret;
+
+ if (!the_abe->active && !abe_check_activity()) {
+ abe_set_opp_processing(ABE_OPP25);
+ the_abe->opp = 25;
+ abe_stop_event_generator();
+ udelay(250);
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(the_abe->dev, the_abe->dev,
+ the_abe->opp_freqs[0]);
+ if (ret)
+ dev_err(the_abe->dev,
+ "failed to scale to lowest OPP\n");
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(abe_dsp_shutdown);
+
+void abe_dsp_set_hs_offset(int left, int right, int mult)
+{
+ /* TODO: do not use abe global structure */
+ if (the_abe == NULL)
+ return;
+
+ if (left >= 8)
+ left -= 16;
+ the_abe->dc_hsl = OMAP_ABE_HS_DC_OFFSET_STEP * left * mult;
+
+ if (right >= 8)
+ right -= 16;
+ the_abe->dc_hsr = OMAP_ABE_HS_DC_OFFSET_STEP * right * mult;
+}
+EXPORT_SYMBOL(abe_dsp_set_hs_offset);
+
+void abe_dsp_set_hf_offset(int left, int right)
+{
+ /* TODO: do not use abe global structure */
+ if (the_abe == NULL)
+ return;
+
+ if (left >= 8)
+ left -= 16;
+ the_abe->dc_hfl = OMAP_ABE_HF_DC_OFFSET_STEP * left;
+
+ if (right >= 8)
+ right -= 16;
+ the_abe->dc_hfr = OMAP_ABE_HF_DC_OFFSET_STEP * right;
+}
+EXPORT_SYMBOL(abe_dsp_set_hf_offset);
+
+void abe_dsp_set_power_mode(int mode)
+{
+ if (the_abe == NULL)
+ return;
+
+ /* TODO: do not use abe global structure */
+ the_abe->power_mode = mode;
+}
+EXPORT_SYMBOL(abe_dsp_set_power_mode);
+
+/*
+ * These TLV settings will need fine tuned for each individual control
+ */
+
+/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(mm_dl1_tlv, -12000, 100, 3000);
+
+/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(tones_dl1_tlv, -12000, 100, 3000);
+
+/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(voice_dl1_tlv, -12000, 100, 3000);
+
+/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(capture_dl1_tlv, -12000, 100, 3000);
+
+/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(mm_dl2_tlv, -12000, 100, 3000);
+
+/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(tones_dl2_tlv, -12000, 100, 3000);
+
+/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(voice_dl2_tlv, -12000, 100, 3000);
+
+/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(capture_dl2_tlv, -12000, 100, 3000);
+
+/* SDT volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(sdt_ul_tlv, -12000, 100, 3000);
+
+/* SDT volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(sdt_dl_tlv, -12000, 100, 3000);
+
+/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(audul_mm_tlv, -12000, 100, 3000);
+
+/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(audul_tones_tlv, -12000, 100, 3000);
+
+/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(audul_vx_ul_tlv, -12000, 100, 3000);
+
+/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(audul_vx_dl_tlv, -12000, 100, 3000);
+
+/* VXREC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(vxrec_mm_dl_tlv, -12000, 100, 3000);
+
+/* VXREC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(vxrec_tones_tlv, -12000, 100, 3000);
+
+/* VXREC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(vxrec_vx_dl_tlv, -12000, 100, 3000);
+
+/* VXREC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(vxrec_vx_ul_tlv, -12000, 100, 3000);
+
+/* DMIC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(dmic_tlv, -12000, 100, 3000);
+
+/* BT UL volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(btul_tlv, -12000, 100, 3000);
+
+/* AMIC volume control from -120 to 30 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(amic_tlv, -12000, 100, 3000);
+
+//TODO: we have to use the shift value atm to represent register id due to current HAL
+static int dl1_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ // TODO: optimise all of these to call HAL abe_enable_gain(mixer, enable)
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ abe_enable_gain(MIXDL1, mc->reg);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ abe_disable_gain(MIXDL1, mc->reg);
+ }
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int dl2_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ abe_enable_gain(MIXDL2, mc->reg);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ abe_disable_gain(MIXDL2, mc->reg);
+ }
+
+ pm_runtime_put_sync(the_abe->dev);
+ return 1;
+}
+
+static int audio_ul_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ abe_enable_gain(MIXAUDUL, mc->reg);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ abe_disable_gain(MIXAUDUL, mc->reg);
+ }
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int vxrec_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ abe_enable_gain(MIXVXREC, mc->reg);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ abe_disable_gain(MIXVXREC, mc->reg);
+ }
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int sdt_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ abe_enable_gain(MIXSDT, mc->reg);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ abe_disable_gain(MIXSDT, mc->reg);
+ }
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int abe_get_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = the_abe->widget_opp[mc->shift];
+ return 0;
+}
+
+static int abe_dsp_set_mono_mixer(int id, int enable)
+{
+ int mixer;
+
+ switch (id) {
+ case MIX_DL1_MONO:
+ mixer = MIXDL1;
+ break;
+ case MIX_DL2_MONO:
+ mixer = MIXDL2;
+ break;
+ case MIX_AUDUL_MONO:
+ mixer = MIXAUDUL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_mono_mixer(mixer, enable);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int abe_put_mono_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int id = mc->shift - MIX_DL1_MONO;
+
+ the_abe->mono_mix[id] = ucontrol->value.integer.value[0];
+ abe_dsp_set_mono_mixer(mc->shift, the_abe->mono_mix[id]);
+
+ return 1;
+}
+
+static int abe_get_mono_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int id = mc->shift - MIX_DL1_MONO;
+
+ ucontrol->value.integer.value[0] = the_abe->mono_mix[id];
+ return 0;
+}
+
+/* router IDs that match our mixer strings */
+static const abe_router_t router[] = {
+ ZERO_labelID, /* strangely this is not 0 */
+ DMIC1_L_labelID, DMIC1_R_labelID,
+ DMIC2_L_labelID, DMIC2_R_labelID,
+ DMIC3_L_labelID, DMIC3_R_labelID,
+ BT_UL_L_labelID, BT_UL_R_labelID,
+ MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID,
+ AMIC_L_labelID, AMIC_R_labelID,
+ VX_REC_L_labelID, VX_REC_R_labelID,
+};
+
+static int ul_mux_put_route(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int mux = ucontrol->value.enumerated.item[0];
+ int reg = e->reg - ABE_MUX(0);
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (mux > ABE_ROUTES_UL)
+ return 0;
+
+ // TODO: get all this via firmware
+ if (reg < 8) {
+ /* 0 .. 9 = MM_UL */
+ the_abe->router[reg] = router[mux];
+ } else if (reg < 12) {
+ /* 10 .. 11 = MM_UL2 */
+ /* 12 .. 13 = VX_UL */
+ the_abe->router[reg + 2] = router[mux];
+ }
+
+ /* 2nd arg here is unused */
+ abe_set_router_configuration(UPROUTE, 0, (u32 *)the_abe->router);
+
+ if (router[mux] != ZERO_labelID)
+ the_abe->widget_opp[e->reg] = e->shift_l;
+ else
+ the_abe->widget_opp[e->reg] = 0;
+
+ snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int ul_mux_get_route(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e =
+ (struct soc_enum *)kcontrol->private_value;
+ int reg = e->reg - ABE_MUX(0), i, rval = 0;
+
+ // TODO: get all this via firmware
+ if (reg < 8) {
+ /* 0 .. 9 = MM_UL */
+ rval = the_abe->router[reg];
+ } else if (reg < 12) {
+ /* 10 .. 11 = MM_UL2 */
+ /* 12 .. 13 = VX_UL */
+ rval = the_abe->router[reg + 2];
+ }
+
+ for (i = 0; i < ARRAY_SIZE(router); i++) {
+ if (router[i] == rval) {
+ ucontrol->value.integer.value[0] = i;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+static int abe_put_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ if (ucontrol->value.integer.value[0]) {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+ } else {
+ the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+ }
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+
+static int volume_put_sdt_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+
+ abe_write_mixer(MIXSDT, abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->reg);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_put_audul_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_mixer(MIXAUDUL, abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->reg);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_put_vxrec_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_mixer(MIXVXREC, abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->reg);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_put_dl1_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_mixer(MIXDL1, abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->reg);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_put_dl2_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_mixer(MIXDL2, abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->reg);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_put_gain(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_gain(mc->reg,
+ abe_val_to_gain(ucontrol->value.integer.value[0]),
+ RAMP_2MS, mc->shift);
+ abe_write_gain(mc->reg,
+ -12000 + (ucontrol->value.integer.value[1] * 100),
+ RAMP_2MS, mc->rshift);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 1;
+}
+
+static int volume_get_dl1_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_mixer(MIXDL1, &val, mc->reg);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int volume_get_dl2_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_mixer(MIXDL2, &val, mc->reg);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int volume_get_audul_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_mixer(MIXAUDUL, &val, mc->reg);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int volume_get_vxrec_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_mixer(MIXVXREC, &val, mc->reg);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int volume_get_sdt_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_mixer(MIXSDT, &val, mc->reg);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int volume_get_gain(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u32 val;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_read_gain(mc->reg, &val, mc->shift);
+ ucontrol->value.integer.value[0] = abe_gain_to_val(val);
+ abe_read_gain(mc->reg, &val, mc->rshift);
+ ucontrol->value.integer.value[1] = abe_gain_to_val(val);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int abe_dsp_set_equalizer(unsigned int id, unsigned int profile)
+{
+ abe_equ_t equ_params;
+ int len;
+
+ if (id >= the_abe->hdr.num_equ)
+ return -EINVAL;
+
+ if (profile >= the_abe->equ_texts[id].count)
+ return -EINVAL;
+
+ len = the_abe->equ_texts[id].coeff;
+ equ_params.equ_length = len;
+ memcpy(equ_params.coef.type1, the_abe->equ[id] + profile * len,
+ len * sizeof(u32));
+ the_abe->equ_profile[id] = profile;
+
+ pm_runtime_get_sync(the_abe->dev);
+ abe_write_equalizer(id + 1, &equ_params);
+ pm_runtime_put_sync(the_abe->dev);
+
+ return 0;
+}
+
+static int abe_get_equalizer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = the_abe->equ_profile[eqc->reg];
+ return 0;
+}
+
+static int abe_put_equalizer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
+ u16 val = ucontrol->value.enumerated.item[0];
+ int ret;
+
+ ret = abe_dsp_set_equalizer(eqc->reg, val);
+ if (ret < 0)
+ return ret;
+
+ return 1;
+}
+
+int snd_soc_info_enum_ext1(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = e->max;
+
+ if (uinfo->value.enumerated.item > e->max - 1)
+ uinfo->value.enumerated.item = e->max - 1;
+ strcpy(uinfo->value.enumerated.name,
+ snd_soc_get_enum_text(e, uinfo->value.enumerated.item));
+
+ return 0;
+}
+
+static const char *route_ul_texts[] = {
+ "None", "DMic0L", "DMic0R", "DMic1L", "DMic1R", "DMic2L", "DMic2R",
+ "BT Left", "BT Right", "MMExt Left", "MMExt Right", "AMic0", "AMic1",
+ "VX Left", "VX Right"
+};
+
+/* ROUTE_UL Mux table */
+static const struct soc_enum abe_enum[] = {
+ SOC_ENUM_SINGLE(MUX_MM_UL10, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL11, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL12, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL13, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL14, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL15, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL16, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL17, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL20, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_MM_UL21, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_VX_UL0, 0, 15, route_ul_texts),
+ SOC_ENUM_SINGLE(MUX_VX_UL1, 0, 15, route_ul_texts),
+};
+
+static const struct snd_kcontrol_new mm_ul00_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[0],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul01_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[1],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul02_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[2],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul03_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[3],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul04_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[4],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul05_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[5],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul06_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[6],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul07_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[7],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul10_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[8],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_ul11_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[9],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_vx0_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[10],
+ ul_mux_get_route, ul_mux_put_route);
+
+static const struct snd_kcontrol_new mm_vx1_control =
+ SOC_DAPM_ENUM_EXT("Route", abe_enum[11],
+ ul_mux_get_route, ul_mux_put_route);
+
+/* DL1 mixer paths */
+static const struct snd_kcontrol_new dl1_mixer_controls[] = {
+ SOC_SINGLE_EXT("Tones", MIX_DL1_INPUT_TONES, MIX_DL1_TONES, 1, 0,
+ abe_get_mixer, dl1_put_mixer),
+ SOC_SINGLE_EXT("Voice", MIX_DL1_INPUT_VX_DL, MIX_DL1_VOICE, 1, 0,
+ abe_get_mixer, dl1_put_mixer),
+ SOC_SINGLE_EXT("Capture", MIX_DL1_INPUT_MM_UL2, MIX_DL1_CAPTURE, 1, 0,
+ abe_get_mixer, dl1_put_mixer),
+ SOC_SINGLE_EXT("Multimedia", MIX_DL1_INPUT_MM_DL, MIX_DL1_MEDIA, 1, 0,
+ abe_get_mixer, dl1_put_mixer),
+};
+
+/* DL2 mixer paths */
+static const struct snd_kcontrol_new dl2_mixer_controls[] = {
+ SOC_SINGLE_EXT("Tones", MIX_DL2_INPUT_TONES, MIX_DL2_TONES, 1, 0,
+ abe_get_mixer, dl2_put_mixer),
+ SOC_SINGLE_EXT("Voice", MIX_DL2_INPUT_VX_DL, MIX_DL2_VOICE, 1, 0,
+ abe_get_mixer, dl2_put_mixer),
+ SOC_SINGLE_EXT("Capture", MIX_DL2_INPUT_MM_UL2, MIX_DL2_CAPTURE, 1, 0,
+ abe_get_mixer, dl2_put_mixer),
+ SOC_SINGLE_EXT("Multimedia", MIX_DL2_INPUT_MM_DL, MIX_DL2_MEDIA, 1, 0,
+ abe_get_mixer, dl2_put_mixer),
+};
+
+/* AUDUL ("Voice Capture Mixer") mixer paths */
+static const struct snd_kcontrol_new audio_ul_mixer_controls[] = {
+ SOC_SINGLE_EXT("Tones Playback", MIX_AUDUL_INPUT_TONES, MIX_AUDUL_TONES, 1, 0,
+ abe_get_mixer, audio_ul_put_mixer),
+ SOC_SINGLE_EXT("Media Playback", MIX_AUDUL_INPUT_MM_DL, MIX_AUDUL_MEDIA, 1, 0,
+ abe_get_mixer, audio_ul_put_mixer),
+ SOC_SINGLE_EXT("Capture", MIX_AUDUL_INPUT_UPLINK, MIX_AUDUL_CAPTURE, 1, 0,
+ abe_get_mixer, audio_ul_put_mixer),
+};
+
+/* VXREC ("Capture Mixer") mixer paths */
+static const struct snd_kcontrol_new vx_rec_mixer_controls[] = {
+ SOC_SINGLE_EXT("Tones", MIX_VXREC_INPUT_TONES, MIX_VXREC_TONES, 1, 0,
+ abe_get_mixer, vxrec_put_mixer),
+ SOC_SINGLE_EXT("Voice Playback", MIX_VXREC_INPUT_VX_DL,
+ MIX_VXREC_VOICE_PLAYBACK, 1, 0, abe_get_mixer, vxrec_put_mixer),
+ SOC_SINGLE_EXT("Voice Capture", MIX_VXREC_INPUT_VX_UL,
+ MIX_VXREC_VOICE_CAPTURE, 1, 0, abe_get_mixer, vxrec_put_mixer),
+ SOC_SINGLE_EXT("Media Playback", MIX_VXREC_INPUT_MM_DL,
+ MIX_VXREC_MEDIA, 1, 0, abe_get_mixer, vxrec_put_mixer),
+};
+
+/* SDT ("Sidetone Mixer") mixer paths */
+static const struct snd_kcontrol_new sdt_mixer_controls[] = {
+ SOC_SINGLE_EXT("Capture", MIX_SDT_INPUT_UP_MIXER, MIX_SDT_CAPTURE, 1, 0,
+ abe_get_mixer, sdt_put_mixer),
+ SOC_SINGLE_EXT("Playback", MIX_SDT_INPUT_DL1_MIXER, MIX_SDT_PLAYBACK, 1, 0,
+ abe_get_mixer, sdt_put_mixer),
+};
+
+/* Virtual PDM_DL Switch */
+static const struct snd_kcontrol_new pdm_dl1_switch_controls =
+ SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_PDM_DL, 1, 0,
+ abe_get_mixer, abe_put_switch);
+
+/* Virtual BT_VX_DL Switch */
+static const struct snd_kcontrol_new bt_vx_dl_switch_controls =
+ SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_BT_VX_DL, 1, 0,
+ abe_get_mixer, abe_put_switch);
+
+/* Virtual MM_EXT_DL Switch */
+static const struct snd_kcontrol_new mm_ext_dl_switch_controls =
+ SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_MM_EXT_DL, 1, 0,
+ abe_get_mixer, abe_put_switch);
+
+static const struct snd_kcontrol_new abe_controls[] = {
+ /* DL1 mixer gains */
+ SOC_SINGLE_EXT_TLV("DL1 Media Playback Volume",
+ MIX_DL1_INPUT_MM_DL, 0, 149, 0,
+ volume_get_dl1_mixer, volume_put_dl1_mixer, mm_dl1_tlv),
+ SOC_SINGLE_EXT_TLV("DL1 Tones Playback Volume",
+ MIX_DL1_INPUT_TONES, 0, 149, 0,
+ volume_get_dl1_mixer, volume_put_dl1_mixer, tones_dl1_tlv),
+ SOC_SINGLE_EXT_TLV("DL1 Voice Playback Volume",
+ MIX_DL1_INPUT_VX_DL, 0, 149, 0,
+ volume_get_dl1_mixer, volume_put_dl1_mixer, voice_dl1_tlv),
+ SOC_SINGLE_EXT_TLV("DL1 Capture Playback Volume",
+ MIX_DL1_INPUT_MM_UL2, 0, 149, 0,
+ volume_get_dl1_mixer, volume_put_dl1_mixer, capture_dl1_tlv),
+
+ /* DL2 mixer gains */
+ SOC_SINGLE_EXT_TLV("DL2 Media Playback Volume",
+ MIX_DL2_INPUT_MM_DL, 0, 149, 0,
+ volume_get_dl2_mixer, volume_put_dl2_mixer, mm_dl2_tlv),
+ SOC_SINGLE_EXT_TLV("DL2 Tones Playback Volume",
+ MIX_DL2_INPUT_TONES, 0, 149, 0,
+ volume_get_dl2_mixer, volume_put_dl2_mixer, tones_dl2_tlv),
+ SOC_SINGLE_EXT_TLV("DL2 Voice Playback Volume",
+ MIX_DL2_INPUT_VX_DL, 0, 149, 0,
+ volume_get_dl2_mixer, volume_put_dl2_mixer, voice_dl2_tlv),
+ SOC_SINGLE_EXT_TLV("DL2 Capture Playback Volume",
+ MIX_DL2_INPUT_MM_UL2, 0, 149, 0,
+ volume_get_dl2_mixer, volume_put_dl2_mixer, capture_dl2_tlv),
+
+ /* VXREC mixer gains */
+ SOC_SINGLE_EXT_TLV("VXREC Media Volume",
+ MIX_VXREC_INPUT_MM_DL, 0, 149, 0,
+ volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_mm_dl_tlv),
+ SOC_SINGLE_EXT_TLV("VXREC Tones Volume",
+ MIX_VXREC_INPUT_TONES, 0, 149, 0,
+ volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_tones_tlv),
+ SOC_SINGLE_EXT_TLV("VXREC Voice DL Volume",
+ MIX_VXREC_INPUT_VX_UL, 0, 149, 0,
+ volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_vx_dl_tlv),
+ SOC_SINGLE_EXT_TLV("VXREC Voice UL Volume",
+ MIX_VXREC_INPUT_VX_DL, 0, 149, 0,
+ volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_vx_ul_tlv),
+
+ /* AUDUL mixer gains */
+ SOC_SINGLE_EXT_TLV("AUDUL Media Volume",
+ MIX_AUDUL_INPUT_MM_DL, 0, 149, 0,
+ volume_get_audul_mixer, volume_put_audul_mixer, audul_mm_tlv),
+ SOC_SINGLE_EXT_TLV("AUDUL Tones Volume",
+ MIX_AUDUL_INPUT_TONES, 0, 149, 0,
+ volume_get_audul_mixer, volume_put_audul_mixer, audul_tones_tlv),
+ SOC_SINGLE_EXT_TLV("AUDUL Voice UL Volume",
+ MIX_AUDUL_INPUT_UPLINK, 0, 149, 0,
+ volume_get_audul_mixer, volume_put_audul_mixer, audul_vx_ul_tlv),
+ SOC_SINGLE_EXT_TLV("AUDUL Voice DL Volume",
+ MIX_AUDUL_INPUT_VX_DL, 0, 149, 0,
+ volume_get_audul_mixer, volume_put_audul_mixer, audul_vx_dl_tlv),
+
+ /* SDT mixer gains */
+ SOC_SINGLE_EXT_TLV("SDT UL Volume",
+ MIX_SDT_INPUT_UP_MIXER, 0, 149, 0,
+ volume_get_sdt_mixer, volume_put_sdt_mixer, sdt_ul_tlv),
+ SOC_SINGLE_EXT_TLV("SDT DL Volume",
+ MIX_SDT_INPUT_DL1_MIXER, 0, 149, 0,
+ volume_get_sdt_mixer, volume_put_sdt_mixer, sdt_dl_tlv),
+
+ /* DMIC gains */
+ SOC_DOUBLE_EXT_TLV("DMIC1 UL Volume",
+ GAINS_DMIC1, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
+ volume_get_gain, volume_put_gain, dmic_tlv),
+
+ SOC_DOUBLE_EXT_TLV("DMIC2 UL Volume",
+ GAINS_DMIC2, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
+ volume_get_gain, volume_put_gain, dmic_tlv),
+
+ SOC_DOUBLE_EXT_TLV("DMIC3 UL Volume",
+ GAINS_DMIC3, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
+ volume_get_gain, volume_put_gain, dmic_tlv),
+
+ SOC_DOUBLE_EXT_TLV("AMIC UL Volume",
+ GAINS_AMIC, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
+ volume_get_gain, volume_put_gain, amic_tlv),
+
+ SOC_DOUBLE_EXT_TLV("BT UL Volume",
+ GAINS_BTUL, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
+ volume_get_gain, volume_put_gain, btul_tlv),
+
+ SOC_SINGLE_EXT("DL1 Mono Mixer", MIXDL1, MIX_DL1_MONO, 1, 0,
+ abe_get_mono_mixer, abe_put_mono_mixer),
+ SOC_SINGLE_EXT("DL2 Mono Mixer", MIXDL2, MIX_DL2_MONO, 1, 0,
+ abe_get_mono_mixer, abe_put_mono_mixer),
+ SOC_SINGLE_EXT("AUDUL Mono Mixer", MIXAUDUL, MIX_AUDUL_MONO, 1, 0,
+ abe_get_mono_mixer, abe_put_mono_mixer),
+};
+
+static const struct snd_soc_dapm_widget abe_dapm_widgets[] = {
+
+ /* Frontend AIFs */
+ SND_SOC_DAPM_AIF_IN("TONES_DL", "Tones Playback", 0,
+ W_AIF_TONES_DL, ABE_OPP_25, 0),
+ SND_SOC_DAPM_AIF_IN("VX_DL", "Voice Playback", 0,
+ W_AIF_VX_DL, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_OUT("VX_UL", "Voice Capture", 0,
+ W_AIF_VX_UL, ABE_OPP_50, 0),
+ /* the MM_UL mapping is intentional */
+ SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0,
+ W_AIF_MM_UL1, ABE_OPP_100, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0,
+ W_AIF_MM_UL2, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL", " MultiMedia1 Playback", 0,
+ W_AIF_MM_DL, ABE_OPP_25, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL_LP", " MultiMedia1 LP Playback", 0,
+ W_AIF_MM_DL_LP, ABE_OPP_25, 0),
+ SND_SOC_DAPM_AIF_IN("VIB_DL", "Vibra Playback", 0,
+ W_AIF_VIB_DL, ABE_OPP_100, 0),
+ SND_SOC_DAPM_AIF_IN("MODEM_DL", "MODEM Playback", 0,
+ W_AIF_MODEM_DL, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_OUT("MODEM_UL", "MODEM Capture", 0,
+ W_AIF_MODEM_UL, ABE_OPP_50, 0),
+
+ /* Backend DAIs */
+ SND_SOC_DAPM_AIF_IN("PDM_UL1", "Analog Capture", 0,
+ W_AIF_PDM_UL1, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_OUT("PDM_DL1", "HS Playback", 0,
+ W_AIF_PDM_DL1, ABE_OPP_25, 0),
+ SND_SOC_DAPM_AIF_OUT("PDM_DL2", "HF Playback", 0,
+ W_AIF_PDM_DL2, ABE_OPP_100, 0),
+ SND_SOC_DAPM_AIF_OUT("PDM_VIB", "Vibra Playback", 0,
+ W_AIF_PDM_VIB, ABE_OPP_100, 0),
+ SND_SOC_DAPM_AIF_IN("BT_VX_UL", "BT Capture", 0,
+ W_AIF_BT_VX_UL, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_OUT("BT_VX_DL", "BT Playback", 0,
+ W_AIF_BT_VX_DL, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_IN("MM_EXT_UL", "FM Capture", 0,
+ W_AIF_MM_EXT_UL, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_EXT_DL", "FM Playback", 0,
+ W_AIF_MM_EXT_DL, ABE_OPP_25, 0),
+ SND_SOC_DAPM_AIF_IN("DMIC0", "DMIC0 Capture", 0,
+ W_AIF_DMIC0, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_IN("DMIC1", "DMIC1 Capture", 0,
+ W_AIF_DMIC1, ABE_OPP_50, 0),
+ SND_SOC_DAPM_AIF_IN("DMIC2", "DMIC2 Capture", 0,
+ W_AIF_DMIC2, ABE_OPP_50, 0),
+
+ /* ROUTE_UL Capture Muxes */
+ SND_SOC_DAPM_MUX("MUX_UL00",
+ W_MUX_UL00, ABE_OPP_50, 0, &mm_ul00_control),
+ SND_SOC_DAPM_MUX("MUX_UL01",
+ W_MUX_UL01, ABE_OPP_50, 0, &mm_ul01_control),
+ SND_SOC_DAPM_MUX("MUX_UL02",
+ W_MUX_UL02, ABE_OPP_50, 0, &mm_ul02_control),
+ SND_SOC_DAPM_MUX("MUX_UL03",
+ W_MUX_UL03, ABE_OPP_50, 0, &mm_ul03_control),
+ SND_SOC_DAPM_MUX("MUX_UL04",
+ W_MUX_UL04, ABE_OPP_50, 0, &mm_ul04_control),
+ SND_SOC_DAPM_MUX("MUX_UL05",
+ W_MUX_UL05, ABE_OPP_50, 0, &mm_ul05_control),
+ SND_SOC_DAPM_MUX("MUX_UL06",
+ W_MUX_UL06, ABE_OPP_50, 0, &mm_ul06_control),
+ SND_SOC_DAPM_MUX("MUX_UL07",
+ W_MUX_UL07, ABE_OPP_50, 0, &mm_ul07_control),
+ SND_SOC_DAPM_MUX("MUX_UL10",
+ W_MUX_UL10, ABE_OPP_50, 0, &mm_ul10_control),
+ SND_SOC_DAPM_MUX("MUX_UL11",
+ W_MUX_UL11, ABE_OPP_50, 0, &mm_ul11_control),
+ SND_SOC_DAPM_MUX("MUX_VX0",
+ W_MUX_VX00, ABE_OPP_50, 0, &mm_vx0_control),
+ SND_SOC_DAPM_MUX("MUX_VX1",
+ W_MUX_VX01, ABE_OPP_50, 0, &mm_vx1_control),
+
+ /* DL1 & DL2 Playback Mixers */
+ SND_SOC_DAPM_MIXER("DL1 Mixer",
+ W_MIXER_DL1, ABE_OPP_25, 0, dl1_mixer_controls,
+ ARRAY_SIZE(dl1_mixer_controls)),
+ SND_SOC_DAPM_MIXER("DL2 Mixer",
+ W_MIXER_DL2, ABE_OPP_100, 0, dl2_mixer_controls,
+ ARRAY_SIZE(dl2_mixer_controls)),
+
+ /* DL1 Mixer Input volumes ?????*/
+ SND_SOC_DAPM_PGA("DL1 Media Volume",
+ W_VOLUME_DL1, 0, 0, NULL, 0),
+
+ /* AUDIO_UL_MIXER */
+ SND_SOC_DAPM_MIXER("Voice Capture Mixer",
+ W_MIXER_AUDIO_UL, ABE_OPP_50, 0, audio_ul_mixer_controls,
+ ARRAY_SIZE(audio_ul_mixer_controls)),
+
+ /* VX_REC_MIXER */
+ SND_SOC_DAPM_MIXER("Capture Mixer",
+ W_MIXER_VX_REC, ABE_OPP_50, 0, vx_rec_mixer_controls,
+ ARRAY_SIZE(vx_rec_mixer_controls)),
+
+ /* SDT_MIXER - TODO: shoult this not be OPP25 ??? */
+ SND_SOC_DAPM_MIXER("Sidetone Mixer",
+ W_MIXER_SDT, ABE_OPP_25, 0, sdt_mixer_controls,
+ ARRAY_SIZE(sdt_mixer_controls)),
+
+ /*
+ * The Following three are virtual switches to select the output port
+ * after DL1 Gain.
+ */
+
+ /* Virtual PDM_DL1 Switch */
+ SND_SOC_DAPM_MIXER("DL1 PDM",
+ W_VSWITCH_DL1_PDM, ABE_OPP_25, 0, &pdm_dl1_switch_controls, 1),
+
+ /* Virtual BT_VX_DL Switch */
+ SND_SOC_DAPM_MIXER("DL1 BT_VX",
+ W_VSWITCH_DL1_BT_VX, ABE_OPP_50, 0, &bt_vx_dl_switch_controls, 1),
+
+ /* Virtual MM_EXT_DL Switch TODO: confrm OPP level here */
+ SND_SOC_DAPM_MIXER("DL1 MM_EXT",
+ W_VSWITCH_DL1_MM_EXT, ABE_OPP_50, 0, &mm_ext_dl_switch_controls, 1),
+
+ /* Virtuals to join our capture sources */
+ SND_SOC_DAPM_MIXER("Sidetone Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Voice Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("DL1 Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("DL2 Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Join our MM_DL and MM_DL_LP playback */
+ SND_SOC_DAPM_MIXER("MM_DL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Virtual MODEM and VX_UL mixer */
+ SND_SOC_DAPM_MIXER("VX UL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("VX DL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Virtual Pins to force backends ON atm */
+ SND_SOC_DAPM_OUTPUT("BE_OUT"),
+ SND_SOC_DAPM_INPUT("BE_IN"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+
+ /* MUX_UL00 - ROUTE_UL - Chan 0 */
+ {"MUX_UL00", "DMic0L", "DMIC0"},
+ {"MUX_UL00", "DMic0R", "DMIC0"},
+ {"MUX_UL00", "DMic1L", "DMIC1"},
+ {"MUX_UL00", "DMic1R", "DMIC1"},
+ {"MUX_UL00", "DMic2L", "DMIC2"},
+ {"MUX_UL00", "DMic2R", "DMIC2"},
+ {"MUX_UL00", "BT Left", "BT_VX_UL"},
+ {"MUX_UL00", "BT Right", "BT_VX_UL"},
+ {"MUX_UL00", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL00", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL00", "AMic0", "PDM_UL1"},
+ {"MUX_UL00", "AMic1", "PDM_UL1"},
+ {"MUX_UL00", "VX Left", "Capture Mixer"},
+ {"MUX_UL00", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL00"},
+
+ /* MUX_UL01 - ROUTE_UL - Chan 1 */
+ {"MUX_UL01", "DMic0L", "DMIC0"},
+ {"MUX_UL01", "DMic0R", "DMIC0"},
+ {"MUX_UL01", "DMic1L", "DMIC1"},
+ {"MUX_UL01", "DMic1R", "DMIC1"},
+ {"MUX_UL01", "DMic2L", "DMIC2"},
+ {"MUX_UL01", "DMic2R", "DMIC2"},
+ {"MUX_UL01", "BT Left", "BT_VX_UL"},
+ {"MUX_UL01", "BT Right", "BT_VX_UL"},
+ {"MUX_UL01", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL01", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL01", "AMic0", "PDM_UL1"},
+ {"MUX_UL01", "AMic1", "PDM_UL1"},
+ {"MUX_UL01", "VX Left", "Capture Mixer"},
+ {"MUX_UL01", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL01"},
+
+ /* MUX_UL02 - ROUTE_UL - Chan 2 */
+ {"MUX_UL02", "DMic0L", "DMIC0"},
+ {"MUX_UL02", "DMic0R", "DMIC0"},
+ {"MUX_UL02", "DMic1L", "DMIC1"},
+ {"MUX_UL02", "DMic1R", "DMIC1"},
+ {"MUX_UL02", "DMic2L", "DMIC2"},
+ {"MUX_UL02", "DMic2R", "DMIC2"},
+ {"MUX_UL02", "BT Left", "BT_VX_UL"},
+ {"MUX_UL02", "BT Right", "BT_VX_UL"},
+ {"MUX_UL02", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL02", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL02", "AMic0", "PDM_UL1"},
+ {"MUX_UL02", "AMic1", "PDM_UL1"},
+ {"MUX_UL02", "VX Left", "Capture Mixer"},
+ {"MUX_UL02", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL02"},
+
+ /* MUX_UL03 - ROUTE_UL - Chan 3 */
+ {"MUX_UL03", "DMic0L", "DMIC0"},
+ {"MUX_UL03", "DMic0R", "DMIC0"},
+ {"MUX_UL03", "DMic1L", "DMIC1"},
+ {"MUX_UL03", "DMic1R", "DMIC1"},
+ {"MUX_UL03", "DMic2L", "DMIC2"},
+ {"MUX_UL03", "DMic2R", "DMIC2"},
+ {"MUX_UL03", "BT Left", "BT_VX_UL"},
+ {"MUX_UL03", "BT Right", "BT_VX_UL"},
+ {"MUX_UL03", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL03", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL03", "AMic0", "PDM_UL1"},
+ {"MUX_UL03", "AMic1", "PDM_UL1"},
+ {"MUX_UL03", "VX Left", "Capture Mixer"},
+ {"MUX_UL03", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL03"},
+
+ /* MUX_UL04 - ROUTE_UL - Chan 4 */
+ {"MUX_UL04", "DMic0L", "DMIC0"},
+ {"MUX_UL04", "DMic0R", "DMIC0"},
+ {"MUX_UL04", "DMic1L", "DMIC1"},
+ {"MUX_UL04", "DMic1R", "DMIC1"},
+ {"MUX_UL04", "DMic2L", "DMIC2"},
+ {"MUX_UL04", "DMic2R", "DMIC2"},
+ {"MUX_UL04", "BT Left", "BT_VX_UL"},
+ {"MUX_UL04", "BT Right", "BT_VX_UL"},
+ {"MUX_UL04", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL04", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL04", "AMic0", "PDM_UL1"},
+ {"MUX_UL04", "AMic1", "PDM_UL1"},
+ {"MUX_UL04", "VX Left", "Capture Mixer"},
+ {"MUX_UL04", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL04"},
+
+ /* MUX_UL05 - ROUTE_UL - Chan 5 */
+ {"MUX_UL05", "DMic0L", "DMIC0"},
+ {"MUX_UL05", "DMic0R", "DMIC0"},
+ {"MUX_UL05", "DMic1L", "DMIC1"},
+ {"MUX_UL05", "DMic1R", "DMIC1"},
+ {"MUX_UL05", "DMic2L", "DMIC2"},
+ {"MUX_UL05", "DMic2R", "DMIC2"},
+ {"MUX_UL05", "BT Left", "BT_VX_UL"},
+ {"MUX_UL05", "BT Right", "BT_VX_UL"},
+ {"MUX_UL05", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL05", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL05", "AMic0", "PDM_UL1"},
+ {"MUX_UL05", "AMic1", "PDM_UL1"},
+ {"MUX_UL05", "VX Left", "Capture Mixer"},
+ {"MUX_UL05", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL05"},
+
+ /* MUX_UL06 - ROUTE_UL - Chan 6 */
+ {"MUX_UL06", "DMic0L", "DMIC0"},
+ {"MUX_UL06", "DMic0R", "DMIC0"},
+ {"MUX_UL06", "DMic1L", "DMIC1"},
+ {"MUX_UL06", "DMic1R", "DMIC1"},
+ {"MUX_UL06", "DMic2L", "DMIC2"},
+ {"MUX_UL06", "DMic2R", "DMIC2"},
+ {"MUX_UL06", "BT Left", "BT_VX_UL"},
+ {"MUX_UL06", "BT Right", "BT_VX_UL"},
+ {"MUX_UL06", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL06", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL06", "AMic0", "PDM_UL1"},
+ {"MUX_UL06", "AMic1", "PDM_UL1"},
+ {"MUX_UL06", "VX Left", "Capture Mixer"},
+ {"MUX_UL06", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL06"},
+
+ /* MUX_UL07 - ROUTE_UL - Chan 7 */
+ {"MUX_UL07", "DMic0L", "DMIC0"},
+ {"MUX_UL07", "DMic0R", "DMIC0"},
+ {"MUX_UL07", "DMic1L", "DMIC1"},
+ {"MUX_UL07", "DMic1R", "DMIC1"},
+ {"MUX_UL07", "DMic2L", "DMIC2"},
+ {"MUX_UL07", "DMic2R", "DMIC2"},
+ {"MUX_UL07", "BT Left", "BT_VX_UL"},
+ {"MUX_UL07", "BT Right", "BT_VX_UL"},
+ {"MUX_UL07", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL07", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL07", "AMic0", "PDM_UL1"},
+ {"MUX_UL07", "AMic1", "PDM_UL1"},
+ {"MUX_UL07", "VX Left", "Capture Mixer"},
+ {"MUX_UL07", "VX Right", "Capture Mixer"},
+ {"MM_UL1", NULL, "MUX_UL07"},
+
+ /* MUX_UL10 - ROUTE_UL - Chan 10 */
+ {"MUX_UL10", "DMic0L", "DMIC0"},
+ {"MUX_UL10", "DMic0R", "DMIC0"},
+ {"MUX_UL10", "DMic1L", "DMIC1"},
+ {"MUX_UL10", "DMic1R", "DMIC1"},
+ {"MUX_UL10", "DMic2L", "DMIC2"},
+ {"MUX_UL10", "DMic2R", "DMIC2"},
+ {"MUX_UL10", "BT Left", "BT_VX_UL"},
+ {"MUX_UL10", "BT Right", "BT_VX_UL"},
+ {"MUX_UL10", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL10", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL10", "AMic0", "PDM_UL1"},
+ {"MUX_UL10", "AMic1", "PDM_UL1"},
+ {"MUX_UL10", "VX Left", "Capture Mixer"},
+ {"MUX_UL10", "VX Right", "Capture Mixer"},
+ {"MM_UL2", NULL, "MUX_UL10"},
+
+ /* MUX_UL11 - ROUTE_UL - Chan 11 */
+ {"MUX_UL11", "DMic0L", "DMIC0"},
+ {"MUX_UL11", "DMic0R", "DMIC0"},
+ {"MUX_UL11", "DMic1L", "DMIC1"},
+ {"MUX_UL11", "DMic1R", "DMIC1"},
+ {"MUX_UL11", "DMic2L", "DMIC2"},
+ {"MUX_UL11", "DMic2R", "DMIC2"},
+ {"MUX_UL11", "BT Left", "BT_VX_UL"},
+ {"MUX_UL11", "BT Right", "BT_VX_UL"},
+ {"MUX_UL11", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_UL11", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_UL11", "AMic0", "PDM_UL1"},
+ {"MUX_UL11", "AMic1", "PDM_UL1"},
+ {"MUX_UL11", "VX Left", "Capture Mixer"},
+ {"MUX_UL11", "VX Right", "Capture Mixer"},
+ {"MM_UL2", NULL, "MUX_UL11"},
+
+ /* MUX_VX0 - ROUTE_UL - Chan 20 */
+ {"MUX_VX0", "DMic0L", "DMIC0"},
+ {"MUX_VX0", "DMic0R", "DMIC0"},
+ {"MUX_VX0", "DMic1L", "DMIC1"},
+ {"MUX_VX0", "DMic1R", "DMIC1"},
+ {"MUX_VX0", "DMic2L", "DMIC2"},
+ {"MUX_VX0", "DMic2R", "DMIC2"},
+ {"MUX_VX0", "BT Left", "BT_VX_UL"},
+ {"MUX_VX0", "BT Right", "BT_VX_UL"},
+ {"MUX_VX0", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_VX0", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_VX0", "AMic0", "PDM_UL1"},
+ {"MUX_VX0", "AMic1", "PDM_UL1"},
+ {"MUX_VX0", "VX Left", "Capture Mixer"},
+ {"MUX_VX0", "VX Right", "Capture Mixer"},
+
+ /* MUX_VX1 - ROUTE_UL - Chan 20 */
+ {"MUX_VX1", "DMic0L", "DMIC0"},
+ {"MUX_VX1", "DMic0R", "DMIC0"},
+ {"MUX_VX1", "DMic1L", "DMIC1"},
+ {"MUX_VX1", "DMic1R", "DMIC1"},
+ {"MUX_VX1", "DMic2L", "DMIC2"},
+ {"MUX_VX1", "DMic2R", "DMIC2"},
+ {"MUX_VX1", "BT Left", "BT_VX_UL"},
+ {"MUX_VX1", "BT Right", "BT_VX_UL"},
+ {"MUX_VX1", "MMExt Left", "MM_EXT_UL"},
+ {"MUX_VX1", "MMExt Right", "MM_EXT_UL"},
+ {"MUX_VX1", "AMic0", "PDM_UL1"},
+ {"MUX_VX1", "AMic1", "PDM_UL1"},
+ {"MUX_VX1", "VX Left", "Capture Mixer"},
+ {"MUX_VX1", "VX Right", "Capture Mixer"},
+
+ /* Headset (DL1) playback path */
+ {"DL1 Mixer", "Tones", "TONES_DL"},
+ {"DL1 Mixer", "Voice", "VX DL VMixer"},
+ {"DL1 Mixer", "Capture", "DL1 Capture VMixer"},
+ {"DL1 Capture VMixer", NULL, "MUX_UL10"},
+ {"DL1 Capture VMixer", NULL, "MUX_UL11"},
+ {"DL1 Mixer", "Multimedia", "MM_DL VMixer"},
+ {"MM_DL VMixer", NULL, "MM_DL"},
+ {"MM_DL VMixer", NULL, "MM_DL_LP"},
+
+ /* Sidetone Mixer */
+ {"Sidetone Mixer", "Playback", "DL1 Mixer"},
+ {"Sidetone Mixer", "Capture", "Sidetone Capture VMixer"},
+ {"Sidetone Capture VMixer", NULL, "MUX_VX0"},
+ {"Sidetone Capture VMixer", NULL, "MUX_VX1"},
+
+ /* Playback Output selection after DL1 Gain */
+ {"DL1 BT_VX", "Switch", "Sidetone Mixer"},
+ {"DL1 MM_EXT", "Switch", "Sidetone Mixer"},
+ {"DL1 PDM", "Switch", "Sidetone Mixer"},
+ {"PDM_DL1", NULL, "DL1 PDM"},
+ {"BT_VX_DL", NULL, "DL1 BT_VX"},
+ {"MM_EXT_DL", NULL, "DL1 MM_EXT"},
+
+ /* Handsfree (DL2) playback path */
+ {"DL2 Mixer", "Tones", "TONES_DL"},
+ {"DL2 Mixer", "Voice", "VX DL VMixer"},
+ {"DL2 Mixer", "Capture", "DL2 Capture VMixer"},
+ {"DL2 Capture VMixer", NULL, "MUX_UL10"},
+ {"DL2 Capture VMixer", NULL, "MUX_UL11"},
+ {"DL2 Mixer", "Multimedia", "MM_DL VMixer"},
+ {"MM_DL VMixer", NULL, "MM_DL"},
+ {"MM_DL VMixer", NULL, "MM_DL_LP"},
+ {"PDM_DL2", NULL, "DL2 Mixer"},
+
+ /* VxREC Mixer */
+ {"Capture Mixer", "Tones", "TONES_DL"},
+ {"Capture Mixer", "Voice Playback", "VX DL VMixer"},
+ {"Capture Mixer", "Voice Capture", "VX UL VMixer"},
+ {"Capture Mixer", "Media Playback", "MM_DL VMixer"},
+ {"MM_DL VMixer", NULL, "MM_DL"},
+ {"MM_DL VMixer", NULL, "MM_DL_LP"},
+
+ /* Audio UL mixer */
+ {"Voice Capture Mixer", "Tones Playback", "TONES_DL"},
+ {"Voice Capture Mixer", "Media Playback", "MM_DL VMixer"},
+ {"MM_DL VMixer", NULL, "MM_DL"},
+ {"MM_DL VMixer", NULL, "MM_DL_LP"},
+ {"Voice Capture Mixer", "Capture", "Voice Capture VMixer"},
+ {"Voice Capture VMixer", NULL, "MUX_VX0"},
+ {"Voice Capture VMixer", NULL, "MUX_VX1"},
+
+ /* BT */
+ {"VX UL VMixer", NULL, "Voice Capture Mixer"},
+
+ /* Vibra */
+ {"PDM_VIB", NULL, "VIB_DL"},
+
+ /* VX and MODEM */
+ {"VX_UL", NULL, "VX UL VMixer"},
+ {"MODEM_UL", NULL, "VX UL VMixer"},
+ {"VX DL VMixer", NULL, "VX_DL"},
+ {"VX DL VMixer", NULL, "MODEM_DL"},
+
+ /* Backend Enablement - TODO: maybe re-work*/
+ {"BE_OUT", NULL, "PDM_DL1"},
+ {"BE_OUT", NULL, "PDM_DL2"},
+ {"BE_OUT", NULL, "PDM_VIB"},
+ {"BE_OUT", NULL, "MM_EXT_DL"},
+ {"BE_OUT", NULL, "BT_VX_DL"},
+ {"PDM_UL1", NULL, "BE_IN"},
+ {"BT_VX_UL", NULL, "BE_IN"},
+ {"MM_EXT_UL", NULL, "BE_IN"},
+ {"DMIC0", NULL, "BE_IN"},
+ {"DMIC1", NULL, "BE_IN"},
+ {"DMIC2", NULL, "BE_IN"},
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static int abe_dbg_get_dma_pos(struct abe_data *abe)
+{
+ return omap_get_dma_dst_pos(abe->dma_ch) - abe->dbg_buffer_addr;
+}
+
+static void abe_dbg_dma_irq(int ch, u16 stat, void *data)
+{
+}
+
+static int abe_dbg_start_dma(struct abe_data *abe, int circular)
+{
+ struct omap_dma_channel_params dma_params;
+ int err;
+
+ /* TODO: start the DMA in either :-
+ *
+ * 1) circular buffer mode where the DMA will restart when it get to
+ * the end of the buffer.
+ * 2) default mode, where DMA stops at the end of the buffer.
+ */
+
+ abe->dma_req = OMAP44XX_DMA_ABE_REQ_7;
+ err = omap_request_dma(abe->dma_req, "ABE debug",
+ abe_dbg_dma_irq, abe, &abe->dma_ch);
+ if (abe->dbg_circular) {
+ /*
+ * Link channel with itself so DMA doesn't need any
+ * reprogramming while looping the buffer
+ */
+ omap_dma_link_lch(abe->dma_ch, abe->dma_ch);
+ }
+
+ memset(&dma_params, 0, sizeof(dma_params));
+ dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+ dma_params.trigger = abe->dma_req;
+ dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
+ dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
+ dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
+ dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
+ dma_params.src_start = D_DEBUG_FIFO_ADDR + ABE_DMEM_BASE_ADDRESS_L3;
+ dma_params.dst_start = abe->dbg_buffer_addr;
+ dma_params.src_port = OMAP_DMA_PORT_MPUI;
+ dma_params.src_ei = 1;
+ dma_params.src_fi = 1 - abe->dbg_elem_bytes;
+
+ dma_params.elem_count = abe->dbg_elem_bytes >> 2; /* 128 bytes shifted into words */
+ dma_params.frame_count = abe->dbg_buffer_bytes / abe->dbg_elem_bytes;
+ omap_set_dma_params(abe->dma_ch, &dma_params);
+
+ omap_enable_dma_irq(abe->dma_ch, OMAP_DMA_FRAME_IRQ);
+ omap_set_dma_src_burst_mode(abe->dma_ch, OMAP_DMA_DATA_BURST_16);
+ omap_set_dma_dest_burst_mode(abe->dma_ch, OMAP_DMA_DATA_BURST_16);
+
+ abe->dbg_reader_offset = 0;
+
+ pm_runtime_get_sync(abe->dev);
+ omap_start_dma(abe->dma_ch);
+ return 0;
+}
+
+static void abe_dbg_stop_dma(struct abe_data *abe)
+{
+ while (omap_get_dma_active_status(abe->dma_ch))
+ omap_stop_dma(abe->dma_ch);
+
+ if (abe->dbg_circular)
+ omap_dma_unlink_lch(abe->dma_ch, abe->dma_ch);
+ omap_free_dma(abe->dma_ch);
+ pm_runtime_put_sync(abe->dev);
+}
+
+static int abe_open_data(struct inode *inode, struct file *file)
+{
+ struct abe_data *abe = inode->i_private;
+
+ abe->dbg_elem_bytes = 128; /* size of debug data per tick */
+
+ if (abe->dbg_format1)
+ abe->dbg_elem_bytes += ABE_DBG_FLAG1_SIZE;
+ if (abe->dbg_format2)
+ abe->dbg_elem_bytes += ABE_DBG_FLAG2_SIZE;
+ if (abe->dbg_format3)
+ abe->dbg_elem_bytes += ABE_DBG_FLAG3_SIZE;
+
+ abe->dbg_buffer_bytes = abe->dbg_elem_bytes * 4 *
+ abe->dbg_buffer_msecs;
+
+ abe->dbg_buffer = dma_alloc_writecombine(abe->dev,
+ abe->dbg_buffer_bytes, &abe->dbg_buffer_addr, GFP_KERNEL);
+ if (abe->dbg_buffer == NULL)
+ return -ENOMEM;
+
+ file->private_data = inode->i_private;
+ abe->dbg_complete = 0;
+ abe_dbg_start_dma(abe, abe->dbg_circular);
+
+ return 0;
+}
+
+static int abe_release_data(struct inode *inode, struct file *file)
+{
+ struct abe_data *abe = inode->i_private;
+
+ abe_dbg_stop_dma(abe);
+
+ dma_free_writecombine(abe->dev, abe->dbg_buffer_bytes,
+ abe->dbg_buffer, abe->dbg_buffer_addr);
+ return 0;
+}
+
+static ssize_t abe_copy_to_user(struct abe_data *abe, char __user *user_buf,
+ size_t count)
+{
+ /* check for reader buffer wrap */
+ if (abe->dbg_reader_offset + count > abe->dbg_buffer_bytes) {
+ int size = abe->dbg_buffer_bytes - abe->dbg_reader_offset;
+
+ /* wrap */
+ if (copy_to_user(user_buf,
+ abe->dbg_buffer + abe->dbg_reader_offset, size))
+ return -EFAULT;
+
+ /* need to just return if non circular */
+ if (!abe->dbg_circular) {
+ abe->dbg_complete = 1;
+ return count;
+ }
+
+ if (copy_to_user(user_buf,
+ abe->dbg_buffer, count - size))
+ return -EFAULT;
+ abe->dbg_reader_offset = count - size;
+ return count;
+ } else {
+ /* no wrap */
+ if (copy_to_user(user_buf,
+ abe->dbg_buffer + abe->dbg_reader_offset, count))
+ return -EFAULT;
+ abe->dbg_reader_offset += count;
+
+ if (!abe->dbg_circular &&
+ abe->dbg_reader_offset == abe->dbg_buffer_bytes)
+ abe->dbg_complete = 1;
+
+ return count;
+ }
+}
+
+static ssize_t abe_read_data(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret = 0;
+ struct abe_data *abe = file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
+ int dma_offset, bytes;
+
+ add_wait_queue(&abe->wait, &wait);
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* TODO: Check if really needed. Or adjust sleep delay
+ * If not delay trace is not working */
+ msleep_interruptible(1);
+ dma_offset = abe_dbg_get_dma_pos(abe);
+
+ /* is DMA finished ? */
+ if (abe->dbg_complete)
+ break;
+
+ /* get maximum amount of debug bytes we can read */
+ if (dma_offset >= abe->dbg_reader_offset) {
+ /* dma ptr is ahead of reader */
+ bytes = dma_offset - abe->dbg_reader_offset;
+ } else {
+ /* dma ptr is behind reader */
+ bytes = dma_offset + abe->dbg_buffer_bytes -
+ abe->dbg_reader_offset;
+ }
+
+ if (count > bytes)
+ count = bytes;
+
+ if (count > 0) {
+ ret = abe_copy_to_user(abe, user_buf, count);
+ break;
+ }
+
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ schedule();
+
+ } while (1);
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&abe->wait, &wait);
+
+ return ret;
+}
+
+static const struct file_operations abe_data_fops = {
+ .open = abe_open_data,
+ .read = abe_read_data,
+ .release = abe_release_data,
+};
+
+static void abe_init_debugfs(struct abe_data *abe)
+{
+ abe->debugfs_root = debugfs_create_dir("omap4-abe", NULL);
+ if (!abe->debugfs_root) {
+ printk(KERN_WARNING "ABE: Failed to create debugfs directory\n");
+ return;
+ }
+
+ abe->debugfs_fmt1 = debugfs_create_bool("format1", 0644,
+ abe->debugfs_root,
+ &abe->dbg_format1);
+ if (!abe->debugfs_fmt1)
+ printk(KERN_WARNING "ABE: Failed to create format1 debugfs file\n");
+
+ abe->debugfs_fmt2 = debugfs_create_bool("format2", 0644,
+ abe->debugfs_root,
+ &abe->dbg_format2);
+ if (!abe->debugfs_fmt2)
+ printk(KERN_WARNING "ABE: Failed to create format2 debugfs file\n");
+
+ abe->debugfs_fmt3 = debugfs_create_bool("format3", 0644,
+ abe->debugfs_root,
+ &abe->dbg_format3);
+ if (!abe->debugfs_fmt3)
+ printk(KERN_WARNING "ABE: Failed to create format3 debugfs file\n");
+
+ abe->debugfs_elem_bytes = debugfs_create_u32("element_bytes", 0604,
+ abe->debugfs_root,
+ &abe->dbg_elem_bytes);
+ if (!abe->debugfs_elem_bytes)
+ printk(KERN_WARNING "ABE: Failed to create element size debugfs file\n");
+
+ abe->debugfs_size = debugfs_create_u32("msecs", 0644,
+ abe->debugfs_root,
+ &abe->dbg_buffer_msecs);
+ if (!abe->debugfs_size)
+ printk(KERN_WARNING "ABE: Failed to create buffer size debugfs file\n");
+
+ abe->debugfs_circ = debugfs_create_bool("circular", 0644,
+ abe->debugfs_root,
+ &abe->dbg_circular);
+ if (!abe->debugfs_size)
+ printk(KERN_WARNING "ABE: Failed to create circular mode debugfs file\n");
+
+ abe->debugfs_data = debugfs_create_file("debug", 0644,
+ abe->debugfs_root,
+ abe, &abe_data_fops);
+ if (!abe->debugfs_data)
+ printk(KERN_WARNING "ABE: Failed to create data debugfs file\n");
+
+ abe->debugfs_opp_level = debugfs_create_u32("opp_level", 0604,
+ abe->debugfs_root,
+ &abe->opp);
+ if (!abe->debugfs_opp_level)
+ printk(KERN_WARNING "ABE: Failed to create OPP level debugfs file\n");
+
+ abe->dbg_buffer_msecs = 500;
+ init_waitqueue_head(&abe->wait);
+}
+
+static void abe_cleanup_debugfs(struct abe_data *abe)
+{
+ debugfs_remove_recursive(abe->debugfs_root);
+}
+
+#else
+
+static inline void abe_init_debugfs(struct abe_data *abe)
+{
+}
+
+static inline void abe_cleanup_debugfs(struct abe_data *abe)
+{
+}
+#endif
+
+static const struct snd_pcm_hardware omap_abe_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .period_bytes_min = 4 * 1024,
+ .period_bytes_max = 24 * 1024,
+ .periods_min = 4,
+ .periods_max = 4,
+ .buffer_bytes_max = 24 * 1024 * 2,
+};
+
+static struct abe_opp_req *abe_opp_req_lookup(struct abe_data *abe,
+ struct device *dev)
+{
+ struct abe_opp_req *req, *tmp_req;
+
+ req = NULL;
+ list_for_each_entry(tmp_req, &abe->opp_req, node) {
+ if (tmp_req->dev == dev) {
+ req = tmp_req;
+ break;
+ }
+ }
+
+ return req;
+}
+
+static int abe_get_opp_req(struct abe_data *abe)
+{
+ struct abe_opp_req *req;
+ int opp = 0;
+
+ list_for_each_entry(req, &abe->opp_req, node)
+ opp |= req->opp;
+
+ opp = (1 << (fls(opp) - 1)) * 25;
+
+ return opp;
+}
+
+int abe_add_opp_req(struct device *dev, int opp)
+{
+ struct abe_opp_req *req;
+ int ret = 0;
+
+ mutex_lock(&the_abe->opp_req_mutex);
+
+ req = abe_opp_req_lookup(the_abe, dev);
+ if (!req) {
+ req = kzalloc(sizeof(struct abe_opp_req), GFP_KERNEL);
+ if (!req) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ req->dev = dev;
+ /* use the same convention as ABE DSP DAPM */
+ req->opp = 1 << opp;
+ list_add(&req->node, &the_abe->opp_req);
+ the_abe->opp_req_count++;
+ } else {
+ req->opp = opp;
+ }
+
+ aess_set_runtime_opp_level(the_abe);
+
+out:
+ mutex_unlock(&the_abe->opp_req_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(abe_add_opp_req);
+
+int abe_remove_opp_req(struct device *dev)
+{
+ struct abe_opp_req *req;
+ int ret = 0;
+
+ mutex_lock(&the_abe->opp_req_mutex);
+
+ req = abe_opp_req_lookup(the_abe, dev);
+ if (!req) {
+ dev_err(dev, "trying to remove an invalid opp req\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ list_del(&req->node);
+ the_abe->opp_req_count--;
+ kfree(req);
+
+ aess_set_runtime_opp_level(the_abe);
+
+out:
+ mutex_unlock(&the_abe->opp_req_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(abe_remove_opp_req);
+
+static int abe_set_opp_mode(struct abe_data *abe, int opp)
+{
+ struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
+ int ret = 0;
+
+ if (abe->opp > opp) {
+ /* Decrease OPP mode - no need of OPP100% */
+ switch (opp) {
+ case 25:
+ abe_set_opp_processing(ABE_OPP25);
+ udelay(250);
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP25]);
+ if (ret)
+ goto err_scale;
+ }
+ break;
+ case 50:
+ default:
+ abe_set_opp_processing(ABE_OPP50);
+ udelay(250);
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP50]);
+ if (ret)
+ goto err_scale;
+ }
+ break;
+ }
+ } else if (abe->opp < opp) {
+ /* Increase OPP mode */
+ switch (opp) {
+ case 25:
+ if (pdata && pdata->device_scale) {
+ pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP25]);
+ if (ret)
+ goto err_scale;
+ }
+ abe_set_opp_processing(ABE_OPP25);
+ break;
+ case 50:
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP50]);
+ if (ret)
+ goto err_scale;
+ }
+ abe_set_opp_processing(ABE_OPP50);
+ break;
+ case 100:
+ default:
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP100]);
+ if (ret)
+ goto err_scale;
+ }
+ abe_set_opp_processing(ABE_OPP100);
+ break;
+ }
+ }
+ abe->opp = opp;
+ dev_dbg(abe->dev, "new OPP level is %d\n", opp);
+
+ return 0;
+
+err_scale:
+ dev_err(abe->dev, "failed to scale to OPP%d\n", opp);
+ return ret;
+}
+
+static int aess_set_runtime_opp_level(struct abe_data *abe)
+{
+ int i, req_opp, opp = 0;
+
+ mutex_lock(&abe->opp_mutex);
+
+ /* now calculate OPP level based upon DAPM widget status */
+ for (i = 0; i < ABE_NUM_WIDGETS; i++) {
+ if (abe->widget_opp[ABE_WIDGET(i)]) {
+ dev_dbg(abe->dev, "OPP: id %d = %d%%\n", i,
+ abe->widget_opp[ABE_WIDGET(i)] * 25);
+ opp |= abe->widget_opp[ABE_WIDGET(i)];
+ }
+ }
+ opp = (1 << (fls(opp) - 1)) * 25;
+
+ /* opps requested outside ABE DSP driver (e.g. McPDM) */
+ req_opp = abe_get_opp_req(abe);
+
+ pm_runtime_get_sync(abe->dev);
+ abe_set_opp_mode(abe, max(opp, req_opp));
+ pm_runtime_put_sync(abe->dev);
+
+ mutex_unlock(&abe->opp_mutex);
+
+ return 0;
+}
+
+static void abe_dsp_init_gains(struct abe_data *abe)
+{
+ /* Uplink gains */
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+
+ abe_mute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ abe_mute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ abe_mute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+
+ abe_mute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+
+ abe_mute_gain(GAINS_BTUL, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_BTUL, GAIN_RIGHT_OFFSET);
+
+ /* Downlink gains */
+ abe_write_gain(GAINS_DL1, GAIN_0dB, RAMP_2MS, GAIN_LEFT_OFFSET);
+ abe_write_gain(GAINS_DL1, GAIN_0dB, RAMP_2MS, GAIN_RIGHT_OFFSET);
+ abe_mute_gain(GAINS_DL1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DL1, GAIN_RIGHT_OFFSET);
+
+ abe_write_gain(GAINS_DL2, GAIN_M7dB, RAMP_2MS, GAIN_LEFT_OFFSET);
+ abe_write_gain(GAINS_DL2, GAIN_M7dB, RAMP_2MS, GAIN_RIGHT_OFFSET);
+ abe_mute_gain(GAINS_DL2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DL2, GAIN_RIGHT_OFFSET);
+
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ /* Sidetone gains */
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+}
+
+static int aess_save_context(struct abe_data *abe)
+{
+ /* mute gains not associated with FEs/BEs */
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ return 0;
+}
+
+static int aess_restore_context(struct abe_data *abe)
+{
+ struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
+ int i, ret;
+
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(the_abe->dev, the_abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP50]);
+ if (ret) {
+ dev_err(abe->dev, "failed to scale to OPP50\n");
+ return ret;
+ }
+ }
+
+ if (pdata->was_context_lost && pdata->was_context_lost(abe->dev))
+ abe_reload_fw(abe->firmware);
+
+ /* unmute gains not associated with FEs/BEs */
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ abe_set_router_configuration(UPROUTE, 0, (u32 *)abe->router);
+
+ /* DC offset cancellation setting */
+ if (abe->power_mode)
+ abe_write_pdmdl_offset(1, abe->dc_hsl * 2, abe->dc_hsr * 2);
+ else
+ abe_write_pdmdl_offset(1, abe->dc_hsl, abe->dc_hsr);
+
+ abe_write_pdmdl_offset(2, abe->dc_hfl, abe->dc_hfr);
+
+ for (i = 0; i < abe->hdr.num_equ; i++)
+ abe_dsp_set_equalizer(i, abe->equ_profile[i]);
+
+ for (i = 0; i < ABE_NUM_MONO_MIXERS; i++)
+ abe_dsp_set_mono_mixer(MIX_DL1_MONO + i, abe->mono_mix[i]);
+
+ return 0;
+}
+
+static int aess_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ int ret = 0;
+
+ mutex_lock(&abe->mutex);
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ pm_runtime_get_sync(abe->dev);
+
+ if (!abe->active++) {
+ abe->opp = 0;
+ aess_restore_context(abe);
+ abe_set_opp_mode(abe, 100);
+ abe_wakeup();
+ }
+
+ switch (dai->id) {
+ case ABE_FRONTEND_DAI_MODEM:
+ break;
+ case ABE_FRONTEND_DAI_LP_MEDIA:
+ snd_soc_set_runtime_hwparams(substream, &omap_abe_hardware);
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1024);
+ break;
+ default:
+ break;
+ }
+
+ mutex_unlock(&abe->mutex);
+ return ret;
+}
+
+static int aess_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ abe_data_format_t format;
+ size_t period_size;
+ u32 dst;
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ if (dai->id != ABE_FRONTEND_DAI_LP_MEDIA)
+ return 0;
+
+ /*Storing substream pointer for irq*/
+ abe->ping_pong_substream = substream;
+
+ format.f = params_rate(params);
+ if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
+ format.samp_format = STEREO_MSB;
+ else
+ format.samp_format = STEREO_16_16;
+
+ if (format.f == 44100)
+ abe_write_event_generator(EVENT_44100);
+
+ period_size = params_period_bytes(params);
+
+ /*Adding ping pong buffer subroutine*/
+ abe_plug_subroutine(&abe_irq_pingpong_player_id,
+ (abe_subroutine2) abe_irq_pingpong_subroutine,
+ SUB_1_PARAM, (u32 *)abe);
+
+ /* Connect a Ping-Pong cache-flush protocol to MM_DL port */
+ abe_connect_irq_ping_pong_port(MM_DL_PORT, &format,
+ abe_irq_pingpong_player_id,
+ period_size, &dst,
+ PING_PONG_WITH_MCU_IRQ);
+
+ /* Memory mapping for hw params */
+ runtime->dma_area = abe->io_base[0] + dst;
+ runtime->dma_addr = 0;
+ runtime->dma_bytes = period_size * 4;
+
+ /* Need to set the first buffer in order to get interrupt */
+ abe_set_ping_pong_buffer(MM_DL_PORT, period_size);
+ abe->first_irq = 1;
+
+ return 0;
+}
+
+static int aess_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+
+ mutex_lock(&abe->mutex);
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+ aess_set_runtime_opp_level(abe);
+ mutex_unlock(&abe->mutex);
+ return 0;
+}
+
+static int aess_close(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+
+ mutex_lock(&abe->mutex);
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ if (!--abe->active) {
+ abe_disable_irq();
+ aess_save_context(abe);
+ abe_dsp_shutdown();
+ } else {
+ /* Only scale OPP level
+ * if ABE is still active */
+ aess_set_runtime_opp_level(abe);
+ }
+
+ pm_runtime_put_sync(abe->dev);
+
+ mutex_unlock(&abe->mutex);
+ return 0;
+}
+
+static int aess_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ int offset, size, err;
+
+ if (dai->id != ABE_FRONTEND_DAI_LP_MEDIA)
+ return -EINVAL;
+
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ size = vma->vm_end - vma->vm_start;
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ err = io_remap_pfn_range(vma, vma->vm_start,
+ (ABE_DMEM_BASE_ADDRESS_MPU +
+ ABE_DMEM_BASE_OFFSET_PING_PONG + offset) >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+
+ if (err)
+ return -EAGAIN;
+
+ return 0;
+}
+
+static snd_pcm_uframes_t aess_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ snd_pcm_uframes_t offset = 0;
+ u32 pingpong;
+
+ if (!abe->first_irq) {
+ abe_read_offset_from_ping_buffer(MM_DL_PORT, &pingpong);
+ offset = (snd_pcm_uframes_t)pingpong;
+ }
+
+ return offset;
+}
+
+static struct snd_pcm_ops omap_aess_pcm_ops = {
+ .open = aess_open,
+ .hw_params = aess_hw_params,
+ .prepare = aess_prepare,
+ .close = aess_close,
+ .pointer = aess_pointer,
+ .mmap = aess_mmap,
+};
+
+static int aess_stream_event(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_platform *platform = dapm->platform;
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+
+ if (abe->active)
+ aess_set_runtime_opp_level(abe);
+
+ return 0;
+}
+
+static int abe_add_widgets(struct snd_soc_platform *platform)
+{
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct fw_header *hdr = &abe->hdr;
+ int i, j;
+
+ /* create equalizer controls */
+ for (i = 0; i < hdr->num_equ; i++) {
+ struct soc_enum *equalizer_enum = &abe->equalizer_enum[i];
+ struct snd_kcontrol_new *equalizer_control =
+ &abe->equalizer_control[i];
+
+ equalizer_enum->reg = i;
+ equalizer_enum->max = abe->equ_texts[i].count;
+ for (j = 0; j < abe->equ_texts[i].count; j++)
+ equalizer_enum->dtexts[j] = abe->equ_texts[i].texts[j];
+
+ equalizer_control->name = abe->equ_texts[i].name;
+ equalizer_control->private_value = (unsigned long)equalizer_enum;
+ equalizer_control->get = abe_get_equalizer;
+ equalizer_control->put = abe_put_equalizer;
+ equalizer_control->info = snd_soc_info_enum_ext1;
+ equalizer_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+
+ dev_dbg(platform->dev, "added EQU mixer: %s profiles %d\n",
+ abe->equ_texts[i].name, abe->equ_texts[i].count);
+
+ for (j = 0; j < abe->equ_texts[i].count; j++)
+ dev_dbg(platform->dev, " %s\n", equalizer_enum->dtexts[j]);
+ }
+
+ snd_soc_add_platform_controls(platform, abe->equalizer_control,
+ hdr->num_equ);
+
+ snd_soc_add_platform_controls(platform, abe_controls,
+ ARRAY_SIZE(abe_controls));
+
+ snd_soc_dapm_new_controls(&platform->dapm, abe_dapm_widgets,
+ ARRAY_SIZE(abe_dapm_widgets));
+
+ snd_soc_dapm_add_routes(&platform->dapm, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(&platform->dapm);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int abe_suspend(struct snd_soc_dai *dai)
+{
+ struct abe_data *abe = the_abe;
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ pm_runtime_get_sync(abe->dev);
+
+ switch (dai->id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_mute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ abe_mute_gain(GAINS_BTUL, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_BTUL, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_mute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_mute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_mute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ default:
+ dev_err(dai->dev, "%s: invalid DAI id %d\n",
+ __func__, dai->id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+out:
+ pm_runtime_put_sync(abe->dev);
+ return ret;
+}
+
+static int abe_resume(struct snd_soc_dai *dai)
+{
+ struct abe_data *abe = the_abe;
+ struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
+ int i, ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ /* context retained, no need to restore */
+ if (pdata->was_context_lost && !pdata->was_context_lost(abe->dev))
+ return 0;
+
+ pm_runtime_get_sync(abe->dev);
+
+ if (pdata && pdata->device_scale) {
+ ret = pdata->device_scale(abe->dev, abe->dev,
+ abe->opp_freqs[OMAP_ABE_OPP50]);
+ if (ret) {
+ dev_err(abe->dev, "failed to scale to OPP50\n");
+ goto out;
+ }
+ }
+
+ abe_reload_fw(abe->firmware);
+
+ switch (dai->id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_unmute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ abe_unmute_gain(GAINS_BTUL, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_BTUL, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_unmute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_unmute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_unmute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ default:
+ dev_err(dai->dev, "%s: invalid DAI id %d\n",
+ __func__, dai->id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ abe_set_router_configuration(UPROUTE, 0, (u32 *)abe->router);
+
+ if (abe->power_mode)
+ abe_write_pdmdl_offset(1, abe->dc_hsl * 2, abe->dc_hsr * 2);
+ else
+ abe_write_pdmdl_offset(1, abe->dc_hsl, abe->dc_hsr);
+
+ abe_write_pdmdl_offset(2, abe->dc_hfl, abe->dc_hfr);
+
+ for (i = 0; i < abe->hdr.num_equ; i++)
+ abe_dsp_set_equalizer(i, abe->equ_profile[i]);
+
+ for (i = 0; i < ABE_NUM_MONO_MIXERS; i++)
+ abe_dsp_set_mono_mixer(MIX_DL1_MONO + i, abe->mono_mix[i]);
+out:
+ pm_runtime_put_sync(abe->dev);
+ return ret;
+}
+#else
+#define abe_suspend NULL
+#define abe_resume NULL
+#endif
+
+static int abe_probe(struct snd_soc_platform *platform)
+{
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ struct opp *opp;
+ const u8 *fw_data;
+ unsigned long freq = ULONG_MAX;
+ int ret = 0, i, opp_count, offset = 0;
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ const struct firmware *fw;
+#endif
+
+ abe->platform = platform;
+
+ pm_runtime_enable(abe->dev);
+ pm_runtime_irq_safe(abe->dev);
+
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ /* request firmware & coefficients */
+ ret = request_firmware(&fw, "omap4_abe", platform->dev);
+ if (ret != 0) {
+ dev_err(abe->dev, "Failed to load firmware: %d\n", ret);
+ return ret;
+ }
+ fw_data = fw->data;
+#else
+ fw_data = (u8 *)abe_get_default_fw();
+#endif
+
+ /* get firmware and coefficients header info */
+ memcpy(&abe->hdr, fw_data, sizeof(struct fw_header));
+ if (abe->hdr.firmware_size > ABE_MAX_FW_SIZE) {
+ dev_err(abe->dev, "Firmware too large at %d bytes: %d\n",
+ abe->hdr.firmware_size, ret);
+ ret = -EINVAL;
+ goto err_fw;
+ }
+ dev_dbg(abe->dev, "ABE firmware size %d bytes\n", abe->hdr.firmware_size);
+
+ if (abe->hdr.coeff_size > ABE_MAX_COEFF_SIZE) {
+ dev_err(abe->dev, "Coefficients too large at %d bytes: %d\n",
+ abe->hdr.coeff_size, ret);
+ ret = -EINVAL;
+ goto err_fw;
+ }
+ dev_dbg(abe->dev, "ABE coefficients size %d bytes\n", abe->hdr.coeff_size);
+
+ /* get coefficient EQU mixer strings */
+ if (abe->hdr.num_equ >= ABE_MAX_EQU) {
+ dev_err(abe->dev, "Too many equalizers got %d\n", abe->hdr.num_equ);
+ ret = -EINVAL;
+ goto err_fw;
+ }
+ abe->equ_texts = kzalloc(abe->hdr.num_equ * sizeof(struct coeff_config),
+ GFP_KERNEL);
+ if (abe->equ_texts == NULL) {
+ ret = -ENOMEM;
+ goto err_fw;
+ }
+ offset = sizeof(struct fw_header);
+ memcpy(abe->equ_texts, fw_data + offset,
+ abe->hdr.num_equ * sizeof(struct coeff_config));
+
+ /* get coefficients from firmware */
+ abe->equ[0] = kmalloc(abe->hdr.coeff_size, GFP_KERNEL);
+ if (abe->equ[0] == NULL) {
+ ret = -ENOMEM;
+ goto err_equ;
+ }
+ offset += abe->hdr.num_equ * sizeof(struct coeff_config);
+ memcpy(abe->equ[0], fw_data + offset, abe->hdr.coeff_size);
+
+ /* allocate coefficient mixer texts */
+ dev_dbg(abe->dev, "loaded %d equalizers\n", abe->hdr.num_equ);
+ for (i = 0; i < abe->hdr.num_equ; i++) {
+ dev_dbg(abe->dev, "equ %d: %s profiles %d\n", i,
+ abe->equ_texts[i].name, abe->equ_texts[i].count);
+ if (abe->equ_texts[i].count >= ABE_MAX_PROFILES) {
+ dev_err(abe->dev, "Too many profiles got %d for equ %d\n",
+ abe->equ_texts[i].count, i);
+ ret = -EINVAL;
+ goto err_texts;
+ }
+ abe->equalizer_enum[i].dtexts =
+ kzalloc(abe->equ_texts[i].count * sizeof(char *), GFP_KERNEL);
+ if (abe->equalizer_enum[i].dtexts == NULL) {
+ ret = -ENOMEM;
+ goto err_texts;
+ }
+ }
+
+ /* initialise coefficient equalizers */
+ for (i = 1; i < abe->hdr.num_equ; i++) {
+ abe->equ[i] = abe->equ[i - 1] +
+ abe->equ_texts[i - 1].count * abe->equ_texts[i - 1].coeff;
+ }
+
+ /* store ABE firmware for later context restore */
+ abe->firmware = kzalloc(abe->hdr.firmware_size, GFP_KERNEL);
+ if (abe->firmware == NULL) {
+ ret = -ENOMEM;
+ goto err_texts;
+ }
+
+ memcpy(abe->firmware,
+ fw_data + sizeof(struct fw_header) + abe->hdr.coeff_size,
+ abe->hdr.firmware_size);
+
+ ret = request_threaded_irq(abe->irq, NULL, abe_irq_handler,
+ IRQF_ONESHOT, "ABE", (void *)abe);
+ if (ret) {
+ dev_err(platform->dev, "request for ABE IRQ %d failed %d\n",
+ abe->irq, ret);
+ goto err_irq;
+ }
+
+ /* query supported opps */
+ rcu_read_lock();
+ opp_count = opp_get_opp_count(abe->dev);
+ if (opp_count <= 0) {
+ dev_err(abe->dev, "invalid OPP data\n");
+ ret = opp_count;
+ goto err_opp;
+ } else if (opp_count > OMAP_ABE_OPP_COUNT) {
+ dev_err(abe->dev, "unsupported OPP count %d (max:%d)\n",
+ opp_count, OMAP_ABE_OPP_COUNT);
+ ret = -EINVAL;
+ goto err_opp;
+ }
+
+ /* assume provided opps are always higher */
+ for (i = OMAP_ABE_OPP_COUNT - 1; i >= 0; i--) {
+ opp = opp_find_freq_floor(abe->dev, &freq);
+ if (IS_ERR_OR_NULL(opp))
+ break;
+ abe->opp_freqs[i] = freq;
+ /* prepare to obtain next available opp */
+ freq--;
+ }
+ /* use lowest available opp for non-populated items */
+ for (freq++; i >= 0; i--)
+ abe->opp_freqs[i] = freq;
+ rcu_read_unlock();
+
+ /* aess_clk has to be enabled to access hal register.
+ * Disable the clk after it has been used.
+ */
+ pm_runtime_get_sync(abe->dev);
+
+ abe_init_mem(abe->io_base);
+
+ abe_reset_hal();
+
+ abe_load_fw(abe->firmware);
+
+ /* "tick" of the audio engine */
+ abe_write_event_generator(EVENT_TIMER);
+
+ abe_dsp_init_gains(abe);
+
+ /* Stop the engine */
+ abe_stop_event_generator();
+ abe_disable_irq();
+
+ pm_runtime_put_sync(abe->dev);
+ abe_add_widgets(platform);
+
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ release_firmware(fw);
+#endif
+ return ret;
+
+err_opp:
+ rcu_read_unlock();
+ free_irq(abe->irq, (void *)abe);
+err_irq:
+ kfree(abe->firmware);
+err_texts:
+ for (i = 0; i < abe->hdr.num_equ; i++)
+ kfree(abe->equalizer_enum[i].texts);
+ kfree(abe->equ[0]);
+err_equ:
+ kfree(abe->equ_texts);
+err_fw:
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ release_firmware(fw);
+#endif
+ return ret;
+}
+
+static int abe_remove(struct snd_soc_platform *platform)
+{
+ struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
+ int i;
+
+ free_irq(abe->irq, (void *)abe);
+
+ for (i = 0; i < abe->hdr.num_equ; i++)
+ kfree(abe->equalizer_enum[i].texts);
+
+ kfree(abe->equ[0]);
+ kfree(abe->equ_texts);
+ kfree(abe->firmware);
+
+ pm_runtime_disable(abe->dev);
+
+ return 0;
+}
+
+static struct snd_soc_platform_driver omap_aess_platform = {
+ .ops = &omap_aess_pcm_ops,
+ .probe = abe_probe,
+ .remove = abe_remove,
+ .suspend = abe_suspend,
+ .resume = abe_resume,
+ .read = abe_dsp_read,
+ .write = abe_dsp_write,
+ .stream_event = aess_stream_event,
+};
+
+static int __devinit abe_engine_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct omap4_abe_dsp_pdata *pdata = pdev->dev.platform_data;
+ struct abe_data *abe;
+ int ret = -EINVAL, i;
+
+ abe = kzalloc(sizeof(struct abe_data), GFP_KERNEL);
+ if (abe == NULL)
+ return -ENOMEM;
+ dev_set_drvdata(&pdev->dev, abe);
+ the_abe = abe;
+
+ /* ZERO_labelID should really be 0 */
+ for (i = 0; i < ABE_ROUTES_UL + 2; i++)
+ abe->router[i] = ZERO_labelID;
+
+ for (i = 0; i < 5; i++) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ abe_memory_bank[i]);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no resource %s\n",
+ abe_memory_bank[i]);
+ goto err;
+ }
+ abe->io_base[i] = ioremap(res->start, resource_size(res));
+ if (!abe->io_base[i]) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+
+ abe->irq = platform_get_irq(pdev, 0);
+ if (abe->irq < 0) {
+ ret = abe->irq;
+ goto err;
+ }
+
+ abe->abe_pdata = pdata;
+ abe->dev = &pdev->dev;
+ mutex_init(&abe->mutex);
+ mutex_init(&abe->opp_mutex);
+ mutex_init(&abe->opp_req_mutex);
+ INIT_LIST_HEAD(&abe->opp_req);
+ abe->opp_req_count = 0;
+
+ ret = snd_soc_register_platform(abe->dev,
+ &omap_aess_platform);
+ if (ret < 0)
+ return ret;
+
+ abe_init_debugfs(abe);
+ return ret;
+
+err:
+ for (--i; i >= 0; i--)
+ iounmap(abe->io_base[i]);
+ kfree(abe);
+ return ret;
+}
+
+static int __devexit abe_engine_remove(struct platform_device *pdev)
+{
+ struct abe_data *abe = dev_get_drvdata(&pdev->dev);
+ int i;
+
+ abe_cleanup_debugfs(abe);
+ snd_soc_unregister_platform(&pdev->dev);
+ for (i = 0; i < 5; i++)
+ iounmap(abe->io_base[i]);
+ kfree(abe);
+ return 0;
+}
+
+static struct platform_driver omap_aess_driver = {
+ .driver = {
+ .name = "aess",
+ .owner = THIS_MODULE,
+ },
+ .probe = abe_engine_probe,
+ .remove = __devexit_p(abe_engine_remove),
+};
+
+static int __init abe_engine_init(void)
+{
+ return platform_driver_register(&omap_aess_driver);
+}
+module_init(abe_engine_init);
+
+static void __exit abe_engine_exit(void)
+{
+ platform_driver_unregister(&omap_aess_driver);
+}
+module_exit(abe_engine_exit);
+
+MODULE_DESCRIPTION("ASoC OMAP4 ABE");
+MODULE_AUTHOR("Liam Girdwood <lrg@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-abe-dsp.h b/sound/soc/omap/omap-abe-dsp.h
new file mode 100644
index 0000000..8462290
--- /dev/null
+++ b/sound/soc/omap/omap-abe-dsp.h
@@ -0,0 +1,177 @@
+/*
+ * omap-abe-dsp.h
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Contact: Liam Girdwood <lrg@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_ABE_DSP_H__
+#define __OMAP_ABE_DSP_H__
+
+#define ABE_MIXER(x) (x)
+
+#define MIX_DL1_TONES ABE_MIXER(0)
+#define MIX_DL1_VOICE ABE_MIXER(1)
+#define MIX_DL1_CAPTURE ABE_MIXER(2)
+#define MIX_DL1_MEDIA ABE_MIXER(3)
+#define MIX_DL2_TONES ABE_MIXER(4)
+#define MIX_DL2_VOICE ABE_MIXER(5)
+#define MIX_DL2_CAPTURE ABE_MIXER(6)
+#define MIX_DL2_MEDIA ABE_MIXER(7)
+#define MIX_AUDUL_TONES ABE_MIXER(8)
+#define MIX_AUDUL_MEDIA ABE_MIXER(9)
+#define MIX_AUDUL_CAPTURE ABE_MIXER(10)
+#define MIX_VXREC_TONES ABE_MIXER(11)
+#define MIX_VXREC_VOICE_PLAYBACK ABE_MIXER(12)
+#define MIX_VXREC_VOICE_CAPTURE ABE_MIXER(13)
+#define MIX_VXREC_MEDIA ABE_MIXER(14)
+#define MIX_SDT_CAPTURE ABE_MIXER(15)
+#define MIX_SDT_PLAYBACK ABE_MIXER(16)
+#define MIX_SWITCH_PDM_DL ABE_MIXER(17)
+#define MIX_SWITCH_BT_VX_DL ABE_MIXER(18)
+#define MIX_SWITCH_MM_EXT_DL ABE_MIXER(19)
+#define MIX_DL1_MONO ABE_MIXER(20)
+#define MIX_DL2_MONO ABE_MIXER(21)
+#define MIX_AUDUL_MONO ABE_MIXER(22)
+
+#define ABE_NUM_MONO_MIXERS (MIX_AUDUL_MONO - MIX_DL1_MONO + 1)
+#define ABE_NUM_MIXERS (MIX_AUDUL_MONO + 1)
+
+#define ABE_MUX(x) (x + ABE_NUM_MIXERS)
+
+#define MUX_MM_UL10 ABE_MUX(0)
+#define MUX_MM_UL11 ABE_MUX(1)
+#define MUX_MM_UL12 ABE_MUX(2)
+#define MUX_MM_UL13 ABE_MUX(3)
+#define MUX_MM_UL14 ABE_MUX(4)
+#define MUX_MM_UL15 ABE_MUX(5)
+#define MUX_MM_UL16 ABE_MUX(6)
+#define MUX_MM_UL17 ABE_MUX(7)
+#define MUX_MM_UL20 ABE_MUX(8)
+#define MUX_MM_UL21 ABE_MUX(9)
+#define MUX_VX_UL0 ABE_MUX(10)
+#define MUX_VX_UL1 ABE_MUX(11)
+
+#define ABE_NUM_MUXES (MUX_VX_UL1 - MUX_MM_UL10)
+
+#define ABE_WIDGET(x) (x + ABE_NUM_MIXERS + ABE_NUM_MUXES)
+
+/* ABE AIF Frontend Widgets */
+#define W_AIF_TONES_DL ABE_WIDGET(0)
+#define W_AIF_VX_DL ABE_WIDGET(1)
+#define W_AIF_VX_UL ABE_WIDGET(2)
+#define W_AIF_MM_UL1 ABE_WIDGET(3)
+#define W_AIF_MM_UL2 ABE_WIDGET(4)
+#define W_AIF_MM_DL ABE_WIDGET(5)
+#define W_AIF_MM_DL_LP W_AIF_MM_DL
+#define W_AIF_VIB_DL ABE_WIDGET(6)
+#define W_AIF_MODEM_DL ABE_WIDGET(7)
+#define W_AIF_MODEM_UL ABE_WIDGET(8)
+
+/* ABE AIF Backend Widgets */
+#define W_AIF_PDM_UL1 ABE_WIDGET(9)
+#define W_AIF_PDM_DL1 ABE_WIDGET(10)
+#define W_AIF_PDM_DL2 ABE_WIDGET(11)
+#define W_AIF_PDM_VIB ABE_WIDGET(12)
+#define W_AIF_BT_VX_UL ABE_WIDGET(13)
+#define W_AIF_BT_VX_DL ABE_WIDGET(14)
+#define W_AIF_MM_EXT_UL ABE_WIDGET(15)
+#define W_AIF_MM_EXT_DL ABE_WIDGET(16)
+#define W_AIF_DMIC0 ABE_WIDGET(17)
+#define W_AIF_DMIC1 ABE_WIDGET(18)
+#define W_AIF_DMIC2 ABE_WIDGET(19)
+
+/* ABE ROUTE_UL MUX Widgets */
+#define W_MUX_UL00 ABE_WIDGET(20)
+#define W_MUX_UL01 ABE_WIDGET(21)
+#define W_MUX_UL02 ABE_WIDGET(22)
+#define W_MUX_UL03 ABE_WIDGET(23)
+#define W_MUX_UL04 ABE_WIDGET(24)
+#define W_MUX_UL05 ABE_WIDGET(25)
+#define W_MUX_UL06 ABE_WIDGET(26)
+#define W_MUX_UL07 ABE_WIDGET(27)
+#define W_MUX_UL10 ABE_WIDGET(28)
+#define W_MUX_UL11 ABE_WIDGET(29)
+#define W_MUX_VX00 ABE_WIDGET(30)
+#define W_MUX_VX01 ABE_WIDGET(31)
+
+/* ABE Volume and Mixer Widgets */
+#define W_MIXER_DL1 ABE_WIDGET(32)
+#define W_MIXER_DL2 ABE_WIDGET(33)
+#define W_VOLUME_DL1 ABE_WIDGET(34)
+#define W_MIXER_AUDIO_UL ABE_WIDGET(35)
+#define W_MIXER_VX_REC ABE_WIDGET(36)
+#define W_MIXER_SDT ABE_WIDGET(37)
+#define W_VSWITCH_DL1_PDM ABE_WIDGET(38)
+#define W_VSWITCH_DL1_BT_VX ABE_WIDGET(39)
+#define W_VSWITCH_DL1_MM_EXT ABE_WIDGET(40)
+
+#define ABE_NUM_WIDGETS (W_VSWITCH_DL1_MM_EXT - W_AIF_TONES_DL)
+#define ABE_WIDGET_LAST W_VSWITCH_DL1_MM_EXT
+
+#define ABE_NUM_DAPM_REG \
+ (ABE_NUM_MIXERS + ABE_NUM_MUXES + ABE_NUM_WIDGETS)
+
+#define ABE_VIRTUAL_SWITCH 0
+#define ABE_ROUTES_UL 14
+
+// TODO: OPP bitmask - Use HAL version after update
+#define ABE_OPP_25 0
+#define ABE_OPP_50 1
+#define ABE_OPP_100 2
+
+/* TODO: size in bytes of debug options */
+#define ABE_DBG_FLAG1_SIZE 0
+#define ABE_DBG_FLAG2_SIZE 0
+#define ABE_DBG_FLAG3_SIZE 0
+
+/* TODO: Pong start offset of DMEM */
+/* Ping pong buffer DMEM offset */
+#define ABE_DMEM_BASE_OFFSET_PING_PONG 0x4000
+
+/* Gain value conversion */
+#define ABE_MAX_GAIN 12000
+#define ABE_GAIN_SCALE 100
+#define abe_gain_to_val(gain) ((val + ABE_MAX_GAIN) / ABE_GAIN_SCALE)
+#define abe_val_to_gain(val) (-ABE_MAX_GAIN + (val * ABE_GAIN_SCALE))
+
+/* Firmware coefficients and equalizers */
+#define ABE_MAX_FW_SIZE (1024 * 128)
+#define ABE_MAX_COEFF_SIZE (1024 * 4)
+#define ABE_COEFF_NAME_SIZE 20
+#define ABE_COEFF_TEXT_SIZE 20
+#define ABE_COEFF_NUM_TEXTS 10
+#define ABE_MAX_EQU 10
+#define ABE_MAX_PROFILES 30
+
+#define OMAP_ABE_OPP25 0
+#define OMAP_ABE_OPP50 1
+#define OMAP_ABE_OPP100 2
+#define OMAP_ABE_OPP_COUNT 3
+
+void abe_dsp_shutdown(void);
+void abe_dsp_pm_get(void);
+void abe_dsp_pm_put(void);
+int abe_add_opp_req(struct device *dev, int opp);
+int abe_remove_opp_req(struct device *dev);
+void abe_dsp_set_power_mode(int mode);
+void abe_dsp_set_hs_offset(int left, int right, int mult);
+void abe_dsp_set_hf_offset(int left, int right);
+
+#endif /* End of __OMAP_ABE_DSP_H__ */
diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c
new file mode 100644
index 0000000..da5ba44
--- /dev/null
+++ b/sound/soc/omap/omap-abe.c
@@ -0,0 +1,1563 @@
+/*
+ * omap-abe.c -- OMAP ALSA SoC DAI driver using Audio Backend
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Contact: Liam Girdwood <lrg@ti.com>
+ * Misael Lopez Cruz <misael.lopez@ti.com>
+ * Sebastien Guiriec <s-guiriec@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dsp.h>
+
+#include <plat/dma-44xx.h>
+#include <plat/dma.h>
+#include "omap-pcm.h"
+#include "omap-abe.h"
+#include "omap-abe-dsp.h"
+#include "abe/abe_main.h"
+#include "abe/port_mgr.h"
+
+#define OMAP_ABE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct omap_abe_data {
+ /* MODEM FE*/
+ struct snd_pcm_substream *modem_substream[2];
+ struct snd_soc_dai *modem_dai;
+
+ struct abe *abe;
+
+ /* BE & FE Ports */
+ struct omap_abe_port *port[OMAP_ABE_MAX_PORT_ID + 1];
+
+ int active_dais;
+ int suspended_dais;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_abe_dai_dma_params[7][2] = {
+{
+ {
+ .name = "Media Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_0,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+ {
+ .name = "Media Capture1",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_3,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+},
+{
+ {},
+ {
+ .name = "Media Capture2",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_4,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+},
+{
+ {
+ .name = "Voice Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_1,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+ {
+ .name = "Voice Capture",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_2,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+},
+{
+ {
+ .name = "Tones Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_5,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },{},
+},
+{
+ {
+ .name = "Vibra Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_6,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },{},
+},
+{
+ {
+ .name = "MODEM Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_1,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+ {
+ .name = "MODEM Capture",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_2,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+},
+{
+ {
+ .name = "Low Power Playback",
+ .dma_req = OMAP44XX_DMA_ABE_REQ_0,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },{},
+},};
+
+static int modem_get_dai(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ struct snd_soc_pcm_runtime *modem_rtd;
+
+ abe_priv->modem_substream[substream->stream] =
+ snd_soc_get_dai_substream(rtd->card,
+ OMAP_ABE_BE_MM_EXT1, !substream->stream);
+
+ if (abe_priv->modem_substream[substream->stream] == NULL)
+ return -ENODEV;
+
+ modem_rtd = abe_priv->modem_substream[substream->stream]->private_data;
+ abe_priv->modem_substream[substream->stream]->runtime = substream->runtime;
+ abe_priv->modem_dai = modem_rtd->cpu_dai;
+
+ return 0;
+}
+
+int omap_abe_set_dl1_output(int output)
+{
+ int gain;
+
+ /*
+ * the output itself is not important, but the DL1 gain
+ * to use when each output is active
+ */
+ switch (output) {
+ case OMAP_ABE_DL1_HEADSET_LP:
+ gain = GAIN_M8dB;
+ break;
+ case OMAP_ABE_DL1_HEADSET_HP:
+ case OMAP_ABE_DL1_EARPIECE:
+ gain = GAIN_M1dB;
+ break;
+ case OMAP_ABE_DL1_NO_PDM:
+ gain = GAIN_0dB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ abe_write_gain(GAINS_DL1, gain, RAMP_2MS, GAIN_LEFT_OFFSET);
+ abe_write_gain(GAINS_DL1, gain, RAMP_2MS, GAIN_RIGHT_OFFSET);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_abe_set_dl1_output);
+
+static int omap_abe_dl1_enabled(struct omap_abe_data *abe_priv)
+{
+ /* DL1 path is common for PDM_DL1, BT_VX_DL and MM_EXT_DL */
+ return omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]) +
+ omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]) +
+ omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]);
+}
+
+static int omap_abe_dl2_enabled(struct omap_abe_data *abe_priv)
+{
+ return omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]);
+}
+
+static void mute_be(struct snd_soc_pcm_runtime *be,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ /*
+ * DL1 Mixer->SDT Mixer and DL1 gain are common for
+ * PDM_DL1, BT_VX_DL and MM_EXT_DL, mute those gains
+ * only if the last active BE
+ */
+ if (omap_abe_dl1_enabled(abe_priv) == 1) {
+ abe_mute_gain(GAINS_DL1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DL1, GAIN_RIGHT_OFFSET);
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ }
+ break;
+ case OMAP_ABE_DAI_PDM_DL2:
+ abe_mute_gain(GAINS_DL2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DL2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_VIB:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ }
+ } else {
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_mute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ abe_mute_gain(GAINS_BTUL, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_BTUL, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_mute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_mute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_mute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ }
+ }
+}
+
+static void unmute_be(struct snd_soc_pcm_runtime *be,
+ struct snd_soc_dai *dai, int stream)
+{
+ dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ /*
+ * DL1 Mixer->SDT Mixer and DL1 gain are common for
+ * PDM_DL1, BT_VX_DL and MM_EXT_DL, unmute when any
+ * of them becomes active
+ */
+ abe_unmute_gain(GAINS_DL1, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DL1, GAIN_RIGHT_OFFSET);
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ break;
+ case OMAP_ABE_DAI_PDM_DL2:
+ abe_unmute_gain(GAINS_DL2, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DL2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_VIB:
+ break;
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ }
+ } else {
+
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_unmute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ abe_unmute_gain(GAINS_BTUL, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_BTUL, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_unmute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_unmute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_unmute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ }
+ }
+}
+
+static void enable_be_port(struct snd_soc_pcm_runtime *be,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ abe_data_format_t format;
+
+ dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
+
+ switch (be->dai_link->be_id) {
+ /* McPDM is a special case, handled by McPDM driver */
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ case OMAP_ABE_DAI_PDM_UL:
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+ /* port can only be configured if it's not running */
+ if (omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]))
+ return;
+
+ /* BT_DL connection to McBSP 1 ports */
+ format.f = 8000;
+ format.samp_format = MONO_RSHIFTED_16;
+ abe_connect_serial_port(BT_VX_DL_PORT, &format, MCBSP1_TX);
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]);
+ } else {
+
+ /* port can only be configured if it's not running */
+ if (omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]))
+ return;
+
+ /* BT_UL connection to McBSP 1 ports */
+ format.f = 8000;
+ format.samp_format = MONO_RSHIFTED_16;
+ abe_connect_serial_port(BT_VX_UL_PORT, &format, MCBSP1_RX);
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]);
+ }
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+ /* port can only be configured if it's not running */
+ if (omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]))
+ return;
+
+ /* MM_EXT connection to McBSP 2 ports */
+ format.f = 48000;
+ format.samp_format = STEREO_RSHIFTED_16;
+ abe_connect_serial_port(MM_EXT_OUT_PORT, &format, MCBSP2_TX);
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]);
+ } else {
+
+ /* port can only be configured if it's not running */
+ if (omap_abe_port_is_enabled(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]))
+ return;
+
+ /* MM_EXT connection to McBSP 2 ports */
+ format.f = 48000;
+ format.samp_format = STEREO_RSHIFTED_16;
+ abe_connect_serial_port(MM_EXT_IN_PORT, &format, MCBSP2_RX);
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]);
+ }
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC0]);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC1]);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC2]);
+ break;
+ }
+}
+
+static void enable_fe_port(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
+
+ switch(dai->id) {
+ case ABE_FRONTEND_DAI_MEDIA:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_DL1]);
+ else
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_UL1]);
+ break;
+ case ABE_FRONTEND_DAI_LP_MEDIA:
+ abe_enable_data_transfer(MM_DL_PORT);
+ break;
+ case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_UL2]);
+ break;
+ case ABE_FRONTEND_DAI_MODEM:
+ case ABE_FRONTEND_DAI_VOICE:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VX_DL]);
+ else
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VX_UL]);
+ break;
+ case ABE_FRONTEND_DAI_TONES:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_TONES]);
+ break;
+ case ABE_FRONTEND_DAI_VIBRA:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_enable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VIB]);
+ break;
+ }
+}
+
+static void disable_be_port(struct snd_soc_pcm_runtime *be,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
+
+ switch (be->dai_link->be_id) {
+ /* McPDM is a special case, handled by McPDM driver */
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ case OMAP_ABE_DAI_PDM_UL:
+ break;
+ case OMAP_ABE_DAI_BT_VX:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]);
+ else
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]);
+ break;
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]);
+ else
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]);
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC0]);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC1]);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_BE_PORT_DMIC2]);
+ break;
+ }
+}
+
+static void disable_fe_port(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
+
+ switch(dai->id) {
+ case ABE_FRONTEND_DAI_MEDIA:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_DL1]);
+ else
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_UL1]);
+ break;
+ case ABE_FRONTEND_DAI_LP_MEDIA:
+ abe_disable_data_transfer(MM_DL_PORT);
+ break;
+ case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_MM_UL2]);
+ break;
+ case ABE_FRONTEND_DAI_MODEM:
+ case ABE_FRONTEND_DAI_VOICE:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VX_DL]);
+ else
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VX_UL]);
+ break;
+ case ABE_FRONTEND_DAI_TONES:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_TONES]);
+ break;
+ case ABE_FRONTEND_DAI_VIBRA:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_abe_port_disable(abe_priv->abe,
+ abe_priv->port[OMAP_ABE_FE_PORT_VIB]);
+ break;
+ }
+}
+
+static void mute_fe_port_capture(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int mute)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(fe->cpu_dai);
+
+ dev_dbg(&fe->dev, "%s: %s FE %s BE %s\n",
+ __func__, mute ? "mute" : "unmute",
+ fe->dai_link->name, be->dai_link->name);
+
+ switch (fe->cpu_dai->id) {
+ case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
+ if (omap_abe_dl1_enabled(abe_priv)) {
+ if (mute)
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ else
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ }
+ if (omap_abe_dl2_enabled(abe_priv)) {
+ if (mute)
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ else
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ }
+ break;
+ case ABE_FRONTEND_DAI_MODEM:
+ case ABE_FRONTEND_DAI_VOICE:
+ if (mute) {
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ } else {
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ }
+ break;
+ case ABE_FRONTEND_DAI_MEDIA:
+ default:
+ break;
+ }
+}
+
+static void mute_fe_port_playback(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int mute)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(fe->cpu_dai);
+
+ dev_dbg(&fe->dev, "%s: %s FE %s BE %s\n",
+ __func__, mute ? "mute" : "unmute",
+ fe->dai_link->name, be->dai_link->name);
+
+ switch (fe->cpu_dai->id) {
+ case ABE_FRONTEND_DAI_MEDIA:
+ case ABE_FRONTEND_DAI_LP_MEDIA:
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ if (mute) {
+ /* mute if last running DL1-related BE */
+ if (omap_abe_dl1_enabled(abe_priv) == 1)
+ abe_mute_gain(MIXDL1,
+ MIX_DL1_INPUT_MM_DL);
+ } else {
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ }
+ break;
+ case OMAP_ABE_DAI_PDM_DL2:
+ if (mute)
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ else
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ break;
+ case OMAP_ABE_DAI_MODEM:
+ case OMAP_ABE_DAI_PDM_VIB:
+ default:
+ break;
+ }
+ break;
+ case ABE_FRONTEND_DAI_VOICE:
+ case ABE_FRONTEND_DAI_MODEM:
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ if (mute) {
+ /* mute if last running DL1-related BE */
+ if (omap_abe_dl1_enabled(abe_priv) == 1)
+ abe_mute_gain(MIXDL1,
+ MIX_DL1_INPUT_VX_DL);
+ } else {
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ }
+ break;
+ case OMAP_ABE_DAI_PDM_DL2:
+ if (mute)
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ else
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ break;
+ case OMAP_ABE_DAI_MODEM:
+ case OMAP_ABE_DAI_PDM_VIB:
+ default:
+ break;
+ }
+ break;
+ case ABE_FRONTEND_DAI_TONES:
+ switch (be->dai_link->be_id) {
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ if (mute) {
+ /* mute if last running DL1-related BE */
+ if (omap_abe_dl1_enabled(abe_priv) == 1)
+ abe_mute_gain(MIXDL1,
+ MIX_DL1_INPUT_TONES);
+ } else{
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+ }
+ break;
+ case OMAP_ABE_DAI_PDM_DL2:
+ if (mute)
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ else
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ break;
+ case OMAP_ABE_DAI_MODEM:
+ case OMAP_ABE_DAI_PDM_VIB:
+ default:
+ break;
+ }
+ break;
+ case ABE_FRONTEND_DAI_VIBRA:
+ default:
+ break;
+ }
+}
+
+static void mute_fe_port(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ mute_fe_port_playback(fe, be, 1);
+ else
+ mute_fe_port_capture(fe, be, 1);
+ }
+}
+
+static void unmute_fe_port(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ mute_fe_port_playback(fe, be, 0);
+ else
+ mute_fe_port_capture(fe, be, 0);
+ }
+}
+
+static void capture_trigger(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int cmd)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+ struct snd_pcm_substream *be_substream;
+ int stream = substream->stream;
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, fe->cpu_dai->name, stream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+
+ /* mute and enable BE ports */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ /* does this trigger() apply to this BE and stream ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_PREPARE) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_STOP))
+ continue;
+
+ be_substream = snd_soc_dsp_get_substream(be, stream);
+
+ /* mute the BE port */
+ mute_be(be, dai, stream);
+
+ /* enable the BE port */
+ enable_be_port(be, dai, stream);
+
+ /* DAI work must be started/stopped at least 250us after ABE */
+ udelay(250);
+
+ /* trigger the BE port */
+ snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_START;
+ }
+
+ /* does this trigger() apply to the FE ? */
+ if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
+ /* Enable Frontend sDMA */
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ enable_fe_port(substream, dai, stream);
+
+ /* unmute FE port */
+ unmute_fe_port(substream, dai, stream);
+ }
+
+ /* Restore ABE GAINS AMIC */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ /* does this trigger() apply to this BE and stream ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ /* unmute this BE port */
+ unmute_be(be, dai, stream);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /* Enable sDMA */
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ enable_fe_port(substream, dai, stream);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ /* Disable sDMA */
+ disable_fe_port(substream, dai, stream);
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ /* does this trigger() apply to the FE ? */
+ if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
+ /* mute FE port */
+ mute_fe_port(substream, dai, stream);
+
+ /* Disable sDMA */
+ disable_fe_port(substream, dai, stream);
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ }
+
+ /* disable BE ports */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ /* does this trigger() apply to this BE and stream ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_START)
+ continue;
+
+ /* only stop if last running user */
+ if (soc_dsp_fe_state_count(be, stream,
+ SND_SOC_DSP_STATE_START) > 1)
+ continue;
+
+ be_substream = snd_soc_dsp_get_substream(be, stream);
+
+ /* mute the BE port */
+ mute_be(be, dai, stream);
+
+ /* disable the BE port */
+ disable_be_port(be, dai, stream);
+
+ /* DAI work must be started/stopped at least 250us after ABE */
+ udelay(250);
+
+ /* trigger BE port */
+ snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_STOP;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void playback_trigger(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, int cmd)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+ struct snd_pcm_substream *be_substream;
+ int stream = substream->stream;
+
+ dev_dbg(&fe->dev, "%s: %s %d\n", __func__, fe->cpu_dai->name, stream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+
+ /* mute and enable ports */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ /* does this trigger() apply to the FE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_PREPARE) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_STOP))
+ continue;
+
+ be_substream = snd_soc_dsp_get_substream(be, stream);
+
+ /* mute BE port */
+ mute_be(be, dai, stream);
+
+ /* enabled BE port */
+ enable_be_port(be, dai, stream);
+
+ /* DAI work must be started/stopped at least 250us after ABE */
+ udelay(250);
+
+ /* trigger BE port */
+ snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
+
+ /* unmute the BE port */
+ unmute_be(be, dai, stream);
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_START;
+ }
+
+ /* does this trigger() apply to the FE ? */
+ if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
+ /* Enable Frontend sDMA */
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ enable_fe_port(substream, dai, stream);
+ }
+
+ /* unmute FE port (sensitive to runtime udpates) */
+ unmute_fe_port(substream, dai, stream);
+
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /* Enable Frontend sDMA */
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ enable_fe_port(substream, dai, stream);
+
+ /* unmute FE port */
+ unmute_fe_port(substream, dai, stream);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ /* mute FE port */
+ mute_fe_port(substream, dai, stream);
+
+ /* disable Frontend sDMA */
+ disable_fe_port(substream, dai, stream);
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+
+ /* mute FE port (sensitive to runtime udpates) */
+ mute_fe_port(substream, dai, stream);
+
+ /* does this trigger() apply to the FE ? */
+ if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
+ /* disable the transfer */
+ disable_fe_port(substream, dai, stream);
+ snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
+ }
+
+ /* disable BE ports */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ /* does this trigger() apply to this BE and stream ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_START)
+ continue;
+
+ /* only stop if last running user */
+ if (soc_dsp_fe_state_count(be, stream,
+ SND_SOC_DSP_STATE_START) > 1)
+ continue;
+
+ be_substream = snd_soc_dsp_get_substream(be, stream);
+
+ /* mute the BE port */
+ mute_be(be, dai, stream);
+
+ /* disable the BE */
+ disable_be_port(be, dai, stream);
+
+ /* DAI work must be started/stopped at least 250us after ABE */
+ udelay(250);
+
+ /* trigger the BE port */
+ snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_STOP;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int omap_abe_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ abe_priv->active_dais++;
+
+ abe_dsp_pm_get();
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+
+ ret = modem_get_dai(substream, dai);
+ if (ret < 0) {
+ dev_err(dai->dev, "failed to get MODEM DAI\n");
+ return ret;
+ }
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
+ __func__, substream->stream);
+
+ ret = snd_soc_dai_startup(abe_priv->modem_substream[substream->stream],
+ abe_priv->modem_dai);
+ if (ret < 0) {
+ dev_err(abe_priv->modem_dai->dev, "failed to open DAI %d\n", ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int omap_abe_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ struct omap_pcm_dma_data *dma_data;
+ abe_data_format_t format;
+ abe_dma_t dma_sink;
+ abe_dma_t dma_params;
+ int data_type = OMAP_DMA_DATA_TYPE_S32;
+ int ret;
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ dma_data = &omap_abe_dai_dma_params[dai->id][substream->stream];
+
+ switch (params_channels(params)) {
+ case 1:
+ if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) {
+ format.samp_format = MONO_RSHIFTED_16;
+ data_type = OMAP_DMA_DATA_TYPE_S16;
+ } else {
+ format.samp_format = MONO_MSB;
+ }
+ break;
+ case 2:
+ if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
+ format.samp_format = STEREO_16_16;
+ else
+ format.samp_format = STEREO_MSB;
+ break;
+ case 3:
+ format.samp_format = THREE_MSB;
+ break;
+ case 4:
+ format.samp_format = FOUR_MSB;
+ break;
+ case 5:
+ format.samp_format = FIVE_MSB;
+ break;
+ case 6 :
+ format.samp_format = SIX_MSB;
+ break;
+ case 7 :
+ format.samp_format = SEVEN_MSB;
+ break;
+ case 8:
+ format.samp_format = EIGHT_MSB;
+ break;
+ default:
+ dev_err(dai->dev, "%d channels not supported",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ format.f = params_rate(params);
+
+ switch (dai->id) {
+ case ABE_FRONTEND_DAI_MEDIA:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ abe_connect_cbpr_dmareq_port(MM_DL_PORT, &format, ABE_CBPR0_IDX,
+ &dma_sink);
+ abe_read_port_address(MM_DL_PORT, &dma_params);
+ } else {
+ abe_connect_cbpr_dmareq_port(MM_UL_PORT, &format, ABE_CBPR3_IDX,
+ &dma_sink);
+ abe_read_port_address(MM_UL_PORT, &dma_params);
+ }
+ break;
+ case ABE_FRONTEND_DAI_LP_MEDIA:
+ return 0;
+ break;
+ case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return -EINVAL;
+ else {
+ abe_connect_cbpr_dmareq_port(MM_UL2_PORT, &format, ABE_CBPR4_IDX,
+ &dma_sink);
+ abe_read_port_address(MM_UL2_PORT, &dma_params);
+ }
+ break;
+ case ABE_FRONTEND_DAI_VOICE:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ abe_connect_cbpr_dmareq_port(VX_DL_PORT, &format, ABE_CBPR1_IDX,
+ &dma_sink);
+ abe_read_port_address(VX_DL_PORT, &dma_params);
+ } else {
+ abe_connect_cbpr_dmareq_port(VX_UL_PORT, &format, ABE_CBPR2_IDX,
+ &dma_sink);
+ abe_read_port_address(VX_UL_PORT, &dma_params);
+ }
+ break;
+ case ABE_FRONTEND_DAI_TONES:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ abe_connect_cbpr_dmareq_port(TONES_DL_PORT, &format, ABE_CBPR5_IDX,
+ &dma_sink);
+ abe_read_port_address(TONES_DL_PORT, &dma_params);
+ } else
+ return -EINVAL;
+ break;
+ case ABE_FRONTEND_DAI_VIBRA:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ abe_connect_cbpr_dmareq_port(VIB_DL_PORT, &format, ABE_CBPR6_IDX,
+ &dma_sink);
+ abe_read_port_address(VIB_DL_PORT, &dma_params);
+ } else
+ return -EINVAL;
+ break;
+ case ABE_FRONTEND_DAI_MODEM:
+ /* MODEM is special case where data IO is performed by McBSP2
+ * directly onto VX_DL and VX_UL (instead of SDMA).
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* Vx_DL connection to McBSP 2 ports */
+ format.samp_format = STEREO_RSHIFTED_16;
+ abe_connect_serial_port(VX_DL_PORT, &format, MCBSP2_RX);
+ abe_read_port_address(VX_DL_PORT, &dma_params);
+ } else {
+ /* Vx_UL connection to McBSP 2 ports */
+ format.samp_format = STEREO_RSHIFTED_16;
+ abe_connect_serial_port(VX_UL_PORT, &format, MCBSP2_TX);
+ abe_read_port_address(VX_UL_PORT, &dma_params);
+ }
+ break;
+ }
+
+ /* configure frontend SDMA data */
+ dma_data->port_addr = (unsigned long)dma_params.data;
+ dma_data->packet_size = dma_params.iter;
+ dma_data->data_type = data_type;
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+ /* call hw_params on McBSP with correct DMA data */
+ snd_soc_dai_set_dma_data(abe_priv->modem_dai, substream,
+ dma_data);
+
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
+ __func__, substream->stream);
+
+ ret = snd_soc_dai_hw_params(abe_priv->modem_substream[substream->stream],
+ params, abe_priv->modem_dai);
+ if (ret < 0)
+ dev_err(abe_priv->modem_dai->dev, "MODEM hw_params failed\n");
+ return ret;
+ }
+
+ snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+ return 0;
+}
+
+static int omap_abe_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+ ret = snd_soc_dai_prepare(abe_priv->modem_substream[substream->stream],
+ abe_priv->modem_dai);
+
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
+ __func__, substream->stream);
+
+ if (ret < 0) {
+ dev_err(abe_priv->modem_dai->dev, "MODEM prepare failed\n");
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int omap_abe_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s cmd %d\n", __func__, dai->name, cmd);
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d cmd %d\n",
+ __func__, substream->stream, cmd);
+
+ ret = snd_soc_dai_trigger(abe_priv->modem_substream[substream->stream],
+ cmd, abe_priv->modem_dai);
+ if (ret < 0) {
+ dev_err(abe_priv->modem_dai->dev, "MODEM trigger failed\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int omap_abe_dai_bespoke_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s cmd %d\n", __func__, dai->name, cmd);
+
+ if ((dai->id == ABE_FRONTEND_DAI_MODEM) &&
+ snd_soc_dsp_is_trigger_for_fe(fe, substream->stream)) {
+
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d cmd %d\n",
+ __func__, substream->stream, cmd);
+
+ ret = snd_soc_dai_trigger(abe_priv->modem_substream[substream->stream],
+ cmd, abe_priv->modem_dai);
+ if (ret < 0) {
+ dev_err(abe_priv->modem_dai->dev, "MODEM trigger failed\n");
+ return ret;
+ }
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ playback_trigger(substream, dai, cmd);
+ else
+ capture_trigger(substream, dai, cmd);
+
+ return ret;
+}
+
+static int omap_abe_dai_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
+ __func__, substream->stream);
+
+ ret = snd_soc_dai_hw_free(abe_priv->modem_substream[substream->stream],
+ abe_priv->modem_dai);
+ if (ret < 0) {
+ dev_err(abe_priv->modem_dai->dev, "MODEM hw_free failed\n");
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static void omap_abe_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+
+ if (dai->id == ABE_FRONTEND_DAI_MODEM) {
+ dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
+ __func__, substream->stream);
+
+ snd_soc_dai_shutdown(abe_priv->modem_substream[substream->stream],
+ abe_priv->modem_dai);
+ }
+
+ abe_dsp_shutdown();
+ abe_dsp_pm_put();
+
+ abe_priv->active_dais--;
+}
+
+#ifdef CONFIG_PM
+static int omap_abe_dai_suspend(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ if (++abe_priv->suspended_dais < abe_priv->active_dais)
+ return 0;
+
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ return 0;
+}
+
+static int omap_abe_dai_resume(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ if (abe_priv->suspended_dais-- < abe_priv->active_dais)
+ return 0;
+
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ return 0;
+}
+#else
+#define omap_abe_dai_suspend NULL
+#define omap_abe_dai_resume NULL
+#endif
+
+static int omap_abe_dai_probe(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv;
+ int i;
+
+ abe_priv = kzalloc(sizeof(struct omap_abe_data), GFP_KERNEL);
+ if (abe_priv == NULL)
+ return -ENOMEM;
+
+ abe_priv->abe = omap_abe_port_mgr_get();
+ if (!abe_priv->abe)
+ goto err;
+
+ for (i = 0; i <= OMAP_ABE_MAX_PORT_ID; i++) {
+
+ abe_priv->port[i] = omap_abe_port_open(abe_priv->abe, i);
+ if (abe_priv->port[i] == NULL) {
+ for (--i; i >= 0; i--)
+ omap_abe_port_close(abe_priv->abe, abe_priv->port[i]);
+
+ goto err_port;
+ }
+ }
+
+ snd_soc_dai_set_drvdata(dai, abe_priv);
+ return 0;
+
+err_port:
+ omap_abe_port_mgr_put(abe_priv->abe);
+err:
+ kfree(abe_priv);
+ return -ENOMEM;
+}
+
+static int omap_abe_dai_remove(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ omap_abe_port_mgr_put(abe_priv->abe);
+ kfree(abe_priv);
+ return 0;
+}
+
+static struct snd_soc_dai_ops omap_abe_dai_ops = {
+ .startup = omap_abe_dai_startup,
+ .shutdown = omap_abe_dai_shutdown,
+ .hw_params = omap_abe_dai_hw_params,
+ .hw_free = omap_abe_dai_hw_free,
+ .prepare = omap_abe_dai_prepare,
+ .trigger = omap_abe_dai_trigger,
+ .bespoke_trigger = omap_abe_dai_bespoke_trigger,
+};
+
+static struct snd_soc_dai_driver omap_abe_dai[] = {
+ { /* Multimedia Playback and Capture */
+ .name = "MultiMedia1",
+ .probe = omap_abe_dai_probe,
+ .remove = omap_abe_dai_remove,
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "MultiMedia1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "MultiMedia1 Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* Multimedia Capture */
+ .name = "MultiMedia2",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .capture = {
+ .stream_name = "MultiMedia2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* Voice Playback and Capture */
+ .name = "Voice",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "Voice Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Voice Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* Tones Playback */
+ .name = "Tones",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "Tones Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* Vibra */
+ .name = "Vibra",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "Vibra Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* MODEM Voice Playback and Capture */
+ .name = "MODEM",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "MODEM Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "MODEM Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+ { /* Low Power HiFi Playback */
+ .name = "MultiMedia1 LP",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
+ .playback = {
+ .stream_name = "MultiMedia1 LP Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ },
+};
+
+static int __devinit omap_abe_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_dais(&pdev->dev, omap_abe_dai,
+ ARRAY_SIZE(omap_abe_dai));
+}
+
+static int __devexit omap_abe_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(omap_abe_dai));
+ return 0;
+}
+
+static struct platform_driver omap_abe_driver = {
+ .driver = {
+ .name = "omap-abe-dai",
+ .owner = THIS_MODULE,
+ },
+ .probe = omap_abe_probe,
+ .remove = __devexit_p(omap_abe_remove),
+};
+
+static int __init omap_abe_init(void)
+{
+ return platform_driver_register(&omap_abe_driver);
+}
+module_init(omap_abe_init);
+
+static void __exit omap_abe_exit(void)
+{
+ platform_driver_unregister(&omap_abe_driver);
+}
+module_exit(omap_abe_exit);
+
+MODULE_AUTHOR("Liam Girdwood <lrg@ti.com>");
+MODULE_DESCRIPTION("OMAP ABE SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-abe.h b/sound/soc/omap/omap-abe.h
new file mode 100644
index 0000000..91c5f1d
--- /dev/null
+++ b/sound/soc/omap/omap-abe.h
@@ -0,0 +1,68 @@
+/*
+ * omap-abe.h
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Contact: Liam Girdwood <lrg@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_ABE_H__
+#define __OMAP_ABE_H__
+
+#define ABE_FRONTEND_DAI_MEDIA 0
+#define ABE_FRONTEND_DAI_MEDIA_CAPTURE 1
+#define ABE_FRONTEND_DAI_VOICE 2
+#define ABE_FRONTEND_DAI_TONES 3
+#define ABE_FRONTEND_DAI_VIBRA 4
+#define ABE_FRONTEND_DAI_MODEM 5
+#define ABE_FRONTEND_DAI_LP_MEDIA 6
+#define ABE_FRONTEND_DAI_NUM 7
+
+/* This must currently match the BE order in DSP */
+#define OMAP_ABE_DAI_PDM_UL 0
+#define OMAP_ABE_DAI_PDM_DL1 1
+#define OMAP_ABE_DAI_PDM_DL2 2
+#define OMAP_ABE_DAI_PDM_VIB 3
+#define OMAP_ABE_DAI_BT_VX 4
+#define OMAP_ABE_DAI_MM_FM 5
+#define OMAP_ABE_DAI_MODEM 6
+#define OMAP_ABE_DAI_DMIC0 7
+#define OMAP_ABE_DAI_DMIC1 8
+#define OMAP_ABE_DAI_DMIC2 9
+#define OMAP_ABE_DAI_NUM 10
+
+#define OMAP_ABE_BE_PDM_DL1 "PDM-DL1"
+#define OMAP_ABE_BE_PDM_UL1 "PDM-UL1"
+#define OMAP_ABE_BE_PDM_DL2 "PDM-DL2"
+#define OMAP_ABE_BE_PDM_VIB "PDM-VIB"
+#define OMAP_ABE_BE_BT_VX_UL "BT-VX-UL"
+#define OMAP_ABE_BE_BT_VX_DL "BT-VX-DL"
+#define OMAP_ABE_BE_MM_EXT0 "FM-EXT"
+#define OMAP_ABE_BE_MM_EXT1 "MODEM-EXT"
+#define OMAP_ABE_BE_DMIC0 "DMIC0"
+#define OMAP_ABE_BE_DMIC1 "DMIC1"
+#define OMAP_ABE_BE_DMIC2 "DMIC2"
+
+#define OMAP_ABE_DL1_NO_PDM 0
+#define OMAP_ABE_DL1_HEADSET_LP 1
+#define OMAP_ABE_DL1_HEADSET_HP 2
+#define OMAP_ABE_DL1_EARPIECE 3
+
+int omap_abe_set_dl1_output(int output);
+
+#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
new file mode 100644
index 0000000..69dd059
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.c
@@ -0,0 +1,158 @@
+/*
+ * omap-hdmi.c
+ *
+ * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ * Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include "omap-pcm.h"
+#include "omap-hdmi.h"
+
+#define DRV_NAME "hdmi-audio-dai"
+
+static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
+ .name = "HDMI playback",
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int err;
+ /*
+ * Make sure that the period bytes are multiple of the DMA packet size.
+ * Largest packet size we use is 32 32-bit words = 128 bytes
+ */
+ err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int err = 0;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ omap_hdmi_dai_dma_params.packet_size = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ omap_hdmi_dai_dma_params.packet_size = 32;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+
+ snd_soc_dai_set_dma_data(dai, substream,
+ &omap_hdmi_dai_dma_params);
+
+ return err;
+}
+
+static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+ .startup = omap_hdmi_dai_startup,
+ .hw_params = omap_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver omap_hdmi_dai = {
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = OMAP_HDMI_RATES,
+ .formats = OMAP_HDMI_FORMATS,
+ },
+ .ops = &omap_hdmi_dai_ops,
+};
+
+static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *hdmi_rsrc;
+
+ hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!hdmi_rsrc) {
+ dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
+ return -EINVAL;
+ }
+
+ omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start
+ + OMAP_HDMI_AUDIO_DMA_PORT;
+
+ hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!hdmi_rsrc) {
+ dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
+ return -EINVAL;
+ }
+
+ omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start;
+
+ ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
+ return ret;
+}
+
+static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_dai(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver hdmi_dai_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = omap_hdmi_probe,
+ .remove = __devexit_p(omap_hdmi_remove),
+};
+
+static int __init hdmi_dai_init(void)
+{
+ return platform_driver_register(&hdmi_dai_driver);
+}
+module_init(hdmi_dai_init);
+
+static void __exit hdmi_dai_exit(void)
+{
+ platform_driver_unregister(&hdmi_dai_driver);
+}
+module_exit(hdmi_dai_exit);
+
+MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
new file mode 100644
index 0000000..34c298d
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.h
@@ -0,0 +1,36 @@
+/*
+ * omap-hdmi.h
+ *
+ * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ * Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_HDMI_H__
+#define __OMAP_HDMI_H__
+
+#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
+
+#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+#endif
diff --git a/sound/soc/omap/omap-mcasp.c b/sound/soc/omap/omap-mcasp.c
new file mode 100644
index 0000000..e0a6e24
--- /dev/null
+++ b/sound/soc/omap/omap-mcasp.c
@@ -0,0 +1,722 @@
+/*
+ * ALSA SoC McASP Audio Layer for TI OMAP processor
+ *
+ * Multi-channel Audio Serial Port Driver
+ *
+ * Author: Jon Hunter <jon-hunter@ti.com>,
+ * Dan Milea <dan.milea@ti.com>,
+ *
+ * Based upon McASP driver written for TI DaVinci
+ *
+ * Copyright: (C) 2011 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/clock.h>
+#include <plat/dma.h>
+#include <plat/dma-44xx.h>
+
+#include "omap-pcm.h"
+#include "omap-mcasp.h"
+
+/*
+ * McASP register definitions
+ */
+#define OMAP_MCASP_PID_REG 0x00
+#define OMAP_MCASP_SYSCONFIG_REG 0x04
+
+#define OMAP_MCASP_PFUNC_REG 0x10
+#define OMAP_MCASP_PDIR_REG 0x14
+#define OMAP_MCASP_PDOUT_REG 0x18
+#define OMAP_MCASP_PDIN_REG 0x1c
+#define OMAP_MCASP_PDSET_REG 0x1c
+#define OMAP_MCASP_PDCLR_REG 0x20
+
+#define OMAP_MCASP_GBLCTL_REG 0x44
+#define OMAP_MCASP_AMUTE_REG 0x48
+
+#define OMAP_MCASP_TXDITCTL_REG 0x50
+
+#define OMAP_MCASP_TXMASK_REG 0xa4
+#define OMAP_MCASP_TXFMT_REG 0xa8
+#define OMAP_MCASP_TXFMCTL_REG 0xac
+
+#define OMAP_MCASP_ACLKXCTL_REG 0xb0
+#define OMAP_MCASP_AHCLKXCTL_REG 0xb4
+#define OMAP_MCASP_TXTDM_REG 0xb8
+#define OMAP_MCASP_EVTCTLX_REG 0xbc
+
+#define OMAP_MCASP_TXSTAT_REG 0xc0
+#define OMAP_MCASP_TXSTAT_MASK 0x1ff
+
+#define OMAP_MCASP_TXTDMSLOT_REG 0xc4
+#define OMAP_MCASP_TXCLKCHK_REG 0xc8
+#define OMAP_MCASP_TXEVTCTL_REG 0xcc
+
+/* Left(even TDM Slot) Channel Status Register File */
+#define OMAP_MCASP_DITCSRA_REG 0x100
+/* Right(odd TDM slot) Channel Status Register File */
+#define OMAP_MCASP_DITCSRB_REG 0x118
+/* Left(even TDM slot) User Data Register File */
+#define OMAP_MCASP_DITUDRA_REG 0x130
+/* Right(odd TDM Slot) User Data Register File */
+#define OMAP_MCASP_DITUDRB_REG 0x148
+
+/* Serializer n Control Register */
+#define OMAP_MCASP_XRSRCTL0_REG 0x180
+
+/* Transmit Buffer for Serializer */
+#define OMAP_MCASP_TXBUF0_REG 0x200
+
+/*
+ * OMAP_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
+ */
+#define AXR0 BIT(0)
+#define PFUNC_AMUTE BIT(25)
+#define ACLKX BIT(26)
+#define AHCLKX BIT(27)
+#define AFSX BIT(28)
+
+/*
+ * OMAP_MCASP_PDIR_REG - Pin Direction Register Bits
+ */
+#define AXR0 BIT(0)
+#define PDIR_AMUTE BIT(25)
+#define ACLKX BIT(26)
+#define AHCLKX BIT(27)
+#define AFSX BIT(28)
+
+/*
+ * OMAP_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
+ */
+#define DITEN BIT(0) /* Transmit DIT mode enable/disable */
+#define VA BIT(2)
+#define VB BIT(3)
+
+/*
+ * OMAP_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
+ */
+#define TXROT(val) (val)
+#define TXROT_MASK TXROT(0x7)
+#define TXSEL BIT(3)
+#define TXSSZ(val) (val<<4)
+#define TXSSZ_MASK TXSSZ(0xf<<4)
+#define TXPAD(val) (val<<13)
+#define TXORD BIT(15)
+#define FSXDLY(val) (val<<16)
+
+#define ROTATE_24 0x6
+#define SLOTSIZE_32 0xf
+
+/*
+ * OMAP_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits
+ */
+#define FSXPOL BIT(0)
+#define AFSXE BIT(1)
+#define FSXDUR BIT(4)
+#define FSXMOD(val) (val<<7)
+
+/*
+ * OMAP_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
+ */
+#define ACLKXDIV(val) (val)
+#define ACLKXE BIT(5)
+#define TX_ASYNC BIT(6)
+
+/*
+ * OMAP_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
+ * Register Bits
+ */
+#define AHCLKXDIV(val) (val)
+#define AHCLKXE BIT(15)
+
+/*
+ * OMAP_MCASP_EVTCTLX_REG - Transmitter Interrupt Control Register bits
+ */
+#define EVTCTLX_XUNDRN BIT(0)
+
+/*
+ * OMAP_MCASP_TXSTAT_REG - Transmit Status Register Bits
+ */
+#define TXSTAT_XUNDRN (0x1 << 0)
+#define TXSTAT_XSYNCERR (0x1 << 1)
+#define TXSTAT_XCKFAIL (0x1 << 2)
+#define TXSTAT_XDMSLOT (0x1 << 3)
+#define TXSTAT_XLAST (0x1 << 4)
+#define TXSTAT_XDATA (0x1 << 5)
+#define TXSTAT_XSTAFRM (0x1 << 6)
+#define TXSTAT_XDMAERR (0x1 << 7)
+#define TXSTAT_XERR (0x1 << 8)
+
+/*
+ * OMAP_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits
+ */
+#define MODE(val) (val)
+#define TXSTATE BIT(4)
+
+/*
+ * OMAP_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
+ */
+#define TXTDMS(n) (1<<n)
+
+/*
+ * OMAP_MCASP_GBLCTL_REG - Global Control Register Bits
+ */
+#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */
+#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/
+#define TXSERCLR BIT(10) /* Transmit Serializer Clear */
+#define TXSMRST BIT(11) /* Transmitter State Machine Reset */
+#define TXFSRST BIT(12) /* Frame Sync Generator Reset */
+
+/*
+ * OMAP_MCASP_AMUTE_REG - Mute Control Register Bits
+ */
+#define MUTENA(val) (val)
+#define MUTEINPOL BIT(2)
+#define MUTEINENA BIT(3)
+#define MUTEIN BIT(4)
+#define MUTEX BIT(6)
+#define MUTEFSX BIT(8)
+#define MUTEBADCLKX BIT(10)
+#define MUTETXDMAERR BIT(12)
+
+/*
+ * OMAP_MCASP_TXEVTCTL_REG - Transmitter DMA Event Control Register bits
+ */
+#define TXDATADMADIS BIT(0)
+
+#define MCASP_ALLOWED_PPM 100
+
+/*
+ * OMAP_MCASP_DITCSRA_REG/OMAP_MCASP_DITCSRB_REG
+ */
+#define OMAP_MCASP_DITCSR_44100HZ (0x0 << 24)
+#define OMAP_MCASP_DITCSR_48000HZ (0x2 << 24)
+#define OMAP_MCASP_DITCSR_32000HZ (0x3 << 24)
+#define OMAP_MCASP_DITCSR_22050HZ (0x4 << 24)
+#define OMAP_MCASP_DITCSR_24000HZ (0x6 << 24)
+#define OMAP_MCASP_DITCSR_88200HZ (0x8 << 24)
+#define OMAP_MCASP_DITCSR_96000HZ (0xA << 24)
+#define OMAP_MCASP_DITCSR_176400HZ (0xC << 24)
+#define OMAP_MCASP_DITCSR_192000HZ (0xE << 24)
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_mcasp_dai_dma_params[] = {
+ {
+ .name = "Audio playback",
+ .dma_req = OMAP44XX_DMA_MCASP1_AXEVT,
+ .data_type = OMAP_DMA_DATA_TYPE_S16,
+ .sync_mode = OMAP_DMA_SYNC_ELEMENT,
+ .port_addr = OMAP44XX_MCASP_DAT_BASE + OMAP_MCASP_TXBUF0_REG,
+ },
+};
+
+static inline void mcasp_set_bits(void __iomem *reg, u32 val)
+{
+ __raw_writel(__raw_readl(reg) | val, reg);
+}
+
+static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
+{
+ __raw_writel((__raw_readl(reg) & ~(val)), reg);
+}
+
+static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
+{
+ __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
+}
+
+static inline void mcasp_set_reg(void __iomem *reg, u32 val)
+{
+ __raw_writel(val, reg);
+}
+
+static inline u32 mcasp_get_reg(void __iomem *reg)
+{
+ return (unsigned int)__raw_readl(reg);
+}
+
+static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
+{
+ int i = 0;
+
+ mcasp_set_bits(regs, val);
+
+ /* programming GBLCTL needs to read back from GBLCTL and verfiy */
+ /* loop count is to avoid the lock-up */
+ for (i = 0; i < 1000; i++) {
+ if ((mcasp_get_reg(regs) & val) == val)
+ break;
+ }
+
+ if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
+ printk(KERN_ERR "GBLCTL write error\n");
+}
+
+static int mcasp_compute_clock_dividers(long fclk_rate, int tgt_sample_rate,
+ int *out_div_lo, int *out_div_hi)
+{
+ /* Given a particular functional clock rate and a target audio sample
+ * rate, determine the proper values for the ACLKXCTL and AHCLKXCTL, the
+ * dividers which produce the high frequency transmit master clock and
+ * the transmit clock.
+ */
+ long divisor;
+ unsigned long ppm;
+ int sample_rate, i;
+ BUG_ON(!out_div_lo);
+ BUG_ON(!out_div_hi);
+
+ /* A single S/PDIF frame requires 128 clocks */
+ divisor = DIV_ROUND_CLOSEST(fclk_rate, tgt_sample_rate << 7);
+ if (!divisor)
+ return -EINVAL;
+
+ sample_rate = (fclk_rate >> 7) / divisor;
+
+ /* ppm calculation in two steps to avoid overflow */
+ ppm = abs(tgt_sample_rate - sample_rate);
+ ppm = (1000000 * ppm) / tgt_sample_rate;
+
+ if (ppm > MCASP_ALLOWED_PPM)
+ return -EINVAL;
+
+ /* At this point, divisor holds the product of the two divider values we
+ * need to use for ACLKXCTL and AHCLKXCTL. ACLKXCTL holds a 5 bit
+ * divider [1, 32], while AHCLKXCTL holds a 12 bit divider [1, 4096].
+ * We need to make sure that we can factor divisor into two integers
+ * which will fit into these divider registers. Find the largest 5-bit
+ * + 1 value which divides divisor and use that as our smaller divider.
+ * After removing this factor from divisor, if the result is <= 4096,
+ * then we have succeeded and will be able to produce the target sample
+ * rate.
+ */
+ for (i = 32; (i > 1) && (divisor % i); --i)
+ ; /* no body */
+
+ /* Make sure to subtract one, registers hold the value of the divider
+ * minus one (IOW, to divide by 5, the register gets programmed with the
+ * value 4. */
+ *out_div_lo = i - 1;
+ *out_div_hi = (divisor / i) - 1;
+
+ return (*out_div_hi <= 4096) ? 0 : -EINVAL;
+}
+
+static int omap_mcasp_start(struct omap_mcasp *mcasp)
+{
+ int i;
+ mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXHCLKRST);
+ mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXCLKRST);
+ mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXSERCLR);
+
+ /* Wait until the DMA has loaded the first sample into TXBUF before we
+ * let the TX state machine and frame sync generator out of reset. */
+ i = 0;
+ while (1) {
+ u32 reg = mcasp_get_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG);
+ if (!(reg & TXSTAT_XDATA))
+ break;
+
+ if (++i > 1000) {
+ printk(KERN_ERR "Timeout waiting for DMA to load first"
+ " sample of audio.\n");
+ return -ETIMEDOUT;
+ }
+
+ udelay(1);
+ }
+
+ mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXSMRST);
+ mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXFSRST);
+ mcasp_clr_bits(mcasp->base + OMAP_MCASP_TXEVTCTL_REG, TXDATADMADIS);
+
+ /* enable IRQ sources */
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_EVTCTLX_REG, EVTCTLX_XUNDRN);
+
+ return 0;
+}
+
+static void omap_mcasp_stop(struct omap_mcasp *mcasp)
+{
+ /* disable IRQ sources */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_EVTCTLX_REG, 0);
+
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, 0);
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG,
+ OMAP_MCASP_TXSTAT_MASK);
+}
+
+/* S/PDIF */
+static int omap_mcasp_setup(struct omap_mcasp *mcasp, unsigned int rate)
+{
+ u32 aclkxdiv, ahclkxdiv, ditcsr;
+ int res;
+
+ /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXFMCTL_REG,
+ AFSXE | FSXMOD(0x180));
+
+ /* Set the TX clock controls : div = 1 and internal */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_ACLKXCTL_REG,
+ ACLKXE | TX_ASYNC);
+
+ /* Set the HS TX clock controls : div = 1 and internal */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_AHCLKXCTL_REG, AHCLKXE);
+
+ /* The SPDIF bit clock is derived from the McASP functional clock.
+ * The McASP has two programmable clock dividers (aclkxdiv and
+ * ahclkxdiv) that are configured via the registers MCASP_ACLKXCTL
+ * and MCASP_AHCLKXCTL. For SPDIF the bit clock frequency should be
+ * 128 * sample rate freq. The dividers are defined as part of
+ * platform data as they are dependent upon the functional clock
+ * setting. Lookup the appropriate dividers for the sampling
+ * frequency that we are playing.
+ */
+ res = mcasp_compute_clock_dividers(clk_get_rate(mcasp->fclk),
+ rate,
+ &aclkxdiv,
+ &ahclkxdiv);
+ if (res) {
+ dev_err(mcasp->dev,
+ "%s: No valid McASP config for sampling rate (%d)!\n",
+ __func__, rate);
+ return res;
+ }
+
+ switch (rate) {
+ case 22050:
+ ditcsr = OMAP_MCASP_DITCSR_22050HZ;
+ break;
+ case 24000:
+ ditcsr = OMAP_MCASP_DITCSR_24000HZ;
+ break;
+ case 32000:
+ ditcsr = OMAP_MCASP_DITCSR_32000HZ;
+ break;
+ case 44100:
+ ditcsr = OMAP_MCASP_DITCSR_44100HZ;
+ break;
+ case 48000:
+ ditcsr = OMAP_MCASP_DITCSR_48000HZ;
+ break;
+ case 88200:
+ ditcsr = OMAP_MCASP_DITCSR_88200HZ;
+ break;
+ case 96000:
+ ditcsr = OMAP_MCASP_DITCSR_96000HZ;
+ break;
+ case 176400:
+ ditcsr = OMAP_MCASP_DITCSR_176400HZ;
+ break;
+ case 192000:
+ ditcsr = OMAP_MCASP_DITCSR_192000HZ;
+ break;
+ default:
+ dev_err(mcasp->dev, "%s: Invalid sampling rate: %d\n",
+ __func__, rate);
+ return -EINVAL;
+ }
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_DITCSRA_REG, ditcsr);
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_DITCSRB_REG, ditcsr);
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_AHCLKXCTL_REG,
+ AHCLKXDIV(ahclkxdiv));
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_ACLKXCTL_REG,
+ AHCLKXDIV(aclkxdiv));
+
+ /* Configure McASP formatter */
+ mcasp_mod_bits(mcasp->base + OMAP_MCASP_TXFMT_REG,
+ TXSSZ(SLOTSIZE_32), TXSSZ_MASK);
+ mcasp_mod_bits(mcasp->base + OMAP_MCASP_TXFMT_REG, TXROT(ROTATE_24),
+ TXROT_MASK);
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXMASK_REG, 0xFFFF);
+
+ /* Set the TX tdm : for all the slots */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXTDM_REG, 0xFFFFFFFF);
+
+ /* configure the serializer for transmit mode operation */
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_XRSRCTL0_REG, MODE(1));
+
+ /* All PINS as McASP */
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_PFUNC_REG, 0);
+
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_PDIR_REG, AXR0);
+
+ /* Enable the DIT */
+ mcasp_set_bits(mcasp->base + OMAP_MCASP_TXDITCTL_REG, DITEN);
+
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG, 0xFF);
+
+ return 0;
+}
+
+static irqreturn_t omap_mcasp_irq_handler(int irq, void *data)
+{
+ struct omap_mcasp *mcasp = data;
+ u32 txstat;
+
+ txstat = mcasp_get_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG);
+ if (txstat & TXSTAT_XUNDRN) {
+ dev_err(mcasp->dev, "%s: Underrun (0x%08x)\n", __func__,
+ txstat);
+
+ /* Try to recover from this state */
+ spin_lock(&mcasp->lock);
+ if (likely(mcasp->stream_rate)) {
+ dev_err(mcasp->dev, "%s: Trying to recover\n",
+ __func__);
+ omap_mcasp_stop(mcasp);
+ omap_mcasp_setup(mcasp, mcasp->stream_rate);
+ omap_mcasp_start(mcasp);
+ }
+ spin_unlock(&mcasp->lock);
+ }
+
+ mcasp_set_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG, txstat);
+
+ return IRQ_HANDLED;
+}
+
+static int omap_mcasp_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+
+ /* HACK: Only allow C2 state */
+ pm_qos_add_request(mcasp->pm_qos, PM_QOS_CPU_DMA_LATENCY, 1150);
+
+ pm_runtime_get_sync(mcasp->dev);
+
+ return 0;
+}
+
+static void omap_mcasp_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_put_sync(mcasp->dev);
+
+ /* HACK: remove qos */
+ pm_qos_remove_request(mcasp->pm_qos);
+}
+
+static int omap_mcasp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+ int stream = substream->stream;
+
+ omap_mcasp_stop(mcasp);
+
+ if (omap_mcasp_setup(mcasp, params_rate(params)) < 0)
+ return -EPERM;
+
+ snd_soc_dai_set_dma_data(dai, substream,
+ &omap_mcasp_dai_dma_params[stream]);
+
+ return 0;
+}
+
+static int omap_mcasp_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *cpu_dai)
+{
+ struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&mcasp->lock, flags);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ mcasp->stream_rate = substream->runtime->rate;
+ ret = omap_mcasp_start(mcasp);
+ break;
+
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ mcasp->stream_rate = 0;
+ omap_mcasp_stop(mcasp);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&mcasp->lock, flags);
+
+ return ret;
+}
+
+static struct snd_soc_dai_ops omap_mcasp_dai_ops = {
+ .startup = omap_mcasp_startup,
+ .shutdown = omap_mcasp_shutdown,
+ .trigger = omap_mcasp_trigger,
+ .hw_params = omap_mcasp_hw_params,
+
+};
+
+#define MCASP_RATES (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+static struct snd_soc_dai_driver omap_mcasp_dai[] = {
+ {
+ .name = "omap-mcasp-dai",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 384,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = MCASP_RATES,
+ },
+ .ops = &omap_mcasp_dai_ops,
+ },
+};
+
+static __devinit int omap_mcasp_probe(struct platform_device *pdev)
+{
+ struct omap_mcasp *mcasp;
+ struct resource *res;
+ long fclk_rate;
+ int ret = 0;
+
+ mcasp = kzalloc(sizeof(struct omap_mcasp), GFP_KERNEL);
+ if (!mcasp)
+ return -ENOMEM;
+
+ spin_lock_init(&mcasp->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no resource\n");
+ ret = -ENODEV;
+ goto err_res;
+ }
+
+ mcasp->base = ioremap(res->start, resource_size(res));
+ if (!mcasp->base) {
+ ret = -ENOMEM;
+ goto err_res;
+ }
+
+ mcasp->irq = platform_get_irq(pdev, 0);
+ if (mcasp->irq < 0) {
+ ret = mcasp->irq;
+ goto err_irq;
+ }
+
+ ret = request_threaded_irq(mcasp->irq, NULL, omap_mcasp_irq_handler,
+ 0, "McASP", mcasp);
+ if (ret) {
+ dev_err(mcasp->dev, "IRQ request failed\n");
+ goto err_irq;
+ }
+
+ mcasp->fclk = clk_get(&pdev->dev, "mcasp_fck");
+ if (!mcasp->fclk) {
+ ret = -ENODEV;
+ goto err_clk;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ fclk_rate = clk_get_rate(mcasp->fclk);
+
+ platform_set_drvdata(pdev, mcasp);
+ mcasp->dev = &pdev->dev;
+
+ ret = snd_soc_register_dai(&pdev->dev, omap_mcasp_dai);
+ if (ret < 0)
+ goto err_dai;
+
+ /* HACK: qos */
+ mcasp->pm_qos = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
+ if (!mcasp->pm_qos) {
+ ret = -ENOMEM;
+ goto err_dai;
+ }
+
+ pm_runtime_put_sync(&pdev->dev);
+
+ return 0;
+
+err_dai:
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+err_clk:
+ free_irq(mcasp->irq, (void *)mcasp);
+err_irq:
+ iounmap(mcasp->base);
+err_res:
+ kfree(mcasp);
+ return ret;
+}
+
+static __devexit int omap_mcasp_remove(struct platform_device *pdev)
+{
+ struct omap_mcasp *mcasp = dev_get_drvdata(&pdev->dev);
+
+ snd_soc_unregister_dai(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ clk_put(mcasp->fclk);
+ free_irq(mcasp->irq, (void *)mcasp);
+ iounmap(mcasp->base);
+ /* HACK: qos */
+ kfree(mcasp->pm_qos);
+ kfree(mcasp);
+
+ return 0;
+}
+
+static struct platform_driver omap_mcasp_driver = {
+ .probe = omap_mcasp_probe,
+ .remove = omap_mcasp_remove,
+ .driver = {
+ .name = "omap-mcasp-dai",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init omap_mcasp_init(void)
+{
+ return platform_driver_register(&omap_mcasp_driver);
+}
+module_init(omap_mcasp_init);
+
+static void __exit omap_mcasp_exit(void)
+{
+ platform_driver_unregister(&omap_mcasp_driver);
+}
+module_exit(omap_mcasp_exit);
+
+MODULE_AUTHOR("Jon Hunter <jon-hunter@ti.com>");
+MODULE_DESCRIPTION("TI OMAP McASP SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcasp.h b/sound/soc/omap/omap-mcasp.h
new file mode 100644
index 0000000..30ce3f0
--- /dev/null
+++ b/sound/soc/omap/omap-mcasp.h
@@ -0,0 +1,37 @@
+/*
+ * ALSA SoC McASP Audio Layer for TI OMAP processor
+ *
+ * MCASP related definitions
+ *
+ * Author: Jon Hunter <jon-hunter@ti.com>,
+ * Dan Milea <dan.milea@ti.com>,
+ *
+ * Based upon McASP driver written for TI DaVinci
+ *
+ * Copyright: (C) 2011 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef OMAP_MCASP_H
+#define OMAP_MCASP_H
+
+#include <linux/io.h>
+#include <plat/mcasp.h>
+
+#define OMAP44XX_MCASP_CFG_BASE 0x49028000
+#define OMAP44XX_MCASP_DAT_BASE 0x4902A000
+
+struct omap_mcasp {
+ struct device *dev;
+ void __iomem *base;
+ spinlock_t lock;
+ struct clk *fclk;
+ int irq;
+ unsigned int stream_rate;
+ struct pm_qos_request_list *pm_qos;
+};
+
+#endif /* OMAP_MCASP_H */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 4b82290..8b6a510 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -258,7 +258,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
default:
return -EINVAL;
}
- if (cpu_is_omap34xx()) {
+ if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
dma_data->set_threshold = omap_mcbsp_set_threshold;
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
if (omap_mcbsp_get_dma_op_mode(bus_id) ==
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index bed09c2..601082e 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -25,7 +25,16 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -33,33 +42,54 @@
#include <sound/soc.h>
#include <plat/dma.h>
-#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include <plat/omap_hwmod.h>
+#include <plat/mcpdm.h>
+#include "../../../arch/arm/mach-omap2/cm1_44xx.h"
+#include "omap-mcpdm.h"
#include "omap-pcm.h"
-
-struct omap_mcpdm_data {
- struct omap_mcpdm_link *links;
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) ||\
+ defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+#include "omap-abe-dsp.h"
+#include "abe/abe_main.h"
+#include "abe/port_mgr.h"
+#endif
+
+#define MCPDM_LEGACY_DAI_DL1 0
+#define MCPDM_LEGACY_DAI_UL1 1
+#define MCPDM_ABE_DAI_DL1 2
+#define MCPDM_ABE_DAI_DL2 3
+#define MCPDM_ABE_DAI_VIB 4
+#define MCPDM_ABE_DAI_UL1 5
+
+#define CLKCTRL_MODULEMODE_MASK 0x0003
+#define CLKCTRL_MODULEMODE_DISABLED 0x0000
+#define CLKCTRL_MODULEMODE_ENABLED 0x0002
+
+struct omap_mcpdm {
+ struct device *dev;
+ unsigned long phys_base;
+ void __iomem *io_base;
+ int irq;
+
+ struct mutex mutex;
+ struct omap_mcpdm_platform_data *pdata;
+ struct completion irq_completion;
+ struct delayed_work esd_work;
+ struct abe *abe;
+ struct omap_abe_port *dl_port;
+ struct omap_abe_port *ul_port;
+
+ u32 *reg_cache;
+
+ /* channel data */
+ u32 dn_channels;
+ u32 up_channels;
int active;
-};
-
-static struct omap_mcpdm_link omap_mcpdm_links[] = {
- /* downlink */
- {
- .irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
- .threshold = 1,
- .format = PDMOUTFORMAT_LJUST,
- },
- /* uplink */
- {
- .irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
- .threshold = 1,
- .format = PDMOUTFORMAT_LJUST,
- },
-};
+ int abe_mode;
-static struct omap_mcpdm_data mcpdm_data = {
- .links = omap_mcpdm_links,
- .active = 0,
+ /* DC offset */
+ unsigned long dl1_offset;
+ unsigned long dl2_offset;
};
/*
@@ -84,64 +114,362 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
},
};
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm,
+ u16 reg, u32 val)
+{
+ __raw_writel(val, mcpdm->io_base + reg);
+}
+
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+ return __raw_readl(mcpdm->io_base + reg);
+}
+
+static inline void omap_mcpdm_write_cache(struct omap_mcpdm *mcpdm,
+ u16 reg, u32 val)
+{
+ mcpdm->reg_cache[reg / sizeof(u32)] = val;
+}
+
+static inline int omap_mcpdm_read_cache(struct omap_mcpdm *mcpdm, u16 reg)
+{
+ return mcpdm->reg_cache[reg / sizeof(u32)];
+}
+
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+ dev_dbg(mcpdm->dev, "***********************\n");
+ dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_IRQSTATUS_RAW));
+ dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_IRQSTATUS));
+ dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_IRQENABLE_SET));
+ dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_IRQENABLE_CLR));
+ dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_IRQWAKE_EN));
+ dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_DMAENABLE_SET));
+ dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_DMAENABLE_CLR));
+ dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_DMAWAKEEN));
+ dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_CTRL));
+ dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_DN_DATA));
+ dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_UP_DATA));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_FIFO_CTRL_DN));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_FIFO_CTRL_UP));
+ dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_DN_OFFSET));
+ dev_dbg(mcpdm->dev, "***********************\n");
+}
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
+
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP and DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
+{
+ u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_CTRL);
+
+ ctrl |= (SW_UP_RST | SW_DN_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+ ctrl |= (mcpdm->up_channels | mcpdm->dn_channels);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+ ctrl &= ~(SW_UP_RST | SW_DN_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+}
+
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP and DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+ u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_CTRL);
+
+ ctrl |= (SW_UP_RST | SW_DN_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+ ctrl &= ~(mcpdm->up_channels | mcpdm->dn_channels);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+ ctrl &= ~(SW_UP_RST | SW_DN_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl);
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+ return omap_mcpdm_read(mcpdm, MCPDM_CTRL) & (PDM_DN_MASK | PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink/downlink for audio recording/playback
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open(struct omap_mcpdm *mcpdm)
+{
+ /* Enable irq request generation */
+ omap_mcpdm_write(mcpdm, MCPDM_IRQENABLE_SET,
+ MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL |
+ MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+ /* Configure uplink threshold */
+ omap_mcpdm_write(mcpdm, MCPDM_FIFO_CTRL_UP, 2);
+ omap_mcpdm_write(mcpdm, MCPDM_FIFO_CTRL_DN, 2);
+
+ /* Configure DMA controller */
+ omap_mcpdm_write(mcpdm, MCPDM_DMAENABLE_SET,
+ DMA_UP_ENABLE | DMA_DN_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink/downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close(struct omap_mcpdm *mcpdm)
+{
+ /* Disable irq request generation */
+ omap_mcpdm_write(mcpdm, MCPDM_IRQENABLE_CLR,
+ MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL |
+ MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+ /* Disable DMA request generation */
+ omap_mcpdm_write(mcpdm, MCPDM_DMAENABLE_CLR,
+ DMA_UP_ENABLE | DMA_DN_ENABLE);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+ struct omap_mcpdm *mcpdm = dev_id;
+ int irq_status;
+
+ irq_status = omap_mcpdm_read(mcpdm, MCPDM_IRQSTATUS);
+
+ /* Acknowledge irq event */
+ omap_mcpdm_write(mcpdm, MCPDM_IRQSTATUS, irq_status);
+
+ if (irq & MCPDM_DN_IRQ_FULL)
+ dev_err(mcpdm->dev, "DN FIFO error %x\n", irq_status);
+
+ if (irq & MCPDM_DN_IRQ_EMPTY)
+ dev_err(mcpdm->dev, "DN FIFO error %x\n", irq_status);
+
+ if (irq & MCPDM_DN_IRQ)
+ dev_dbg(mcpdm->dev, "DN write request\n");
+
+ if (irq & MCPDM_UP_IRQ_FULL)
+ dev_err(mcpdm->dev, "UP FIFO error %x\n", irq_status);
+
+ if (irq & MCPDM_UP_IRQ_EMPTY)
+ dev_err(mcpdm->dev, "UP FIFO error %x\n", irq_status);
+
+ if (irq & MCPDM_UP_IRQ)
+ dev_dbg(mcpdm->dev, "UP write request\n");
+
+ return IRQ_HANDLED;
+}
+
+/* Enable/disable DC offset cancelation for the analog
+ * headset path (PDM channels 1 and 2).
+ */
+static void omap_mcpdm_set_offset(struct omap_mcpdm *mcpdm)
+{
+ int offset;
+
+ if (mcpdm->dl1_offset > DN_OFST_MAX) {
+ dev_err(mcpdm->dev, "DC DL1 offset out of range\n");
+ return;
+ }
+
+ if (mcpdm->dl2_offset > DN_OFST_MAX) {
+ dev_err(mcpdm->dev, "DC DL2 offset out of range\n");
+ return;
+ }
+
+ offset = (mcpdm->dl1_offset << DN_OFST_RX1) |
+ (mcpdm->dl2_offset << DN_OFST_RX2);
+
+ /* offset cancellation for channel 1 */
+ if (mcpdm->dl1_offset)
+ offset |= DN_OFST_RX1_EN;
+ else
+ offset &= ~DN_OFST_RX1_EN;
+
+ /* offset cancellation for channel 2 */
+ if (mcpdm->dl2_offset)
+ offset |= DN_OFST_RX2_EN;
+ else
+ offset &= ~DN_OFST_RX2_EN;
+
+ omap_mcpdm_write(mcpdm, MCPDM_DN_OFFSET, offset);
+}
+
+static ssize_t mcpdm_dl1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcpdm *mcpdm = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%ld\n", mcpdm->dl1_offset);
+}
+
+static ssize_t mcpdm_dl1_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_mcpdm *mcpdm = dev_get_drvdata(dev);
+ int ret;
+ unsigned long value;
+
+ ret = strict_strtol(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ if (value > DN_OFST_MAX)
+ return -EINVAL;
+
+ mcpdm->dl1_offset = value;
+ return count;
+}
+
+static ssize_t mcpdm_dl2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcpdm *mcpdm = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%ld\n", mcpdm->dl2_offset);
+}
+
+static ssize_t mcpdm_dl2_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_mcpdm *mcpdm = dev_get_drvdata(dev);
+ int ret;
+ unsigned long value;
+
+ ret = strict_strtol(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ if (value > DN_OFST_MAX)
+ return -EINVAL;
+
+ mcpdm->dl2_offset = value;
+ return count;
+}
+
+static DEVICE_ATTR(dl1, 0644, mcpdm_dl1_show, mcpdm_dl1_set);
+static DEVICE_ATTR(dl2, 0644, mcpdm_dl2_show, mcpdm_dl2_set);
+
static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+ u32 ctrl;
+ u32 val;
int err = 0;
- if (!dai->active)
- err = omap_mcpdm_request();
+ dev_dbg(dai->dev, "%s: active %d\n", __func__, dai->active);
+
+ mutex_lock(&mcpdm->mutex);
+
+ /* nothing to do if already active */
+ if (mcpdm->active++)
+ goto out;
+
+ if (dai->id >= MCPDM_ABE_DAI_DL1)
+ mcpdm->abe_mode = 1;
+ else
+ mcpdm->abe_mode = 0;
+
+ pm_runtime_get_sync(mcpdm->dev);
+
+ val = __raw_readl(OMAP4430_CM1_ABE_PDM_CLKCTRL);
+ if ((val & CLKCTRL_MODULEMODE_MASK) != CLKCTRL_MODULEMODE_ENABLED) {
+ WARN(1, "Clock not enabled: PDM_CLKCTRL=0x%x\n", val);
+ mcpdm->active--;
+ pm_runtime_put_sync(mcpdm->dev);
+ err = -ENODEV;
+ goto out;
+ }
+ /* Enable McPDM watch dog for ES above ES 1.0 to avoid saturation */
+ if (omap_rev() != OMAP4430_REV_ES1_0) {
+ ctrl = omap_mcpdm_read(mcpdm, MCPDM_CTRL);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, ctrl | WD_EN);
+ }
+
+ omap_mcpdm_set_offset(mcpdm);
+ omap_mcpdm_open(mcpdm);
+ schedule_delayed_work(&mcpdm->esd_work, msecs_to_jiffies(250));
+out:
+ mutex_unlock(&mcpdm->mutex);
return err;
}
static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- if (!dai->active)
- omap_mcpdm_free();
-}
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
-static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- int stream = substream->stream;
- int err = 0;
+ dev_dbg(dai->dev, "%s: active %d\n", __func__, dai->active);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!mcpdm_priv->active++)
- omap_mcpdm_start(stream);
- break;
+ mutex_lock(&mcpdm->mutex);
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (!--mcpdm_priv->active)
- omap_mcpdm_stop(stream);
- break;
- default:
- err = -EINVAL;
+ if (--mcpdm->active)
+ goto out;
+
+ if (mcpdm->abe_mode) {
+ if (omap_mcpdm_active(mcpdm)) {
+ omap_abe_port_disable(mcpdm->abe, mcpdm->dl_port);
+ omap_abe_port_disable(mcpdm->abe, mcpdm->ul_port);
+ udelay(250);
+ abe_remove_opp_req(mcpdm->dev);
+ omap_mcpdm_stop(mcpdm);
+ }
+ } else {
+ omap_mcpdm_stop(mcpdm);
}
- return err;
+ cancel_delayed_work_sync(&mcpdm->esd_work);
+ omap_mcpdm_close(mcpdm);
+
+ pm_runtime_put_sync(mcpdm->dev);
+
+out:
+ mutex_unlock(&mcpdm->mutex);
}
static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int stream = substream->stream;
- int channels, err, link_mask = 0;
+ int channels, link_mask = 0;
snd_soc_dai_set_dma_data(dai, substream,
&omap_mcpdm_dai_dma_params[stream]);
+ /* ABE DAIs have fixed channels */
+ if (mcpdm->abe_mode) {
+ mcpdm->dn_channels = PDM_DN_MASK | PDM_CMD_MASK;
+ mcpdm->up_channels = PDM_UP1_EN | PDM_UP2_EN;
+ return 0;
+ }
+
channels = params_channels(params);
switch (channels) {
case 4:
@@ -164,58 +492,224 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- mcpdm_links[stream].channels = link_mask << 3;
- err = omap_mcpdm_playback_open(&mcpdm_links[stream]);
- } else {
- mcpdm_links[stream].channels = link_mask << 0;
- err = omap_mcpdm_capture_open(&mcpdm_links[stream]);
- }
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ /* Downlink channels */
+ mcpdm->dn_channels = (link_mask << 3) & (PDM_DN_MASK | PDM_CMD_MASK);
+ else
+ /* Uplink channels */
+ mcpdm->up_channels = link_mask & (PDM_UP_MASK | PDM_STATUS_MASK);
- return err;
+ return 0;
}
-static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
- int stream = substream->stream;
- int err;
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = omap_mcpdm_playback_close(&mcpdm_links[stream]);
- else
- err = omap_mcpdm_capture_close(&mcpdm_links[stream]);
+ mutex_lock(&mcpdm->mutex);
- return err;
+ if (omap_mcpdm_active(mcpdm))
+ goto out;
+
+ if (mcpdm->abe_mode) {
+ /* Check if ABE McPDM is already started */
+ if (omap_abe_port_is_enabled(mcpdm->abe, mcpdm->ul_port) ||
+ omap_abe_port_is_enabled(mcpdm->abe, mcpdm->dl_port))
+ goto out;
+
+ /* PDM tasks require ABE OPP 50 */
+ abe_add_opp_req(mcpdm->dev, ABE_OPP_50);
+
+ /* start ATC before McPDM IP */
+ omap_abe_port_enable(mcpdm->abe, mcpdm->dl_port);
+ omap_abe_port_enable(mcpdm->abe, mcpdm->ul_port);
+
+ /* wait 250us for ABE tick */
+ udelay(250);
+ }
+
+ omap_mcpdm_start(mcpdm);
+
+out:
+ mutex_unlock(&mcpdm->mutex);
+ return 0;
+}
+
+static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "cmd %d\n", cmd);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ break;
+ default:
+ break;
+ }
+ omap_mcpdm_reg_dump(mcpdm);
+ return 0;
+}
+
+static void mcpdm_esd_work(struct work_struct *work)
+{
+ struct omap_mcpdm *mcpdm = container_of(work, struct omap_mcpdm,
+ esd_work.work);
+
+ if (omap_mcpdm_read(mcpdm, MCPDM_STATUS)) {
+ if (mcpdm->abe_mode) {
+ omap_abe_port_disable(mcpdm->abe, mcpdm->dl_port);
+ omap_abe_port_disable(mcpdm->abe, mcpdm->ul_port);
+ udelay(250);
+ }
+ omap_mcpdm_stop(mcpdm);
+
+ if (mcpdm->abe_mode) {
+ omap_abe_port_enable(mcpdm->abe, mcpdm->dl_port);
+ omap_abe_port_enable(mcpdm->abe, mcpdm->ul_port);
+ udelay(250);
+ }
+ omap_mcpdm_start(mcpdm);
+ }
+ schedule_delayed_work(&mcpdm->esd_work, msecs_to_jiffies(250));
}
static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
.startup = omap_mcpdm_dai_startup,
.shutdown = omap_mcpdm_dai_shutdown,
- .trigger = omap_mcpdm_dai_trigger,
.hw_params = omap_mcpdm_dai_hw_params,
- .hw_free = omap_mcpdm_dai_hw_free,
+ .prepare = omap_mcpdm_prepare,
+ .trigger = omap_mcpdm_dai_trigger,
};
-#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+#ifdef CONFIG_PM
+static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+ /* save context only if we are streaming */
+ if (!mcpdm->active)
+ return 0;
+
+ omap_mcpdm_write_cache(mcpdm, MCPDM_DN_OFFSET,
+ omap_mcpdm_read(mcpdm, MCPDM_DN_OFFSET));
+ omap_mcpdm_write_cache(mcpdm, MCPDM_IRQENABLE_SET,
+ omap_mcpdm_read(mcpdm, MCPDM_IRQENABLE_SET));
+ omap_mcpdm_write_cache(mcpdm, MCPDM_DMAENABLE_SET,
+ omap_mcpdm_read(mcpdm, MCPDM_DMAENABLE_SET));
+ omap_mcpdm_write_cache(mcpdm, MCPDM_FIFO_CTRL_DN,
+ omap_mcpdm_read(mcpdm, MCPDM_FIFO_CTRL_DN));
+ omap_mcpdm_write_cache(mcpdm, MCPDM_FIFO_CTRL_UP,
+ omap_mcpdm_read(mcpdm, MCPDM_FIFO_CTRL_UP));
+ omap_mcpdm_write_cache(mcpdm, MCPDM_CTRL,
+ omap_mcpdm_read(mcpdm, MCPDM_CTRL));
+
+ pm_runtime_put_sync(mcpdm->dev);
+
+ return 0;
+}
+
+static int omap_mcpdm_resume(struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+ struct omap_mcpdm_platform_data *pdata = mcpdm->pdata;
+
+ /* restore context only if we were streaming */
+ if (!mcpdm->active)
+ return 0;
+
+ if (!pdata->was_context_lost(mcpdm->dev))
+ return 0;
+
+ pm_runtime_get_sync(mcpdm->dev);
+
+ /* restore from reg cache */
+ omap_mcpdm_write(mcpdm, MCPDM_DN_OFFSET,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_DN_OFFSET));
+ omap_mcpdm_write(mcpdm, MCPDM_IRQENABLE_SET,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_IRQENABLE_SET));
+ omap_mcpdm_write(mcpdm, MCPDM_DMAENABLE_SET,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_DMAENABLE_SET));
+ omap_mcpdm_write(mcpdm, MCPDM_FIFO_CTRL_DN,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_FIFO_CTRL_DN));
+ omap_mcpdm_write(mcpdm, MCPDM_FIFO_CTRL_UP,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_FIFO_CTRL_UP));
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL,
+ omap_mcpdm_read_cache(mcpdm, MCPDM_CTRL));
-static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+ return 0;
+}
+#else
+#define omap_mcpdm_suspend NULL
+#define omap_mcpdm_resume NULL
+#endif
+
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ pm_runtime_enable(mcpdm->dev);
+
+ /* Disable lines while request is ongoing */
+ pm_runtime_get_sync(mcpdm->dev);
+ omap_mcpdm_write(mcpdm, MCPDM_CTRL, 0x00);
+
+ ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+ 0, "McPDM", (void *)mcpdm);
+ if (ret)
+ dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
+
+ pm_runtime_put_sync(mcpdm->dev);
+ return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
{
- snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+ free_irq(mcpdm->irq, (void *)mcpdm);
+ pm_runtime_disable(mcpdm->dev);
+
return 0;
}
-static struct snd_soc_dai_driver omap_mcpdm_dai = {
- .probe = omap_mcpdm_dai_probe,
+#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE
+
+static struct snd_soc_dai_driver omap_mcpdm_dai[] = {
+{
+ .name = "mcpdm-dl",
+ .id = MCPDM_LEGACY_DAI_DL1,
+ .probe = omap_mcpdm_probe,
+ .remove = omap_mcpdm_remove,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
.playback = {
.channels_min = 1,
.channels_max = 4,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
},
+ .ops = &omap_mcpdm_dai_ops,
+},
+{
+ .name = "mcpdm-ul",
+ .id = MCPDM_LEGACY_DAI_UL1,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
.capture = {
.channels_min = 1,
.channels_max = 2,
@@ -223,31 +717,196 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
.formats = OMAP_MCPDM_FORMATS,
},
.ops = &omap_mcpdm_dai_ops,
-};
+},
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) ||\
+ defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+{
+ .name = "mcpdm-dl1",
+ .id = MCPDM_ABE_DAI_DL1,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .ops = &omap_mcpdm_dai_ops,
+},
+{
+ .name = "mcpdm-dl2",
+ .id = MCPDM_ABE_DAI_DL2,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .ops = &omap_mcpdm_dai_ops,
+},
+{
+ .name = "mcpdm-vib",
+ .id = MCPDM_ABE_DAI_VIB,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .ops = &omap_mcpdm_dai_ops,
+},
+{
+ .name = "mcpdm-ul1",
+ .id = MCPDM_ABE_DAI_UL1,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
+ .suspend = omap_mcpdm_suspend,
+ .resume = omap_mcpdm_resume,
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .ops = &omap_mcpdm_dai_ops,
+},
+#endif
+ };
static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
{
- int ret;
+ struct omap_mcpdm_platform_data *pdata = pdev->dev.platform_data;
+ struct omap_mcpdm *mcpdm;
+ struct resource *res;
+ int ret = 0, err;
- ret = omap_mcpdm_probe(pdev);
- if (ret < 0)
- return ret;
- ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
+ mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+ if (!mcpdm)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mcpdm);
+
+ mutex_init(&mcpdm->mutex);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no resource\n");
+ goto err_res;
+ }
+
+ mcpdm->io_base = ioremap(res->start, resource_size(res));
+ if (!mcpdm->io_base) {
+ ret = -ENOMEM;
+ goto err_iomap;
+ }
+
+ mcpdm->reg_cache = kzalloc(resource_size(res), GFP_KERNEL);
+ if (!mcpdm->reg_cache) {
+ ret = -ENOMEM;
+ goto err_cache;
+ }
+
+ mcpdm->irq = platform_get_irq(pdev, 0);
+ if (mcpdm->irq < 0) {
+ ret = mcpdm->irq;
+ goto err_irq;
+ }
+
+ mcpdm->dev = &pdev->dev;
+ mcpdm->pdata = pdata;
+
+ /* DL1 and DL2 DC offset values will be different for each device */
+ mcpdm->dl1_offset = DN_OFST_MAX >> 1;
+ mcpdm->dl2_offset = DN_OFST_MAX >> 1;
+ err = device_create_file(mcpdm->dev, &dev_attr_dl1);
+ if (err < 0)
+ dev_err(mcpdm->dev,"failed to DL1 DC offset sysfs: %d\n", err);
+ err = device_create_file(mcpdm->dev, &dev_attr_dl2);
+ if (err < 0)
+ dev_err(mcpdm->dev,"failed to DL2 DC offset sysfs: %d\n", err);
+
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) ||\
+ defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+
+ mcpdm->abe = omap_abe_port_mgr_get();
+ if (!mcpdm->abe)
+ goto err_irq;
+
+ mcpdm->ul_port = omap_abe_port_open(mcpdm->abe, OMAP_ABE_BE_PORT_PDM_UL1);
+ if (!mcpdm->ul_port)
+ goto err_ul;
+
+ mcpdm->dl_port = omap_abe_port_open(mcpdm->abe, OMAP_ABE_BE_PORT_PDM_DL1);
+ if (!mcpdm->dl_port)
+ goto err_dl;
+#endif
+
+ INIT_DELAYED_WORK(&mcpdm->esd_work, mcpdm_esd_work);
+
+ ret = snd_soc_register_dais(&pdev->dev, omap_mcpdm_dai,
+ ARRAY_SIZE(omap_mcpdm_dai));
if (ret < 0)
- omap_mcpdm_remove(pdev);
+ goto err_dai;
+
+ return 0;
+
+err_dai:
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) ||\
+ defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ omap_abe_port_close(mcpdm->abe, mcpdm->dl_port);
+err_dl:
+ omap_abe_port_close(mcpdm->abe, mcpdm->ul_port);
+err_ul:
+ omap_abe_port_mgr_put(mcpdm->abe);
+#endif
+err_irq:
+ kfree(mcpdm->reg_cache);
+err_cache:
+ iounmap(mcpdm->io_base);
+err_iomap:
+ release_mem_region(res->start, resource_size(res));
+err_res:
+ kfree(mcpdm);
return ret;
}
static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dai(&pdev->dev);
- omap_mcpdm_remove(pdev);
+ struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(omap_mcpdm_dai));
+
+ device_remove_file(&pdev->dev, &dev_attr_dl1);
+ device_remove_file(&pdev->dev, &dev_attr_dl2);
+
+#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) ||\
+ defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
+ omap_abe_port_close(mcpdm->abe, mcpdm->dl_port);
+ omap_abe_port_close(mcpdm->abe, mcpdm->ul_port);
+ omap_abe_port_mgr_put(mcpdm->abe);
+#endif
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(mcpdm->io_base);
+ kfree(mcpdm->reg_cache);
+ kfree(mcpdm);
return 0;
}
static struct platform_driver asoc_mcpdm_driver = {
.driver = {
- .name = "omap-mcpdm-dai",
+ .name = "omap-mcpdm",
.owner = THIS_MODULE,
},
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644
index 0000000..3aa5011
--- /dev/null
+++ b/sound/soc/omap/omap-mcpdm.h
@@ -0,0 +1,120 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#include <linux/platform_device.h>
+
+#define MCPDM_REVISION 0x00
+#define MCPDM_SYSCONFIG 0x10
+#define MCPDM_IRQSTATUS_RAW 0x24
+#define MCPDM_IRQSTATUS 0x28
+#define MCPDM_IRQENABLE_SET 0x2C
+#define MCPDM_IRQENABLE_CLR 0x30
+#define MCPDM_IRQWAKE_EN 0x34
+#define MCPDM_DMAENABLE_SET 0x38
+#define MCPDM_DMAENABLE_CLR 0x3C
+#define MCPDM_DMAWAKEEN 0x40
+#define MCPDM_CTRL 0x44
+#define MCPDM_DN_DATA 0x48
+#define MCPDM_UP_DATA 0x4C
+#define MCPDM_FIFO_CTRL_DN 0x50
+#define MCPDM_FIFO_CTRL_UP 0x54
+#define MCPDM_DN_OFFSET 0x58
+#define MCPDM_STATUS 0x68
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ (1 << 0)
+#define MCPDM_DN_IRQ_EMPTY (1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2)
+#define MCPDM_DN_IRQ_FULL (1 << 3)
+
+#define MCPDM_UP_IRQ (1 << 8)
+#define MCPDM_UP_IRQ_EMPTY (1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10)
+#define MCPDM_UP_IRQ_FULL (1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK 0x00F
+#define MCPDM_UPLINK_IRQ_MASK 0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define DMA_DN_ENABLE 0x1
+#define DMA_UP_ENABLE 0x2
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define PDM_UP1_EN 0x0001
+#define PDM_UP2_EN 0x0002
+#define PDM_UP3_EN 0x0004
+#define PDM_DN1_EN 0x0008
+#define PDM_DN2_EN 0x0010
+#define PDM_DN3_EN 0x0020
+#define PDM_DN4_EN 0x0040
+#define PDM_DN5_EN 0x0080
+#define PDMOUTFORMAT 0x0100
+#define CMD_INT 0x0200
+#define STATUS_INT 0x0400
+#define SW_UP_RST 0x0800
+#define SW_DN_RST 0x1000
+#define WD_EN 0x4000
+#define PDM_UP_MASK 0x007
+#define PDM_DN_MASK 0x0F8
+#define PDM_CMD_MASK 0x200
+#define PDM_STATUS_MASK 0x400
+
+
+#define PDMOUTFORMAT_LJUST (0 << 8)
+#define PDMOUTFORMAT_RJUST (1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define UP_THRES_MAX 0xF
+#define DN_THRES_MAX 0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define DN_OFST_RX1_EN 0x0001
+#define DN_OFST_RX2_EN 0x0100
+
+#define DN_OFST_RX1 1
+#define DN_OFST_RX2 9
+#define DN_OFST_MAX 0x1F
+
+#define MCPDM_UPLINK 1
+#define MCPDM_DOWNLINK 2
+
+#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index e6a6b99..a2a464f 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -198,6 +198,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
else if (!substream->runtime->no_period_wakeup)
omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+ else {
+ /*
+ * No period wakeup:
+ * we need to disable BLOCK_IRQ, which is enabled by the omap
+ * dma core at request dma time.
+ */
+ omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
+ }
if (!(cpu_class_is_omap1())) {
omap_set_dma_src_burst_mode(prtd->dma_ch,
@@ -235,6 +243,11 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
prtd->period_index = -1;
omap_stop_dma(prtd->dma_ch);
+ /* Since we are using self linking, there is a
+ chance that the DMA as re-enabled the channel
+ just after disabling it */
+ while (omap_get_dma_active_status(prtd->dma_ch))
+ omap_stop_dma(prtd->dma_ch);
break;
default:
ret = -EINVAL;
@@ -280,6 +293,15 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
goto out;
+ if (cpu_is_omap44xx()) {
+ /* ABE needs a step of 24 * 4 data bits, and HDMI 32 * 4
+ * Ensure buffer size satisfies both constraints.
+ */
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 384);
+ if (ret < 0)
+ goto out;
+ }
prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
if (prtd == NULL) {
@@ -366,9 +388,10 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
}
-static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
@@ -376,14 +399,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = omap_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = omap_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
new file mode 100644
index 0000000..9024735
--- /dev/null
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -0,0 +1,133 @@
+/*
+ * omap4-hdmi-card.c
+ *
+ * OMAP ALSA SoC machine driver for TI OMAP4 HDMI
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+#include <video/omapdss.h>
+
+#define DRV_NAME "omap4-hdmi-audio"
+
+static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ int i, count = 0;
+ struct omap_overlay_manager *mgr = NULL;
+ struct device *dev = substream->pcm->card->dev;
+
+ /* Find DSS HDMI device */
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+ mgr = omap_dss_get_overlay_manager(i);
+ if (mgr && mgr->device
+ && mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
+ break;
+ }
+
+ if (i == omap_dss_get_num_overlay_managers()) {
+ dev_err(dev, "HDMI display device not found!\n");
+ return -ENODEV;
+ }
+
+ /* Make sure HDMI is power-on to avoid L3 interconnect errors */
+ while (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ msleep(50);
+ if (count > 5)
+ return -EIO;
+ dev_err(dev, "HDMI display is not active!\n");
+ count++;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops omap4_hdmi_dai_ops = {
+ .hw_params = omap4_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_link omap4_hdmi_dai = {
+ .name = "HDMI",
+ .stream_name = "HDMI",
+ .cpu_dai_name = "hdmi-audio-dai",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "omap-hdmi-codec",
+ .codec_dai_name = "hdmi-audio-codec",
+ .ops = &omap4_hdmi_dai_ops,
+};
+
+static struct snd_soc_card snd_soc_omap4_hdmi = {
+ .name = "OMAP4HDMI",
+ .dai_link = &omap4_hdmi_dai,
+ .num_links = 1,
+};
+
+static __devinit int omap4_hdmi_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_omap4_hdmi;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ card->dev = NULL;
+ return ret;
+ }
+ return 0;
+}
+
+static int __devexit omap4_hdmi_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ card->dev = NULL;
+ return 0;
+}
+
+static struct platform_driver omap4_hdmi_driver = {
+ .driver = {
+ .name = "omap4-hdmi-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = omap4_hdmi_probe,
+ .remove = __devexit_p(omap4_hdmi_remove),
+};
+
+static int __init omap4_hdmi_init(void)
+{
+ return platform_driver_register(&omap4_hdmi_driver);
+}
+module_init(omap4_hdmi_init);
+
+static void __exit omap4_hdmi_exit(void)
+{
+ platform_driver_unregister(&omap4_hdmi_driver);
+}
+module_exit(omap4_hdmi_exit);
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 189e039..9fc42e7 100644..100755
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -21,34 +21,133 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/i2c.h>
#include <sound/core.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include <sound/soc-dsp.h>
#include <asm/mach-types.h>
#include <plat/hardware.h>
#include <plat/mux.h>
+#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include "omap-mcpdm.h"
+#include "omap-abe.h"
+#include "omap-abe-dsp.h"
#include "omap-pcm.h"
+#include "omap-mcbsp.h"
#include "../codecs/twl6040.h"
static int twl6040_power_mode;
+static int mcbsp_cfg;
+static struct snd_soc_codec *twl6040_codec;
-static int sdp4430_hw_params(struct snd_pcm_substream *substream,
+static int sdp4430_modem_mcbsp_configure(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, int flag)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_substream *modem_substream[2];
+ struct snd_soc_pcm_runtime *modem_rtd;
+ int channels;
+
+ if (flag) {
+ modem_substream[substream->stream] =
+ snd_soc_get_dai_substream(rtd->card,
+ OMAP_ABE_BE_MM_EXT1,
+ substream->stream);
+ if (unlikely(modem_substream[substream->stream] == NULL))
+ return -ENODEV;
+
+ modem_rtd =
+ modem_substream[substream->stream]->private_data;
+
+ if (!mcbsp_cfg) {
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+
+ if (unlikely(ret < 0)) {
+ printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
+ goto exit;
+ } else {
+ mcbsp_cfg = 1;
+ }
+ }
+
+ if (params != NULL) {
+ /* Configure McBSP internal buffer usage */
+ /* this need to be done for playback and/or record */
+ channels = params_channels(params);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_mcbsp_set_rx_threshold(
+ modem_rtd->cpu_dai->id, channels);
+ else
+ omap_mcbsp_set_tx_threshold(
+ modem_rtd->cpu_dai->id, channels);
+ }
+ } else {
+ mcbsp_cfg = 0;
+ }
+
+exit:
+ return ret;
+}
+
+static int sdp4430_modem_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
+ int ret;
+
+ ret = sdp4430_modem_mcbsp_configure(substream, params, 1);
+ if (ret)
+ printk(KERN_ERR "can't set modem cpu DAI configuration\n");
+
+ return ret;
+}
+
+static int sdp4430_modem_hw_free(struct snd_pcm_substream *substream)
+{
+ int ret;
+
+ ret = sdp4430_modem_mcbsp_configure(substream, NULL, 0);
+ if (ret)
+ printk(KERN_ERR "can't clear modem cpu DAI configuration\n");
+
+ return ret;
+}
+
+static struct snd_soc_ops sdp4430_modem_ops = {
+ .hw_params = sdp4430_modem_hw_params,
+ .hw_free = sdp4430_modem_hw_free,
+};
+
+static int sdp4430_mcpdm_startup(struct snd_pcm_substream *substream)
+{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int clk_id, freq;
- int ret;
+ struct twl6040 *twl6040 = codec->control_data;
+ int clk_id, freq, ret;
+
+ /* TWL6040 supplies McPDM PAD_CLKS */
+ ret = twl6040_enable(twl6040);
+ if (ret) {
+ printk(KERN_ERR "failed to enable TWL6040\n");
+ return ret;
+ }
if (twl6040_power_mode) {
- clk_id = TWL6040_SYSCLK_SEL_HPPLL;
+ clk_id = TWL6040_HPPLL_ID;
freq = 38400000;
} else {
- clk_id = TWL6040_SYSCLK_SEL_LPPLL;
+ clk_id = TWL6040_LPPLL_ID;
freq = 32768;
}
@@ -57,15 +156,95 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
SND_SOC_CLOCK_IN);
if (ret) {
printk(KERN_ERR "can't set codec system clock\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ twl6040_disable(twl6040);
+ return ret;
+}
+
+static void sdp4430_mcpdm_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct twl6040 *twl6040 = codec->control_data;
+
+ /* TWL6040 supplies McPDM PAD_CLKS */
+ twl6040_disable(twl6040);
+}
+
+static struct snd_soc_ops sdp4430_mcpdm_ops = {
+ .startup = sdp4430_mcpdm_startup,
+ .shutdown = sdp4430_mcpdm_shutdown,
+};
+
+static int sdp4430_mcbsp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int be_id;
+
+
+ be_id = rtd->dai_link->be_id;
+
+ if (be_id == OMAP_ABE_DAI_MM_FM) {
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ } else if (be_id == OMAP_ABE_DAI_BT_VX) {
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_B |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ }
+
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
return ret;
}
+
+ /*
+ * TODO: where does this clock come from (external source??) -
+ * do we need to enable it.
+ */
+ /* Set McBSP clock to external */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
+ 64 * params_rate(params),
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ printk(KERN_ERR "can't set cpu system clock\n");
+
return ret;
}
-static struct snd_soc_ops sdp4430_ops = {
- .hw_params = sdp4430_hw_params,
+static struct snd_soc_ops sdp4430_mcbsp_ops = {
+ .hw_params = sdp4430_mcbsp_hw_params,
};
+static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ unsigned int be_id = rtd->dai_link->be_id;
+
+ if (be_id == OMAP_ABE_DAI_MM_FM)
+ channels->min = 2;
+ else if (be_id == OMAP_ABE_DAI_BT_VX)
+ channels->min = 1;
+ snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK],
+ SNDRV_PCM_FORMAT_S16_LE);
+ return 0;
+}
+
/* Headset jack */
static struct snd_soc_jack hs_jack;
@@ -95,6 +274,7 @@ static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
return 0;
twl6040_power_mode = ucontrol->value.integer.value[0];
+ abe_dsp_set_power_mode(twl6040_power_mode);
return 1;
}
@@ -146,11 +326,34 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"AFMR", NULL, "Aux/FM Stereo In"},
};
+static int sdp4430_set_pdm_dl1_gains(struct snd_soc_dapm_context *dapm)
+{
+ int output, val;
+
+ if (snd_soc_dapm_get_pin_power(dapm, "Earphone Spk")) {
+ output = OMAP_ABE_DL1_EARPIECE;
+ } else if (snd_soc_dapm_get_pin_power(dapm, "Headset Stereophone")) {
+ val = snd_soc_read(twl6040_codec, TWL6040_REG_HSLCTL);
+ if (val & TWL6040_HSDACMODEL)
+ /* HSDACL in LP mode */
+ output = OMAP_ABE_DL1_HEADSET_LP;
+ else
+ /* HSDACL in HP mode */
+ output = OMAP_ABE_DL1_HEADSET_HP;
+ } else {
+ output = OMAP_ABE_DL1_NO_PDM;
+ }
+
+ return omap_abe_set_dl1_output(output);
+}
+
static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
+ struct twl6040 *twl6040 = codec->control_data;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
+ int hsotrim, left_offset, right_offset, mode, ret;
+
/* Add SDP4430 specific controls */
ret = snd_soc_add_controls(codec, sdp4430_controls,
@@ -175,6 +378,14 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_enable_pin(dapm, "Headset Mic");
snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
+ /* allow audio paths from the audio modem to run during suspend */
+ snd_soc_dapm_ignore_suspend(dapm, "Ext Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
+ snd_soc_dapm_ignore_suspend(dapm, "AFML");
+ snd_soc_dapm_ignore_suspend(dapm, "AFMR");
+ snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone");
+
ret = snd_soc_dapm_sync(dapm);
if (ret)
return ret;
@@ -193,37 +404,454 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
else
snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
+ /* DC offset cancellation computation */
+ hsotrim = snd_soc_read(codec, TWL6040_REG_HSOTRIM);
+ right_offset = (hsotrim & TWL6040_HSRO) >> TWL6040_HSRO_OFFSET;
+ left_offset = hsotrim & TWL6040_HSLO;
+
+ if (twl6040_get_icrev(twl6040) < TWL6040_REV_1_3)
+ /* For ES under ES_1.3 HS step is 2 mV */
+ mode = 2;
+ else
+ /* For ES_1.3 HS step is 1 mV */
+ mode = 1;
+
+ abe_dsp_set_hs_offset(left_offset, right_offset, mode);
+
+ /* don't wait before switching of HS power */
+ rtd->pmdown_time = 0;
+
return ret;
}
+static int sdp4430_twl6040_dl2_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int hfotrim, left_offset, right_offset;
+
+ /* DC offset cancellation computation */
+ hfotrim = snd_soc_read(codec, TWL6040_REG_HFOTRIM);
+ right_offset = (hfotrim & TWL6040_HFRO) >> TWL6040_HFRO_OFFSET;
+ left_offset = hfotrim & TWL6040_HFLO;
+
+ abe_dsp_set_hf_offset(left_offset, right_offset);
+
+ /* don't wait before switching of HF power */
+ rtd->pmdown_time = 0;
+
+ return 0;
+}
+
+static int sdp4430_twl6040_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+
+ /* don't wait before switching of FE power */
+ rtd->pmdown_time = 0;
+
+ return 0;
+}
+
+static int sdp4430_bt_init(struct snd_soc_pcm_runtime *rtd)
+{
+
+ /* don't wait before switching of BT power */
+ rtd->pmdown_time = 0;
+
+ return 0;
+}
+
+static int sdp4430_stream_event(struct snd_soc_dapm_context *dapm)
+{
+ /*
+ * set DL1 gains dynamically according to the active output
+ * (Headset, Earpiece) and HSDAC power mode
+ */
+ return sdp4430_set_pdm_dl1_gains(dapm);
+}
+
+/* TODO: make this a separate BT CODEC driver or DUMMY */
+static struct snd_soc_dai_driver dai[] = {
+{
+ .name = "Bluetooth",
+ .playback = {
+ .stream_name = "BT Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "BT Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+},
+/* TODO: make this a separate FM CODEC driver or DUMMY */
+{
+ .name = "FM Digital",
+ .playback = {
+ .stream_name = "FM Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "FM Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+},
+{
+ .name = "HDMI",
+ .playback = {
+ .stream_name = "HDMI Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ },
+},
+};
+
+struct snd_soc_dsp_link fe_media = {
+ .playback = true,
+ .capture = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+struct snd_soc_dsp_link fe_media_capture = {
+ .capture = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+struct snd_soc_dsp_link fe_tones = {
+ .playback = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+struct snd_soc_dsp_link fe_vib = {
+ .playback = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+struct snd_soc_dsp_link fe_modem = {
+ .playback = true,
+ .capture = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+struct snd_soc_dsp_link fe_lp_media = {
+ .playback = true,
+ .trigger =
+ {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai = {
- .name = "TWL6040",
- .stream_name = "TWL6040",
- .cpu_dai_name ="omap-mcpdm-dai",
- .codec_dai_name = "twl6040-hifi",
- .platform_name = "omap-pcm-audio",
- .codec_name = "twl6040-codec",
- .init = sdp4430_twl6040_init,
- .ops = &sdp4430_ops,
+static struct snd_soc_dai_link sdp4430_dai[] = {
+
+/*
+ * Frontend DAIs - i.e. userspace visible interfaces (ALSA PCMs)
+ */
+
+ {
+ .name = "SDP4430 Media",
+ .stream_name = "Multimedia",
+
+ /* ABE components - MM-UL & MM_DL */
+ .cpu_dai_name = "MultiMedia1",
+ .platform_name = "omap-pcm-audio",
+
+ .dynamic = 1, /* BE is dynamic */
+ .init = sdp4430_twl6040_fe_init,
+ .dsp_link = &fe_media,
+ },
+ {
+ .name = "SDP4430 Media Capture",
+ .stream_name = "Multimedia Capture",
+
+ /* ABE components - MM-UL2 */
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "omap-pcm-audio",
+
+ .dynamic = 1, /* BE is dynamic */
+ .dsp_link = &fe_media_capture,
+ },
+ {
+ .name = "SDP4430 Voice",
+ .stream_name = "Voice",
+
+ /* ABE components - VX-UL & VX-DL */
+ .cpu_dai_name = "Voice",
+ .platform_name = "omap-pcm-audio",
+
+ .dynamic = 1, /* BE is dynamic */
+ .dsp_link = &fe_media,
+ .no_host_mode = SND_SOC_DAI_LINK_OPT_HOST,
+ },
+ {
+ .name = "SDP4430 Tones Playback",
+ .stream_name = "Tone Playback",
+
+ /* ABE components - TONES_DL */
+ .cpu_dai_name = "Tones",
+ .platform_name = "omap-pcm-audio",
+
+ .dynamic = 1, /* BE is dynamic */
+ .dsp_link = &fe_tones,
+ },
+ {
+ .name = "SDP4430 Vibra Playback",
+ .stream_name = "VIB-DL",
+
+ /* ABE components - DMIC UL 2 */
+ .cpu_dai_name = "Vibra",
+ .platform_name = "omap-pcm-audio",
+
+ .dynamic = 1, /* BE is dynamic */
+ .dsp_link = &fe_vib,
+ },
+ {
+ .name = "SDP4430 MODEM",
+ .stream_name = "MODEM",
+
+ /* ABE components - MODEM <-> McBSP2 */
+ .cpu_dai_name = "MODEM",
+ .platform_name = "aess",
+
+ .dynamic = 1, /* BE is dynamic */
+ .init = sdp4430_twl6040_fe_init,
+ .dsp_link = &fe_modem,
+ .ops = &sdp4430_modem_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = "SDP4430 Media LP",
+ .stream_name = "Multimedia",
+
+ /* ABE components - MM-DL (mmap) */
+ .cpu_dai_name = "MultiMedia1 LP",
+ .platform_name = "aess",
+
+ .dynamic = 1, /* BE is dynamic */
+ .dsp_link = &fe_lp_media,
+ },
+ {
+ .name = "Legacy McBSP",
+ .stream_name = "Multimedia",
+
+ /* ABE components - MCBSP2 - MM-EXT */
+ .cpu_dai_name = "omap-mcbsp-dai.1",
+ .platform_name = "omap-pcm-audio",
+
+ /* FM */
+ .codec_dai_name = "FM Digital",
+
+ .no_codec = 1, /* TODO: have a dummy CODEC */
+ .ops = &sdp4430_mcbsp_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = "Legacy McPDM",
+ .stream_name = "Headset Playback",
+
+ /* ABE components - DL1 */
+ .cpu_dai_name = "mcpdm-dl",
+ .platform_name = "omap-pcm-audio",
+
+ /* Phoenix - DL1 DAC */
+ .codec_dai_name = "twl6040-dl1",
+ .codec_name = "twl6040-codec",
+
+ .ops = &sdp4430_mcpdm_ops,
+ .ignore_suspend = 1,
+ },
+
+/*
+ * Backend DAIs - i.e. dynamically matched interfaces, invisible to userspace.
+ * Matched to above interfaces at runtime, based upon use case.
+ */
+
+ {
+ .name = OMAP_ABE_BE_PDM_DL1,
+ .stream_name = "HS Playback",
+
+ /* ABE components - DL1 */
+ .cpu_dai_name = "mcpdm-dl1",
+ .platform_name = "aess",
+
+ /* Phoenix - DL1 DAC */
+ .codec_dai_name = "twl6040-dl1",
+ .codec_name = "twl6040-codec",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .init = sdp4430_twl6040_init,
+ .ops = &sdp4430_mcpdm_ops,
+ .be_id = OMAP_ABE_DAI_PDM_DL1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = OMAP_ABE_BE_PDM_UL1,
+ .stream_name = "Analog Capture",
+
+ /* ABE components - UL1 */
+ .cpu_dai_name = "mcpdm-ul1",
+ .platform_name = "aess",
+
+ /* Phoenix - UL ADC */
+ .codec_dai_name = "twl6040-ul",
+ .codec_name = "twl6040-codec",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .ops = &sdp4430_mcpdm_ops,
+ .be_id = OMAP_ABE_DAI_PDM_UL,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = OMAP_ABE_BE_PDM_DL2,
+ .stream_name = "HF Playback",
+
+ /* ABE components - DL2 */
+ .cpu_dai_name = "mcpdm-dl2",
+ .platform_name = "aess",
+
+ /* Phoenix - DL2 DAC */
+ .codec_dai_name = "twl6040-dl2",
+ .codec_name = "twl6040-codec",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .init = sdp4430_twl6040_dl2_init,
+ .ops = &sdp4430_mcpdm_ops,
+ .be_id = OMAP_ABE_DAI_PDM_DL2,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = OMAP_ABE_BE_PDM_VIB,
+ .stream_name = "Vibra",
+
+ /* ABE components - VIB1 DL */
+ .cpu_dai_name = "mcpdm-vib",
+ .platform_name = "aess",
+
+ /* Phoenix - PDM to PWM */
+ .codec_dai_name = "twl6040-vib",
+ .codec_name = "twl6040-codec",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .ops = &sdp4430_mcpdm_ops,
+ .be_id = OMAP_ABE_DAI_PDM_VIB,
+ },
+ {
+ .name = OMAP_ABE_BE_BT_VX_UL,
+ .stream_name = "BT Capture",
+
+ /* ABE components - MCBSP1 - BT-VX */
+ .cpu_dai_name = "omap-mcbsp-dai.0",
+ .platform_name = "aess",
+
+ /* Bluetooth */
+ .codec_dai_name = "Bluetooth",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .no_codec = 1, /* TODO: have a dummy CODEC */
+ .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+ .ops = &sdp4430_mcbsp_ops,
+ .be_id = OMAP_ABE_DAI_BT_VX,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = OMAP_ABE_BE_BT_VX_DL,
+ .stream_name = "BT Playback",
+
+ /* ABE components - MCBSP1 - BT-VX */
+ .cpu_dai_name = "omap-mcbsp-dai.0",
+ .platform_name = "aess",
+
+ /* Bluetooth */
+ .codec_dai_name = "Bluetooth",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .no_codec = 1, /* TODO: have a dummy CODEC */
+ .init = sdp4430_bt_init,
+ .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+ .ops = &sdp4430_mcbsp_ops,
+ .be_id = OMAP_ABE_DAI_BT_VX,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = OMAP_ABE_BE_MM_EXT0,
+ .stream_name = "FM",
+
+ /* ABE components - MCBSP2 - MM-EXT */
+ .cpu_dai_name = "omap-mcbsp-dai.1",
+ .platform_name = "aess",
+
+ /* FM */
+ .codec_dai_name = "FM Digital",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .no_codec = 1, /* TODO: have a dummy CODEC */
+ .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+ .ops = &sdp4430_mcbsp_ops,
+ .be_id = OMAP_ABE_DAI_MM_FM,
+ },
+ {
+ .name = OMAP_ABE_BE_MM_EXT1,
+ .stream_name = "MODEM",
+
+ /* ABE components - MCBSP2 - MM-EXT */
+ .cpu_dai_name = "omap-mcbsp-dai.1",
+ .platform_name = "aess",
+
+ /* MODEM */
+ .codec_dai_name = "MODEM",
+
+ .no_pcm = 1, /* don't create ALSA pcm for this */
+ .no_codec = 1, /* TODO: have a dummy CODEC */
+ .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+ .ops = &sdp4430_mcbsp_ops,
+ .be_id = OMAP_ABE_DAI_MODEM,
+ .ignore_suspend = 1,
+ },
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_sdp4430 = {
- .name = "SDP4430",
- .dai_link = &sdp4430_dai,
- .num_links = 1,
+ .driver_name = "OMAP4",
+ .long_name = "TI OMAP4 Board",
+ .dai_link = sdp4430_dai,
+ .num_links = ARRAY_SIZE(sdp4430_dai),
+ .stream_event = sdp4430_stream_event,
};
static struct platform_device *sdp4430_snd_device;
+struct i2c_adapter *adapter;
static int __init sdp4430_soc_init(void)
{
int ret;
- if (!machine_is_omap_4430sdp())
+ if (!machine_is_omap_4430sdp() && !machine_is_omap4_panda()) {
+ pr_debug("Not SDP4430 or PandaBoard!\n");
return -ENODEV;
+ }
printk(KERN_INFO "SDP4430 SoC init\n");
+ if (machine_is_omap_4430sdp())
+ snd_soc_sdp4430.name = "SDP4430";
+ else if (machine_is_omap4_panda())
+ snd_soc_sdp4430.name = "Panda";
sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
if (!sdp4430_snd_device) {
@@ -231,14 +859,17 @@ static int __init sdp4430_soc_init(void)
return -ENOMEM;
}
+ ret = snd_soc_register_dais(&sdp4430_snd_device->dev, dai, ARRAY_SIZE(dai));
+ if (ret < 0)
+ goto err;
platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
ret = platform_device_add(sdp4430_snd_device);
if (ret)
goto err;
- /* Codec starts in HP mode */
- twl6040_power_mode = 1;
+ twl6040_codec = snd_soc_card_get_codec(&snd_soc_sdp4430,
+ "twl6040-codec");
return 0;
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index fab20a5..da28394 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -85,9 +85,11 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
-static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index ab3ccae..80c85fd 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -443,10 +443,11 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
-static int s6000_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
{
- struct snd_soc_pcm_runtime *runtime = pcm->private_data;
+ struct snd_card *card = runtime->card->snd_card;
+ struct snd_soc_dai *dai = runtime->cpu_dai;
+ struct snd_pcm *pcm = runtime->pcm;
struct s6000_pcm_dma_params *params;
int res;
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 5cb3b88..9465588 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -425,9 +425,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
static u64 dma_mask = DMA_BIT_MASK(32);
-static int dma_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int dma_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
pr_debug("Entered %s\n", __func__);
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index c326d29..db74005 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -327,10 +327,10 @@ static void camelot_pcm_free(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-static int camelot_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_pcm *pcm = rtd->pcm;
+
/* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
* in MMAP mode (i.e. aplay -M)
*/
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 4a9da6b..339a1df 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -1129,10 +1129,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-static int fsi_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_pcm *pcm = rtd->pcm;
+
/*
* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
* in MMAP mode (i.e. aplay -M)
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index a423bab..f8f6816 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -527,10 +527,11 @@ static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
return bytes_to_frames(ss->runtime, ptr);
}
-static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
/* card->dev == socdev->dev, see snd_soc_new_pcms() */
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
struct siu_info *info = siu_i2s_data;
struct platform_device *pdev = to_platform_device(card->dev);
int ret;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e2bfe1d..c171182 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -38,6 +38,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-dsp.h>
#include <sound/initval.h>
#define CREATE_TRACE_POINTS
@@ -45,7 +46,6 @@
#define NAME_SIZE 32
-static DEFINE_MUTEX(pcm_mutex);
static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
#ifdef CONFIG_DEBUG_FS
@@ -60,6 +60,7 @@ static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
+int soc_dsp_debugfs_add(struct snd_soc_pcm_runtime *rtd);
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -123,6 +124,24 @@ static int format_register_str(struct snd_soc_codec *codec,
return 0;
}
+/* ASoC no host IO hardware.
+ * TODO: fine tune these values for all host less transfers.
+ */
+static const struct snd_pcm_hardware no_host_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .period_bytes_min = PAGE_SIZE >> 2,
+ .period_bytes_max = PAGE_SIZE >> 1,
+ .periods_min = 2,
+ .periods_max = 4,
+ .buffer_bytes_max = PAGE_SIZE,
+};
+
/* codec register dump */
static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
size_t count, loff_t pos)
@@ -527,7 +546,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
* then initialized and any private data can be allocated. This also calls
* startup for the cpu DAI, platform, machine and codec DAI.
*/
-static int soc_pcm_open(struct snd_pcm_substream *substream)
+int soc_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -538,7 +557,19 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
int ret = 0;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
+ snd_soc_set_runtime_hwparams(substream, &no_host_hardware);
+
+ if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
+ ret = rtd->dai_link->ops->startup(substream);
+ if (ret < 0) {
+ printk(KERN_ERR "asoc: %s startup failed\n",
+ rtd->dai_link->name);
+ goto machine_err;
+ }
+ }
/* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) {
@@ -546,7 +577,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (ret < 0) {
printk(KERN_ERR "asoc: can't open interface %s\n",
cpu_dai->name);
- goto out;
+ goto cpu_err;
}
}
@@ -567,13 +598,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
}
- if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
- ret = rtd->dai_link->ops->startup(substream);
- if (ret < 0) {
- printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
- goto machine_err;
- }
- }
+ /* DSP DAI links compat checks are different */
+ if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
+ goto dynamic;
/* Check that the codec and cpu DAIs are compatible */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -658,6 +685,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
runtime->hw.rate_max);
+dynamic:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
cpu_dai->playback_active++;
codec_dai->playback_active++;
@@ -668,14 +696,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
cpu_dai->active++;
codec_dai->active++;
rtd->codec->active++;
- mutex_unlock(&pcm_mutex);
+ rtd->dai_link->active++;
+ mutex_unlock(&rtd->pcm_mutex);
return 0;
config_err:
- if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
- rtd->dai_link->ops->shutdown(substream);
-
-machine_err:
if (codec_dai->driver->ops->shutdown)
codec_dai->driver->ops->shutdown(substream, codec_dai);
@@ -686,8 +711,12 @@ codec_dai_err:
platform_err:
if (cpu_dai->driver->ops->shutdown)
cpu_dai->driver->ops->shutdown(substream, cpu_dai);
-out:
- mutex_unlock(&pcm_mutex);
+cpu_err:
+ if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
+ rtd->dai_link->ops->shutdown(substream);
+
+machine_err:
+ mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -702,7 +731,7 @@ static void close_delayed_work(struct work_struct *work)
container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
pr_debug("pop wq checking: %s status: %s waiting: %s\n",
codec_dai->driver->playback.stream_name,
@@ -717,7 +746,7 @@ static void close_delayed_work(struct work_struct *work)
SND_SOC_DAPM_STREAM_STOP);
}
- mutex_unlock(&pcm_mutex);
+ mutex_unlock(&rtd->pcm_mutex);
}
/*
@@ -725,7 +754,7 @@ static void close_delayed_work(struct work_struct *work)
* freed here. The cpu DAI, codec DAI, machine and platform are also
* shutdown.
*/
-static int soc_codec_close(struct snd_pcm_substream *substream)
+int soc_pcm_close(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
@@ -733,7 +762,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
cpu_dai->playback_active--;
@@ -746,6 +775,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
cpu_dai->active--;
codec_dai->active--;
codec->active--;
+ rtd->dai_link->active--;
/* Muting the DAC suppresses artifacts caused during digital
* shutdown, for example from stopping clocks.
@@ -759,11 +789,12 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->shutdown)
codec_dai->driver->ops->shutdown(substream, codec_dai);
+ if (platform->driver->ops && platform->driver->ops->close)
+ platform->driver->ops->close(substream);
+
if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
rtd->dai_link->ops->shutdown(substream);
- if (platform->driver->ops && platform->driver->ops->close)
- platform->driver->ops->close(substream);
cpu_dai->runtime = NULL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -778,7 +809,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
SND_SOC_DAPM_STREAM_STOP);
}
- mutex_unlock(&pcm_mutex);
+ mutex_unlock(&rtd->pcm_mutex);
return 0;
}
@@ -787,7 +818,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
* rate, etc. This function is non atomic and can be called multiple times,
* it can refer to the runtime info.
*/
-static int soc_pcm_prepare(struct snd_pcm_substream *substream)
+int soc_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
@@ -795,7 +826,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret = 0;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
ret = rtd->dai_link->ops->prepare(substream);
@@ -848,7 +879,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
snd_soc_dai_digital_mute(codec_dai, 0);
out:
- mutex_unlock(&pcm_mutex);
+ mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -857,7 +888,7 @@ out:
* function can also be called multiple times and can allocate buffers
* (using snd_pcm_lib_* ). It's non-atomic.
*/
-static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
+int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -866,7 +897,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret = 0;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
ret = rtd->dai_link->ops->hw_params(substream, params);
@@ -905,8 +936,21 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
rtd->rate = params_rate(params);
+ /* malloc a page for hostless IO.
+ * FIXME: rework with alsa-lib changes so that this malloc is not required.
+ */
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
+ substream->dma_buffer.dev.dev = &rtd->dev;
+ substream->dma_buffer.dev.dev->coherent_dma_mask = ISA_DMA_THRESHOLD;
+ substream->dma_buffer.private_data = NULL;
+
+ ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
+ if (ret < 0)
+ goto platform_err;
+ }
out:
- mutex_unlock(&pcm_mutex);
+ mutex_unlock(&rtd->pcm_mutex);
return ret;
platform_err:
@@ -921,14 +965,14 @@ codec_err:
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
rtd->dai_link->ops->hw_free(substream);
- mutex_unlock(&pcm_mutex);
+ mutex_unlock(&rtd->pcm_mutex);
return ret;
}
/*
* Frees resources allocated by hw_params, can be called multiple times
*/
-static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
+int soc_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
@@ -936,7 +980,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec;
- mutex_lock(&pcm_mutex);
+ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
/* apply codec digital mute */
if (!codec->active)
@@ -957,11 +1001,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai);
- mutex_unlock(&pcm_mutex);
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
+ snd_pcm_lib_free_pages(substream);
+ mutex_unlock(&rtd->pcm_mutex);
return 0;
}
-static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
@@ -989,12 +1035,40 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
+int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ if (codec_dai->driver->ops->bespoke_trigger) {
+ ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (platform->driver->bespoke_trigger) {
+ ret = platform->driver->bespoke_trigger(substream, cmd);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (cpu_dai->driver->ops->bespoke_trigger) {
+ ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
/*
* soc level wrapper for pointer callback
* If cpu_dai, codec_dai, platform driver has the delay callback, than
* the runtime->delay will be updated accordingly.
*/
-static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
+snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
@@ -1021,16 +1095,74 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
-/* ASoC PCM operations */
-static struct snd_pcm_ops soc_pcm_ops = {
- .open = soc_pcm_open,
- .close = soc_codec_close,
- .hw_params = soc_pcm_hw_params,
- .hw_free = soc_pcm_hw_free,
- .prepare = soc_pcm_prepare,
- .trigger = soc_pcm_trigger,
- .pointer = soc_pcm_pointer,
-};
+static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+
+ if (platform->driver->ops->ioctl)
+ return platform->driver->ops->ioctl(substream, cmd, arg);
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+struct snd_soc_codec *snd_soc_card_get_codec(struct snd_soc_card *card,
+ const char *codec_name)
+{
+ struct snd_soc_codec *codec = NULL;
+
+ list_for_each_entry(codec, &card->codec_dev_list, card_list) {
+ if (!strcmp(codec->name, codec_name))
+ return codec;
+ }
+
+ return codec;
+}
+EXPORT_SYMBOL(snd_soc_card_get_codec);
+
+int snd_soc_card_active_links(struct snd_soc_card *card)
+{
+ int i;
+ int count = 0;
+
+ for (i = 0; i < card->num_rtd; i++) {
+ /* count FEs: dynamic and legacy */
+ if (!card->rtd[i].dai_link->no_pcm)
+ count += card->rtd[i].dai_link->active;
+ }
+
+ return count;
+}
+EXPORT_SYMBOL(snd_soc_card_active_links);
+
+struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
+ const char *dai_link, int stream)
+{
+ int i;
+
+ for (i = 0; i < card->num_links; i++) {
+ if (card->rtd[i].dai_link->no_pcm &&
+ !strcmp(card->rtd[i].dai_link->name, dai_link))
+ return card->rtd[i].pcm->streams[stream].substream;
+ }
+ dev_dbg(card->dev, "failed to find dai link %s\n", dai_link);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
+
+struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
+ const char *dai_link)
+{
+ int i;
+
+ for (i = 0; i < card->num_links; i++) {
+ if (!strcmp(card->rtd[i].dai_link->name, dai_link))
+ return &card->rtd[i];
+ }
+ dev_dbg(card->dev, "failed to find rtd %s\n", dai_link);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
#ifdef CONFIG_PM_SLEEP
/* powers down audio subsystem for suspend */
@@ -1040,6 +1172,9 @@ int snd_soc_suspend(struct device *dev)
struct snd_soc_codec *codec;
int i;
+ /* cancel pending deferred resume if any */
+ cancel_work_sync(&card->deferred_resume_work);
+
/* If the initialization of this soc device failed, there is no codec
* associated with it. Just bail out in this case.
*/
@@ -1061,16 +1196,22 @@ int snd_soc_suspend(struct device *dev)
struct snd_soc_dai *dai = card->rtd[i].codec_dai;
struct snd_soc_dai_driver *drv = dai->driver;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (drv->ops->digital_mute && dai->playback_active)
- drv->ops->digital_mute(dai, 1);
+ if (card->rtd[i].dai_link->dynamic)
+ soc_dsp_be_digital_mute(&card->rtd[i], 1);
+ else {
+ if (drv->ops->digital_mute && dai->playback_active)
+ drv->ops->digital_mute(dai, 1);
+ }
}
/* suspend all pcms */
for (i = 0; i < card->num_rtd; i++) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
snd_pcm_suspend_all(card->rtd[i].pcm);
@@ -1083,14 +1224,19 @@ int snd_soc_suspend(struct device *dev)
struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
struct snd_soc_platform *platform = card->rtd[i].platform;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
- cpu_dai->driver->suspend(cpu_dai);
- if (platform->driver->suspend && !platform->suspended) {
- platform->driver->suspend(cpu_dai);
- platform->suspended = 1;
+ if (card->rtd[i].dai_link->dynamic) {
+ soc_dsp_fe_suspend(&card->rtd[i]);
+ } else {
+ if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
+ cpu_dai->driver->suspend(cpu_dai);
+ if (platform->driver->suspend && !platform->suspended) {
+ platform->driver->suspend(cpu_dai);
+ platform->suspended = 1;
+ }
}
}
@@ -1103,7 +1249,8 @@ int snd_soc_suspend(struct device *dev)
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
if (driver->playback.stream_name != NULL)
@@ -1137,11 +1284,15 @@ int snd_soc_suspend(struct device *dev)
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
- cpu_dai->driver->suspend(cpu_dai);
+ if (card->rtd[i].dai_link->dynamic)
+ soc_dsp_be_ac97_cpu_dai_suspend(&card->rtd[i]);
+ else
+ if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
+ cpu_dai->driver->suspend(cpu_dai);
}
if (card->suspend_post)
@@ -1177,11 +1328,15 @@ static void soc_resume_deferred(struct work_struct *work)
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
- cpu_dai->driver->resume(cpu_dai);
+ if (card->rtd[i].dai_link->dynamic)
+ soc_dsp_be_ac97_cpu_dai_resume(&card->rtd[i]);
+ else
+ if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
+ cpu_dai->driver->resume(cpu_dai);
}
list_for_each_entry(codec, &card->codec_dev_list, card_list) {
@@ -1206,7 +1361,8 @@ static void soc_resume_deferred(struct work_struct *work)
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
if (driver->playback.stream_name != NULL)
@@ -1223,25 +1379,35 @@ static void soc_resume_deferred(struct work_struct *work)
struct snd_soc_dai *dai = card->rtd[i].codec_dai;
struct snd_soc_dai_driver *drv = dai->driver;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (drv->ops->digital_mute && dai->playback_active)
- drv->ops->digital_mute(dai, 0);
+ if (card->rtd[i].dai_link->dynamic)
+ soc_dsp_be_digital_mute(&card->rtd[i], 0);
+ else {
+ if (drv->ops->digital_mute && dai->playback_active)
+ drv->ops->digital_mute(dai, 0);
+ }
}
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
struct snd_soc_platform *platform = card->rtd[i].platform;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (card->rtd[i].dai_link->ignore_suspend ||
+ card->rtd[i].dai_link->no_pcm)
continue;
- if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
- cpu_dai->driver->resume(cpu_dai);
- if (platform->driver->resume && platform->suspended) {
- platform->driver->resume(cpu_dai);
- platform->suspended = 0;
+ if (card->rtd[i].dai_link->dynamic) {
+ soc_dsp_fe_resume(&card->rtd[i]);
+ } else {
+ if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
+ cpu_dai->driver->resume(cpu_dai);
+ if (platform->driver->resume && platform->suspended) {
+ platform->driver->resume(cpu_dai);
+ platform->suspended = 0;
+ }
}
}
@@ -1286,8 +1452,30 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
#define snd_soc_resume NULL
#endif
+#define NULL_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |\
+ SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |\
+ SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32)
+
static struct snd_soc_dai_ops null_dai_ops = {
};
+static struct snd_soc_dai_driver null_codec_dai_drv = {
+ .name = "null-codec-dai",
+ .ops = &null_dai_ops,
+ .capture = {
+ .channels_min = 1 ,
+ .channels_max = 16,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = NULL_FORMATS,
+ },
+ .playback = {
+ .channels_min = 1 ,
+ .channels_max = 16,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = NULL_FORMATS,
+ },
+};
+static struct snd_soc_codec_driver null_codec_drv = {};
static int soc_bind_dai_link(struct snd_soc_card *card, int num)
{
@@ -1329,7 +1517,7 @@ find_codec:
/* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
list_for_each_entry(codec_dai, &dai_list, list) {
- if (codec->dev == codec_dai->dev &&
+ if ((codec->dev == codec_dai->dev || codec->driver == &null_codec_drv) &&
!strcmp(codec_dai->name, dai_link->codec_dai_name)) {
rtd->codec_dai = codec_dai;
goto find_platform;
@@ -1396,7 +1584,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
module_put(codec->dev->driver->owner);
}
-static void soc_remove_dai_link(struct snd_soc_card *card, int num)
+static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_codec *codec = rtd->codec;
@@ -1413,7 +1601,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}
/* remove the CODEC DAI */
- if (codec_dai && codec_dai->probed) {
+ if (codec_dai && codec_dai->probed &&
+ codec_dai->driver->remove_order == order) {
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
@@ -1421,10 +1610,12 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}
codec_dai->probed = 0;
list_del(&codec_dai->card_list);
+ module_put(codec_dai->dev->driver->owner);
}
/* remove the platform */
- if (platform && platform->probed) {
+ if (platform && platform->probed &&
+ platform->driver->remove_order == order) {
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
@@ -1436,11 +1627,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}
/* remove the CODEC */
- if (codec && codec->probed)
+ if (codec && codec->probed &&
+ codec->driver->remove_order == order)
soc_remove_codec(codec);
/* remove the cpu_dai */
- if (cpu_dai && cpu_dai->probed) {
+ if (cpu_dai && cpu_dai->probed &&
+ cpu_dai->driver->remove_order == order) {
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
@@ -1454,11 +1647,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
static void soc_remove_dai_links(struct snd_soc_card *card)
{
- int i;
-
- for (i = 0; i < card->num_rtd; i++)
- soc_remove_dai_link(card, i);
+ int dai, order;
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ for (dai = 0; dai < card->num_rtd; dai++)
+ soc_remove_dai_link(card, dai, order);
+ }
card->num_rtd = 0;
}
@@ -1575,6 +1770,11 @@ static int soc_post_component_init(struct snd_soc_card *card,
rtd->dev.parent = card->dev;
rtd->dev.release = rtd_release;
rtd->dev.init_name = name;
+ mutex_init(&rtd->pcm_mutex);
+ INIT_LIST_HEAD(&rtd->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
+ INIT_LIST_HEAD(&rtd->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients);
+ INIT_LIST_HEAD(&rtd->dsp[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
+ INIT_LIST_HEAD(&rtd->dsp[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
ret = device_register(&rtd->dev);
if (ret < 0) {
dev_err(card->dev,
@@ -1596,10 +1796,21 @@ static int soc_post_component_init(struct snd_soc_card *card,
dev_err(codec->dev,
"asoc: failed to add codec sysfs files: %d\n", ret);
+#ifdef CONFIG_DEBUG_FS
+ /* add DSP sysfs entries */
+ if (!dai_link->dynamic)
+ goto out;
+
+ ret = soc_dsp_debugfs_add(rtd);
+ if (ret < 0)
+ dev_err(&rtd->dev, "asoc: failed to add dsp sysfs entries: %d\n", ret);
+
+out:
+#endif
return 0;
}
-static int soc_probe_dai_link(struct snd_soc_card *card, int num)
+static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_dai_link *dai_link = &card->dai_link[num];
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
@@ -1608,19 +1819,22 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
int ret;
- dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
+ dev_dbg(card->dev, "probe %s dai link %d late %d\n",
+ card->name, num, order);
/* config components */
codec_dai->codec = codec;
cpu_dai->platform = platform;
codec_dai->card = card;
cpu_dai->card = card;
+ codec->dapm.card = platform->dapm.card = card;
/* set default power off timeout */
rtd->pmdown_time = pmdown_time;
/* probe the cpu_dai */
- if (!cpu_dai->probed) {
+ if (!cpu_dai->probed &&
+ cpu_dai->driver->probe_order == order) {
if (!try_module_get(cpu_dai->dev->driver->owner))
return -ENODEV;
@@ -1639,17 +1853,20 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
}
/* probe the CODEC */
- if (!codec->probed) {
+ if (!codec->probed &&
+ codec->driver->probe_order == order) {
ret = soc_probe_codec(card, codec);
if (ret < 0)
return ret;
}
/* probe the platform */
- if (!platform->probed) {
+ if (!platform->probed &&
+ platform->driver->probe_order == order) {
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
+ platform->card = card;
if (platform->driver->probe) {
ret = platform->driver->probe(platform);
if (ret < 0) {
@@ -1665,12 +1882,15 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
}
/* probe the CODEC DAI */
- if (!codec_dai->probed) {
+ if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
+ if (!try_module_get(codec_dai->dev->driver->owner))
+ return -ENODEV;
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
codec_dai->name);
+ module_put(codec_dai->dev->driver->owner);
return ret;
}
}
@@ -1680,6 +1900,10 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
list_add(&codec_dai->card_list, &card->dai_dev_list);
}
+ /* complete DAI probe during last probe */
+ if (order != SND_SOC_COMP_ORDER_LAST)
+ return 0;
+
/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
@@ -1820,7 +2044,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
enum snd_soc_compress_type compress_type;
- int ret, i;
+ int ret, i, order;
mutex_lock(&card->mutex);
@@ -1876,6 +2100,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
card->dapm.bias_level = SND_SOC_BIAS_OFF;
card->dapm.dev = card->dev;
card->dapm.card = card;
+ card->dapm.stream_event = card->stream_event;
list_add(&card->dapm.list, &card->dapm_list);
#ifdef CONFIG_DEBUG_FS
@@ -1898,12 +2123,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
goto card_probe_error;
}
- for (i = 0; i < card->num_links; i++) {
- ret = soc_probe_dai_link(card, i);
- if (ret < 0) {
- pr_err("asoc: failed to instantiate card %s: %d\n",
+ /* early DAI link probe */
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_probe_dai_link(card, i, order);
+ if (ret < 0) {
+ pr_err("asoc: failed to instantiate card %s: %d\n",
card->name, ret);
- goto probe_dai_err;
+ goto probe_dai_err;
+ }
}
}
@@ -2092,6 +2321,11 @@ int snd_soc_poweroff(struct device *dev)
}
EXPORT_SYMBOL_GPL(snd_soc_poweroff);
+void soc_shutdown(struct platform_device *pdev)
+{
+ snd_soc_poweroff(&pdev->dev);
+}
+
const struct dev_pm_ops snd_soc_pm_ops = {
.suspend = snd_soc_suspend,
.resume = snd_soc_resume,
@@ -2108,6 +2342,7 @@ static struct platform_driver soc_driver = {
},
.probe = soc_probe,
.remove = soc_remove,
+ .shutdown = soc_shutdown,
};
/* create a new pcm */
@@ -2117,6 +2352,7 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_pcm_substream *substream[2];
struct snd_pcm *pcm;
char new_name[64];
int ret = 0, playback = 0, capture = 0;
@@ -2125,10 +2361,15 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
snprintf(new_name, sizeof(new_name), "%s %s-%d",
rtd->dai_link->stream_name, codec_dai->name, num);
- if (codec_dai->driver->playback.channels_min)
- playback = 1;
- if (codec_dai->driver->capture.channels_min)
- capture = 1;
+ if (rtd->dai_link->dynamic) {
+ playback = rtd->dai_link->dsp_link->playback;
+ capture = rtd->dai_link->dsp_link->capture;
+ } else {
+ if (codec_dai->driver->playback.channels_min)
+ playback = 1;
+ if (codec_dai->driver->capture.channels_min)
+ capture = 1;
+ }
dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
ret = snd_pcm_new(rtd->card->snd_card, new_name,
@@ -2140,25 +2381,67 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->pcm = pcm;
pcm->private_data = rtd;
+
+ substream[SNDRV_PCM_STREAM_PLAYBACK] =
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ substream[SNDRV_PCM_STREAM_CAPTURE] =
+ pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+
+ if (rtd->dai_link->no_pcm) {
+ if (playback)
+ substream[SNDRV_PCM_STREAM_PLAYBACK]->private_data = rtd;
+ if (capture)
+ substream[SNDRV_PCM_STREAM_CAPTURE]->private_data = rtd;
+ goto out;
+ }
+
+ /* setup any hostless PCMs - i.e. no host IO is performed */
+ if (rtd->dai_link->no_host_mode) {
+ substream[SNDRV_PCM_STREAM_PLAYBACK]->hw_no_buffer = 1;
+ substream[SNDRV_PCM_STREAM_CAPTURE]->hw_no_buffer = 1;
+ snd_soc_set_runtime_hwparams(substream[SNDRV_PCM_STREAM_PLAYBACK],
+ &no_host_hardware);
+ snd_soc_set_runtime_hwparams(substream[SNDRV_PCM_STREAM_CAPTURE],
+ &no_host_hardware);
+ }
+
+ /* ASoC PCM operations */
+ if (rtd->dai_link->dynamic) {
+ rtd->ops.open = soc_dsp_fe_dai_open;
+ rtd->ops.hw_params = soc_dsp_fe_dai_hw_params;
+ rtd->ops.prepare = soc_dsp_fe_dai_prepare;
+ rtd->ops.trigger = soc_dsp_fe_dai_trigger;
+ rtd->ops.hw_free = soc_dsp_fe_dai_hw_free;
+ rtd->ops.close = soc_dsp_fe_dai_close;
+ rtd->ops.pointer = soc_pcm_pointer;
+ rtd->ops.ioctl = soc_pcm_ioctl;
+ } else {
+ rtd->ops.open = soc_pcm_open;
+ rtd->ops.hw_params = soc_pcm_hw_params;
+ rtd->ops.prepare = soc_pcm_prepare;
+ rtd->ops.trigger = soc_pcm_trigger;
+ rtd->ops.hw_free = soc_pcm_hw_free;
+ rtd->ops.close = soc_pcm_close;
+ rtd->ops.pointer = soc_pcm_pointer;
+ rtd->ops.ioctl = soc_pcm_ioctl;
+ }
+
if (platform->driver->ops) {
- soc_pcm_ops.mmap = platform->driver->ops->mmap;
- soc_pcm_ops.pointer = platform->driver->ops->pointer;
- soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
- soc_pcm_ops.copy = platform->driver->ops->copy;
- soc_pcm_ops.silence = platform->driver->ops->silence;
- soc_pcm_ops.ack = platform->driver->ops->ack;
- soc_pcm_ops.page = platform->driver->ops->page;
+ rtd->ops.ack = platform->driver->ops->ack;
+ rtd->ops.copy = platform->driver->ops->copy;
+ rtd->ops.silence = platform->driver->ops->silence;
+ rtd->ops.page = platform->driver->ops->page;
+ rtd->ops.mmap = platform->driver->ops->mmap;
}
if (playback)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
if (capture)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
if (platform->driver->pcm_new) {
- ret = platform->driver->pcm_new(rtd->card->snd_card,
- codec_dai, pcm);
+ ret = platform->driver->pcm_new(rtd);
if (ret < 0) {
pr_err("asoc: platform pcm constructor failed\n");
return ret;
@@ -2166,6 +2449,7 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
}
pcm->private_free = platform->driver->pcm_free;
+out:
printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
@@ -2189,6 +2473,28 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
+unsigned int snd_soc_platform_read(struct snd_soc_platform *platform,
+ unsigned int reg)
+{
+ unsigned int ret;
+
+ ret = platform->driver->read(platform, reg);
+ dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
+ trace_snd_soc_preg_read(platform, reg, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_read);
+
+unsigned int snd_soc_platform_write(struct snd_soc_platform *platform,
+ unsigned int reg, unsigned int val)
+{
+ dev_dbg(platform->dev, "write %x = %x\n", reg, val);
+ trace_snd_soc_preg_write(platform, reg, val);
+ return platform->driver->write(platform, reg, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_write);
+
/**
* snd_soc_codec_readable_register: Report if a register is readable.
*
@@ -2411,6 +2717,8 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
const struct snd_pcm_hardware *hw)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ if (!runtime)
+ return 0;
runtime->hw.info = hw->info;
runtime->hw.formats = hw->formats;
runtime->hw.period_bytes_min = hw->period_bytes_min;
@@ -2504,6 +2812,36 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
EXPORT_SYMBOL_GPL(snd_soc_add_controls);
/**
+ * snd_soc_add_platform_controls - add an array of controls to a platform.
+ * Convienience function to add a list of controls.
+ *
+ * @platform: platform to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = platform->card->snd_card;
+ int err, i;
+
+ for (i = 0; i < num_controls; i++) {
+ const struct snd_kcontrol_new *control = &controls[i];
+ err = snd_ctl_add(card, snd_soc_cnew(control, platform,
+ control->name, NULL));
+ if (err < 0) {
+ dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
+
+/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
@@ -2525,7 +2863,8 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
if (uinfo->value.enumerated.item > e->max - 1)
uinfo->value.enumerated.item = e->max - 1;
strcpy(uinfo->value.enumerated.name,
- e->texts[uinfo->value.enumerated.item]);
+ snd_soc_get_enum_text(e, uinfo->value.enumerated.item));
+
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
@@ -2689,7 +3028,7 @@ int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
if (uinfo->value.enumerated.item > e->max - 1)
uinfo->value.enumerated.item = e->max - 1;
strcpy(uinfo->value.enumerated.name,
- e->texts[uinfo->value.enumerated.item]);
+ snd_soc_get_enum_text(e, uinfo->value.enumerated.item));
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
@@ -3370,6 +3709,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
int snd_soc_register_card(struct snd_soc_card *card)
{
int i;
+ int ret = 0;
if (!card->name || !card->dev)
return -EINVAL;
@@ -3387,12 +3727,43 @@ int snd_soc_register_card(struct snd_soc_card *card)
return -ENOMEM;
card->rtd_aux = &card->rtd[card->num_links];
- for (i = 0; i < card->num_links; i++)
+ for (i = 0; i < card->num_links; i++) {
card->rtd[i].dai_link = &card->dai_link[i];
+ if (card->rtd[i].dai_link->dynamic) {
+
+ card->rtd[i].dai_link->codec_name = "null-codec";
+ card->rtd[i].dai_link->codec_dai_name = "null-codec-dai";
+
+ ret = snd_soc_register_codec(card->dev, &null_codec_drv,
+ &null_codec_dai_drv, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to register dynamic DAI link %d\n",
+ __func__, ret);
+ goto out;
+ }
+
+ continue;
+ }
+ if (card->rtd[i].dai_link->no_codec) {
+ card->rtd[i].dai_link->codec_name = "null-codec";
+
+ ret = snd_soc_register_codec(card->dev, &null_codec_drv,
+ &null_codec_dai_drv, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to register dynamic DAI link %d\n",
+ __func__, ret);
+ goto out;
+ }
+ continue;
+ }
+ }
INIT_LIST_HEAD(&card->list);
card->instantiated = 0;
mutex_init(&card->mutex);
+ mutex_init(&card->dapm_mutex);
+ mutex_init(&card->dsp_mutex);
+ mutex_init(&card->power_mutex);
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
@@ -3401,7 +3772,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
dev_dbg(card->dev, "Registered card '%s'\n", card->name);
- return 0;
+out:
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_register_card);
@@ -3646,7 +4018,10 @@ int snd_soc_register_platform(struct device *dev,
}
platform->dev = dev;
+ platform->dapm.platform = platform;
platform->driver = platform_drv;
+ platform->dapm.dev = dev;
+ platform->dapm.stream_event = platform_drv->stream_event;
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
@@ -3739,7 +4114,10 @@ int snd_soc_register_codec(struct device *dev,
return -ENOMEM;
/* create CODEC component name */
- codec->name = fmt_single_name(dev, &codec->id);
+ if (codec_drv == &null_codec_drv)
+ codec->name = kstrdup("null-codec", GFP_KERNEL);
+ else
+ codec->name = fmt_single_name(dev, &codec->id);
if (codec->name == NULL) {
kfree(codec);
return -ENOMEM;
@@ -3759,6 +4137,7 @@ int snd_soc_register_codec(struct device *dev,
codec->dapm.dev = dev;
codec->dapm.codec = codec;
codec->dapm.seq_notifier = codec_drv->seq_notifier;
+ codec->dapm.stream_event = codec_drv->stream_event;
codec->dev = dev;
codec->driver = codec_drv;
codec->num_dai = num_dai;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 0c9dee2..042d4ae 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -48,6 +48,10 @@
#include <trace/events/asoc.h>
+#define PATH_MAX_HOPS 16
+
+int soc_dsp_runtime_update(struct snd_soc_dapm_widget *);
+
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 0,
@@ -126,6 +130,390 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
}
+static inline struct snd_card *dapm_get_card(struct snd_soc_dapm_context *dapm)
+{
+ if (dapm->codec)
+ return dapm->codec->card->snd_card;
+ else if (dapm->platform)
+ return dapm->platform->card->snd_card;
+ else
+ BUG();
+}
+
+static inline struct snd_soc_card *dapm_get_soc_card(
+ struct snd_soc_dapm_context *dapm)
+{
+ if (dapm->codec)
+ return dapm->codec->card;
+ else if (dapm->platform)
+ return dapm->platform->card;
+ else
+ BUG();
+}
+
+static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
+{
+ if (w->codec)
+ return snd_soc_read(w->codec, reg);
+ else if (w->platform)
+ return snd_soc_platform_read(w->platform, reg);
+ return 0;
+}
+
+static int soc_widget_write(struct snd_soc_dapm_widget *w,int reg, int val)
+{
+ if (w->codec)
+ return snd_soc_write(w->codec, reg, val);
+ else if (w->platform)
+ return snd_soc_platform_write(w->platform, reg, val);
+ return 0;
+}
+
+int soc_widget_update_bits(struct snd_soc_dapm_widget *w, unsigned short reg,
+ unsigned int mask, unsigned int value)
+{
+ int change;
+ unsigned int old, new;
+
+ old = soc_widget_read(w, reg);
+ new = (old & ~mask) | value;
+ change = old != new;
+ if (change)
+ soc_widget_write(w, reg, new);
+
+ return change;
+}
+
+int soc_widget_test_bits(struct snd_soc_dapm_widget *w, unsigned short reg,
+ unsigned int mask, unsigned int value)
+{
+ int change;
+ unsigned int old, new;
+
+ old = soc_widget_read(w, reg);
+ new = (old & ~mask) | value;
+ change = old != new;
+
+ return change;
+}
+
+/* reset 'walked' bit for each dapm path */
+static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_dapm_path *p;
+
+ list_for_each_entry(p, &dapm->card->paths, list)
+ p->walked = 0;
+}
+
+static void dapm_clear_paths(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_dapm_path *p;
+ struct snd_soc_dapm_widget *w;
+ struct list_head *l;
+
+ list_for_each(l, &dapm->card->paths) {
+ p = list_entry(l, struct snd_soc_dapm_path, list);
+ p->length = 0;
+ }
+ list_for_each(l, &dapm->card->widgets) {
+ w = list_entry(l, struct snd_soc_dapm_widget, list);
+ w->hops = 0;
+ }
+ dapm_clear_walk(dapm);
+}
+
+static int dapm_add_unique_widget(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget_list **list, struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_widget_list *wlist;
+ int wlistsize, wlistentries, i;
+
+ /* is the list empty ? */
+ if (*list == NULL) {
+
+ wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
+ sizeof(struct snd_soc_dapm_widget *);
+ *list = kzalloc(wlistsize, GFP_KERNEL);
+ if (*list == NULL) {
+ dev_err(dapm->dev, "can't allocate widget list for %s\n", w->name);
+ return -ENOMEM;
+ }
+ } else {
+
+ wlist = *list;
+ /* is this widget already in the list */
+ for (i = 0; i < wlist->num_widgets; i++) {
+ if (wlist->widgets[i] == w)
+ return 0;
+ }
+
+ wlistentries = wlist->num_widgets + 1;
+ wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
+ wlistentries * sizeof(struct snd_soc_dapm_widget *);
+ *list = krealloc(wlist, wlistsize, GFP_KERNEL);
+ if (*list == NULL) {
+ dev_err(dapm->dev, "can't allocate widget list for %s\n", w->name);
+ return -ENOMEM;
+ }
+ }
+ wlist = *list;
+
+ /* insert the widget */
+ dev_dbg(dapm->dev, "added %s in widget list pos %d\n",
+ w->name, wlist->num_widgets);
+ wlist->widgets[wlist->num_widgets] = w;
+ wlist->num_widgets++;
+ return 1;
+}
+
+static int is_output_widget_ep(struct snd_soc_dapm_widget *widget)
+{
+ switch (widget->id) {
+ case snd_soc_dapm_adc:
+ case snd_soc_dapm_aif_out:
+ return 1;
+ case snd_soc_dapm_output:
+ if (widget->connected && !widget->ext)
+ return 1;
+ else
+ return 0;
+ case snd_soc_dapm_hp:
+ case snd_soc_dapm_spk:
+ case snd_soc_dapm_line:
+ return !list_empty(&widget->sources);
+ default:
+ return 0;
+ }
+}
+
+static int is_input_widget_ep(struct snd_soc_dapm_widget *widget)
+{
+ switch (widget->id) {
+ case snd_soc_dapm_dac:
+ case snd_soc_dapm_aif_in:
+ return 1;
+ case snd_soc_dapm_input:
+ if (widget->connected && !widget->ext)
+ return 1;
+ else
+ return 0;
+ case snd_soc_dapm_mic:
+ return !list_empty(&widget->sources);
+ default:
+ return 0;
+ }
+}
+
+/*
+ * find all the paths between source and sink
+ */
+static int dapm_find_playback_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *root,
+ struct snd_soc_dapm_widget_list **list, int hops)
+{
+ struct list_head *lp;
+ struct snd_soc_dapm_path *path;
+ int dist = 0;
+
+ if (hops > PATH_MAX_HOPS)
+ return 0;
+
+ if (is_output_widget_ep(root) && hops != 1) {
+ dev_dbg(dapm->dev," ! %d: valid playback route found\n", hops);
+ dapm->num_valid_paths++;
+ return 1;
+ }
+
+ if (root->hops && root->hops <= hops)
+ return 0;
+ root->hops = hops;
+
+ /* check all the output paths on this source widget by walking
+ * from source to sink */
+ list_for_each(lp, &root->sinks) {
+ path = list_entry(lp, struct snd_soc_dapm_path, list_source);
+
+ dev_dbg(dapm->dev," %c %d: %s -> %s -> %s\n",
+ path->connect ? '*' : ' ', hops,
+ root->name, path->name, path->sink->name);
+
+ /* been here before ? */
+ if (path->length && path->length <= hops)
+ continue;
+
+ /* check down the next path if connected */
+ if (path->sink && path->connect &&
+ dapm_find_playback_paths(dapm, path->sink, list, hops + 1)) {
+ path->length = hops;
+
+ /* add widget to list */
+ dapm_add_unique_widget(dapm, list, path->sink);
+
+ if (!dist || dist > path->length)
+ dist = path->length;
+ }
+ }
+
+ return dist;
+}
+
+static int dapm_find_capture_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *root,
+ struct snd_soc_dapm_widget_list **list, int hops)
+{
+ struct list_head *lp;
+ struct snd_soc_dapm_path *path;
+ int dist = 0;
+
+ if (hops > PATH_MAX_HOPS)
+ return 0;
+
+ if (is_input_widget_ep(root) && hops != 1) {
+ dev_dbg(dapm->dev," ! %d: valid capture route found\n", hops);
+ dapm->num_valid_paths++;
+ return 1;
+ }
+
+ if (root->hops && root->hops <= hops)
+ return 0;
+ root->hops = hops;
+
+ /* check all the output paths on this source widget by walking from
+ * sink to source */
+ list_for_each(lp, &root->sources) {
+ path = list_entry(lp, struct snd_soc_dapm_path, list_sink);
+
+ dev_dbg(dapm->dev," %c %d: %s <- %s <- %s\n",
+ path->connect ? '*' : ' ', hops,
+ root->name, path->name, path->source->name);
+
+ /* been here before ? */
+ if (path->length && path->length <= hops)
+ continue;
+
+ /* check down the next path if connected */
+ if (path->source && path->connect &&
+ dapm_find_capture_paths(dapm, path->source, list, hops + 1)) {
+ path->length = hops;
+
+ /* add widget to list */
+ dapm_add_unique_widget(dapm, list, path->source);
+
+ if (!dist || dist > path->length)
+ dist = path->length;
+ }
+ }
+
+ return dist;
+}
+
+/*
+ * traverse the tree from sink to source via the shortest path
+ */
+static int dapm_get_playback_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *root,
+ struct snd_soc_dapm_widget_list **list)
+{
+ dev_dbg(dapm->dev, "Playback: checking paths from %s\n",root->name);
+ dapm_find_playback_paths(dapm, root, list, 1);
+ return dapm->num_valid_paths;
+}
+
+static int dapm_get_capture_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *root,
+ struct snd_soc_dapm_widget_list **list)
+{
+ dev_dbg(dapm->dev, "Capture: checking paths to %s\n", root->name);
+ dapm_find_capture_paths(dapm, root, list, 1);
+ return dapm->num_valid_paths;
+}
+
+/**
+ * snd_soc_dapm_get_connected_widgets_type - query audio path and it's widgets.
+ * @dapm: the dapm context.
+ * @stream_name: stream name.
+ * @list: list of active widgets for this stream.
+ * @stream: stream direction.
+ * @type: Initial widget type.
+ *
+ * Queries DAPM graph as to whether an valid audio stream path exists for
+ * the DAPM stream and initial widget type specified. This takes into account
+ * current mixer and mux kcontrol settings. Creates list of valid widgets.
+ *
+ * Returns the number of valid paths or negative error.
+ */
+int snd_soc_dapm_get_connected_widgets_type(struct snd_soc_dapm_context *dapm,
+ const char *stream_name, struct snd_soc_dapm_widget_list **list,
+ int stream, enum snd_soc_dapm_type type)
+{
+ struct snd_soc_dapm_widget *w;
+ int paths;
+
+ /* get stream root widget AIF, DAC or ADC from stream string and direction */
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+
+ if (!w->sname)
+ continue;
+
+ if (w->id != type)
+ continue;
+
+ if (strstr(w->sname, stream_name))
+ goto found;
+ }
+ dev_err(dapm->dev, "root widget not found\n");
+ return 0;
+
+found:
+ dapm->num_valid_paths = 0;
+ *list = NULL;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ paths = dapm_get_playback_paths(dapm, w, list);
+ else
+ paths = dapm_get_capture_paths(dapm, w, list);
+
+ dapm_clear_paths(dapm);
+ return paths;
+}
+/**
+ * snd_soc_dapm_get_connected_widgets_name - query audio path and it's widgets.
+ * @dapm: the dapm context.
+ * @name: initial widget name.
+ * @list: list of active widgets for this stream.
+ * @stream: stream direction.
+ *
+ * Queries DAPM graph as to whether an valid audio stream path exists for
+ * the initial widget specified by name. This takes into account
+ * current mixer and mux kcontrol settings. Creates list of valid widgets.
+ *
+ * Returns the number of valid paths or negative error.
+ */
+int snd_soc_dapm_get_connected_widgets_name(struct snd_soc_dapm_context *dapm,
+ const char *name, struct snd_soc_dapm_widget_list **list, int stream)
+{
+ struct snd_soc_dapm_widget *w;
+ int paths;
+
+ /* get stream root widget AIF, DAC or ADC from stream string and direction */
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+
+ if (strstr(w->name, name))
+ goto found;
+ }
+ dev_err(dapm->dev, "root widget %s not found\n", name);
+ return 0;
+
+found:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ paths = dapm_get_playback_paths(dapm, w, list);
+ else
+ paths = dapm_get_capture_paths(dapm, w, list);
+
+ dapm_clear_paths(dapm);
+ return paths;
+}
+
/**
* snd_soc_dapm_set_bias_level - set the bias level for the system
* @dapm: DAPM context
@@ -196,7 +584,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- val = snd_soc_read(w->codec, reg);
+ val = soc_widget_read(w, reg);
val = (val >> shift) & mask;
if ((invert && !val) || (!invert && val))
@@ -212,12 +600,12 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
- val = snd_soc_read(w->codec, e->reg);
+ val = soc_widget_read(w, e->reg);
item = (val >> e->shift_l) & (bitmask - 1);
p->connect = 0;
for (i = 0; i < e->max; i++) {
- if (!(strcmp(p->name, e->texts[i])) && item == i)
+ if (!(strcmp(p->name, snd_soc_get_enum_text(e, i))) && item == i)
p->connect = 1;
}
}
@@ -233,7 +621,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
* that the default mux choice (the first) will be
* correctly powered up during initialization.
*/
- if (!strcmp(p->name, e->texts[0]))
+ if (!strcmp(p->name, snd_soc_get_enum_text(e, 0)))
p->connect = 1;
}
break;
@@ -242,7 +630,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
w->kcontrol_news[i].private_value;
int val, item;
- val = snd_soc_read(w->codec, e->reg);
+ val = soc_widget_read(w, e->reg);
val = (val >> e->shift_l) & e->mask;
for (item = 0; item < e->max; item++) {
if (val == e->values[item])
@@ -251,7 +639,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
p->connect = 0;
for (i = 0; i < e->max; i++) {
- if (!(strcmp(p->name, e->texts[i])) && item == i)
+ if (!(strcmp(p->name, snd_soc_get_enum_text(e, i))) && item == i)
p->connect = 1;
}
}
@@ -292,11 +680,11 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
int i;
for (i = 0; i < e->max; i++) {
- if (!(strcmp(control_name, e->texts[i]))) {
+ if (!(strcmp(control_name, snd_soc_get_enum_text(e, i)))) {
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &dest->sources);
list_add(&path->list_source, &src->sinks);
- path->name = (char*)e->texts[i];
+ path->name = (char*)snd_soc_get_enum_text(e, i);
dapm_set_path_status(dest, path, 0);
return 0;
}
@@ -494,7 +882,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
wlist->widgets[wlistentries - 1] = w;
if (!kcontrol) {
- if (dapm->codec)
+ if (dapm->codec && dapm->codec->name_prefix)
prefix = dapm->codec->name_prefix;
else
prefix = NULL;
@@ -516,7 +904,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
* cut the prefix off the front of the widget name.
*/
kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist,
- name + prefix_len, prefix);
+ name, prefix);
ret = snd_ctl_add(card, kcontrol);
if (ret < 0) {
dev_err(dapm->dev,
@@ -546,15 +934,6 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
return 0;
}
-/* reset 'walked' bit for each dapm path */
-static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
-{
- struct snd_soc_dapm_path *p;
-
- list_for_each_entry(p, &dapm->card->paths, list)
- p->walked = 0;
-}
-
/* We implement power down on suspend by checking the power state of
* the ALSA card - when we are suspending the ALSA state for the card
* is set to D3.
@@ -683,7 +1062,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
else
val = w->off_val;
- snd_soc_update_bits(w->codec, -(w->reg + 1),
+ soc_widget_update_bits(w, -(w->reg + 1),
w->mask << w->shift, val << w->shift);
return 0;
@@ -855,14 +1234,15 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
struct list_head *pending)
{
struct snd_soc_card *card = dapm->card;
- struct snd_soc_dapm_widget *w;
+ struct snd_soc_dapm_widget *w, *_w;
int reg, power;
unsigned int value = 0;
unsigned int mask = 0;
unsigned int cur_mask;
- reg = list_first_entry(pending, struct snd_soc_dapm_widget,
- power_list)->reg;
+ _w = list_first_entry(pending, struct snd_soc_dapm_widget,
+ power_list);
+ reg = _w->reg;
list_for_each_entry(w, pending, power_list) {
cur_mask = 1 << w->shift;
@@ -887,11 +1267,17 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
}
if (reg >= 0) {
+ /* Any widget will do, they should all be updating the
+ * same register.
+ */
+ w = list_first_entry(pending, struct snd_soc_dapm_widget,
+ power_list);
+
pop_dbg(dapm->dev, card->pop_time,
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
value, mask, reg, card->pop_time);
pop_wait(card->pop_time);
- snd_soc_update_bits(dapm->codec, reg, mask, value);
+ soc_widget_update_bits(_w, reg, mask, value);
}
list_for_each_entry(w, pending, power_list) {
@@ -1114,12 +1500,14 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
trace_snd_soc_dapm_start(card);
list_for_each_entry(d, &card->dapm_list, list)
- if (d->n_widgets || d->codec == NULL)
+ if (d->n_widgets || d->codec == NULL ||
+ strstr(d->codec->name, "null-codec"))
d->dev_power = 0;
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down.
*/
+ mutex_lock(&card->power_mutex);
list_for_each_entry(w, &card->widgets, list) {
switch (w->id) {
case snd_soc_dapm_pre:
@@ -1165,7 +1553,11 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
dapm->dev_power = 1;
break;
case SND_SOC_DAPM_STREAM_STOP:
- dapm->dev_power = !!dapm->codec->active;
+#warning need re-work
+ if (dapm->codec)
+ dapm->dev_power = !!dapm->codec->active;
+ else
+ dapm->dev_power = 0;
break;
case SND_SOC_DAPM_STREAM_SUSPEND:
dapm->dev_power = 0;
@@ -1221,6 +1613,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
trace_snd_soc_dapm_done(card);
+ mutex_unlock(&card->power_mutex);
+
return 0;
}
@@ -1399,7 +1793,7 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int change,
int mux, struct soc_enum *e)
{
@@ -1416,29 +1810,33 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
/* find dapm widget path assoc with kcontrol */
list_for_each_entry(path, &widget->dapm->card->paths, list) {
+
if (path->kcontrol != kcontrol)
continue;
- if (!path->name || !e->texts[mux])
+ if (!path->name || !snd_soc_get_enum_text(e, mux))
continue;
found = 1;
/* we now need to match the string in the enum to the path */
- if (!(strcmp(path->name, e->texts[mux])))
+ if (!(strcmp(path->name, snd_soc_get_enum_text(e, mux))))
path->connect = 1; /* new connection */
else
path->connect = 0; /* old connection must be powered down */
}
- if (found)
+ if (found) {
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+ soc_dsp_runtime_update(widget);
+ }
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
- struct snd_kcontrol *kcontrol, int connect)
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
int found = 0;
@@ -1459,26 +1857,25 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
break;
}
- if (found)
+ if (found) {
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+ soc_dsp_runtime_update(widget);
+ }
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
-static ssize_t dapm_widget_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t widget_show(struct snd_soc_dapm_context *dapm,
+ const char *name, char *buf, ssize_t count)
{
- struct snd_soc_pcm_runtime *rtd =
- container_of(dev, struct snd_soc_pcm_runtime, dev);
- struct snd_soc_codec *codec =rtd->codec;
struct snd_soc_dapm_widget *w;
- int count = 0;
char *state = "not set";
- list_for_each_entry(w, &codec->card->widgets, list) {
- if (w->dapm != &codec->dapm)
- continue;
+ count += sprintf(buf + count, "\n%s\n", name);
+
+ list_for_each_entry(w, &dapm->card->widgets, list) {
/* only display widgets that burnm power */
switch (w->id) {
@@ -1503,7 +1900,7 @@ static ssize_t dapm_widget_show(struct device *dev,
}
}
- switch (codec->dapm.bias_level) {
+ switch (dapm->bias_level) {
case SND_SOC_BIAS_ON:
state = "On";
break;
@@ -1522,6 +1919,21 @@ static ssize_t dapm_widget_show(struct device *dev,
return count;
}
+/* show dapm widget status in sys fs */
+static ssize_t dapm_widget_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct snd_soc_pcm_runtime *rtd =
+ container_of(dev, struct snd_soc_pcm_runtime, dev);
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_platform *platform = rtd->platform;
+ ssize_t count = 0;
+
+ count += widget_show(&codec->dapm, codec->name, buf, count);
+ count += widget_show(&platform->dapm, platform->name, buf, count);
+ return count;
+}
+
static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
int snd_soc_dapm_sys_add(struct device *dev)
@@ -1867,7 +2279,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
/* Read the initial power state from the device */
if (w->reg >= 0) {
- val = snd_soc_read(w->codec, w->reg);
+ val = soc_widget_read(w, w->reg);
val &= 1 << w->shift;
if (w->invert)
val = !val;
@@ -1886,6 +2298,24 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
+const char *snd_soc_dapm_get_aif(struct snd_soc_dapm_context *dapm,
+ const char *stream_name, enum snd_soc_dapm_type type)
+{
+ struct snd_soc_dapm_widget *w;
+
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+
+ if (!w->sname)
+ continue;
+
+ if (w->id == type && strstr(w->sname, stream_name))
+ return w->name;
+
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_aif);
+
/**
* snd_soc_dapm_get_volsw - dapm mixer get callback
* @kcontrol: mixer control
@@ -1983,7 +2413,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mixer_update_power(widget, kcontrol, connect);
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
@@ -2074,7 +2504,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
}
@@ -2135,8 +2565,8 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
widget->value = ucontrol->value.enumerated.item[0];
- dapm_mux_update_power(widget, kcontrol, change,
- widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change,
+ widget->value, e);
}
}
@@ -2239,7 +2669,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
}
@@ -2355,6 +2785,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
dapm->n_widgets++;
w->dapm = dapm;
w->codec = dapm->codec;
+ w->platform = dapm->platform;
INIT_LIST_HEAD(&w->sources);
INIT_LIST_HEAD(&w->sinks);
INIT_LIST_HEAD(&w->list);
@@ -2401,6 +2832,9 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
+ if (!dapm)
+ return;
+
list_for_each_entry(w, &dapm->card->widgets, list)
{
if (!w->sname || w->dapm != dapm)
@@ -2425,8 +2859,41 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
}
dapm_power_widgets(dapm, event);
+ /* do we need to notify any clients that DAPM stream is complete */
+ if (dapm->stream_event)
+ dapm->stream_event(dapm);
+}
+
+static void soc_dapm_platform_stream_event(struct snd_soc_platform *platform,
+ const char *stream, int event)
+{
+ soc_dapm_stream_event(&platform->dapm, stream, event);
}
+static void soc_dapm_codec_stream_event(struct snd_soc_codec *codec,
+ const char *stream, int event)
+{
+ soc_dapm_stream_event(&codec->dapm, stream, event);
+}
+
+void snd_soc_dapm_platform_stream_event(struct snd_soc_platform *platform,
+ const char *stream, int event)
+{
+ mutex_lock(&platform->card->dapm_mutex);
+ soc_dapm_platform_stream_event(platform, stream, event);
+ mutex_unlock(&platform->card->dapm_mutex);
+}
+EXPORT_SYMBOL(snd_soc_dapm_platform_stream_event);
+
+void snd_soc_dapm_codec_stream_event(struct snd_soc_codec *codec,
+ const char *stream, int event)
+{
+ mutex_lock(&codec->card->dapm_mutex);
+ soc_dapm_codec_stream_event(codec, stream, event);
+ mutex_unlock(&codec->card->dapm_mutex);
+}
+EXPORT_SYMBOL(snd_soc_dapm_codec_stream_event);
+
/**
* snd_soc_dapm_stream_event - send a stream event to the dapm core
* @rtd: PCM runtime data
@@ -2441,14 +2908,16 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
const char *stream, int event)
{
- struct snd_soc_codec *codec = rtd->codec;
-
if (stream == NULL)
return 0;
- mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
- mutex_unlock(&codec->mutex);
+ mutex_lock(&rtd->card->dapm_mutex);
+
+ soc_dapm_platform_stream_event(rtd->platform, stream, event);
+ soc_dapm_codec_stream_event(rtd->codec, stream, event);
+ soc_dapm_stream_event(&rtd->card->dapm, stream, event);
+
+ mutex_unlock(&rtd->card->dapm_mutex);
return 0;
}
@@ -2556,6 +3025,27 @@ int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
/**
+ * snd_soc_dapm_get_pin_power - get audio pin power state
+ * @dapm: DAPM context
+ * @pin: audio signal pin endpoint (or start point)
+ *
+ * Get audio pin power state - powered or not-powered.
+ *
+ * Returns 1 if powered, otherwise 0.
+ */
+int snd_soc_dapm_get_pin_power(struct snd_soc_dapm_context *dapm,
+ const char *pin)
+{
+ struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
+
+ if (w)
+ return w->power;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_power);
+
+/**
* snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
* @dapm: DAPM context
* @pin: audio signal pin endpoint (or start point)
@@ -2633,6 +3123,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
void snd_soc_dapm_shutdown(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
+ struct snd_soc_platform *platform;
list_for_each_entry(codec, &card->codec_dev_list, card_list) {
soc_dapm_shutdown_codec(&codec->dapm);
@@ -2640,6 +3131,11 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
snd_soc_dapm_set_bias_level(&codec->dapm,
SND_SOC_BIAS_OFF);
}
+
+ list_for_each_entry(platform, &card->platform_dev_list, card_list) {
+ soc_dapm_shutdown_codec(&platform->dapm);
+ snd_soc_dapm_set_bias_level(&platform->dapm, SND_SOC_BIAS_OFF);
+ }
}
/* Module information */
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
new file mode 100644
index 0000000..199b428
--- /dev/null
+++ b/sound/soc/soc-dsp.c
@@ -0,0 +1,1737 @@
+/*
+ * soc-dsp.c -- ALSA SoC Audio DSP
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/ac97_codec.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dsp.h>
+
+int soc_pcm_open(struct snd_pcm_substream *);
+void soc_pcm_close(struct snd_pcm_substream *);
+int soc_pcm_hw_params(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+int soc_pcm_hw_free(struct snd_pcm_substream *);
+int soc_pcm_prepare(struct snd_pcm_substream *);
+int soc_pcm_trigger(struct snd_pcm_substream *, int);
+int soc_pcm_bespoke_trigger(struct snd_pcm_substream *, int);
+
+/* count the number of FE clients in a particular state */
+int soc_dsp_fe_state_count(struct snd_soc_pcm_runtime *be, int stream,
+ enum snd_soc_dsp_state state)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ int count = 0;
+
+ list_for_each_entry(dsp_params, &be->dsp[stream].fe_clients, list_fe) {
+ if (dsp_params->fe->dsp[stream].state == state)
+ count++;
+ }
+
+ return count;
+}
+EXPORT_SYMBOL(soc_dsp_fe_state_count);
+
+static inline int be_connect(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* only add new dsp_paramss */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ if (dsp_params->be == be && dsp_params->fe == fe)
+ return 0;
+ }
+
+ dsp_params = kzalloc(sizeof(struct snd_soc_dsp_params), GFP_KERNEL);
+ if (!dsp_params)
+ return -ENOMEM;
+
+ dsp_params->be = be;
+ dsp_params->fe = fe;
+ be->dsp[stream].runtime = fe->dsp[stream].runtime;
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_NEW;
+ list_add(&dsp_params->list_be, &fe->dsp[stream].be_clients);
+ list_add(&dsp_params->list_fe, &be->dsp[stream].fe_clients);
+
+ dev_dbg(&fe->dev, " connected new DSP %s path %s %s %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name,
+ stream ? "<-" : "->", be->dai_link->name);
+
+#ifdef CONFIG_DEBUG_FS
+ dsp_params->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
+ fe->debugfs_dsp_root, &dsp_params->state);
+#endif
+
+ return 1;
+}
+
+static inline void be_reparent(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ struct snd_pcm_substream *fe_substream, *be_substream;
+
+ /* reparent if BE is connected to other FEs */
+ if (!be->dsp[stream].users)
+ return;
+
+ be_substream = snd_soc_dsp_get_substream(be, stream);
+
+ list_for_each_entry(dsp_params, &be->dsp[stream].fe_clients, list_fe) {
+ if (dsp_params->fe != fe) {
+
+ dev_dbg(&fe->dev, " reparent %s path %s %s %s\n",
+ stream ? "capture" : "playback",
+ dsp_params->fe->dai_link->name,
+ stream ? "<-" : "->", dsp_params->be->dai_link->name);
+
+ fe_substream = snd_soc_dsp_get_substream(dsp_params->fe,
+ stream);
+ be_substream->runtime = fe_substream->runtime;
+ break;
+ }
+ }
+}
+
+static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params, *d;
+
+ list_for_each_entry_safe(dsp_params, d, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ dev_dbg(&fe->dev, "BE %s disconnect check for %s\n",
+ stream ? "capture" : "playback",
+ be->dai_link->name);
+
+ if (dsp_params->state == SND_SOC_DSP_LINK_STATE_FREE) {
+ dev_dbg(&fe->dev, " freed DSP %s path %s %s %s\n",
+ stream ? "capture" : "playback",
+ fe->dai_link->name, stream ? "<-" : "->",
+ be->dai_link->name);
+
+ /* BEs still alive need new FE */
+ be_reparent(fe, be, stream);
+
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(dsp_params->debugfs_state);
+#endif
+
+ list_del(&dsp_params->list_be);
+ list_del(&dsp_params->list_fe);
+ kfree(dsp_params);
+ }
+ }
+}
+
+static struct snd_soc_pcm_runtime *be_get_rtd(struct snd_soc_card *card,
+ struct snd_soc_dapm_widget *widget)
+{
+ struct snd_soc_pcm_runtime *be;
+ int i;
+
+ if (!widget->sname)
+ return NULL;
+
+ for (i = 0; i < card->num_links; i++) {
+ be = &card->rtd[i];
+
+ if (!strcmp(widget->sname, be->dai_link->stream_name))
+ return be;
+ }
+
+ return NULL;
+}
+
+static struct snd_soc_dapm_widget *be_get_widget(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_widget *widget;
+
+ list_for_each_entry(widget, &card->widgets, list) {
+
+ if (!widget->sname)
+ continue;
+
+ if (!strcmp(widget->sname, rtd->dai_link->stream_name))
+ return widget;
+ }
+
+ return NULL;
+}
+
+static int widget_in_list(struct snd_soc_dapm_widget_list *list,
+ struct snd_soc_dapm_widget *widget)
+{
+ int i;
+
+ for (i = 0; i < list->num_widgets; i++) {
+ if (widget == list->widgets[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Find the corresponding BE DAIs that source or sink audio to this
+ * FE substream.
+ */
+static int dsp_add_new_paths(struct snd_soc_pcm_runtime *fe,
+ int stream, int pending)
+{
+ struct snd_soc_dai *cpu_dai = fe->cpu_dai;
+ struct snd_soc_card *card = fe->card;
+ struct snd_soc_dapm_widget_list *list = NULL;
+ enum snd_soc_dapm_type fe_type, be_type;
+ int i, count = 0, err, paths;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ fe_type = snd_soc_dapm_aif_in;
+ be_type = snd_soc_dapm_aif_out;
+ } else {
+ fe_type = snd_soc_dapm_aif_out;
+ be_type = snd_soc_dapm_aif_in;
+ }
+
+ /* get number of valid playback paths and their widgets */
+ paths = snd_soc_dapm_get_connected_widgets_type(&card->dapm,
+ cpu_dai->driver->name, &list, stream, fe_type);
+
+ dev_dbg(&fe->dev, "found %d audio %s paths\n", paths,
+ stream ? "capture" : "playback");
+ if (!paths)
+ goto out;
+
+ /* find BE DAI widgets and and connect the to FE */
+ for (i = 0; i < list->num_widgets; i++) {
+
+ if (list->widgets[i]->id == be_type) {
+ struct snd_soc_pcm_runtime *be;
+
+ /* is there a valid BE rtd for this widget */
+ be = be_get_rtd(card, list->widgets[i]);
+ if (!be) {
+ dev_err(&fe->dev, "no BE found for %s\n",
+ list->widgets[i]->name);
+ continue;
+ }
+
+ /* don't connect if FE is not running */
+ if (!fe->dsp[stream].runtime)
+ continue;
+
+ /* newly connected FE and BE */
+ err = be_connect(fe, be, stream);
+ if (err < 0) {
+ dev_err(&fe->dev, "can't connect %s\n", list->widgets[i]->name);
+ break;
+ } else if (err == 0)
+ continue;
+
+ be->dsp[stream].runtime_update = pending;
+ count++;
+ }
+ }
+
+out:
+ /* list could be not initialized if root widget not found */
+ if (list != NULL)
+ kfree(list);
+ return count;
+}
+
+/*
+ * Find the corresponding BE DAIs that source or sink audio to this
+ * FE substream.
+ */
+static int dsp_prune_old_paths(struct snd_soc_pcm_runtime *fe, int stream,
+ int pending)
+{
+ struct snd_soc_dai *cpu_dai = fe->cpu_dai;
+ struct snd_soc_card *card = fe->card;
+ struct snd_soc_dsp_params *dsp_params;
+ struct snd_soc_dapm_widget_list *list = NULL;
+ int count = 0, paths;
+ enum snd_soc_dapm_type fe_type, be_type;
+ struct snd_soc_dapm_widget *widget;
+
+ dev_dbg(&fe->dev, "scan for old %s %s streams\n", fe->dai_link->name,
+ stream ? "capture" : "playback");
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ fe_type = snd_soc_dapm_aif_in;
+ be_type = snd_soc_dapm_aif_out;
+ } else {
+ fe_type = snd_soc_dapm_aif_out;
+ be_type = snd_soc_dapm_aif_in;
+ }
+
+ /* get number of valid playback paths and their widgets */
+ paths = snd_soc_dapm_get_connected_widgets_type(&card->dapm,
+ cpu_dai->driver->name, &list, stream, fe_type);
+
+ dev_dbg(&fe->dev, "found %d audio %s paths\n", paths,
+ stream ? "capture" : "playback");
+ if (!paths) {
+ /* prune all BEs */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
+ dsp_params->be->dsp[stream].runtime_update = pending;
+ count++;
+ }
+
+ dev_dbg(&fe->dev, "pruned all %s BE for FE %s\n", fe->dai_link->name,
+ stream ? "capture" : "playback");
+ goto out;
+ }
+
+ /* search card for valid BE AIFs */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ /* is there a valid widget for this BE */
+ widget = be_get_widget(card, dsp_params->be);
+ if (!widget) {
+ dev_err(&fe->dev, "no widget found for %s\n",
+ dsp_params->be->dai_link->name);
+ continue;
+ }
+
+ /* prune the BE if it's no longer in our active list */
+ if (widget_in_list(list, widget))
+ continue;
+
+ dev_dbg(&fe->dev, "pruning %s BE %s for %s\n",
+ stream ? "capture" : "playback", dsp_params->be->dai_link->name,
+ fe->dai_link->name);
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
+ dsp_params->be->dsp[stream].runtime_update = pending;
+ count++;
+ }
+
+ /* the number of old paths pruned */
+out:
+ /* list could be not initialized if root widget not found */
+ if (list != NULL)
+ kfree(list);
+ return count;
+}
+
+/*
+ * Clear the runtime pending state of all BE's.
+ */
+static void fe_clear_pending(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be)
+ dsp_params->be->dsp[stream].runtime_update =
+ SND_SOC_DSP_UPDATE_NO;
+}
+
+/* Unwind the BE startup */
+static void soc_dsp_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* disable any enabled and non active backends */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ if (--be->dsp[stream].users != 0)
+ continue;
+
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_OPEN)
+ continue;
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE;
+ }
+}
+
+/* Startup all new BE */
+static int soc_dsp_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ int err, count = 0;
+
+ /* only startup BE DAIs that are either sinks or sources to this FE DAI */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ /* first time the dsp_params is open ? */
+ if (be->dsp[stream].users++ != 0)
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_NEW) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_CLOSE))
+ continue;
+
+ dev_dbg(&be->dev, "dsp: open BE %s\n", be->dai_link->name);
+
+ be_substream->runtime = be->dsp[stream].runtime;
+ err = soc_pcm_open(be_substream);
+ if (err < 0) {
+ dev_err(&be->dev, "BE open failed %d\n", err);
+ be->dsp[stream].users--;
+ be->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE;
+ be_substream->runtime = NULL;
+ goto unwind;
+ }
+ be->dsp[stream].state = SND_SOC_DSP_STATE_OPEN;
+ count++;
+ }
+
+ return count;
+
+unwind:
+ /* disable any enabled and non active backends */
+ list_for_each_entry_continue_reverse(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (--be->dsp[stream].users != 0)
+ continue;
+
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_OPEN)
+ continue;
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE;
+ }
+
+ return err;
+}
+
+void soc_dsp_set_dynamic_runtime(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
+ runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
+ runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
+ runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
+ runtime->hw.formats &= cpu_dai_drv->playback.formats;
+ runtime->hw.rates = cpu_dai_drv->playback.rates;
+ } else {
+ runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
+ runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
+ runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
+ runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
+ runtime->hw.formats &= cpu_dai_drv->capture.formats;
+ runtime->hw.rates = cpu_dai_drv->capture.rates;
+ }
+}
+
+static int soc_dsp_fe_dai_startup(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_pcm_runtime *runtime = fe_substream->runtime;
+ int runtime_update, stream = fe_substream->stream, ret = 0;
+
+ mutex_lock(&fe->card->dsp_mutex);
+
+ runtime_update = fe->dsp[stream].runtime_update;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ ret = soc_dsp_be_dai_startup(fe, fe_substream->stream);
+ if (ret < 0)
+ goto be_err;
+
+ dev_dbg(&fe->dev, "dsp: open FE %s\n", fe->dai_link->name);
+
+ /* start the DAI frontend */
+ ret = soc_pcm_open(fe_substream);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: failed to start FE %d\n", ret);
+ goto unwind;
+ }
+
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_OPEN;
+
+ soc_dsp_set_dynamic_runtime(fe_substream);
+ snd_pcm_limit_hw_rates(runtime);
+
+ mutex_unlock(&fe->card->dsp_mutex);
+ return 0;
+
+unwind:
+ soc_dsp_be_dai_startup_unwind(fe, fe_substream->stream);
+be_err:
+ fe->dsp[stream].runtime_update = runtime_update;
+ mutex_unlock(&fe->card->dsp_mutex);
+ return ret;
+}
+
+/* BE shutdown - called on DAPM sync updates (i.e. FE is already running)*/
+static int soc_dsp_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* only shutdown backends that are either sinks or sources to this frontend DAI */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if (--be->dsp[stream].users != 0)
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_HW_FREE) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_OPEN))
+ continue;
+
+ dev_dbg(&be->dev, "dsp: close BE %s\n",
+ dsp_params->fe->dai_link->name);
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE;
+ }
+ return 0;
+}
+
+/* FE +BE shutdown - called on FE PCM ops */
+static int soc_dsp_fe_dai_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int runtime_update, stream = substream->stream;
+
+ mutex_lock(&fe->card->dsp_mutex);
+
+ runtime_update = fe->dsp[stream].runtime_update;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ /* shutdown the BEs */
+ soc_dsp_be_dai_shutdown(fe, substream->stream);
+
+ dev_dbg(&fe->dev, "dsp: close FE %s\n", fe->dai_link->name);
+
+ /* now shutdown the frontend */
+ soc_pcm_close(substream);
+
+ /* run the stream event for each BE */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->playback.stream_name,
+ SND_SOC_DAPM_STREAM_STOP);
+ else
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->capture.stream_name,
+ SND_SOC_DAPM_STREAM_STOP);
+
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE;
+ fe->dsp[stream].runtime_update = runtime_update;
+
+ mutex_unlock(&fe->card->dsp_mutex);
+ return 0;
+}
+
+static int soc_dsp_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ int ret;
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ /* first time the dsp_params is open ? */
+ if (be->dsp[stream].users != 1)
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_OPEN) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_HW_FREE))
+ continue;
+
+ dev_dbg(&be->dev, "dsp: hw_params BE %s\n",
+ dsp_params->fe->dai_link->name);
+
+ /* copy params for each dsp_params */
+ memcpy(&dsp_params->hw_params, &fe->dsp[stream].hw_params,
+ sizeof(struct snd_pcm_hw_params));
+
+ /* perform any hw_params fixups */
+ if (be->dai_link->be_hw_params_fixup) {
+ ret = be->dai_link->be_hw_params_fixup(be,
+ &dsp_params->hw_params);
+ if (ret < 0) {
+ dev_err(&be->dev,
+ "dsp: hw_params BE fixup failed %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ ret = soc_pcm_hw_params(be_substream, &dsp_params->hw_params);
+ if (ret < 0) {
+ dev_err(&dsp_params->be->dev, "dsp: hw_params BE failed %d\n", ret);
+ return ret;
+ }
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_HW_PARAMS;
+ }
+ return 0;
+}
+
+int soc_dsp_fe_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int ret, runtime_update, stream = substream->stream;
+
+ mutex_lock(&fe->card->dsp_mutex);
+
+ runtime_update = fe->dsp[stream].runtime_update;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ memcpy(&fe->dsp[substream->stream].hw_params, params,
+ sizeof(struct snd_pcm_hw_params));
+ ret = soc_dsp_be_dai_hw_params(fe, substream->stream);
+ if (ret < 0)
+ goto out;
+
+ dev_dbg(&fe->dev, "dsp: hw_params FE %s\n", fe->dai_link->name);
+
+ /* call hw_params on the frontend */
+ ret = soc_pcm_hw_params(substream, params);
+ if (ret < 0)
+ dev_err(&fe->dev,"dsp: hw_params FE failed %d\n", ret);
+
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_HW_PARAMS;
+
+out:
+ fe->dsp[stream].runtime_update = runtime_update;
+ mutex_unlock(&fe->card->dsp_mutex);
+ return ret;
+}
+
+static int dsp_do_trigger(struct snd_soc_dsp_params *dsp_params,
+ struct snd_pcm_substream *substream, int cmd)
+{
+ int ret;
+
+ dev_dbg(&dsp_params->be->dev, "dsp: trigger BE %s cmd %d\n",
+ dsp_params->fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ if (ret < 0)
+ dev_err(&dsp_params->be->dev,"dsp: trigger BE failed %d\n", ret);
+
+ return ret;
+}
+
+int soc_dsp_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ int ret = 0;
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_PREPARE) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_STOP))
+ continue;
+
+ ret = dsp_do_trigger(dsp_params, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_START)
+ continue;
+
+ if (soc_dsp_fe_state_count(be, stream,
+ SND_SOC_DSP_STATE_START) > 1)
+ continue;
+
+ ret = dsp_do_trigger(dsp_params, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_STOP;
+ break;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(soc_dsp_be_dai_trigger);
+
+int soc_dsp_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
+ int stream = substream->stream, ret;
+ int runtime_update = fe->dsp[stream].runtime_update;
+
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ switch (dsp_link->trigger[stream]) {
+ case SND_SOC_DSP_TRIGGER_PRE:
+ /* call trigger on the frontend before the backend. */
+
+ dev_dbg(&fe->dev, "dsp: pre trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
+ goto out;
+ }
+
+ ret = soc_dsp_be_dai_trigger(fe, substream->stream, cmd);
+ break;
+ case SND_SOC_DSP_TRIGGER_POST:
+ /* call trigger on the frontend after the backend. */
+
+ ret = soc_dsp_be_dai_trigger(fe, substream->stream, cmd);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
+ goto out;
+ }
+
+ dev_dbg(&fe->dev, "dsp: post trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ break;
+ case SND_SOC_DSP_TRIGGER_BESPOKE:
+ /* bespoke trigger() - handles both FE and BEs */
+
+ dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_bespoke_trigger(substream, cmd);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
+ goto out;
+ }
+ break;
+ default:
+ dev_err(&fe->dev, "dsp: invalid trigger cmd %d for %s\n", cmd,
+ fe->dai_link->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_STOP;
+ break;
+ }
+
+out:
+ fe->dsp[stream].runtime_update = runtime_update;
+ return ret;
+}
+
+static int soc_dsp_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+ int ret = 0;
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_HW_PARAMS) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_STOP))
+ continue;
+
+ dev_dbg(&be->dev, "dsp: prepare BE %s\n",
+ dsp_params->fe->dai_link->name);
+
+ ret = soc_pcm_prepare(be_substream);
+ if (ret < 0) {
+ dev_err(&be->dev, "dsp: backend prepare failed %d\n",
+ ret);
+ break;
+ }
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_PREPARE;
+ }
+ return ret;
+}
+
+int soc_dsp_fe_dai_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int runtime_update, stream = substream->stream, ret = 0;
+
+ mutex_lock(&fe->card->dsp_mutex);
+
+ dev_dbg(&fe->dev, "dsp: prepare FE %s\n", fe->dai_link->name);
+
+ runtime_update = fe->dsp[stream].runtime_update;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ /* there is no point preparing this FE if there are no BEs */
+ if (list_empty(&fe->dsp[stream].be_clients)) {
+ dev_err(&fe->dev, "dsp: no backend DAIs enabled for %s\n",
+ fe->dai_link->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = soc_dsp_be_dai_prepare(fe, substream->stream);
+ if (ret < 0)
+ goto out;
+
+ /* call prepare on the frontend */
+ ret = soc_pcm_prepare(substream);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: prepare FE %s failed\n", fe->dai_link->name);
+ goto out;
+ }
+
+ /* run the stream event for each BE */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->playback.stream_name,
+ SNDRV_PCM_TRIGGER_START);
+ else
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->capture.stream_name,
+ SNDRV_PCM_TRIGGER_START);
+
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_PREPARE;
+
+out:
+ fe->dsp[stream].runtime_update = runtime_update;
+ mutex_unlock(&fe->card->dsp_mutex);
+ return ret;
+}
+
+static int soc_dsp_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* only hw_params backends that are either sinks or sources
+ * to this frontend DAI */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dsp_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dsp_is_op_for_be(fe, be, stream))
+ continue;
+
+ /* only free hw when no longer used */
+ if (be->dsp[stream].users != 1)
+ continue;
+
+ if ((be->dsp[stream].state != SND_SOC_DSP_STATE_HW_PARAMS) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_PREPARE) &&
+ (be->dsp[stream].state != SND_SOC_DSP_STATE_STOP))
+ continue;
+
+ dev_dbg(&be->dev, "dsp: hw_free BE %s\n",
+ dsp_params->fe->dai_link->name);
+
+ soc_pcm_hw_free(be_substream);
+
+ be->dsp[stream].state = SND_SOC_DSP_STATE_HW_FREE;
+ }
+
+ return 0;
+}
+
+int soc_dsp_fe_dai_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int ret, runtime_update, stream = substream->stream;
+
+ mutex_lock(&fe->card->dsp_mutex);
+
+ runtime_update = fe->dsp[stream].runtime_update;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_FE;
+
+ dev_dbg(&fe->dev, "dsp: hw_free FE %s\n", fe->dai_link->name);
+
+ /* call hw_free on the frontend */
+ ret = soc_pcm_hw_free(substream);
+ if (ret < 0)
+ dev_err(&fe->dev,"dsp: hw_free FE %s failed\n", fe->dai_link->name);
+
+ /* only hw_params backends that are either sinks or sources
+ * to this frontend DAI */
+ ret = soc_dsp_be_dai_hw_free(fe, stream);
+
+ fe->dsp[stream].state = SND_SOC_DSP_STATE_HW_FREE;
+ fe->dsp[stream].runtime_update = runtime_update;
+
+ mutex_unlock(&fe->card->dsp_mutex);
+ return ret;
+}
+
+/*
+ * FE stream event, send event to all active BEs.
+ */
+int soc_dsp_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
+ int dir, const char *stream, int event)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* resume for playback */
+ list_for_each_entry(dsp_params, &fe->dsp[dir].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ dev_dbg(&be->dev, "pm: BE %s stream %s event %d dir %d\n",
+ be->dai_link->name, stream, event, dir);
+
+ snd_soc_dapm_stream_event(be, stream, event);
+ }
+
+ return 0;
+}
+
+static int dsp_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
+ struct snd_pcm_substream *substream = snd_soc_dsp_get_substream(fe, stream);
+ int ret;
+
+ dev_dbg(&fe->dev, "runtime %s close on FE %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name);
+
+ if (dsp_link->trigger[stream] == SND_SOC_DSP_TRIGGER_BESPOKE) {
+ /* call bespoke trigger - FE takes care of all BE triggers */
+ dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd stop\n",
+ fe->dai_link->name);
+
+ ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
+ return ret;
+ }
+ } else {
+ dev_dbg(&fe->dev, "dsp: trigger FE %s cmd stop\n",
+ fe->dai_link->name);
+
+ ret = soc_dsp_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = soc_dsp_be_dai_hw_free(fe, stream);
+ if (ret < 0)
+ return ret;
+
+ ret = soc_dsp_be_dai_shutdown(fe, stream);
+ if (ret < 0)
+ return ret;
+
+ /* run the stream event for each BE */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->playback.stream_name,
+ SNDRV_PCM_TRIGGER_STOP);
+ else
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->capture.stream_name,
+ SNDRV_PCM_TRIGGER_STOP);
+
+ return 0;
+}
+
+static int dsp_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
+ struct snd_pcm_substream *substream = snd_soc_dsp_get_substream(fe, stream);
+ struct snd_soc_dsp_params *dsp_params;
+ int ret;
+
+ dev_dbg(&fe->dev, "runtime %s open on FE %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name);
+
+ ret = soc_dsp_be_dai_startup(fe, stream);
+ if (ret < 0) {
+ goto disconnect;
+ return ret;
+ }
+
+ ret = soc_dsp_be_dai_hw_params(fe, stream);
+ if (ret < 0) {
+ goto close;
+ return ret;
+ }
+ ret = soc_dsp_be_dai_prepare(fe, stream);
+ if (ret < 0) {
+ goto hw_free;
+ return ret;
+ }
+
+ /* run the stream event for each BE */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->playback.stream_name,
+ SNDRV_PCM_TRIGGER_START);
+ else
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->capture.stream_name,
+ SNDRV_PCM_TRIGGER_START);
+
+ if (dsp_link->trigger[stream] == SND_SOC_DSP_TRIGGER_BESPOKE) {
+ /* call trigger on the frontend - FE takes care of all BE triggers */
+ dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd start\n",
+ fe->dai_link->name);
+
+ ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: bespoke trigger FE failed %d\n", ret);
+ goto stream_stop;
+ }
+ } else {
+ dev_dbg(&fe->dev, "dsp: trigger FE %s cmd start\n",
+ fe->dai_link->name);
+
+ ret = soc_dsp_be_dai_trigger(fe, stream,
+ SNDRV_PCM_TRIGGER_START);
+ if (ret < 0) {
+ dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
+ goto stream_stop;
+ }
+ }
+
+ return 0;
+
+stream_stop:
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->playback.stream_name,
+ SNDRV_PCM_TRIGGER_STOP);
+ else
+ soc_dsp_dapm_stream_event(fe, stream,
+ fe->cpu_dai->driver->capture.stream_name,
+ SNDRV_PCM_TRIGGER_STOP);
+hw_free:
+ soc_dsp_be_dai_hw_free(fe, stream);
+close:
+ soc_dsp_be_dai_shutdown(fe, stream);
+disconnect:
+ /* disconnect any non started BEs */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ if (be->dsp[stream].state != SND_SOC_DSP_STATE_START)
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
+ }
+
+ return ret;
+}
+
+static int dsp_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ int ret;
+
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_BE;
+ ret = dsp_run_update_startup(fe, stream);
+ if (ret < 0)
+ dev_err(&fe->dev, "failed to startup some BEs\n");
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_NO;
+
+ return ret;
+}
+
+static int dsp_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ int ret;
+
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_BE;
+ ret = dsp_run_update_shutdown(fe, stream);
+ if (ret < 0)
+ dev_err(&fe->dev, "failed to shutdown some BEs\n");
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_NO;
+
+ return ret;
+}
+
+/* called when any mixer updates change FE -> BE the stream */
+int soc_dsp_runtime_update(struct snd_soc_dapm_widget *widget)
+{
+ struct snd_soc_card *card;
+ int i, ret = 0, start, stop;
+
+ if (widget->codec)
+ card = widget->codec->card;
+ else if (widget->platform)
+ card = widget->platform->card;
+ else
+ return -EINVAL;
+
+ mutex_lock(&widget->dapm->card->dsp_mutex);
+
+ for (i = 0; i < card->num_rtd; i++) {
+ struct snd_soc_pcm_runtime *fe = &card->rtd[i];
+
+ /* make sure link is BE */
+ if (!fe->dai_link->dsp_link)
+ continue;
+
+ /* only check active links */
+ if (!fe->cpu_dai->active) {
+ continue;
+ }
+
+ /* DAPM sync will call this to update DSP paths */
+ dev_dbg(card->dev, "DSP runtime update for FE %s\n", fe->dai_link->name);
+
+ /* skip if FE doesn't have playback capability */
+ if (!fe->cpu_dai->driver->playback.channels_min)
+ goto capture;
+
+ /* update new playback paths */
+ start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
+ if (start) {
+ dsp_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ }
+
+ /* update old playback paths */
+ stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
+ if (stop) {
+ dsp_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ }
+
+capture:
+ /* skip if FE doesn't have capture capability */
+ if (!fe->cpu_dai->driver->capture.channels_min)
+ continue;
+
+ /* update new capture paths */
+ start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
+ if (start) {
+ dsp_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
+ }
+
+ /* update old capture paths */
+ stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
+ if (stop) {
+ dsp_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
+ be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
+ }
+ }
+
+ mutex_unlock(&widget->dapm->card->dsp_mutex);
+ return ret;
+}
+
+int soc_dsp_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->codec_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "BE digital mute %s\n", be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->ops->digital_mute && dai->playback_active)
+ drv->ops->digital_mute(dai, mute);
+ }
+
+ return 0;
+}
+
+int soc_dsp_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* suspend for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI playback suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && !drv->ac97_control)
+ drv->suspend(dai);
+ }
+
+ /* suspend for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI capture suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && !drv->ac97_control)
+ drv->suspend(dai);
+ }
+
+ return 0;
+}
+
+int soc_dsp_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* suspend for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI playback suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && drv->ac97_control)
+ drv->suspend(dai);
+ }
+
+ /* suspend for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI capture suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && drv->ac97_control)
+ drv->suspend(dai);
+ }
+
+ return 0;
+}
+
+int soc_dsp_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* suspend for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_platform *platform = be->platform;
+ struct snd_soc_platform_driver *drv = platform->driver;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ dev_dbg(&be->dev, "pm: BE platform playback suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && !platform->suspended) {
+ drv->suspend(dai);
+ platform->suspended = 1;
+ }
+ }
+
+ /* suspend for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_platform *platform = be->platform;
+ struct snd_soc_platform_driver *drv = platform->driver;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ dev_dbg(&be->dev, "pm: BE platform capture suspend %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->suspend && !platform->suspended) {
+ drv->suspend(dai);
+ platform->suspended = 1;
+ }
+ }
+
+ return 0;
+}
+
+int soc_dsp_fe_suspend(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dai *dai = fe->cpu_dai;
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_platform_driver *plat_drv = platform->driver;
+
+ if (dai_drv->suspend && !dai_drv->ac97_control)
+ dai_drv->suspend(dai);
+
+ if (plat_drv->suspend && !platform->suspended) {
+ plat_drv->suspend(dai);
+ platform->suspended = 1;
+ }
+
+ soc_dsp_be_cpu_dai_suspend(fe);
+ soc_dsp_be_platform_suspend(fe);
+
+ return 0;
+}
+
+int soc_dsp_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* resume for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI playback resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && !drv->ac97_control)
+ drv->resume(dai);
+ }
+
+ /* suspend for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI capture resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && !drv->ac97_control)
+ drv->resume(dai);
+ }
+
+ return 0;
+}
+
+int soc_dsp_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* resume for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI playback resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && drv->ac97_control)
+ drv->resume(dai);
+ }
+
+ /* suspend for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ dev_dbg(&be->dev, "pm: BE CPU DAI capture resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && drv->ac97_control)
+ drv->resume(dai);
+ }
+
+ return 0;
+}
+
+int soc_dsp_be_platform_resume(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dsp_params *dsp_params;
+
+ /* resume for playback */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_platform *platform = be->platform;
+ struct snd_soc_platform_driver *drv = platform->driver;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ dev_dbg(&be->dev, "pm: BE platform playback resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && platform->suspended) {
+ drv->resume(dai);
+ platform->suspended = 0;
+ }
+ }
+
+ /* resume for capture */
+ list_for_each_entry(dsp_params,
+ &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+ struct snd_soc_platform *platform = be->platform;
+ struct snd_soc_platform_driver *drv = platform->driver;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ dev_dbg(&be->dev, "pm: BE platform capture resume %s\n",
+ be->dai_link->name);
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ if (drv->resume && platform->suspended) {
+ drv->resume(dai);
+ platform->suspended = 0;
+ }
+ }
+
+ return 0;
+}
+
+int soc_dsp_fe_resume(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dai *dai = fe->cpu_dai;
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_platform_driver *plat_drv = platform->driver;
+
+ soc_dsp_be_cpu_dai_resume(fe);
+ soc_dsp_be_platform_resume(fe);
+
+ if (dai_drv->resume && !dai_drv->ac97_control)
+ dai_drv->resume(dai);
+
+ if (plat_drv->resume && platform->suspended) {
+ plat_drv->resume(dai);
+ platform->suspended = 0;
+ }
+
+ return 0;
+}
+
+/* called when opening FE stream */
+int soc_dsp_fe_dai_open(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+ int err, ret;
+ int stream = fe_substream->stream;
+
+ fe->dsp[fe_substream->stream].runtime = fe_substream->runtime;
+
+ /* calculate valid and active FE <-> BE dsp_paramss */
+ err = dsp_add_new_paths(fe, fe_substream->stream, 0);
+ if (err <= 0) {
+ dev_warn(&fe->dev, "asoc: %s no valid %s route from source to sink\n",
+ fe->dai_link->name, fe_substream->stream ? "capture" : "playback");
+ }
+
+ ret = soc_dsp_fe_dai_startup(fe_substream);
+ if (ret < 0) {
+ /* clean up all links */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be)
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
+
+ be_disconnect(fe, stream);
+ fe->dsp[stream].runtime = NULL;
+ }
+ return ret;
+}
+
+/* called when closing FE stream */
+int soc_dsp_fe_dai_close(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_soc_dsp_params *dsp_params;
+ int stream = fe_substream->stream, ret;
+
+ ret = soc_dsp_fe_dai_shutdown(fe_substream);
+
+ /* mark FE's links ready to prune */
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be)
+ dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
+
+ be_disconnect(fe, stream);
+
+ fe->dsp[stream].runtime = NULL;
+
+ return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static char *dsp_state_string(enum snd_soc_dsp_state state)
+{
+ switch (state) {
+ case SND_SOC_DSP_STATE_NEW:
+ return "new";
+ case SND_SOC_DSP_STATE_OPEN:
+ return "open";
+ case SND_SOC_DSP_STATE_HW_PARAMS:
+ return "hw_params";
+ case SND_SOC_DSP_STATE_PREPARE:
+ return "prepare";
+ case SND_SOC_DSP_STATE_START:
+ return "start";
+ case SND_SOC_DSP_STATE_STOP:
+ return "stop";
+ case SND_SOC_DSP_STATE_HW_FREE:
+ return "hw_free";
+ case SND_SOC_DSP_STATE_CLOSE:
+ return "close";
+ }
+
+ return "unknown";
+}
+
+static int soc_dsp_state_open_file(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t soc_dsp_show_state(struct snd_soc_pcm_runtime *fe,
+ int stream, char *buf, size_t size)
+{
+ struct snd_pcm_hw_params *params = &fe->dsp[stream].hw_params;
+ struct snd_soc_dsp_params *dsp_params;
+ ssize_t offset = 0;
+
+ /* FE state */
+ offset += snprintf(buf + offset, size - offset,
+ "[%s - %s]\n", fe->dai_link->name,
+ stream ? "Capture" : "Playback");
+
+ offset += snprintf(buf + offset, size - offset, "State: %s\n",
+ dsp_state_string(fe->dsp[stream].state));
+
+ if ((fe->dsp[stream].state >= SND_SOC_DSP_STATE_HW_PARAMS) &&
+ (fe->dsp[stream].state <= SND_SOC_DSP_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ "Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+
+ /* BEs state */
+ offset += snprintf(buf + offset, size - offset, "Backends:\n");
+
+ if (list_empty(&fe->dsp[stream].be_clients)) {
+ offset += snprintf(buf + offset, size - offset,
+ " No active DSP links\n");
+ goto out;
+ }
+
+ list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dsp_params->be;
+
+ offset += snprintf(buf + offset, size - offset,
+ "- %s\n", be->dai_link->name);
+
+ offset += snprintf(buf + offset, size - offset,
+ " State: %s\n",
+ dsp_state_string(fe->dsp[stream].state));
+
+ if ((be->dsp[stream].state >= SND_SOC_DSP_STATE_HW_PARAMS) &&
+ (be->dsp[stream].state <= SND_SOC_DSP_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ " Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+ }
+
+out:
+ return offset;
+}
+
+static ssize_t soc_dsp_state_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct snd_soc_pcm_runtime *fe = file->private_data;
+ ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
+ char *buf;
+
+ buf = kmalloc(out_count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (fe->cpu_dai->driver->playback.channels_min)
+ offset += soc_dsp_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
+ buf + offset, out_count - offset);
+
+ if (fe->cpu_dai->driver->capture.channels_min)
+ offset += soc_dsp_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
+ buf + offset, out_count - offset);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
+
+ kfree(buf);
+
+ return ret;
+}
+
+static const struct file_operations soc_dsp_state_fops = {
+ .open = soc_dsp_state_open_file,
+ .read = soc_dsp_state_read_file,
+ .llseek = default_llseek,
+};
+
+int soc_dsp_debugfs_add(struct snd_soc_pcm_runtime *rtd)
+{
+ rtd->debugfs_dsp_root = debugfs_create_dir(rtd->dai_link->name,
+ rtd->card->debugfs_card_root);
+ if (!rtd->debugfs_dsp_root) {
+ dev_dbg(&rtd->dev,
+ "ASoC: Failed to create dsp debugfs directory %s\n",
+ rtd->dai_link->name);
+ return -EINVAL;
+ }
+
+ rtd->debugfs_dsp_state = debugfs_create_file("state", 0644,
+ rtd->debugfs_dsp_root,
+ rtd, &soc_dsp_state_fops);
+
+ return 0;
+}
+#endif
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
+MODULE_DESCRIPTION("ALSA SoC DSP Core");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index f4aa4e0..34aa972 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -288,9 +288,10 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
+static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_soc_dai *dai = rtd->cpu_dai;
+ struct snd_pcm *pcm = rtd->pcm;
struct platform_device *pdev = to_platform_device(dai->platform->dev);
struct txx9aclc_soc_device *dev;
struct resource *r;