diff options
Diffstat (limited to 'packages/linux/linux-ezx-2.6.24/patches/ezx-asoc.patch')
-rw-r--r-- | packages/linux/linux-ezx-2.6.24/patches/ezx-asoc.patch | 1302 |
1 files changed, 0 insertions, 1302 deletions
diff --git a/packages/linux/linux-ezx-2.6.24/patches/ezx-asoc.patch b/packages/linux/linux-ezx-2.6.24/patches/ezx-asoc.patch deleted file mode 100644 index 4ba0f4cddf..0000000000 --- a/packages/linux/linux-ezx-2.6.24/patches/ezx-asoc.patch +++ /dev/null @@ -1,1302 +0,0 @@ -Index: linux-2.6.24/sound/soc/codecs/pcap2.c -=================================================================== ---- /dev/null -+++ linux-2.6.24/sound/soc/codecs/pcap2.c -@@ -0,0 +1,796 @@ -+/* -+ * pcap2.c - PCAP2 ASIC Audio driver -+ * -+ * Copyright (C) 2007 Daniel Ribeiro <wyrm@openezx.org> -+ * -+ * 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.24/sound/soc/codecs/pcap2.h -=================================================================== ---- /dev/null -+++ linux-2.6.24/sound/soc/codecs/pcap2.h -@@ -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.24/sound/soc/pxa/Kconfig -=================================================================== ---- linux-2.6.24.orig/sound/soc/pxa/Kconfig -+++ linux-2.6.24/sound/soc/pxa/Kconfig -@@ -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.24/sound/soc/pxa/ezx.c -=================================================================== ---- /dev/null -+++ linux-2.6.24/sound/soc/pxa/ezx.c -@@ -0,0 +1,349 @@ -+/* -+ * ezx.c - Machine specific code for EZX phones -+ * -+ * Copyright (C) 2007 Daniel Ribeiro <wyrm@openezx.org> -+ * -+ * 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.24/sound/soc/codecs/Makefile -=================================================================== ---- linux-2.6.24.orig/sound/soc/codecs/Makefile -+++ linux-2.6.24/sound/soc/codecs/Makefile -@@ -4,6 +4,7 @@ - snd-soc-wm8753-objs := wm8753.o - snd-soc-wm9712-objs := wm9712.o - snd-soc-cs4270-objs := cs4270.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 -@@ -11,3 +12,4 @@ - obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o - obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o - obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -+obj-$(CONFIG_SND_SOC_PCAP2) += snd-soc-pcap2.o -Index: linux-2.6.24/sound/soc/codecs/Kconfig -=================================================================== ---- linux-2.6.24.orig/sound/soc/codecs/Kconfig -+++ linux-2.6.24/sound/soc/codecs/Kconfig -@@ -37,3 +37,6 @@ - bool - depends on SND_SOC_CS4270 - -+config SND_SOC_PCAP2 -+ tristate -+ depends on SND_SOC && EZX_PCAP -Index: linux-2.6.24/sound/soc/pxa/Makefile -=================================================================== ---- linux-2.6.24.orig/sound/soc/pxa/Makefile -+++ linux-2.6.24/sound/soc/pxa/Makefile -@@ -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 |