summaryrefslogtreecommitdiff
path: root/packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch')
-rw-r--r--packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch1302
1 files changed, 0 insertions, 1302 deletions
diff --git a/packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch b/packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch
deleted file mode 100644
index 2226022a2c..0000000000
--- a/packages/linux/linux-ezx-2.6.23/patches/ezx-asoc.patch
+++ /dev/null
@@ -1,1302 +0,0 @@
-Index: linux-2.6.23/sound/soc/codecs/pcap2.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23/sound/soc/codecs/pcap2.c 2007-10-22 22:28:06.000000000 +0200
-@@ -0,0 +1,796 @@
-+/*
-+ * pcap2.c - PCAP2 ASIC Audio driver
-+ *
-+ * Copyright (C) 2007 Daniel Ribeiro <drwyrm@gmail.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.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/moduleparam.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/platform_device.h>
-+#include <sound/driver.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 <asm/arch/pxa-regs.h>
-+#include <asm/arch/ezx-pcap.h>
-+#include <asm/arch/ezx.h>
-+#include <asm/arch/hardware.h>
-+
-+#include "pcap2.h"
-+
-+#define AUDIO_NAME "pcap2-codec"
-+#define PCAP2_VERSION "0.1"
-+
-+extern int ezx_pcap_write(u_int8_t, u_int32_t);
-+extern int ezx_pcap_read(u_int8_t, u_int32_t *);
-+static struct snd_soc_device *pcap2_codec_socdev;
-+
-+/*
-+ * Debug
-+ */
-+
-+//#define PCAP2_DEBUG
-+
-+#ifdef PCAP2_DEBUG
-+#define dbg(format, arg...) \
-+ printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
-+#else
-+#define dbg(format, arg...)
-+#endif
-+
-+#define err(format, arg...) \
-+ printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
-+#define info(format, arg...) \
-+ printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
-+#define warn(format, arg...) \
-+ printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
-+
-+#define dump_registers() pcap2_codec_read(NULL, 13); \
-+ pcap2_codec_read(NULL, 12); \
-+ pcap2_codec_read(NULL, 11); \
-+ pcap2_codec_read(NULL, 26);
-+
-+
-+
-+
-+/*
-+ * ASoC limits register value to 16 bits and pcap uses 32 bit registers
-+ * to work around this, we get 16 bits from low, mid or high positions.
-+ * ASoC limits register number to 8 bits we use 0x1f for register
-+ * number and 0xe0 for register offset. -WM
-+ */
-+static int pcap2_codec_write(struct snd_soc_codec *codec, unsigned int reg,
-+ unsigned int value)
-+{
-+ unsigned int tmp;
-+
-+ ezx_pcap_read((reg & 0x1f), &tmp);
-+
-+ if (reg & SL) {
-+ tmp &= 0xffff0000;
-+ tmp |= (value & 0xffff);
-+ }
-+ else if (reg & SM) {
-+ tmp &= 0xff0000ff;
-+ tmp |= ((value << 8) & 0x00ffff00);
-+ }
-+ else if (reg & SH) {
-+ tmp &= 0xffff;
-+ tmp |= ((value << 16) & 0xffff0000);
-+ }
-+ else
-+ tmp = value;
-+
-+ dbg("codec_write reg=%x, rval=%08x, fval=%08x", reg, tmp, value);
-+ ezx_pcap_write((reg & 0x1f), tmp);
-+ return 0;
-+
-+}
-+
-+static unsigned int pcap2_codec_read(struct snd_soc_codec *codec, unsigned int reg)
-+{
-+ unsigned int tmp, ret;
-+
-+ ezx_pcap_read((reg & 0x1f), &tmp);
-+ ret = tmp;
-+ if (reg & SL)
-+ ret = (tmp & 0xffff);
-+ else if (reg & SM)
-+ ret = ((tmp >> 8) & 0xffff);
-+ else if (reg & SH)
-+ ret = ((tmp >> 16) & 0xffff);
-+
-+ dbg("codec_read reg=%x, rval=%08x, fval=%08x", reg, tmp, ret);
-+ return(ret);
-+
-+}
-+
-+static const char *pcap2_output_select[] = {"2ch", "2->1ch", "2->1ch -3db", "2->1ch -6db"};
-+
-+static const struct soc_enum pcap2_enum[] = {
-+SOC_ENUM_SINGLE((PCAP2_OUTPUT_AMP|SH), 3, 4, pcap2_output_select),
-+};
-+
-+static const struct snd_kcontrol_new pcap2_input_mixer_controls[] = {
-+SOC_DAPM_SINGLE("A3 Switch", (PCAP2_INPUT_AMP|SL), 6, 1, 0),
-+SOC_DAPM_SINGLE("A5 Switch", (PCAP2_INPUT_AMP|SL), 8, 1, 0),
-+};
-+
-+static const struct snd_kcontrol_new pcap2_output_mixer_controls[] = {
-+SOC_DAPM_SINGLE("A1 Switch", (PCAP2_OUTPUT_AMP|SL), 0, 1, 0),
-+SOC_DAPM_SINGLE("A2 Switch", (PCAP2_OUTPUT_AMP|SL), 1, 1, 0),
-+SOC_DAPM_SINGLE("AR Switch", (PCAP2_OUTPUT_AMP|SL), 5, 1, 0),
-+SOC_DAPM_SINGLE("AL Switch", (PCAP2_OUTPUT_AMP|SL), 6, 1, 0),
-+};
-+
-+/* pcap2 codec non DAPM controls */
-+static const struct snd_kcontrol_new pcap2_codec_snd_controls[] = {
-+SOC_SINGLE("Output gain", (PCAP2_OUTPUT_AMP|SM), 5, 15, 0),
-+SOC_SINGLE("Input gain", (PCAP2_INPUT_AMP|SL), 0, 31, 0),
-+};
-+
-+static const struct snd_kcontrol_new pcap2_codec_dm_mux_control[] = {
-+ SOC_DAPM_ENUM("Output Mode", pcap2_enum[0]),
-+};
-+
-+/* add non dapm controls */
-+static int pcap2_codec_add_controls(struct snd_soc_codec *codec)
-+{
-+ int err, i;
-+
-+ for (i = 0; i < ARRAY_SIZE(pcap2_codec_snd_controls); i++) {
-+ if ((err = snd_ctl_add(codec->card,
-+ snd_soc_cnew(&pcap2_codec_snd_controls[i],codec, NULL))) < 0)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/* pcap2 codec DAPM controls */
-+static const struct snd_soc_dapm_widget pcap2_codec_dapm_widgets[] = {
-+ SND_SOC_DAPM_DAC("ST_DAC", "ST_DAC playback", SND_SOC_NOPM, 0, 0),
-+ SND_SOC_DAPM_DAC("CDC_DAC", "CDC_DAC playback", SND_SOC_NOPM, 0, 0),
-+ SND_SOC_DAPM_ADC("CDC_ADC", "CDC_DAC capture", SND_SOC_NOPM, 0, 0),
-+ SND_SOC_DAPM_PGA("PGA_ST", (PCAP2_OUTPUT_AMP|SL), 9, 0, NULL, 0),
-+ SND_SOC_DAPM_PGA("PGA_CDC", (PCAP2_OUTPUT_AMP|SL), 8, 0, NULL, 0),
-+ SND_SOC_DAPM_PGA("PGA_R", (PCAP2_OUTPUT_AMP|SL), 11, 0, NULL, 0),
-+ SND_SOC_DAPM_PGA("PGA_L", (PCAP2_OUTPUT_AMP|SL), 12, 0, NULL, 0),
-+ SND_SOC_DAPM_MUX("Downmixer", SND_SOC_NOPM, 0, 0, pcap2_codec_dm_mux_control),
-+ SND_SOC_DAPM_PGA("PGA_A1CTRL", (PCAP2_OUTPUT_AMP|SH), 1, 1, NULL, 0),
-+ SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, &pcap2_output_mixer_controls[0], ARRAY_SIZE(pcap2_output_mixer_controls)),
-+ SND_SOC_DAPM_OUTPUT("A1"), /* Earpiece */
-+ SND_SOC_DAPM_OUTPUT("A2"), /* LoudSpeaker */
-+ SND_SOC_DAPM_OUTPUT("AR"), /* headset right */
-+ SND_SOC_DAPM_OUTPUT("AL"), /* headset left */
-+
-+ SND_SOC_DAPM_MICBIAS("BIAS1", (PCAP2_INPUT_AMP|SL), 10, 0),
-+ SND_SOC_DAPM_MICBIAS("BIAS2", (PCAP2_INPUT_AMP|SL), 11, 0),
-+ SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, &pcap2_input_mixer_controls[0], ARRAY_SIZE(pcap2_input_mixer_controls)),
-+ SND_SOC_DAPM_INPUT("A3"), /* Headset Mic */
-+ SND_SOC_DAPM_INPUT("A5"), /* Builtin Mic */
-+};
-+
-+static const char *audio_map[][3] = {
-+ { "A1", NULL, "Output Mixer" },
-+ { "A2", NULL, "Output Mixer" },
-+ { "AR", NULL, "Output Mixer" },
-+ { "AL", NULL, "Output Mixer" },
-+
-+ { "Output Mixer", "A1 Switch", "PGA_A1CTRL" },
-+ { "Output Mixer", "A2 Switch", "Downmixer" },
-+ { "Output Mixer", "AR Switch", "PGA_R" },
-+ { "Output Mixer", "AL Switch", "PGA_L" },
-+
-+ { "PGA_A1CTRL", NULL, "Downmixer" },
-+
-+ { "Downmixer", "2->1ch", "PGA_L" },
-+ { "Downmixer", "2->1ch", "PGA_R" },
-+ { "Downmixer", "2->1ch -3db", "PGA_L" },
-+ { "Downmixer", "2->1ch -3db", "PGA_R" },
-+ { "Downmixer", "2->1ch -6db", "PGA_L" },
-+ { "Downmixer", "2->1ch -6db", "PGA_R" },
-+ { "Downmixer", "2ch", "PGA_R" },
-+
-+ { "PGA_R", NULL, "PGA_ST" },
-+ { "PGA_L", NULL, "PGA_ST" },
-+ { "PGA_R", NULL, "PGA_CDC" },
-+
-+ { "PGA_ST", NULL, "ST_DAC" },
-+ { "PGA_CDC", NULL, "CDC_DAC" },
-+
-+ /* input path */
-+ { "BIAS1", NULL, "A3" },
-+ { "BIAS2", NULL, "A5" },
-+
-+ { "Input Mixer", "A3 Switch", "BIAS1" },
-+ { "Input Mixer", "A5 Switch", "BIAS2" },
-+
-+ { "PGA_R", NULL, "Input Mixer" },
-+
-+ { "PGA_CDC", NULL, "PGA_R" },
-+ { "CDC_ADC", NULL, "PGA_CDC" },
-+
-+ /* terminator */
-+ {NULL, NULL, NULL},
-+};
-+
-+static int pcap2_codec_add_widgets(struct snd_soc_codec *codec)
-+{
-+ int i;
-+
-+ for(i = 0; i < ARRAY_SIZE(pcap2_codec_dapm_widgets); i++) {
-+ snd_soc_dapm_new_control(codec, &pcap2_codec_dapm_widgets[i]);
-+ }
-+
-+ /* set up audio path interconnects */
-+ for(i = 0; audio_map[i][0] != NULL; i++) {
-+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
-+ audio_map[i][1], audio_map[i][2]);
-+ }
-+
-+ snd_soc_dapm_new_widgets(codec);
-+ return 0;
-+}
-+
-+static int pcap2_codec_dapm_event(struct snd_soc_codec *codec, int event)
-+{
-+ unsigned int input = pcap2_codec_read(codec, PCAP2_INPUT_AMP);
-+
-+ input &= ~PCAP2_INPUT_AMP_LOWPWR;
-+
-+ switch (event) {
-+ case SNDRV_CTL_POWER_D0:
-+ case SNDRV_CTL_POWER_D1:
-+ case SNDRV_CTL_POWER_D2:
-+ case SNDRV_CTL_POWER_D3hot: /* Off, with power */
-+ dbg("dapm: ON\n");
-+ break;
-+ case SNDRV_CTL_POWER_D3cold: /* Off, without power */
-+ input |= PCAP2_INPUT_AMP_LOWPWR;
-+ dbg("dapm: OFF\n");
-+ break;
-+ }
-+ codec->dapm_state = event;
-+ pcap2_codec_write(codec, PCAP2_INPUT_AMP, input);
-+ return 0;
-+}
-+
-+static int pcap2_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_codec_dai *codec_dai = rtd->dai->codec_dai;
-+ struct snd_soc_codec *codec = codec_dai->codec;
-+ unsigned int tmp;
-+
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ tmp = pcap2_codec_read(codec, PCAP2_ST_DAC);
-+
-+ tmp &= ~PCAP2_ST_DAC_RATE_MASK;
-+ switch(params_rate(params)) {
-+ case 8000:
-+ break;
-+ case 11025:
-+ tmp |= PCAP2_ST_DAC_RATE_11025;
-+ break;
-+ case 12000:
-+ tmp |= PCAP2_ST_DAC_RATE_12000;
-+ break;
-+ case 16000:
-+ tmp |= PCAP2_ST_DAC_RATE_16000;
-+ break;
-+ case 22050:
-+ tmp |= PCAP2_ST_DAC_RATE_22050;
-+ break;
-+ case 24000:
-+ tmp |= PCAP2_ST_DAC_RATE_24000;
-+ break;
-+ case 32000:
-+ tmp |= PCAP2_ST_DAC_RATE_32000;
-+ break;
-+ case 44100:
-+ tmp |= PCAP2_ST_DAC_RATE_44100;
-+ break;
-+ case 48000:
-+ tmp |= PCAP2_ST_DAC_RATE_48000;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ tmp |= PCAP2_ST_DAC_RESET_DF;
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, tmp);
-+ }
-+ else {
-+ tmp = pcap2_codec_read(codec, PCAP2_CODEC);
-+
-+ tmp &= ~PCAP2_CODEC_RATE_MASK;
-+ switch(params_rate(params)) {
-+ case 8000:
-+ break;
-+ case 16000:
-+ tmp |= PCAP2_CODEC_RATE_16000;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ tmp |= PCAP2_CODEC_RESET_DF;
-+ pcap2_codec_write(codec, PCAP2_CODEC, tmp);
-+ }
-+
-+ return 0;
-+}
-+
-+static int pcap2_hw_free(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+ struct snd_soc_codec *codec = codec_dai->codec;
-+ struct snd_soc_dapm_widget *w;
-+ unsigned int tmp;
-+
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ snd_soc_dapm_set_endpoint(codec, "ST_DAC", 0);
-+ tmp = pcap2_codec_read(codec, PCAP2_ST_DAC);
-+ tmp &= ~(PCAP2_ST_DAC_EN | PCAP2_ST_DAC_CLK_EN);
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, tmp);
-+ }
-+ else {
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ snd_soc_dapm_set_endpoint(codec, "CDC_DAC", 0);
-+ else
-+ snd_soc_dapm_set_endpoint(codec, "CDC_ADC", 0);
-+ list_for_each_entry(w, &codec->dapm_widgets, list) {
-+ if ((!strcmp(w->name, "CDC_DAC") || !strcmp(w->name, "CDC_ADC")) && w->connected)
-+ goto in_use;
-+ }
-+ tmp = pcap2_codec_read(codec, PCAP2_CODEC);
-+ tmp &= ~(PCAP2_CODEC_EN | PCAP2_CODEC_CLK_EN);
-+ pcap2_codec_write(codec, PCAP2_CODEC, tmp);
-+ }
-+in_use:
-+ snd_soc_dapm_sync_endpoints(codec);
-+
-+ return 0;
-+}
-+
-+static int pcap2_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
-+ int clk_id, unsigned int freq, int dir)
-+{
-+ struct snd_soc_codec *codec = codec_dai->codec;
-+
-+ unsigned int tmp;
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ /* ST_DAC */
-+
-+ tmp = pcap2_codec_read(codec, PCAP2_ST_DAC);
-+
-+ tmp &= ~PCAP2_ST_DAC_CLKSEL_MASK;
-+ switch (clk_id) {
-+ case PCAP2_CLK_AP:
-+ tmp |= PCAP2_ST_DAC_CLKSEL_AP;
-+ break;
-+ case PCAP2_CLK_BP:
-+ break;
-+ default:
-+ return -ENODEV;
-+ }
-+
-+ tmp &= ~PCAP2_ST_DAC_CLK_MASK;
-+ switch (freq) {
-+ case 13000000:
-+ break;
-+/* case 15M36:
-+ tmp |= PCAP2_ST_DAC_CLK_15M36;
-+ break;
-+ case 16M8:
-+ tmp |= PCAP2_ST_DAC_CLK_16M8;
-+ break;
-+ case 19M44:
-+ tmp |= PCAP2_ST_DAC_CLK_19M44;
-+ break;
-+*/ case 26000000:
-+ tmp |= PCAP2_ST_DAC_CLK_26M;
-+ break;
-+/* case EXT_MCLK:
-+ tmp |= PCAP2_ST_DAC_CLK_MCLK;
-+ break;
-+ case FSYNC:
-+ tmp |= PCAP2_ST_DAC_CLK_FSYNC;
-+ break;
-+ case BITCLK:
-+ tmp |= PCAP2_ST_DAC_CLK_BITCLK;
-+ break;
-+*/ default:
-+ return -EINVAL;
-+ }
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, tmp);
-+ }
-+ else {
-+ /* MONO_DAC */
-+ tmp = pcap2_codec_read(codec, PCAP2_CODEC);
-+
-+ tmp &= ~PCAP2_CODEC_CLKSEL_MASK;
-+ switch (clk_id) {
-+ case PCAP2_CLK_AP:
-+ tmp |= PCAP2_CODEC_CLKSEL_AP;
-+ break;
-+ case PCAP2_CLK_BP:
-+ break;
-+ default:
-+ return -ENODEV;
-+ }
-+
-+ tmp &= ~PCAP2_CODEC_CLK_MASK;
-+ switch (freq) {
-+ case 13000000:
-+ break;
-+/* case 15M36:
-+ tmp |= PCAP2_CODEC_CLK_15M36;
-+ break;
-+ case 16M8:
-+ tmp |= PCAP2_CODEC_CLK_16M8;
-+ break;
-+ case 19M44:
-+ tmp |= PCAP2_CODEC_CLK_19M44;
-+ break;
-+*/ case 26000000:
-+ tmp |= PCAP2_CODEC_CLK_26M;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ pcap2_codec_write(codec, PCAP2_CODEC, tmp);
-+ }
-+ return 0;
-+}
-+
-+static int pcap2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
-+ unsigned int fmt)
-+{
-+ struct snd_soc_codec *codec = codec_dai->codec;
-+ unsigned int tmp = 0;
-+
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ /* ST_DAC */
-+
-+ /* disable CODEC */
-+ pcap2_codec_write(codec, PCAP2_CODEC, 0);
-+
-+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+ case SND_SOC_DAIFMT_CBM_CFM:
-+ break;
-+ case SND_SOC_DAIFMT_CBS_CFS:
-+ tmp |= 0x1;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+ case SND_SOC_DAIFMT_I2S:
-+ tmp |= 0x4000;
-+ break;
-+/* case SND_SOC_NET:
-+ tmp |= 0x2000;
-+ break;
-+*/ case SND_SOC_DAIFMT_DSP_B:
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+ case SND_SOC_DAIFMT_IB_IF:
-+ break;
-+ case SND_SOC_DAIFMT_NB_NF:
-+ tmp |= 0x60000;
-+ break;
-+ case SND_SOC_DAIFMT_IB_NF:
-+ tmp |= 0x40000;
-+ break;
-+ case SND_SOC_DAIFMT_NB_IF:
-+ tmp |= 0x20000;
-+ break;
-+ }
-+ /* set dai to AP */
-+ tmp |= 0x1000;
-+
-+ /* set BCLK */
-+ tmp |= 0x18000;
-+
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, tmp);
-+ }
-+ else {
-+ /* MONO_DAC */
-+
-+ /* disable ST_DAC */
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, 0);
-+
-+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+ case SND_SOC_DAIFMT_CBM_CFM:
-+ break;
-+ case SND_SOC_DAIFMT_CBS_CFS:
-+ tmp |= 0x2;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+ case SND_SOC_DAIFMT_DSP_B:
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+ case SND_SOC_DAIFMT_IB_IF:
-+ break;
-+ case SND_SOC_DAIFMT_NB_NF:
-+ tmp |= 0x600;
-+ break;
-+ case SND_SOC_DAIFMT_IB_NF:
-+ tmp |= 0x400;
-+ break;
-+ case SND_SOC_DAIFMT_NB_IF:
-+ tmp |= 0x200;
-+ break;
-+ }
-+ if (codec_dai->id == PCAP2_MONO_DAI)
-+ /* set dai to AP */
-+ tmp |= 0x8000;
-+
-+ tmp |= 0x5; /* IHF / OHF */
-+
-+ pcap2_codec_write(codec, PCAP2_CODEC, tmp);
-+ }
-+ return 0;
-+}
-+
-+static int pcap2_prepare(struct snd_pcm_substream *substream)
-+{
-+
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+ struct snd_soc_codec *codec = codec_dai->codec;
-+ unsigned int tmp;
-+ /* FIXME enable clock only if codec is master */
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ snd_soc_dapm_set_endpoint(codec, "ST_DAC", 1);
-+ snd_soc_dapm_set_endpoint(codec, "CDC_DAC", 0);
-+ snd_soc_dapm_set_endpoint(codec, "CDC_ADC", 0);
-+ tmp = pcap2_codec_read(codec, PCAP2_ST_DAC);
-+ tmp |= (PCAP2_ST_DAC_EN | PCAP2_ST_DAC_CLK_EN);
-+ pcap2_codec_write(codec, PCAP2_ST_DAC, tmp);
-+ }
-+ else {
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ snd_soc_dapm_set_endpoint(codec, "CDC_DAC", 1);
-+ else
-+ snd_soc_dapm_set_endpoint(codec, "CDC_ADC", 1);
-+ snd_soc_dapm_set_endpoint(codec, "ST_DAC", 0);
-+ tmp = pcap2_codec_read(codec, PCAP2_CODEC);
-+ tmp |= (PCAP2_CODEC_EN | PCAP2_CODEC_CLK_EN);
-+ pcap2_codec_write(codec, PCAP2_CODEC, tmp);
-+ }
-+ snd_soc_dapm_sync_endpoints(codec);
-+ mdelay(1);
-+#ifdef PCAP2_DEBUG
-+ dump_registers();
-+#endif
-+ return 0;
-+}
-+
-+/*
-+ * Define codec DAI.
-+ */
-+struct snd_soc_codec_dai pcap2_dai[] = {
-+{
-+ .name = "PCAP2 MONO",
-+ .id = 0,
-+ .playback = {
-+ .stream_name = "CDC_DAC playback",
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .capture = {
-+ .stream_name = "CDC_DAC capture",
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .ops = {
-+ .prepare = pcap2_prepare,
-+ .hw_params = pcap2_hw_params,
-+ .hw_free = pcap2_hw_free,
-+ },
-+ .dai_ops = {
-+// .digital_mute = pcap2_mute,
-+ .set_fmt = pcap2_set_dai_fmt,
-+ .set_sysclk = pcap2_set_dai_sysclk,
-+ },
-+},
-+{
-+ .name = "PCAP2 STEREO",
-+ .id = 1,
-+ .playback = {
-+ .stream_name = "ST_DAC playback",
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
-+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
-+ SNDRV_PCM_RATE_48000),
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .capture = { /* FIXME: PCAP support this?? */
-+ .stream_name = "ST_DAC capture",
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
-+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
-+ SNDRV_PCM_RATE_48000),
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .ops = {
-+ .prepare = pcap2_prepare,
-+ .hw_params = pcap2_hw_params,
-+ .hw_free = pcap2_hw_free,
-+ },
-+ .dai_ops = {
-+// .digital_mute = pcap2_mute,
-+ .set_fmt = pcap2_set_dai_fmt,
-+ .set_sysclk = pcap2_set_dai_sysclk,
-+ },
-+},
-+{
-+ .name = "PCAP2 BP",
-+ .id = 2,
-+ .playback = {
-+ .stream_name = "BP playback",
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = SNDRV_PCM_RATE_8000,
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .ops = {
-+ .prepare = pcap2_prepare,
-+ .hw_params = pcap2_hw_params,
-+ .hw_free = pcap2_hw_free,
-+ },
-+ .dai_ops = {
-+// .digital_mute = pcap2_mute,
-+ .set_fmt = pcap2_set_dai_fmt,
-+ .set_sysclk = pcap2_set_dai_sysclk,
-+ },
-+},
-+};
-+EXPORT_SYMBOL_GPL(pcap2_dai);
-+
-+static int pcap2_codec_suspend(struct platform_device *pdev, pm_message_t state)
-+{
-+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-+ struct snd_soc_codec *codec = socdev->codec;
-+
-+ dbg("pcap2_codec_suspend");
-+ pcap2_codec_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
-+ return 0;
-+}
-+
-+static int pcap2_codec_resume(struct platform_device *pdev)
-+{
-+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-+ struct snd_soc_codec *codec = socdev->codec;
-+
-+ dbg("pcap2_codec_resume");
-+ pcap2_codec_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
-+ pcap2_codec_dapm_event(codec, codec->suspend_dapm_state);
-+ return 0;
-+}
-+
-+/*
-+ * initialise the PCAP2 driver
-+ * register the mixer and dsp interfaces with the kernel
-+ */
-+static int pcap2_codec_init(struct snd_soc_device *socdev)
-+{
-+ struct snd_soc_codec *codec = socdev->codec;
-+ int ret = 0;
-+
-+ dbg("pcap2_codec_init");
-+ codec->name = "PCAP2 Audio";
-+ codec->owner = THIS_MODULE;
-+ codec->read = pcap2_codec_read;
-+ codec->write = pcap2_codec_write;
-+ codec->dapm_event = pcap2_codec_dapm_event;
-+ codec->dai = pcap2_dai;
-+ codec->num_dai = ARRAY_SIZE(pcap2_dai);
-+
-+ /* register pcms */
-+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-+ if (ret < 0) {
-+ return ret;
-+ }
-+ /* power on device */
-+ pcap2_codec_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
-+ /* set the update bits */
-+
-+ pcap2_codec_add_controls(codec);
-+ pcap2_codec_add_widgets(codec);
-+ ret = snd_soc_register_card(socdev);
-+ if (ret < 0) {
-+ snd_soc_free_pcms(socdev);
-+ snd_soc_dapm_free(socdev);
-+ }
-+
-+ return ret;
-+}
-+
-+static int pcap2_codec_probe(struct platform_device *pdev)
-+{
-+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-+ struct pcap2_codec_setup_data *setup;
-+ struct snd_soc_codec *codec;
-+ int ret = 0;
-+ info("PCAP2 Audio Codec %s", PCAP2_VERSION);
-+
-+ setup = socdev->codec_data;
-+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-+ if (codec == NULL)
-+ return -ENOMEM;
-+
-+ socdev->codec = codec;
-+ mutex_init(&codec->mutex);
-+ INIT_LIST_HEAD(&codec->dapm_widgets);
-+ INIT_LIST_HEAD(&codec->dapm_paths);
-+
-+ pcap2_codec_socdev = socdev;
-+
-+ ret = pcap2_codec_init(socdev);
-+ return ret;
-+}
-+
-+/* power down chip and remove */
-+static int pcap2_codec_remove(struct platform_device *pdev)
-+{
-+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-+ struct snd_soc_codec *codec = socdev->codec;
-+ if (codec->control_data)
-+ pcap2_codec_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
-+ snd_soc_free_pcms(socdev);
-+ snd_soc_dapm_free(socdev);
-+
-+ kfree(codec);
-+
-+ return 0;
-+}
-+
-+/* codec device ops */
-+struct snd_soc_codec_device soc_codec_dev_pcap2 = {
-+ .probe = pcap2_codec_probe,
-+ .remove = pcap2_codec_remove,
-+ .suspend = pcap2_codec_suspend,
-+ .resume = pcap2_codec_resume,
-+};
-+
-+EXPORT_SYMBOL_GPL(soc_codec_dev_pcap2);
-+
-+MODULE_DESCRIPTION("ASoC PCAP2 codec");
-+MODULE_AUTHOR("Daniel Ribeiro");
-+MODULE_LICENSE("GPL");
-Index: linux-2.6.23/sound/soc/codecs/pcap2.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23/sound/soc/codecs/pcap2.h 2007-10-22 22:28:06.000000000 +0200
-@@ -0,0 +1,81 @@
-+/*
-+ * 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 _PCAP2_H
-+#define _PCAP2_H
-+
-+/* 16 bit reads/writes on pcap registers (ugly workaround) */
-+#define SL (1 << 5) /* lower 16 bits */
-+#define SM (1 << 6) /* mid 16 bits */
-+#define SH (1 << 7) /* higher 16 bits */
-+
-+/* PCAP2 register space */
-+#define PCAP2_CODEC 0x0b
-+#define PCAP2_OUTPUT_AMP 0x0c
-+#define PCAP2_ST_DAC 0x0d
-+#define PCAP2_INPUT_AMP 0x1a
-+
-+#define PCAP2_MONO_DAI 0
-+#define PCAP2_STEREO_DAI 1
-+#define PCAP2_BP_DAI 2
-+
-+#define PCAP2_CLK_BP 0
-+#define PCAP2_CLK_AP 1
-+
-+#define PCAP2_CODEC_EN 0x2000
-+#define PCAP2_CODEC_CLK_EN 0x1000
-+#define PCAP2_CODEC_RESET_DF 0x800
-+#define PCAP2_CODEC_RATE_MASK 0x4000
-+#define PCAP2_CODEC_RATE_8000 0x0
-+#define PCAP2_CODEC_RATE_16000 0x4000
-+#define PCAP2_CODEC_CLKSEL_MASK 0x10000
-+#define PCAP2_CODEC_CLKSEL_AP 0x10000
-+#define PCAP2_CODEC_CLKSEL_BP 0x0
-+#define PCAP2_CODEC_CLK_MASK 0x1c0
-+#define PCAP2_CODEC_CLK_13M 0x0
-+#define PCAP2_CODEC_CLK_15M36 0x40
-+#define PCAP2_CODEC_CLK_16M8 0x80
-+#define PCAP2_CODEC_CLK_19M44 0xc0
-+#define PCAP2_CODEC_CLK_26M 0x100
-+
-+#define PCAP2_ST_DAC_EN 0x80
-+#define PCAP2_ST_DAC_CLK_EN 0x20
-+#define PCAP2_ST_DAC_RESET_DF 0x40
-+#define PCAP2_ST_DAC_RATE_MASK 0xf00
-+#define PCAP2_ST_DAC_RATE_8000 0x0
-+#define PCAP2_ST_DAC_RATE_11025 0x100
-+#define PCAP2_ST_DAC_RATE_12000 0x200
-+#define PCAP2_ST_DAC_RATE_16000 0x300
-+#define PCAP2_ST_DAC_RATE_22050 0x400
-+#define PCAP2_ST_DAC_RATE_24000 0x500
-+#define PCAP2_ST_DAC_RATE_32000 0x600
-+#define PCAP2_ST_DAC_RATE_44100 0x700
-+#define PCAP2_ST_DAC_RATE_48000 0x800
-+#define PCAP2_ST_DAC_CLKSEL_MASK 0x80000
-+#define PCAP2_ST_DAC_CLKSEL_AP 0x80000
-+#define PCAP2_ST_DAC_CLKSEL_BP 0x0
-+#define PCAP2_ST_DAC_CLK_MASK 0x1c
-+#define PCAP2_ST_DAC_CLK_13M 0x0
-+#define PCAP2_ST_DAC_CLK_15M36 0x4
-+#define PCAP2_ST_DAC_CLK_16M8 0x8
-+#define PCAP2_ST_DAC_CLK_19M44 0xc
-+#define PCAP2_ST_DAC_CLK_26M 0x10
-+#define PCAP2_ST_DAC_CLK_MCLK 0x14
-+#define PCAP2_ST_DAC_CLK_FSYNC 0x18
-+#define PCAP2_ST_DAC_CLK_BITCLK 0x1c
-+
-+#define PCAP2_INPUT_AMP_LOWPWR 0x80000
-+#define PCAP2_INPUT_AMP_V2EN2 0x200000
-+
-+#define PCAP2_OUTPUT_AMP_PGAR_EN 0x800
-+#define PCAP2_OUTPUT_AMP_PGAL_EN 0x1000
-+#define PCAP2_OUTPUT_AMP_CDC_SW 0x100
-+#define PCAP2_OUTPUT_AMP_ST_DAC_SW 0x200
-+
-+extern struct snd_soc_codec_dai pcap2_dai[];
-+extern struct snd_soc_codec_device soc_codec_dev_pcap2;
-+
-+#endif
-Index: linux-2.6.23/sound/soc/pxa/Kconfig
-===================================================================
---- linux-2.6.23.orig/sound/soc/pxa/Kconfig 2007-10-22 22:27:11.000000000 +0200
-+++ linux-2.6.23/sound/soc/pxa/Kconfig 2007-10-22 22:29:23.000000000 +0200
-@@ -57,3 +57,12 @@
- help
- Say Y if you want to add support for SoC audio on Sharp
- Zaurus SL-C6000x models (Tosa).
-+
-+config SND_PXA2XX_SOC_EZX
-+ tristate "SoC Audio support for EZX"
-+ depends on SND_PXA2XX_SOC && PXA_EZX
-+ select SND_PXA2XX_SOC_SSP
-+ select SND_SOC_PCAP2
-+ help
-+ Say Y if you want to add support for SoC audio on
-+ Motorola EZX Phones (a780/e680).
-Index: linux-2.6.23/sound/soc/pxa/ezx.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23/sound/soc/pxa/ezx.c 2007-10-22 22:28:06.000000000 +0200
-@@ -0,0 +1,349 @@
-+/*
-+ * ezx.c - Machine specific code for EZX phones
-+ *
-+ * Copyright (C) 2007 Daniel Ribeiro <drwyrm@gmail.com>
-+ *
-+ * 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/timer.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/soc.h>
-+#include <sound/soc-dapm.h>
-+
-+#include <asm/mach-types.h>
-+#include <asm/arch/pxa-regs.h>
-+#include <asm/arch/hardware.h>
-+
-+#include <asm/arch/ezx-pcap.h>
-+
-+#include "../codecs/pcap2.h"
-+#include "pxa2xx-pcm.h"
-+#include "pxa2xx-ssp.h"
-+
-+#define GPIO_HW_ATTENUATE_A780 96
-+
-+static struct snd_soc_codec *control_codec;
-+
-+static void ezx_ext_control(struct snd_soc_codec *codec)
-+{
-+ if (ezx_pcap_read_bit(pbit(PCAP_REG_PSTAT, PCAP_IRQ_A1)))
-+ snd_soc_dapm_set_endpoint(codec, "Headset", 1);
-+ else
-+ snd_soc_dapm_set_endpoint(codec, "Headset", 0);
-+ if (ezx_pcap_read_bit(pbit(PCAP_REG_PSTAT, PCAP_IRQ_MB2)))
-+ snd_soc_dapm_set_endpoint(codec, "External Mic", 1);
-+ else
-+ snd_soc_dapm_set_endpoint(codec, "External Mic", 0);
-+
-+ snd_soc_dapm_sync_endpoints(codec);
-+}
-+
-+static irqreturn_t jack_irq(int irq, void *data)
-+{
-+ ezx_ext_control(control_codec);
-+ return IRQ_HANDLED;
-+}
-+
-+
-+/*
-+ * Alsa operations
-+ * Only implement the required operations for your platform.
-+ * These operations are specific to the machine only.
-+ */
-+
-+ /*
-+ * Called by ALSA when a PCM substream is opened, private data can be allocated.
-+ */
-+static int ezx_machine_startup(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_codec *codec = rtd->socdev->codec;
-+
-+ /* check the jack status at stream startup */
-+ ezx_ext_control(codec);
-+ return 0;
-+}
-+
-+/*
-+ * Called by ALSA when the hardware params are set by application. This
-+ * function can also be called multiple times and can allocate buffers
-+ * (using snd_pcm_lib_* ). It's non-atomic.
-+ */
-+static int ezx_machine_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_codec_dai *codec_dai = rtd->dai->codec_dai;
-+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+ int ret;
-+
-+ /* set codec DAI configuration */
-+ if (codec_dai->id == PCAP2_STEREO_DAI)
-+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
-+ SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM);
-+ else
-+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
-+ SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-+ if(ret < 0)
-+ return ret;
-+
-+ /* Turn on clock output on CLK_PIO */
-+ OSCC |= 0x8;
-+
-+ /* set clock source */
-+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, PCAP2_CLK_AP,
-+ 13000000, SND_SOC_CLOCK_IN);
-+ if(ret < 0)
-+ return ret;
-+
-+ /* set cpu DAI configuration */
-+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B |
-+ SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = cpu_dai->dai_ops.set_tristate(cpu_dai, 0);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai,PXA2XX_SSP_CLK_EXT,
-+ 0, SND_SOC_CLOCK_IN);
-+ if (ret < 0)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Free's resources allocated by hw_params, can be called multiple times
-+ */
-+static int ezx_machine_hw_free(struct snd_pcm_substream *substream)
-+{
-+ OSCC &= ~0x8; /* turn off clock output on CLK_PIO */
-+
-+ return 0;
-+}
-+
-+static int ezx_machine_prepare(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+ if (codec_dai->id == PCAP2_STEREO_DAI) {
-+ /* override pxa2xx-ssp sample size for stereo/network mode */
-+ SSCR0_P(cpu_dai->id+1) &= ~(SSCR0_DSS | SSCR0_EDSS);
-+ SSCR0_P(cpu_dai->id+1) |= (SSCR0_EDSS | SSCR0_DataSize(16));
-+ }
-+ return 0;
-+}
-+
-+/* machine Alsa PCM operations */
-+static struct snd_soc_ops ezx_ops = {
-+ .startup = ezx_machine_startup,
-+ .prepare = ezx_machine_prepare,
-+ .hw_free = ezx_machine_hw_free,
-+ .hw_params = ezx_machine_hw_params,
-+};
-+
-+static int bp_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_codec_dai *codec_dai = rtd->dai->codec_dai;
-+// struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+ int ret = 0;
-+ /* set codec DAI configuration */
-+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
-+ SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-+ if(ret < 0)
-+ return ret;
-+
-+ /* set clock source */
-+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, PCAP2_CLK_BP,
-+ 13000000, SND_SOC_CLOCK_IN);
-+
-+ return ret;
-+}
-+
-+
-+
-+/* machine dapm widgets */
-+static const struct snd_soc_dapm_widget ezx_dapm_widgets[] = {
-+ SND_SOC_DAPM_HP("Headset", NULL),
-+ SND_SOC_DAPM_SPK("Earpiece", NULL),
-+ SND_SOC_DAPM_SPK("Loudspeaker", NULL),
-+ SND_SOC_DAPM_MIC("Built-in Mic", NULL),
-+ SND_SOC_DAPM_MIC("External Mic", NULL),
-+};
-+
-+/* machine audio map (connections to the codec pins) */
-+static const char *audio_map[][3] = {
-+ { "Headset", NULL, "AR" },
-+ { "Headset", NULL, "AL" },
-+ { "Earpiece", NULL, "A1" },
-+ { "Loudspeaker", NULL, "A2" },
-+
-+ { "Built-in Mic", NULL, "A5" },
-+ { "External Mic", NULL, "A3" },
-+
-+ {NULL, NULL, NULL},
-+};
-+
-+/*
-+ * Initialise the machine audio subsystem.
-+ */
-+static int ezx_machine_init(struct snd_soc_codec *codec)
-+{
-+ int i;
-+ /* mark unused codec pins as NC */
-+// snd_soc_dapm_set_endpoint(codec, "FIXME", 0);
-+ control_codec = codec;
-+
-+ /* Add ezx specific controls */
-+// for (i = 0; i < ARRAY_SIZE(ezx_controls); i++) {
-+// if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&ezx_controls[i], codec, NULL))) < 0)
-+// return err;
-+// }
-+
-+ /* Add ezx specific widgets */
-+ for(i = 0; i < ARRAY_SIZE(ezx_dapm_widgets); i++) {
-+ snd_soc_dapm_new_control(codec, &ezx_dapm_widgets[i]);
-+ }
-+ /* Set up ezx specific audio path interconnects */
-+ for(i = 0; audio_map[i][0] != NULL; i++) {
-+ snd_soc_dapm_connect_input(codec, audio_map[i][0], audio_map[i][1], audio_map[i][2]);
-+ }
-+
-+ /* synchronise subsystem */
-+ snd_soc_dapm_sync_endpoints(codec);
-+ return 0;
-+}
-+
-+static struct snd_soc_cpu_dai bp_dai =
-+{
-+ .name = "Baseband",
-+ .id = 0,
-+ .type = SND_SOC_DAI_PCM,
-+ .playback = {
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = SNDRV_PCM_RATE_8000,
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .capture = {
-+ .channels_min = 1,
-+ .channels_max = 1,
-+ .rates = SNDRV_PCM_RATE_8000,
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+ },
-+ .ops = {
-+// .startup = bp_startup,
-+// .shutdown = bp_shutdown,
-+ .hw_params = bp_hw_params,
-+// .hw_free = bp_hw_free,
-+ },
-+};
-+
-+/* template digital audio interface glue - connects codec <--> CPU */
-+static struct snd_soc_dai_link ezx_dai[] = {
-+{
-+ .name = "PCAP2 STEREO",
-+ .stream_name = "stereo playback",
-+ .cpu_dai = &pxa_ssp_dai[PXA2XX_DAI_SSP3],
-+ .codec_dai = &pcap2_dai[PCAP2_STEREO_DAI],
-+ .init = ezx_machine_init,
-+ .ops = &ezx_ops,
-+},
-+{
-+ .name = "PCAP2 MONO",
-+ .stream_name = "mono playback",
-+ .cpu_dai = &pxa_ssp_dai[PXA2XX_DAI_SSP3],
-+ .codec_dai = &pcap2_dai[PCAP2_MONO_DAI],
-+// .init = ezx_machine_init, /* the stereo call already registered our controls */
-+ .ops = &ezx_ops,
-+},
-+{
-+ .name = "PCAP2 BP",
-+ .stream_name = "BP Audio",
-+ .cpu_dai = &bp_dai,
-+ .codec_dai = &pcap2_dai[PCAP2_BP_DAI],
-+},
-+};
-+
-+/* template audio machine driver */
-+static struct snd_soc_machine snd_soc_machine_ezx = {
-+ .name = "Motorola EZX",
-+// .probe
-+// .remove
-+// .suspend_pre
-+// .resume_post
-+ .dai_link = ezx_dai,
-+ .num_links = ARRAY_SIZE(ezx_dai),
-+};
-+
-+/* template audio subsystem */
-+static struct snd_soc_device ezx_snd_devdata = {
-+ .machine = &snd_soc_machine_ezx,
-+ .platform = &pxa2xx_soc_platform,
-+ .codec_dev = &soc_codec_dev_pcap2,
-+};
-+
-+static struct platform_device *ezx_snd_device;
-+
-+static int __init ezx_init(void)
-+{
-+ int ret;
-+ ezx_snd_device = platform_device_alloc("soc-audio", -1);
-+ if (!ezx_snd_device)
-+ return -ENOMEM;
-+
-+ platform_set_drvdata(ezx_snd_device, &ezx_snd_devdata);
-+ ezx_snd_devdata.dev = &ezx_snd_device->dev;
-+ ret = platform_device_add(ezx_snd_device);
-+
-+ if (ret)
-+ platform_device_put(ezx_snd_device);
-+ /* configure gpio for ssp3 */
-+ pxa_gpio_mode(GPIO83_SFRM3_MD); /* SFRM */
-+ pxa_gpio_mode(GPIO81_STXD3_MD); /* TXD */
-+ pxa_gpio_mode(GPIO52_SCLK3_MD); /* SCLK */
-+ pxa_gpio_mode(GPIO89_SRXD3_MD); /* RXD */
-+
-+ /* configure gpio for ssp2 */
-+ pxa_gpio_mode(37 | GPIO_IN); /* SFRM */
-+ pxa_gpio_mode(38 | GPIO_IN); /* TXD */
-+ pxa_gpio_mode(22 | GPIO_IN); /* SCLK */
-+ pxa_gpio_mode(88 | GPIO_IN); /* RXD */
-+
-+ pxa_gpio_mode(GPIO_HW_ATTENUATE_A780 | GPIO_OUT);
-+ pxa_gpio_set_value(GPIO_HW_ATTENUATE_A780, 1);
-+
-+ /* request jack irq */
-+ request_irq(EZX_IRQ_HEADJACK, &jack_irq, IRQF_DISABLED, "headphone jack", NULL);
-+ request_irq(EZX_IRQ_MIC, &jack_irq, IRQF_DISABLED, "mic jack", NULL);
-+
-+ return ret;
-+}
-+
-+static void __exit ezx_exit(void)
-+{
-+ free_irq(EZX_IRQ_HEADJACK, NULL);
-+ free_irq(EZX_IRQ_MIC, NULL);
-+ platform_device_unregister(ezx_snd_device);
-+}
-+
-+module_init(ezx_init);
-+module_exit(ezx_exit);
-+
-Index: linux-2.6.23/sound/soc/codecs/Makefile
-===================================================================
---- linux-2.6.23.orig/sound/soc/codecs/Makefile 2007-10-10 09:38:42.000000000 +0200
-+++ linux-2.6.23/sound/soc/codecs/Makefile 2007-10-22 22:30:09.000000000 +0200
-@@ -3,9 +3,11 @@
- snd-soc-wm8750-objs := wm8750.o
- snd-soc-wm8753-objs := wm8753.o
- snd-soc-wm9712-objs := wm9712.o
-+snd-soc-pcap2-objs := pcap2.o
-
- obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
- obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
- obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
- obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
- obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
-+obj-$(CONFIG_SND_SOC_PCAP2) += snd-soc-pcap2.o
-Index: linux-2.6.23/sound/soc/codecs/Kconfig
-===================================================================
---- linux-2.6.23.orig/sound/soc/codecs/Kconfig 2007-10-10 09:38:42.000000000 +0200
-+++ linux-2.6.23/sound/soc/codecs/Kconfig 2007-10-22 22:28:06.000000000 +0200
-@@ -17,3 +17,7 @@
- config SND_SOC_WM9712
- tristate
- depends on SND_SOC
-+
-+config SND_SOC_PCAP2
-+ tristate
-+ depends on SND_SOC && EZX_PCAP
-Index: linux-2.6.23/sound/soc/pxa/Makefile
-===================================================================
---- linux-2.6.23.orig/sound/soc/pxa/Makefile 2007-10-22 22:27:11.000000000 +0200
-+++ linux-2.6.23/sound/soc/pxa/Makefile 2007-10-22 22:28:06.000000000 +0200
-@@ -14,9 +14,10 @@
- snd-soc-poodle-objs := poodle.o
- snd-soc-tosa-objs := tosa.o
- snd-soc-spitz-objs := spitz.o
-+snd-soc-ezx-objs := ezx.o
-
- obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
- obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
- obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
- obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
--
-+obj-$(CONFIG_SND_PXA2XX_SOC_EZX) += snd-soc-ezx.o