r935 - in trunk/oe/packages: . linux-qemu linux-qemu/linux-rp-2.6.17


Sat Feb 10 01:18:30 CET 2007


Author: 
Date: 2007-02-10 01:18:29 +0100 (Sat, 10 Feb 2007)
New Revision: 935

Added:
   trunk/oe/packages/linux-qemu/
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/00-hostap.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/10-pcnet.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/add-oz-release-string.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/asoc-v0.12.4_2.6.17.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/connectplus-remove-ide-HACK.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-akita
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-c7x0
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-collie
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-hx2000
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-poodle
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemuarm
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemux86
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-spitz
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-tosa
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/hrw-pcmcia-ids-r5.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/orinoco-remove-all-which-are-in-hostap-HACK.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/pxa-serial-hack.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/squashfs3.0-2.6.15.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/tosa-lcdnoise-r0.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/versatile-change-fb-orientation.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/vesafb-tng-1.0-rc2-git-20060629.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-reset-loop-r2.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-suspend-cold-res-r2.patch
   trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm97xx-lcdnoise-r0.patch
   trunk/oe/packages/linux-qemu/linux-rp-neo1973_2.6.17.bb
   trunk/oe/packages/linux-qemu/linux-rp.inc
   trunk/oe/packages/linux-qemu/linux-rp_2.6.17.bb
Log:
oe/linux-qemu: add proper Qemu kernel w/ portrait VGA framebuffer resolution


Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/00-hostap.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/00-hostap.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/00-hostap.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,45 @@
+Platform: Sharp Zaurus C760 running 2.6.16 and pcmciautils 013.
+
+root at c7x0:~# pccardctl ident
+Socket 0:
+  product info: "Pretec", "CompactWLAN Card 802.11b", "2.5"
+  manfid: 0x0156, 0x0002
+  function: 6 (network)
+
+==========================================================================
+From: Jochen Friedrich 
+
+Yet another card known to work OK with hostap_cs:
+
+# pccardctl ident
+Socket 0:
+  no product info available
+Socket 1:
+  product info: "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", ""
+  manfid: 0x0156, 0x0002
+  function: 6 (network)
+
+==========================================================================
+
+Signed-off-by: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+ drivers/net/wireless/hostap/hostap_cs.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+Index: linux/drivers/net/wireless/hostap/hostap_cs.c
+===================================================================
+--- linux.orig/drivers/net/wireless/hostap/hostap_cs.c	2006-05-17 10:23:00.000000000 +0200
++++ linux/drivers/net/wireless/hostap/hostap_cs.c	2006-05-17 10:25:45.000000000 +0200
+@@ -923,6 +923,12 @@
+ 	PCMCIA_DEVICE_PROD_ID12(
+ 		"ZoomAir 11Mbps High", "Rate wireless Networking",
+ 		0x273fe3db, 0x32a1eaee),
++	PCMCIA_DEVICE_PROD_ID123(
++			"Pretec", "CompactWLAN Card 802.11b", "2.5",
++			0x1cadd3e5, 0xe697636c, 0x7a5bfcf1),
++	PCMCIA_DEVICE_PROD_ID123(
++		"U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02",
++		0xc7b8df9d, 0x1700d087, 0x4b74baa0),
+ 	PCMCIA_DEVICE_NULL
+ };
+ MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/10-pcnet.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/10-pcnet.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/10-pcnet.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,27 @@
+
+From: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+Add TRENDnet TE-CF100 ethernet adapter to pcnet_cs list.
+
+product info: "Fast Ethernet", "CF Size PC Card", "1.0", ""
+ manfid: 0x0149, 0xc1ab
+
+Signed-off-by: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+ drivers/net/pcmcia/pcnet_cs.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: netdev-2.6/drivers/net/pcmcia/pcnet_cs.c
+===================================================================
+--- netdev-2.6.orig/drivers/net/pcmcia/pcnet_cs.c	2006-05-18 11:06:43.294022480 +0200
++++ netdev-2.6/drivers/net/pcmcia/pcnet_cs.c	2006-05-18 11:10:31.548322552 +0200
+@@ -1768,6 +1768,8 @@
+ 	PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"),
+ 	PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
+ 	PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
++	PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", 
++		0xb4be14e3, 0x43ac239b, 0x0877b627),
+ 	PCMCIA_DEVICE_NULL
+ };
+ MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
+

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/add-oz-release-string.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/add-oz-release-string.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/add-oz-release-string.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,24 @@
+
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- linux-2.6.11-rc1/init/version.c~add-oz-release-string
++++ linux-2.6.11-rc1/init/version.c
+@@ -29,5 +29,5 @@
+ EXPORT_SYMBOL(system_utsname);
+ 
+ const char linux_banner[] =
+-	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
++	"Linux version " UTS_RELEASE OPENZAURUS_RELEASE " (" LINUX_COMPILE_BY "@"
+ 	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+--- linux-2.6.11-rc1/Makefile~add-oz-release-string
++++ linux-2.6.11-rc1/Makefile
+@@ -827,6 +827,7 @@
+ 	  exit 1; \
+ 	fi; \
+ 	(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
++	echo \#define OPENZAURUS_RELEASE \"$(OPENZAURUS_RELEASE)\"; \
+ 	  echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \
+ 	 echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \
+ 	)

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/asoc-v0.12.4_2.6.17.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/asoc-v0.12.4_2.6.17.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/asoc-v0.12.4_2.6.17.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,31713 @@
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt
+@@ -0,0 +1,546 @@
++ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
++SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
++
++
++AC97
++====
++
++  AC97 is a five wire interface commonly found on many PC sound cards. It is
++now also popular in many portable devices. This DAI has a reset line and time
++multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
++The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
++frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
++frame is 21uS long and is divided into 13 time slots.
++
++The AC97 specification can be found at :-
++http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
++
++
++I2S
++===
++
++ I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
++Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
++left/right clock (LRC) synchronise the link. I2S is flexible in that either the
++controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
++usually varies depending on the sample rate and the master system clock
++(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
++ADC and DAC LRCLK's, this allows for similtanious capture and playback at
++different sample rates.
++
++I2S has several different operating modes:-
++
++ o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
++         transition.
++
++ o Left Justified - MSB is transmitted on transition of LRC.
++
++ o Right Justified - MSB is transmitted sample size BCLK's before LRC
++                     transition.
++
++PCM
++===
++
++PCM is another 4 wire interface, very similar to I2S, that can support a more
++flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
++to synchronise the link whilst the Tx and Rx lines are used to transmit and
++receive the audio data. Bit clock usually varies depending on sample rate
++whilst sync runs at the sample rate. PCM also supports Time Division
++Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
++is sometimes referred to as network mode).
++
++Common PCM operating modes:-
++
++ o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
++
++ o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
++
++
++ASoC DAI Configuration
++======================
++
++Every CODEC DAI and SoC DAI must have their capabilities defined in order to
++be configured together at runtime when the audio and clocking parameters are
++known. This is achieved by creating an array of struct snd_soc_hw_mode in the
++the CODEC and SoC interface drivers. Each element in the array describes a DAI
++mode and each mode is usually based upon the DAI system clock to sample rate
++ratio (FS).
++
++i.e. 48k sample rate @ 256 FS = sytem clock of 12.288 MHz
++     48000 * 256 = 12288000
++
++The CPU and Codec DAI modes are then ANDed together at runtime to determine the
++rutime DAI configuration for both the Codec and CPU.
++
++When creating a new codec or SoC DAI it's probably best to start of with a few
++sample rates first and then test your interface.
++
++struct snd_soc_dai_mode is defined (in soc.h) as:-
++
++/* SoC DAI mode */
++struct snd_soc_dai_mode {
++	u16 fmt;		/* SND_SOC_DAIFMT_* */
++	u16 tdm;		/* SND_SOC_HWTDM_* */
++	u64 pcmfmt; 	/* SNDRV_PCM_FMTBIT_* */
++	u16 pcmrate;	/* SND_SOC_HWRATE_* */
++	u16 pcmdir:2;	/* SND_SOC_HWDIR_* */
++	u16 flags:8;	/* hw flags */
++	u16 fs;			/* mclk to rate divider */
++	u64 bfs;		/* mclk to bclk dividers */
++	unsigned long priv;		/* private mode data */
++};
++
++fmt:
++----
++This field defines the DAI mode hardware format (e.g. I2S settings) and
++supports the following settings:-
++
++ 1) hardware DAI formats
++
++#define SND_SOC_DAIFMT_I2S        (1 << 0)	/* I2S mode */
++#define SND_SOC_DAIFMT_RIGHT_J    (1 << 1)	/* Right justified mode */
++#define SND_SOC_DAIFMT_LEFT_J     (1 << 2)	/* Left Justified mode */
++#define SND_SOC_DAIFMT_DSP_A      (1 << 3)	/* L data msb after FRM */
++#define SND_SOC_DAIFMT_DSP_B      (1 << 4)	/* L data msb during FRM */
++#define SND_SOC_DAIFMT_AC97       (1 << 5)	/* AC97 */
++
++ 2) hw DAI signal inversions
++
++#define SND_SOC_DAIFMT_NB_NF		(1 << 8)	/* normal bit clock + frame */
++#define SND_SOC_DAIFMT_NB_IF		(1 << 9)	/* normal bclk + inv frm */
++#define SND_SOC_DAIFMT_IB_NF		(1 << 10)	/* invert bclk + nor frm */
++#define SND_SOC_DAIFMT_IB_IF		(1 << 11)	/* invert bclk + frm */
++
++ 3) hw clock masters
++    This is wrt the codec, the inverse is true for the interface
++    i.e. if the codec is clk and frm master then the interface is
++    clk and frame slave.
++
++#define SND_SOC_DAIFMT_CBM_CFM		(1 << 12)	/* codec clk & frm master */
++#define SND_SOC_DAIFMT_CBS_CFM		(1 << 13)	/* codec clk slave & frm master */
++#define SND_SOC_DAIFMT_CBM_CFS		(1 << 14)	/* codec clk master & frame slave */
++#define SND_SOC_DAIFMT_CBS_CFS		(1 << 15)	/* codec clk & frm slave */
++
++At least one option from each section must be selected. Multiple selections are
++also supported e.g.
++
++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF
++
++
++tdm:
++------
++This field defines the Time Division Multiplexing left and right word
++positions for the DAI mode if applicable. Set to SND_SOC_DAITDM_LRDW(0,0) for
++no TDM.
++
++
++pcmfmt:
++---------
++The hardware PCM format. This describes the PCM formats supported by the DAI
++mode e.g.
++
++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++ 	SNDRV_PCM_FORMAT_S24_3LE
++
++pcmrate:
++----------
++The PCM sample rates supported by the DAI mode. e.g.
++
++ .pcmrate = 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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000
++
++
++pcmdir:
++---------
++The stream directions supported by this mode. e.g. playback and capture
++
++
++flags:
++--------
++The DAI hardware flags supported by the mode.
++
++/* use bfs mclk divider mode (BCLK = MCLK / x) */
++#define SND_SOC_DAI_BFS_DIV		0x1
++/* use bfs rate mulitplier  (BCLK = RATE * x)*/
++#define SND_SOC_DAI_BFS_RATE	0x2
++/* use bfs rcw multiplier (BCLK = RATE * CHN * WORD SIZE) */
++#define SND_SOC_DAI_BFS_RCW		0x4
++/* capture and playback can use different clocks */
++#define SND_SOC_DAI_ASYNC		0x8
++
++NOTE: Bitclock division and mulitiplication modes can be safely matched by the
++core logic.
++
++
++fs:
++-----
++The FS supported by this DAI mode FS is the ratio between the system clock and
++the sample rate. See above
++
++bfs:
++------
++BFS is the ratio of BCLK to MCLK or the ratio of BCLK to sample rate (this
++depends on the codec or CPU DAI).
++
++The BFS supported by the DAI mode. This can either be the ratio between the
++bitclock (BCLK) and the sample rate OR the ratio between the system clock and
++the sample rate. Depends on the flags above.
++
++priv:
++-----
++private codec mode data.
++
++
++
++Examples
++========
++
++Note that Codec DAI and CPU DAI examples are interchangeable in these examples
++as long as the bus master is reversed. i.e.
++
++  SND_SOC_DAIFMT_CBM_CFM would become SND_SOC_DAIFMT_CBS_CFS
++  and vice versa.
++
++This applies to all SND_SOC_DAIFMT_CB*_CF*.
++
++Example 1
++---------
++
++Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
++BCLK of either MCLK/2 or MCLK/4.
++
++	/* codec master */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(2) | SND_SOC_FSBD(4),
++	}
++
++
++Example 2
++---------
++Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
++BCLK of either Rate * 32 or Rate * 64.
++
++	/* codec master */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 32,
++	},
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++
++
++Example 3
++---------
++Codec that runs at 8k & 48k @ 256FS in master mode, can generate a BCLK that
++is a multiple of Rate * channels * word size. (RCW) i.e.
++
++	BCLK = 8000 * 2 * 16 (8k, stereo, 16bit)
++	     = 256kHz
++
++This codecs supports a RCW multiple of 1,2
++
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1) | SND_SOC_FSBW(2),
++	}
++
++
++Example 4
++---------
++Codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
++BCLK of either Rate * 32 or Rate * 64. Codec can also run in slave mode as long
++as BCLK is rate * 32 or rate * 64.
++
++	/* codec master */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 32,
++	},
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++
++	/* codec slave */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = 32,
++	},
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = 64,
++	},
++
++
++Example 5
++---------
++Codec that only runs at 8k, 16k, 32k, 48k, 96k @ 128FS, 192FS & 256FS in master
++mode and can generate a BCLK of MCLK / (1,2,4,8,16). Codec can also run in slave
++mode as and does not care about FS or BCLK (as long as there is enough bandwidth).
++
++	#define CODEC_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++	#define CODEC_RATES \
++	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\
++	 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
++
++	/* codec master @ 128, 192 & 256 FS */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = CODEC_RATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 128,
++		.bfs = CODEC_FSB,
++	},
++
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = CODEC_RATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 192,
++		.bfs = CODEC_FSB
++	},
++
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = CODEC_RATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = CODEC_FSB,
++	},
++
++	/* codec slave */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = CODEC_RATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++
++
++Example 6
++---------
++Codec that only runs at 8k, 44.1k, 48k @ different FS in master mode (for use
++with a fixed MCLK) and can generate a BCLK of MCLK / (1,2,4,8,16).
++Codec can also run in slave mode as and does not care about FS or BCLK (as long
++as there is enough bandwidth). Codec can support 16, 24 and 32 bit PCM sample
++sizes.
++
++	#define CODEC_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++	#define CODEC_PCM_FORMATS \
++	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++	SNDRV_PCM_FORMAT_S24_3LE | SNDRV_PCM_FORMAT_S24_LE | SNDRV_PCM_FORMAT_S32_LE)
++
++	/* codec master */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = CODEC_FSB,
++	},
++
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = CODEC_FSB,
++	},
++
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = CODEC_FSB,
++	},
++
++	/* codec slave */
++	{
++		.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
++		.pcmrate = CODEC_RATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++
++
++Example 7
++---------
++AC97 Codec that does not support VRA (i.e only runs at 48k).
++
++	#define AC97_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++	#define AC97_PCM_FORMATS \
++	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S18_3LE | \
++	SNDRV_PCM_FORMAT_S20_3LE)
++
++	/* AC97 with no VRA */
++	{
++		.pcmfmt = AC97_PCM_FORMATS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++	}
++
++
++Example 8
++---------
++
++CPU DAI that supports 8k - 48k @ 256FS and BCLK = MCLK / 4 in master mode.
++Slave mode (CPU DAI is FRAME master) supports 8k - 96k at any FS as long as
++BCLK = 64 * rate. (Intel XScale I2S controller).
++
++	#define PXA_I2S_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
++
++	#define PXA_I2S_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++	#define PXA_I2S_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++	/* priv is divider */
++	static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
++	/* pxa2xx I2S frame and clock master modes */
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x48,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x34,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x24,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x1a,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0xd,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0xc,
++	},
++
++	/* pxa2xx I2S frame master and clock slave mode */
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = PXA_I2S_RATES,
++		.pcmdir = PXA_I2S_DIR,
++		.fs = SND_SOC_FS_ALL,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.bfs = 64,
++		.priv = 0x48,
++	},
++};
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt
+@@ -0,0 +1,314 @@
++Audio Clocking
++==============
++
++This text describes the audio clocking terms in ASoC and digital audio in
++general. Note: Audio clocking can be complex !
++
++
++Master Clock
++------------
++
++Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
++or SYSCLK). This audio master clock can be derived from a number of sources
++(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
++audio playback and capture sample rates.
++
++Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
++their speed can be altered by software (depending on the system use and to save
++power). Other master clocks are fixed at at set frequency (i.e. crystals).
++
++
++DAI Clocks
++----------
++The Digital Audio Interface is usually driven by a Bit Clock (often referred to
++as BCLK). This clock is used to drive the digital audio data across the link
++between the codec and CPU.
++
++The DAI also has a frame clock to signal the start of each audio frame. This
++clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
++runs at exactly the sample rate (LRC = Rate).
++
++Bit Clock can be generated as follows:-
++
++BCLK = MCLK / x
++
++ or
++
++BCLK = LRC * x
++
++ or
++
++BCLK = LRC * Channels * Word Size
++
++This relationship depends on the codec or SoC CPU in particular. ASoC can quite
++easily match BCLK generated by division (SND_SOC_DAI_BFS_DIV) with BCLK by
++multiplication (SND_SOC_DAI_BFS_RATE) or BCLK generated  by
++Rate * Channels * Word size (RCW or SND_SOC_DAI_BFS_RCW).
++
++
++ASoC Clocking
++-------------
++
++The ASoC core determines the clocking for each particular configuration at
++runtime. This is to allow for dynamic audio clocking wereby the audio clock is
++variable and depends on the system state or device usage scenario. i.e. a voice
++call requires slower clocks (and hence less power) than MP3 playback.
++
++ASoC will call the config_sysclock() function for the target machine during the
++audio parameters configuration. The function is responsible for then clocking
++the machine audio subsytem and returning the audio clock speed to the core.
++This function should also call the codec and cpu DAI clock_config() functions
++to configure their respective internal clocking if required.
++
++
++ASoC Clocking Control Flow
++--------------------------
++
++The ASoC core will call the machine drivers config_sysclock() when most of the
++DAI capabilities are known. The machine driver is then responsible for calling
++the codec and/or CPU DAI drivers with the selected capabilities and the current
++MCLK. Note that the machine driver is also resonsible for setting the MCLK (and
++enabling it).
++
++   (1) Match Codec and CPU DAI capabilities. At this point we have
++       matched the majority of the DAI fields and now need to make sure this
++       mode is currently clockable.
++
++   (2) machine->config_sysclk() is now called with the matched DAI FS, sample
++       rate and BCLK master. This function then gets/sets the current audio
++       clock (depening on usage) and calls the codec and CPUI DAI drivers with
++       the FS, rate, BCLK master and MCLK.
++
++   (3) Codec/CPU DAI config_sysclock(). This function checks that the FS, rate,
++       BCLK master and MCLK are acceptable for the codec or CPU DAI. It also
++       sets the DAI internal state to work with said clocks.
++
++The config_sysclk() functions for CPU, codec and machine should return the MCLK
++on success and 0 on failure.
++
++
++Examples (b = BCLK, l = LRC)
++============================
++
++Example 1
++---------
++
++Simple codec that only runs at 48k @ 256FS in master mode.
++
++CPU only runs as slave DAI, however it generates a variable MCLK.
++
++             --------                 ---------
++            |        | <----mclk---  |         |
++            | Codec  |b -----------> |  CPU    |
++            |        |l -----------> |         |
++            |        |               |         |
++             --------                 ---------
++
++The codec driver has the following config_sysclock()
++
++	static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
++		struct snd_soc_clock_info *info, unsigned int clk)
++	{
++		/* make sure clock is 256 * rate */
++		if(info->rate << 8 == clk) {
++			dai->mclk = clk;
++			return clk;
++		}
++
++		return 0;
++	}
++
++The CPU I2S DAI driver has the following config_sysclk()
++
++	static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
++		struct snd_soc_clock_info *info, unsigned int clk)
++	{
++		/* can we support this clk */
++		if(set_audio_clk(clk) < 0)
++			return -EINVAL;
++
++		dai->mclk = clk;
++		return dai->clk;
++	}
++
++The machine driver config_sysclk() in this example is as follows:-
++
++	unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++		struct snd_soc_clock_info *info)
++	{
++		int clk = info->rate * info->fs;
++
++		/* check that CPU can deliver clock */
++		if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
++			return -EINVAL;
++
++		/* can codec work with this clock */
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
++	}
++
++
++Example 2
++---------
++
++Codec that can master at 8k and 48k at various FS (and hence supports a fixed
++set of input MCLK's) and can also be slave at various FS .
++
++The CPU can master at 8k and 48k @256 FS and can be slave at any FS.
++
++MCLK is a 12.288MHz crystal on this machine.
++
++             --------                 ---------
++            |        |  <---xtal---> |         |
++            | Codec  |b <----------> |  CPU    |
++            |        |l <----------> |         |
++            |        |               |         |
++             --------                 ---------
++
++
++The codec driver has the following config_sysclock()
++
++	/* supported input clocks */
++	const static int hifi_clks[] = {11289600, 12000000, 12288000,
++		16934400, 18432000};
++
++	static unsigned int config_hsysclk(struct snd_soc_codec_dai *dai,
++		struct snd_soc_clock_info *info, unsigned int clk)
++	{
++		int i;
++
++		/* is clk supported  */
++		for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) {
++			if(clk == hifi_clks[i]) {
++				dai->mclk = clk;
++				return clk;
++			}
++		}
++
++		/* this clk is not supported */
++		return 0;
++	}
++
++The CPU I2S DAI driver has the following config_sysclk()
++
++	static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
++		struct snd_soc_clock_info *info, unsigned int clk)
++	{
++		/* are we master or slave */
++		if (info->bclk_master &
++			(SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
++
++			/* we can only master @ 256FS */
++			if(info->rate << 8 == clk) {
++				dai->mclk = clk;
++				return dai->mclk;
++			}
++		} else {
++			/* slave we can run at any FS */
++			dai->mclk = clk;
++			return dai->mclk;
++		}
++
++		/* not supported */
++		return dai->clk;
++	}
++
++The machine driver config_sysclk() in this example is as follows:-
++
++	unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++		struct snd_soc_clock_info *info)
++	{
++		int clk = 12288000; /* 12.288MHz */
++
++		/* who's driving the link */
++		if (info->bclk_master &
++			(SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
++			/* codec master */
++
++			/* check that CPU can work with clock */
++			if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
++				return -EINVAL;
++
++			/* can codec work with this clock */
++			return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
++		} else {
++			/* cpu master */
++
++			/* check that codec can work with clock */
++			if(rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk) < 0)
++				return -EINVAL;
++
++			/* can CPU work with this clock */
++			return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk);
++		}
++	}
++
++
++
++Example 3
++---------
++
++Codec that masters at 8k ... 48k @256 FS. Codec can also be slave and
++doesn't care about FS. The codec has an internal PLL and dividers to generate
++the necessary internal clocks (for 256FS).
++
++CPU can only be slave and doesn't care about FS.
++
++MCLK is a non controllable 13MHz clock from the CPU.
++
++
++             --------                 ---------
++            |        | <----mclk---  |         |
++            | Codec  |b <----------> |  CPU    |
++            |        |l <----------> |         |
++            |        |               |         |
++             --------                 ---------
++
++The codec driver has the following config_sysclock()
++
++	/* valid PCM clock dividers * 2 */
++	static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16};
++
++	static unsigned int config_vsysclk(struct snd_soc_codec_dai *dai,
++		struct snd_soc_clock_info *info, unsigned int clk)
++	{
++		int i, j, best_clk = info->fs * info->rate;
++
++		/* can we run at this clk without the PLL ? */
++		for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) {
++			if ((best_clk >> 1) * pcm_divs[i] == clk) {
++				dai->pll_in = 0;
++				dai->clk_div = pcm_divs[i];
++				dai->mclk = best_clk;
++				return dai->mclk;
++			}
++		}
++
++		/* now check for PLL support */
++		for (i = 0; i < ARRAY_SIZE(pll_div); i++) {
++			if (pll_div[i].pll_in == clk) {
++				for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) {
++					if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) {
++						dai->pll_in = clk;
++						dai->pll_out = pll_div[i].pll_out;
++						dai->clk_div = pcm_divs[j];
++						dai->mclk = best_clk;
++						return dai->mclk;
++					}
++				}
++			}
++		}
++
++		/* this clk is not supported */
++		return 0;
++	}
++
++
++The CPU I2S DAI driver has the does not need a config_sysclk() as it can slave
++at any FS.
++
++	unsigned int config_sysclk(struct snd_soc_pcm_runtime *rtd,
++		struct snd_soc_clock_info *info)
++	{
++		/* codec has pll that generates mclk from 13MHz xtal */
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
++	}
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/codec.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/codec.txt
+@@ -0,0 +1,232 @@
++ASoC Codec Driver
++=================
++
++The codec driver is generic and hardware independent code that configures the
++codec to provide audio capture and playback. It should contain no code that is
++specific to the target platform or machine. All platform and machine specific
++code should be added to the platform and machine drivers respectively.
++
++Each codec driver must provide the following features:-
++
++ 1) Digital audio interface (DAI) description
++ 2) Digital audio interface configuration
++ 3) PCM's description
++ 4) Codec control IO - using I2C, 3 Wire(SPI) or both API's
++ 5) Mixers and audio controls
++ 6) Sysclk configuration
++ 7) Codec audio operations
++
++Optionally, codec drivers can also provide:-
++
++ 8) DAPM description.
++ 9) DAPM event handler.
++10) DAC Digital mute control.
++
++It's probably best to use this guide in conjuction with the existing codec
++driver code in sound/soc/codecs/
++
++ASoC Codec driver breakdown
++===========================
++
++1 - Digital Audio Interface (DAI) description
++---------------------------------------------
++The DAI is a digital audio data transfer link between the codec and host SoC
++CPU. It typically has data transfer capabilities in both directions
++(playback and capture) and can run at a variety of different speeds.
++Supported interfaces currently include AC97, I2S and generic PCM style links.
++Please read DAI.txt for implementation information.
++
++
++2 - Digital Audio Interface (DAI) configuration
++-----------------------------------------------
++DAI configuration is handled by the codec_pcm_prepare function and is
++responsible for configuring and starting the DAI on the codec. This can be
++called multiple times and is atomic. It can access the runtime parameters.
++
++This usually consists of a large function with numerous switch statements to
++set up each configuration option. These options are set by the core at runtime.
++
++
++3 - Codec PCM's
++---------------
++Each codec must have it's PCM's defined. This defines the number of channels,
++stream names, callbacks and codec name. It is also used to register the DAI
++with the ASoC core. The PCM structure also associates the DAI capabilities with
++the ALSA PCM.
++
++e.g.
++
++static struct snd_soc_pcm_codec wm8731_pcm_client = {
++	.name = "WM8731",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8731_config_sysclk,
++	.ops = {
++		.prepare = wm8731_pcm_prepare,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8731_hwfmt),
++		.modes = &wm8731_hwfmt[0],
++	},
++};
++
++
++4 - Codec control IO
++--------------------
++The codec can ususally be controlled via an I2C or SPI style interface (AC97
++combines control with data in the DAI). The codec drivers will have to provide
++functions to read and write the codec registers along with supplying a register
++cache:-
++
++	/* IO control data and register cache */
++    void *control_data; /* codec control (i2c/3wire) data */
++    void *reg_cache;
++
++Codec read/write should do any data formatting and call the hardware read write
++below to perform the IO. These functions are called by the core and alsa when
++performing DAPM or changing the mixer:-
++
++    unsigned int (*read)(struct snd_soc_codec *, unsigned int);
++    int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
++
++Codec hardware IO functions - usually points to either the I2C, SPI or AC97
++read/write:-
++
++	hw_write_t hw_write;
++	hw_read_t hw_read;
++
++
++5 - Mixers and audio controls
++-----------------------------
++All the codec mixers and audio controls can be defined using the convenience
++macros defined in soc.h.
++
++    #define SOC_SINGLE(xname, reg, shift, mask, invert)
++
++Defines a single control as follows:-
++
++  xname = Control name e.g. "Playback Volume"
++  reg = codec register
++  shift = control bit(s) offset in register
++  mask = control bit size(s) e.g. mask of 7 = 3 bits
++  invert = the control is inverted
++
++Other macros include:-
++
++    #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
++
++A stereo control
++
++    #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
++
++A stereo control spanning 2 registers
++
++    #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
++
++Defines an single enumerated control as follows:-
++
++   xreg = register
++   xshift = control bit(s) offset in register
++   xmask = control bit(s) size
++   xtexts = pointer to array of strings that describe each setting
++
++   #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
++
++Defines a stereo enumerated control
++
++
++6 - System clock configuration.
++-------------------------------
++The system clock that drives the audio subsystem can change depending on sample
++rate and the system power state. i.e.
++
++o Higher sample rates sometimes need a higher system clock.
++o Low system power states can sometimes limit the available clocks.
++
++This function is a callback that the machine driver can call to set and
++determine if the clock and sample rate combination is supported by the codec at
++the present time (and system state).
++
++NOTE: If the codec has a PLL then it has a lot more flexability wrt clock and
++sample rate combinations.
++
++Your config_sysclock function should return the MCLK if it's a valid
++combination for your codec else 0;
++
++Please read clocking.txt now.
++
++
++7 - Codec Audio Operations
++--------------------------
++The codec driver also supports the following alsa operations:-
++
++/* SoC audio ops */
++struct snd_soc_ops {
++	int (*startup)(snd_pcm_substream_t *);
++	void (*shutdown)(snd_pcm_substream_t *);
++	int (*hw_params)(snd_pcm_substream_t *, snd_pcm_hw_params_t *);
++	int (*hw_free)(snd_pcm_substream_t *);
++	int (*prepare)(snd_pcm_substream_t *);
++};
++
++Please refer to the alsa driver PCM documentation for details.
++http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
++
++
++8 - DAPM description.
++---------------------
++The Dynamic Audio Power Management description describes the codec's power
++components, their relationships and registers to the ASoC core. Please read
++dapm.txt for details of building the description.
++
++Please also see the examples in other codec drivers.
++
++
++9 - DAPM event handler
++----------------------
++This function is a callback that handles codec domain PM calls and system
++domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
++when not in use.
++
++Power states:-
++
++	SNDRV_CTL_POWER_D0: /* full On */
++	/* vref/mid, clk and osc on, active */
++
++	SNDRV_CTL_POWER_D1: /* partial On */
++	SNDRV_CTL_POWER_D2: /* partial On */
++
++	SNDRV_CTL_POWER_D3hot: /* Off, with power */
++	/* everything off except vref/vmid, inactive */
++
++	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
++
++
++10 - Codec DAC digital mute control.
++------------------------------------
++Most codecs have a digital mute before the DAC's that can be used to minimise
++any system noise.  The mute stops any digital data from entering the DAC.
++
++A callback can be created that is called by the core for each codec DAI when the
++mute is applied or freed.
++
++i.e.
++
++static int wm8974_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
++	if(mute)
++		wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
++	else
++		wm8974_write(codec, WM8974_DAC, mute_reg);
++	return 0;
++}
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/dapm.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/dapm.txt
+@@ -0,0 +1,297 @@
++Dynamic Audio Power Management for Portable Devices
++===================================================
++
++1. Description
++==============
++
++Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
++to use the minimum amount of power within the audio subsystem at all times. It
++is independent of other kernel PM and as such, can easily co-exist with the
++other PM systems.
++
++DAPM is also completely transparent to all user space applications as all power
++switching is done within the ASoC core. No code changes or recompiling are
++required for user space applications. DAPM makes power switching descisions based
++upon any audio stream (capture/playback) activity and audio mixer settings
++within the device.
++
++DAPM spans the whole machine. It covers power control within the entire audio
++subsystem, this includes internal codec power blocks and machine level power
++systems.
++
++There are 4 power domains within DAPM
++
++   1. Codec domain - VREF, VMID (core codec and audio power)
++      Usually controlled at codec probe/remove and suspend/resume, although
++      can be set at stream time if power is not needed for sidetone, etc.
++
++   2. Platform/Machine domain - physically connected inputs and outputs
++      Is platform/machine and user action specific, is configured by the
++      machine driver and responds to asynchronous events e.g when HP
++      are inserted
++
++   3. Path domain - audio susbsystem signal paths
++      Automatically set when mixer and mux settings are changed by the user.
++      e.g. alsamixer, amixer.
++
++   4. Stream domain - DAC's and ADC's.
++      Enabled and disabled when stream playback/capture is started and
++      stopped respectively. e.g. aplay, arecord.
++
++All DAPM power switching descisons are made automatically by consulting an audio
++routing map of the whole machine. This map is specific to each machine and
++consists of the interconnections between every audio component (including
++internal codec components). All audio components that effect power are called
++widgets hereafter.
++
++
++2. DAPM Widgets
++===============
++
++Audio DAPM widgets fall into a number of types:-
++
++ o Mixer      - Mixes several analog signals into a single analog signal.
++ o Mux        - An analog switch that outputs only 1 of it's inputs.
++ o PGA        - A programmable gain amplifier or attenuation widget.
++ o ADC        - Analog to Digital Converter
++ o DAC        - Digital to Analog Converter
++ o Switch     - An analog switch
++ o Input      - A codec input pin
++ o Output     - A codec output pin
++ o Headphone  - Headphone (and optional Jack)
++ o Mic        - Mic (and optional Jack)
++ o Line       - Line Input/Output (and optional Jack)
++ o Speaker    - Speaker
++ o Pre        - Special PRE widget (exec before all others)
++ o Post       - Special POST widget (exec after all others)
++
++(Widgets are defined in include/sound/soc-dapm.h)
++
++Widgets are usually added in the codec driver and the machine driver. There are
++convience macros defined in soc-dapm.h that can be used to quickly build a
++list of widgets of the codecs and machines DAPM widgets.
++
++Most widgets have a name, register, shift and invert. Some widgets have extra
++parameters for stream name and kcontrols.
++
++
++2.1 Stream Domain Widgets
++-------------------------
++
++Stream Widgets relate to the stream power domain and only consist of ADC's
++(analog to digital converters) and DAC's (digital to analog converters).
++
++Stream widgets have the following format:-
++
++SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
++
++NOTE: the stream name must match the corresponding stream name in your codecs
++snd_soc_codec_dai.
++
++e.g. stream widgets for HiFi playback and capture
++
++SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
++SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
++
++
++2.2 Path Domain Widgets
++-----------------------
++
++Path domain widgets have a ability to control or effect the audio signal or
++audio paths within the audio subsystem. They have the following form:-
++
++SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
++
++Any widget kcontrols can be set using the controls and num_controls members.
++
++e.g. Mixer widget (the kcontrols are declared first)
++
++/* Output Mixer */
++static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
++SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
++SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
++};
++
++SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
++	ARRAY_SIZE(wm8731_output_mixer_controls)),
++
++
++2.3 Platform/Machine domain Widgets
++-----------------------------------
++
++Machine widgets are different from codec widgets in that they don't have a
++codec register bit associated with them. A machine widget is assigned to each
++machine audio component (non codec) that can be independently powered. e.g.
++
++ o Speaker Amp
++ o Microphone Bias
++ o Jack connectors
++
++A machine widget can have an optional call back.
++
++e.g. Jack connector widget for an external Mic that enables Mic Bias
++when the Mic is inserted:-
++
++static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
++{
++	if(SND_SOC_DAPM_EVENT_ON(event))
++		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
++	else
++		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
++
++	return 0;
++}
++
++SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
++
++
++2.4 Codec Domain
++----------------
++
++The Codec power domain has no widgets and is handled by the codecs DAPM event
++handler. This handler is called when the codec powerstate is changed wrt to any
++stream event or by kernel PM events.
++
++
++2.5 Virtual Widgets
++-------------------
++
++Sometimes widgets exist in the codec or machine audio map that don't have any
++corresponding register bit for power control. In this case it's necessary to
++create a virtual widget - a widget with no control bits e.g.
++
++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
++
++This can be used to merge to signal paths together in software.
++
++After all the widgets have been defined, they can then be added to the DAPM
++subsystem individually with a call to snd_soc_dapm_new_control().
++
++
++3. Codec Widget Interconnections
++================================
++
++Widgets are connected to each other within the codec and machine by audio
++paths (called interconnections). Each interconnection must be defined in order
++to create a map of all audio paths between widgets.
++This is easiest with a diagram of the codec (and schematic of the machine audio
++system), as it requires joining widgets together via their audio signal paths.
++
++i.e. from the WM8731 codec's output mixer (wm8731.c)
++
++The WM8731 output mixer has 3 inputs (sources)
++
++ 1. Line Bypass Input
++ 2. DAC (HiFi playback)
++ 3. Mic Sidetone Input
++
++Each input in this example has a kcontrol associated with it (defined in example
++above) and is connected to the output mixer via it's kcontrol name. We can now
++connect the destination widget (wrt audio signal) with it's source widgets.
++
++	/* output mixer */
++	{"Output Mixer", "Line Bypass Switch", "Line Input"},
++	{"Output Mixer", "HiFi Playback Switch", "DAC"},
++	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
++
++So we have :-
++
++	Destination Widget  <=== Path Name <=== Source Widget
++
++Or:-
++
++	Sink, Path, Source
++
++Or :-
++
++	"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
++
++When there is no path name connecting widgets (e.g. a direct connection) we
++pass NULL for the path name.
++
++Interconnections are created with a call to:-
++
++snd_soc_dapm_connect_input(codec, sink, path, source);
++
++Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
++interconnections have been registered with the core. This causes the core to
++scan the codec and machine so that the internal DAPM state matches the
++physical state of the machine.
++
++
++3.1 Machine Widget Interconnections
++-----------------------------------
++Machine widget interconnections are created in the same way as codec ones and
++directly connect the codec pins to machine level widgets.
++
++e.g. connects the speaker out codec pins to the internal speaker.
++
++	/* ext speaker connected to codec pins LOUT2, ROUT2  */
++	{"Ext Spk", NULL , "ROUT2"},
++	{"Ext Spk", NULL , "LOUT2"},
++
++This allows the DAPM to power on and off pins that are connected (and in use)
++and pins that are NC respectively.
++
++
++4 Endpoint Widgets
++===================
++An endpoint is a start or end point (widget) of an audio signal within the
++machine and includes the codec. e.g.
++
++ o Headphone Jack
++ o Internal Speaker
++ o Internal Mic
++ o Mic Jack
++ o Codec Pins
++
++When a codec pin is NC it can be marked as not used with a call to
++
++snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
++
++The last argument is 0 for inactive and 1 for active. This way the pin and its
++input widget will never be powered up and consume power.
++
++This also applies to machine widgets. e.g. if a headphone is connected to a
++jack then the jack can be marked active. If the headphone is removed, then
++the headphone jack can be marked inactive.
++
++
++5 DAPM Widget Events
++====================
++
++Some widgets can register their interest with the DAPM core in PM events.
++e.g. A Speaker with an amplifier registers a widget so the amplifier can be
++powered only when the spk is in use.
++
++/* turn speaker amplifier on/off depending on use */
++static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
++{
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
++	else
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
++
++	return 0;
++}
++
++/* corgi machine dapm widgets */
++static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
++	SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
++
++Please see soc-dapm.h for all other widgets that support events.
++
++
++5.1 Event types
++---------------
++
++The following event types are supported by event widgets.
++
++/* dapm event types */
++#define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
++#define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
++#define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
++#define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
++#define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
++#define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/machine.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/machine.txt
+@@ -0,0 +1,114 @@
++ASoC Machine Driver
++===================
++
++The ASoC machine (or board) driver is the code that glues together the platform
++and codec drivers.
++
++The machine driver can contain codec and platform specific code. It registers
++the audio subsystem with the kernel as a platform device and is represented by
++the following struct:-
++
++/* SoC machine */
++struct snd_soc_machine {
++	char *name;
++
++	int (*probe)(struct platform_device *pdev);
++	int (*remove)(struct platform_device *pdev);
++
++	/* the pre and post PM functions are used to do any PM work before and
++	 * after the codec and DAI's do any PM work. */
++	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
++	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
++	int (*resume_pre)(struct platform_device *pdev);
++	int (*resume_post)(struct platform_device *pdev);
++
++	/* machine stream operations */
++	struct snd_soc_ops *ops;
++
++	/* CPU <--> Codec DAI links  */
++	struct snd_soc_dai_link *dai_link;
++	int num_links;
++};
++
++probe()/remove()
++----------------
++probe/remove are optional. Do any machine specific probe here.
++
++
++suspend()/resume()
++------------------
++The machine driver has pre and post versions of suspend and resume to take care
++of any machine audio tasks that have to be done before or after the codec, DAI's
++and DMA is suspended and resumed. Optional.
++
++
++Machine operations
++------------------
++The machine specific audio operations can be set here. Again this is optional.
++
++
++Machine DAI Configuration
++-------------------------
++The machine DAI configuration glues all the codec and CPU DAI's together. It can
++also be used to set up the DAI system clock and for any machine related DAI
++initialisation e.g. the machine audio map can be connected to the codec audio
++map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
++for examples.
++
++struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
++
++/* corgi digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link corgi_dai = {
++	.name = "WM8731",
++	.stream_name = "WM8731",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8731_dai,
++	.init = corgi_wm8731_init,
++	.config_sysclk = corgi_config_sysclk,
++};
++
++struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
++
++/* corgi audio machine driver */
++static struct snd_soc_machine snd_soc_machine_corgi = {
++	.name = "Corgi",
++	.dai_link = &corgi_dai,
++	.num_links = 1,
++	.ops = &corgi_ops,
++};
++
++
++Machine Audio Subsystem
++-----------------------
++
++The machine soc device glues the platform, machine and codec driver together.
++Private data can also be set here. e.g.
++
++/* corgi audio private data */
++static struct wm8731_setup_data corgi_wm8731_setup = {
++	.i2c_address = 0x1b,
++};
++
++/* corgi audio subsystem */
++static struct snd_soc_device corgi_snd_devdata = {
++	.machine = &snd_soc_machine_corgi,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8731,
++	.codec_data = &corgi_wm8731_setup,
++};
++
++
++Machine Power Map
++-----------------
++
++The machine driver can optionally extend the codec power map and to become an
++audio power map of the audio subsystem. This allows for automatic power up/down
++of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
++sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
++details.
++
++
++Machine Controls
++----------------
++
++Machine specific audio mixer controls can be added in the dai init function.
+\ No newline at end of file
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/overview.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/overview.txt
+@@ -0,0 +1,83 @@
++ALSA SoC Layer
++==============
++
++The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
++better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
++iMX, etc) and portable audio codecs. Currently there is some support in the
++kernel for SoC audio, however it has some limitations:-
++
++  * Currently, codec drivers are often tightly coupled to the underlying SoC
++    cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
++    different wm8731 drivers for 4 different SoC platforms.
++
++  * There is no standard method to signal user initiated audio events.
++    e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
++    event. These are quite common events on portable devices and ofter require
++    machine specific code to re route audio, enable amps etc after such an event.
++
++  * Current drivers tend to power up the entire codec when playing
++    (or recording) audio. This is fine for a PC, but tends to waste a lot of
++    power on portable devices. There is also no support for saving power via
++    changing codec oversampling rates, bias currents, etc.
++
++
++ASoC Design
++===========
++
++The ASoC layer is designed to address these issues and provide the following
++features :-
++
++  * Codec independence. Allows reuse of codec drivers on other platforms
++    and machines.
++
++  * Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
++    and codec registers it's audio interface capabilities with the core and are
++    subsequently matched and configured when the application hw params are known.
++
++  * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
++    it's minimum power state at all times. This includes powering up/down
++    internal power blocks depending on the internal codec audio routing and any
++    active streams.
++
++  * Pop and click reduction. Pops and clicks can be reduced by powering the
++    codec up/down in the correct sequence (including using digital mute). ASoC
++    signals the codec when to change power states.
++
++  * Machine specific controls: Allow machines to add controls to the sound card
++    e.g. volume control for speaker amp.
++
++To achieve all this, ASoC basically splits an embedded audio system into 3
++components :-
++
++  * Codec driver: The codec driver is platform independent and contains audio
++    controls, audio interface capabilities, codec dapm definition and codec IO
++    functions.
++
++  * Platform driver: The platform driver contains the audio dma engine and audio
++    interface drivers (e.g. I2S, AC97, PCM) for that platform.
++
++  * Machine driver: The machine driver handles any machine specific controls and
++    audio events. i.e. turing on an amp at start of playback.
++
++
++Documentation
++=============
++
++The documentation is spilt into the following sections:-
++
++overview.txt: This file.
++
++codec.txt: Codec driver internals.
++
++DAI.txt: Description of Digital Audio Interface standards and how to configure
++a DAI within your codec and CPU DAI drivers.
++
++dapm.txt: Dynamic Audio Power Management
++
++platform.txt: Platform audio DMA and DAI.
++
++machine.txt: Machine driver internals.
++
++pop_clicks.txt: How to minimise audio artifacts.
++
++clocking.txt: ASoC clocking for best power performance.
+\ No newline at end of file
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/platform.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/platform.txt
+@@ -0,0 +1,58 @@
++ASoC Platform Driver
++====================
++
++An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
++and control. The platform drivers only target the SoC CPU and must have no board
++specific code.
++
++Audio DMA
++=========
++
++The platform DMA driver optionally supports the following alsa operations:-
++
++/* SoC audio ops */
++struct snd_soc_ops {
++	int (*startup)(snd_pcm_substream_t *);
++	void (*shutdown)(snd_pcm_substream_t *);
++	int (*hw_params)(snd_pcm_substream_t *, snd_pcm_hw_params_t *);
++	int (*hw_free)(snd_pcm_substream_t *);
++	int (*prepare)(snd_pcm_substream_t *);
++	int (*trigger)(snd_pcm_substream_t *, int);
++};
++
++The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
++
++struct snd_soc_platform {
++	char *name;
++
++	int (*probe)(struct platform_device *pdev);
++	int (*remove)(struct platform_device *pdev);
++	int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
++	int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
++
++	/* pcm creation and destruction */
++	int (*pcm_new)(snd_card_t *, struct snd_soc_codec_dai *, snd_pcm_t *);
++	void (*pcm_free)(snd_pcm_t *);
++
++	/* platform stream ops */
++	snd_pcm_ops_t *pcm_ops;
++};
++
++Please refer to the alsa driver documentation for details of audio DMA.
++http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
++
++An example DMA driver is soc/pxa/pxa2xx-pcm.c
++
++
++SoC DAI Drivers
++===============
++
++Each SoC DAI driver must provide the following features:-
++
++ 1) Digital audio interface (DAI) description
++ 2) Digital audio interface configuration
++ 3) PCM's description
++ 4) Sysclk configuration
++ 5) Suspend and resume (optional)
++
++Please see codec.txt for a description of items 1 - 4.
+Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/pops_clicks.txt
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/pops_clicks.txt
+@@ -0,0 +1,52 @@
++Audio Pops and Clicks
++=====================
++
++Pops and clicks are unwanted audio artifacts caused by the powering up and down
++of components within the audio subsystem. This is noticable on PC's when an audio
++module is either loaded or unloaded (at module load time the sound card is
++powered up and causes a popping noise on the speakers).
++
++Pops and clicks can be more frequent on portable systems with DAPM. This is because
++the components within the subsystem are being dynamically powered depending on
++the audio usage and this can subsequently cause a small pop or click every time a
++component power state is changed.
++
++
++Minimising Playback Pops and Clicks
++===================================
++
++Playback pops in portable audio subsystems cannot be completely eliminated atm,
++however future audio codec hardware will have better pop and click supression.
++Pops can be reduced within playback by powering the audio components in a
++specific order. This order is different for startup and shutdown and follows
++some basic rules:-
++
++ Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
++
++ Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
++
++This assumes that the codec PCM output path from the DAC is via a mixer and then
++a PGA (programmable gain amplifier) before being output to the speakers.
++
++
++Minimising Capture Pops and Clicks
++==================================
++
++Capture artifacts are somewhat easier to get rid as we can delay activating the
++ADC until all the pops have occured. This follows similar power rules to
++playback in that components are powered in a sequence depending upon stream
++startup or shutdown.
++
++ Startup Order - Input PGA --> Mixers --> ADC
++
++ Shutdown Order - ADC --> Mixers --> Input PGA
++
++
++Zipper Noise
++============
++An unwanted zipper noise can occur within the audio playback or capture stream
++when a volume control is changed near its maximum gain value. The zipper noise
++is heard when the gain increase or decrease changes the mean audio signal
++amplitude too quickly. It can be minimised by enabling the zero cross setting
++for each volume control. The ZC forces the gain change to occur when the signal
++crosses the zero amplitude line.
+Index: linux-2.6-pxa-new/include/sound/ac97_codec.h
+===================================================================
+--- linux-2.6-pxa-new.orig/include/sound/ac97_codec.h
++++ linux-2.6-pxa-new/include/sound/ac97_codec.h
+@@ -425,6 +425,7 @@ struct snd_ac97_build_ops {
+ 
+ struct snd_ac97_bus_ops {
+ 	void (*reset) (struct snd_ac97 *ac97);
++	void (*warm_reset)(struct snd_ac97 *ac97);
+ 	void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
+ 	unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);
+ 	void (*wait) (struct snd_ac97 *ac97);
+Index: linux-2.6-pxa-new/include/sound/soc-dapm.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/include/sound/soc-dapm.h
+@@ -0,0 +1,286 @@
++/*
++ * linux/sound/soc-dapm.h -- ALSA SoC Dynamic Audio Power Management
++ *
++ * Author:		Liam Girdwood
++ * Created:		Aug 11th 2005
++ * Copyright:	Wolfson Microelectronics. PLC.
++ *
++ * 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_DAPM_H
++#define __LINUX_SND_SOC_DAPM_H
++
++#include <linux/device.h>
++#include <linux/types.h>
++#include <sound/control.h>
++#include <sound/soc.h>
++
++/* widget has no PM register bit */
++#define SND_SOC_NOPM	-1
++
++/*
++ * SoC dynamic audio power managment
++ *
++ * We can have upto 4 power domains
++ * 	1. Codec domain - VREF, VMID
++ *     Usually controlled at codec probe/remove, although can be set
++ *     at stream time if power is not needed for sidetone, etc.
++ *  2. Platform/Machine domain - physically connected inputs and outputs
++ *     Is platform/machine and user action specific, is set in the machine
++ *     driver and by userspace e.g when HP are inserted
++ *  3. Path domain - Internal codec path mixers
++ *     Are automatically set when mixer and mux settings are
++ *     changed by the user.
++ *  4. Stream domain - DAC's and ADC's.
++ *     Enabled when stream playback/capture is started.
++ */
++
++/* codec domain */
++#define SND_SOC_DAPM_VMID(wname) \
++{	.id = snd_soc_dapm_vmid, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0}
++
++/* platform domain */
++#define SND_SOC_DAPM_INPUT(wname) \
++{	.id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0}
++#define SND_SOC_DAPM_OUTPUT(wname) \
++{	.id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0}
++#define SND_SOC_DAPM_MIC(wname, wevent) \
++{	.id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
++#define SND_SOC_DAPM_HP(wname, wevent) \
++{	.id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
++#define SND_SOC_DAPM_SPK(wname, wevent) \
++{	.id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
++#define SND_SOC_DAPM_LINE(wname, wevent) \
++{	.id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
++
++/* path domain */
++#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
++	 wcontrols, wncontrols) \
++{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
++#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
++	 wcontrols, wncontrols)\
++{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
++#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
++{	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
++#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
++{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
++#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
++{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
++
++/* path domain with event - event handler must return 0 for success */
++#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
++	wncontrols, wevent, wflags) \
++{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
++	.event = wevent, .event_flags = wflags}
++#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
++	wncontrols, wevent, wflags) \
++{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
++	.event = wevent, .event_flags = wflags}
++#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
++{	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
++	.event = wevent, .event_flags = wflags}
++#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
++	wevent, wflags) \
++{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1 \
++	.event = wevent, .event_flags = wflags}
++#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
++	wevent, wflags) \
++{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
++	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
++	.event = wevent, .event_flags = wflags}
++
++/* events that are pre and post DAPM */
++#define SND_SOC_DAPM_PRE(wname, wevent) \
++{	.id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
++#define SND_SOC_DAPM_POST(wname, wevent) \
++{	.id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
++	.num_kcontrols = 0, .event = wevent, \
++	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
++
++/* stream domain */
++#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
++{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
++	.shift = wshift, .invert = winvert}
++#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
++{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
++	.shift = wshift, .invert = winvert}
++
++/* dapm kcontrol types */
++#define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_volsw, \
++	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
++	.private_value =  SOC_SINGLE_VALUE(reg, shift, mask, invert) }
++#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \
++	power) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
++	.info = snd_soc_info_volsw, \
++ 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
++ 	.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
++ 		 ((mask) << 16) | ((invert) << 24) }
++#define SOC_DAPM_ENUM(xname, xenum) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_enum_double, \
++ 	.get = snd_soc_dapm_get_enum_double, \
++ 	.put = snd_soc_dapm_put_enum_double, \
++  	.private_value = (unsigned long)&xenum }
++
++/* dapm stream operations */
++#define SND_SOC_DAPM_STREAM_NOP			0x0
++#define SND_SOC_DAPM_STREAM_START		0x1
++#define SND_SOC_DAPM_STREAM_STOP		0x2
++#define SND_SOC_DAPM_STREAM_SUSPEND		0x4
++#define SND_SOC_DAPM_STREAM_RESUME		0x8
++#define SND_SOC_DAPM_STREAM_PAUSE_PUSH	0x10
++#define SND_SOC_DAPM_STREAM_PAUSE_RELEASE	0x20
++
++/* dapm event types */
++#define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
++#define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
++#define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
++#define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
++#define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
++#define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
++
++/* convenience event type detection */
++#define SND_SOC_DAPM_EVENT_ON(e)	\
++	(e & (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU))
++#define SND_SOC_DAPM_EVENT_OFF(e)	\
++	(e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD))
++
++struct snd_soc_dapm_widget;
++enum snd_soc_dapm_type;
++struct snd_soc_dapm_path;
++struct snd_soc_dapm_pin;
++
++/* dapm controls */
++int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
++	const struct snd_soc_dapm_widget *widget);
++
++/* dapm path setup */
++int snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
++	const char *sink_name, const char *control_name, const char *src_name);
++int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
++void snd_soc_dapm_free(struct snd_soc_device *socdev);
++
++/* dapm events */
++int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
++	int event);
++
++/* dapm sys fs - used by the core */
++int snd_soc_dapm_sys_add(struct device *dev);
++
++/* dapm audio endpoint control */
++int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
++	char *pin, int status);
++int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
++
++/* dapm widget types */
++enum snd_soc_dapm_type {
++	snd_soc_dapm_input = 0,		/* input pin */
++	snd_soc_dapm_output,		/* output pin */
++	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
++	snd_soc_dapm_mixer,			/* mixes several analog signals together */
++	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
++	snd_soc_dapm_adc,			/* analog to digital converter */
++	snd_soc_dapm_dac,			/* digital to analog converter */
++	snd_soc_dapm_micbias,		/* microphone bias (power) */
++	snd_soc_dapm_mic,			/* microphone */
++	snd_soc_dapm_hp,			/* headphones */
++	snd_soc_dapm_spk,			/* speaker */
++	snd_soc_dapm_line,			/* line input/output */
++	snd_soc_dapm_switch,		/* analog switch */
++	snd_soc_dapm_vmid,			/* codec bias/vmid - to minimise pops */
++	snd_soc_dapm_pre,			/* machine specific pre widget - exec first */
++	snd_soc_dapm_post,			/* machine specific post widget - exec last */
++};
++
++/* dapm audio path between two widgets */
++struct snd_soc_dapm_path {
++	char *name;
++	char *long_name;
++
++	/* source (input) and sink (output) widgets */
++	struct snd_soc_dapm_widget *source;
++	struct snd_soc_dapm_widget *sink;
++	struct snd_kcontrol *kcontrol;
++
++	/* status */
++	u32 connect:1;	/* source and sink widgets are connected */
++	u32 walked:1;	/* path has been walked */
++
++	struct list_head list_source;
++	struct list_head list_sink;
++	struct list_head list;
++};
++
++/* dapm widget */
++struct snd_soc_dapm_widget {
++	enum snd_soc_dapm_type id;
++	char *name;		/* widget name */
++	char *sname;	/* stream name */
++	struct snd_soc_codec *codec;
++	struct list_head list;
++
++	/* dapm control */
++	short reg;						/* negative reg = no direct dapm */
++	unsigned char shift;			/* bits to shift */
++	unsigned int saved_value;		/* widget saved value */
++	unsigned int value;				/* widget current value */
++	unsigned char power:1;			/* block power status */
++	unsigned char invert:1;			/* invert the power bit */
++	unsigned char active:1;			/* active stream on DAC, ADC's */
++	unsigned char connected:1;		/* connected codec pin */
++	unsigned char new:1;			/* cnew complete */
++	unsigned char ext:1;			/* has external widgets */
++	unsigned char muted:1;			/* muted for pop reduction */
++	unsigned char suspend:1;		/* was active before suspend */
++	unsigned char pmdown:1;			/* waiting for timeout */
++
++	/* external events */
++	unsigned short event_flags;		/* flags to specify event types */
++	int (*event)(struct snd_soc_dapm_widget*, int);
++
++	/* kcontrols that relate to this widget */
++	int num_kcontrols;
++	const struct snd_kcontrol_new *kcontrols;
++
++	/* widget input and outputs */
++	struct list_head sources;
++	struct list_head sinks;
++};
++
++#endif
+Index: linux-2.6-pxa-new/include/sound/soc.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/include/sound/soc.h
+@@ -0,0 +1,487 @@
++/*
++ * linux/sound/soc.h -- ALSA SoC Layer
++ *
++ * Author:		Liam Girdwood
++ * Created:		Aug 11th 2005
++ * Copyright:	Wolfson Microelectronics. PLC.
++ *
++ * 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_H
++#define __LINUX_SND_SOC_H
++
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/control.h>
++#include <sound/ac97_codec.h>
++
++#define SND_SOC_VERSION "0.12.4"
++
++/*
++ * Convenience kcontrol builders
++ */
++#define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\
++	((shift) << 12) | ((mask) << 16) | ((invert) << 24))
++#define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\
++	((invert) << 31))
++#define SOC_SINGLE(xname, reg, shift, mask, invert) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
++	.put = snd_soc_put_volsw, \
++	.private_value =  SOC_SINGLE_VALUE(reg, shift, mask, invert) }
++#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
++	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
++	.put = snd_soc_put_volsw, \
++	.private_value = (reg) | ((shift_left) << 8) | \
++		((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
++#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
++	.info = snd_soc_info_volsw_2r, \
++	.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
++	.private_value = (reg_left) | ((shift) << 8)  | \
++		((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) }
++#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
++{	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
++	.mask = xmask, .texts = xtexts }
++#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
++	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
++#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \
++{	.mask = xmask, .texts = xtexts }
++#define SOC_ENUM(xname, xenum) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
++	.info = snd_soc_info_enum_double, \
++	.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
++	.private_value = (unsigned long)&xenum }
++#define SOC_SINGLE_EXT(xname, xreg, xmask, xinvert,\
++	 xhandler_get, xhandler_put) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_volsw_ext, \
++	.get = xhandler_get, .put = xhandler_put, \
++	.private_value =  SOC_SINGLE_VALUE_EXT(xreg, xmask, xinvert) }
++#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_bool_ext, \
++	.get = xhandler_get, .put = xhandler_put, \
++	.private_value = xdata }
++#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
++{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
++	.info = snd_soc_info_enum_ext, \
++	.get = xhandler_get, .put = xhandler_put, \
++	.private_value = (unsigned long)&xenum }
++
++/*
++ * Digital Audio Interface (DAI) types
++ */
++#define SND_SOC_DAI_AC97	0x1
++#define SND_SOC_DAI_I2S		0x2
++#define SND_SOC_DAI_PCM		0x4
++
++/*
++ * DAI hardware audio formats
++ */
++#define SND_SOC_DAIFMT_I2S		(1 << 0)	/* I2S mode */
++#define SND_SOC_DAIFMT_RIGHT_J	(1 << 1)	/* Right justified mode */
++#define SND_SOC_DAIFMT_LEFT_J	(1 << 2)	/* Left Justified mode */
++#define SND_SOC_DAIFMT_DSP_A	(1 << 3)	/* L data msb after FRM or LRC */
++#define SND_SOC_DAIFMT_DSP_B	(1 << 4)	/* L data msb during FRM or LRC */
++#define SND_SOC_DAIFMT_AC97		(1 << 5)	/* AC97 */
++
++/*
++ * DAI hardware signal inversions
++ */
++#define SND_SOC_DAIFMT_NB_NF		(1 << 8)	/* normal bit clock + frame */
++#define SND_SOC_DAIFMT_NB_IF		(1 << 9)	/* normal bclk + inv frm */
++#define SND_SOC_DAIFMT_IB_NF		(1 << 10)	/* invert bclk + nor frm */
++#define SND_SOC_DAIFMT_IB_IF		(1 << 11)	/* invert bclk + frm */
++
++/*
++ * DAI hardware clock masters
++ * This is wrt the codec, the inverse is true for the interface
++ * i.e. if the codec is clk and frm master then the interface is
++ * clk and frame slave.
++ */
++#define SND_SOC_DAIFMT_CBM_CFM	(1 << 12) /* codec clk & frm master */
++#define SND_SOC_DAIFMT_CBS_CFM	(1 << 13) /* codec clk slave & frm master */
++#define SND_SOC_DAIFMT_CBM_CFS	(1 << 14) /* codec clk master & frame slave */
++#define SND_SOC_DAIFMT_CBS_CFS	(1 << 15) /* codec clk & frm slave */
++
++#define SND_SOC_DAIFMT_FORMAT_MASK		0x00ff
++#define SND_SOC_DAIFMT_INV_MASK			0x0f00
++#define SND_SOC_DAIFMT_CLOCK_MASK		0xf000
++
++/*
++ * DAI hardware audio direction
++ */
++#define SND_SOC_DAIDIR_PLAYBACK		0x1
++#define SND_SOC_DAIDIR_CAPTURE		0x2
++
++/*
++ * DAI hardware Time Division Multiplexing (TDM) Slots
++ * Left and Right data word positions
++ * This is measured in words (sample size) and not bits.
++ */
++#define SND_SOC_DAITDM_LRDW(l,r)	((l << 8) | r)
++
++/*
++ * DAI hardware clock ratios
++ * bit clock can either be a generated by dividing mclk or
++ * by multiplying sample rate, hence there are 2 definitions below
++ * depending on codec type.
++ */
++/* ratio of sample rate to mclk/sysclk */
++#define SND_SOC_FS_ALL			0xffff	/* all mclk supported */
++
++/* bit clock dividers */
++#define SND_SOC_FSBD(x)			(1 << (x - 1))	/* ratio mclk:bclk */
++#define SND_SOC_FSBD_REAL(x)	(ffs(x))
++
++/* bit clock ratio to (sample rate * channels * word size) */
++#define SND_SOC_FSBW(x)			(1 << (x - 1))
++#define SND_SOC_FSBW_REAL(x)		(ffs(x))
++/* all bclk ratios supported */
++#define SND_SOC_FSB_ALL			~0ULL
++
++/*
++ * DAI hardware flags
++ */
++/* use bfs mclk divider mode (BCLK = MCLK / x) */
++#define SND_SOC_DAI_BFS_DIV		0x1
++/* use bfs rate mulitplier  (BCLK = RATE * x)*/
++#define SND_SOC_DAI_BFS_RATE	0x2
++/* use bfs rcw multiplier (BCLK = RATE * CHN * WORD SIZE) */
++#define SND_SOC_DAI_BFS_RCW		0x4
++/* capture and playback can use different clocks */
++#define SND_SOC_DAI_ASYNC		0x8
++/* can use gated BCLK */
++#define SND_SOC_DAI_GATED		0x10
++
++/*
++ * AC97 codec ID's bitmask
++ */
++#define SND_SOC_DAI_AC97_ID0	(1 << 0)
++#define SND_SOC_DAI_AC97_ID1	(1 << 1)
++#define SND_SOC_DAI_AC97_ID2	(1 << 2)
++#define SND_SOC_DAI_AC97_ID3	(1 << 3)
++
++struct snd_soc_device;
++struct snd_soc_pcm_stream;
++struct snd_soc_ops;
++struct snd_soc_dai_mode;
++struct snd_soc_pcm_runtime;
++struct snd_soc_codec_dai;
++struct snd_soc_cpu_dai;
++struct snd_soc_codec;
++struct snd_soc_machine_config;
++struct soc_enum;
++struct snd_soc_ac97_ops;
++struct snd_soc_clock_info;
++
++typedef int (*hw_write_t)(void *,const char* ,int);
++typedef int (*hw_read_t)(void *,char* ,int);
++
++extern struct snd_ac97_bus_ops soc_ac97_ops;
++
++/* pcm <-> DAI connect */
++void snd_soc_free_pcms(struct snd_soc_device *socdev);
++int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
++int snd_soc_register_card(struct snd_soc_device *socdev);
++
++/* set runtime hw params */
++int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
++	const struct snd_pcm_hardware *hw);
++int snd_soc_get_rate(int rate);
++
++/* codec IO */
++#define snd_soc_read(codec, reg) codec->read(codec, reg)
++#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
++
++/* codec register bit access */
++int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
++				unsigned short mask, unsigned short value);
++int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
++				unsigned short mask, unsigned short value);
++
++int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
++	struct snd_ac97_bus_ops *ops, int num);
++void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
++
++/*
++ *Controls
++ */
++struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
++	void *data, char *long_name);
++int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo);
++int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol);
++
++/* SoC PCM stream information */
++struct snd_soc_pcm_stream {
++	char *stream_name;
++	unsigned int rate_min;		/* min rate */
++	unsigned int rate_max;		/* max rate */
++	unsigned int channels_min;	/* min channels */
++	unsigned int channels_max;	/* max channels */
++	unsigned int active:1;		/* stream is in use */
++};
++
++/* SoC audio ops */
++struct snd_soc_ops {
++	int (*startup)(struct snd_pcm_substream *);
++	void (*shutdown)(struct snd_pcm_substream *);
++	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
++	int (*hw_free)(struct snd_pcm_substream *);
++	int (*prepare)(struct snd_pcm_substream *);
++	int (*trigger)(struct snd_pcm_substream *, int);
++};
++
++/* SoC DAI hardware mode */
++struct snd_soc_dai_mode {
++	u16 fmt;		/* SND_SOC_DAIFMT_* */
++	u16 tdm;		/* SND_SOC_HWTDM_* */
++	u64 pcmfmt; 	/* SNDRV_PCM_FMTBIT_* */
++	u16 pcmrate;	/* SND_SOC_HWRATE_* */
++	u16 pcmdir:2;	/* SND_SOC_HWDIR_* */
++	u16 flags:8;	/* hw flags */
++	u16 fs;			/* mclk to rate divider */
++	u64 bfs;		/* mclk to bclk dividers */
++	unsigned long priv;		/* private mode data */
++};
++
++/* DAI capabilities */
++struct snd_soc_dai_cap {
++	int num_modes;				/* number of DAI modes */
++	struct snd_soc_dai_mode *mode;	/* array of supported DAI modes */
++};
++
++/* SoC Codec DAI */
++struct snd_soc_codec_dai {
++	char *name;
++	int id;
++
++	/* DAI capabilities */
++	struct snd_soc_pcm_stream playback;
++	struct snd_soc_pcm_stream capture;
++	struct snd_soc_dai_cap caps;
++
++	/* DAI runtime info */
++	struct snd_soc_dai_mode dai_runtime;
++	struct snd_soc_ops ops;
++	unsigned int (*config_sysclk)(struct snd_soc_codec_dai*,
++		struct snd_soc_clock_info *info, unsigned int clk);
++	int (*digital_mute)(struct snd_soc_codec *,
++		struct snd_soc_codec_dai*, int);
++	unsigned int mclk;		/* the audio master clock */
++	unsigned int pll_in;	/* the PLL input clock */
++	unsigned int pll_out;	/* the PLL output clock */
++	unsigned int clk_div;	/* internal clock divider << 1 (for fractions) */
++	unsigned int active;
++	unsigned char pop_wait:1;
++
++	/* DAI private data */
++	void *private_data;
++};
++
++/* SoC CPU DAI */
++struct snd_soc_cpu_dai {
++
++	/* DAI description */
++	char *name;
++	unsigned int id;
++	unsigned char type;
++
++	/* DAI callbacks */
++	int (*probe)(struct platform_device *pdev);
++	void (*remove)(struct platform_device *pdev);
++	int (*suspend)(struct platform_device *pdev,
++		struct snd_soc_cpu_dai *cpu_dai);
++	int (*resume)(struct platform_device *pdev,
++		struct snd_soc_cpu_dai *cpu_dai);
++	unsigned int (*config_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
++		struct snd_soc_clock_info *info, unsigned int clk);
++
++	/* DAI capabilities */
++	struct snd_soc_pcm_stream capture;
++	struct snd_soc_pcm_stream playback;
++	struct snd_soc_dai_cap caps;
++
++	/* DAI runtime info */
++	struct snd_soc_dai_mode dai_runtime;
++	struct snd_soc_ops ops;
++	struct snd_pcm_runtime *runtime;
++	unsigned char active:1;
++	unsigned int mclk;
++	void *dma_data;
++
++	/* DAI private data */
++	void *private_data;
++};
++
++/* SoC Audio Codec */
++struct snd_soc_codec {
++	char *name;
++	struct module *owner;
++	struct mutex mutex;
++
++	/* callbacks */
++	int (*dapm_event)(struct snd_soc_codec *codec, int event);
++
++	/* runtime */
++	struct snd_card *card;
++	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
++	unsigned int active;
++	unsigned int pcm_devs;
++	void *private_data;
++
++	/* codec IO */
++	void *control_data; /* codec control (i2c/3wire) data */
++	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
++	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
++	hw_write_t hw_write;
++	hw_read_t hw_read;
++	void *reg_cache;
++	short reg_cache_size;
++	short reg_cache_step;
++
++	/* dapm */
++	struct list_head dapm_widgets;
++	struct list_head dapm_paths;
++	unsigned int dapm_state;
++	unsigned int suspend_dapm_state;
++
++	/* codec DAI's */
++	struct snd_soc_codec_dai *dai;
++	unsigned int num_dai;
++};
++
++/* codec device */
++struct snd_soc_codec_device {
++	int (*probe)(struct platform_device *pdev);
++	int (*remove)(struct platform_device *pdev);
++	int (*suspend)(struct platform_device *pdev, pm_message_t state);
++	int (*resume)(struct platform_device *pdev);
++};
++
++/* SoC platform interface */
++struct snd_soc_platform {
++	char *name;
++
++	int (*probe)(struct platform_device *pdev);
++	int (*remove)(struct platform_device *pdev);
++	int (*suspend)(struct platform_device *pdev,
++		struct snd_soc_cpu_dai *cpu_dai);
++	int (*resume)(struct platform_device *pdev,
++		struct snd_soc_cpu_dai *cpu_dai);
++
++	/* pcm creation and destruction */
++	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *,
++		struct snd_pcm *);
++	void (*pcm_free)(struct snd_pcm *);
++
++	/* platform stream ops */
++	struct snd_pcm_ops *pcm_ops;
++};
++
++/* SoC machine DAI configuration, glues a codec and cpu DAI together */
++struct snd_soc_dai_link  {
++	char *name;			/* Codec name */
++	char *stream_name;		/* Stream name */
++
++	/* DAI */
++	struct snd_soc_codec_dai *codec_dai;
++	struct snd_soc_cpu_dai *cpu_dai;
++	u32 flags;			/* DAI config preference flags */
++
++	/* codec/machine specific init - e.g. add machine controls */
++	int (*init)(struct snd_soc_codec *codec);
++
++	/* audio sysclock configuration */
++	unsigned int (*config_sysclk)(struct snd_soc_pcm_runtime *rtd,
++		struct snd_soc_clock_info *info);
++};
++
++/* SoC machine */
++struct snd_soc_machine {
++	char *name;
++
++	int (*probe)(struct platform_device *pdev);
++	int (*remove)(struct platform_device *pdev);
++
++	/* the pre and post PM functions are used to do any PM work before and
++	 * after the codec and DAI's do any PM work. */
++	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
++	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
++	int (*resume_pre)(struct platform_device *pdev);
++	int (*resume_post)(struct platform_device *pdev);
++
++	/* machine stream operations */
++	struct snd_soc_ops *ops;
++
++	/* CPU <--> Codec DAI links  */
++	struct snd_soc_dai_link *dai_link;
++	int num_links;
++};
++
++/* SoC Device - the audio subsystem */
++struct snd_soc_device {
++	struct device *dev;
++	struct snd_soc_machine *machine;
++	struct snd_soc_platform *platform;
++	struct snd_soc_codec *codec;
++	struct snd_soc_codec_device *codec_dev;
++	void *codec_data;
++};
++
++/* runtime channel data */
++struct snd_soc_pcm_runtime {
++	struct snd_soc_codec_dai *codec_dai;
++	struct snd_soc_cpu_dai *cpu_dai;
++	struct snd_soc_device *socdev;
++};
++
++/* enumerated kcontrol */
++struct soc_enum {
++	unsigned short reg;
++	unsigned short reg2;
++	unsigned char shift_l;
++	unsigned char shift_r;
++	unsigned int mask;
++	const char **texts;
++	void *dapm;
++};
++
++/* clocking configuration data */
++struct snd_soc_clock_info {
++	unsigned int rate;
++	unsigned int fs;
++	unsigned int bclk_master;
++};
++
++#endif
+Index: linux-2.6-pxa-new/sound/Kconfig
+===================================================================
+--- linux-2.6-pxa-new.orig/sound/Kconfig
++++ linux-2.6-pxa-new/sound/Kconfig
+@@ -76,6 +76,8 @@ source "sound/sparc/Kconfig"
+ 
+ source "sound/parisc/Kconfig"
+ 
++source "sound/soc/Kconfig"
++
+ endmenu
+ 
+ menu "Open Sound System"
+Index: linux-2.6-pxa-new/sound/soc/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/Kconfig
+@@ -0,0 +1,37 @@
++#
++# SoC audio configuration
++#
++
++menu "SoC audio support"
++	depends on SND!=n
++
++config SND_SOC_AC97_BUS
++	bool
++
++config SND_SOC
++	tristate "SoC audio support"
++	---help---
++
++	  If you want SoC support, you should say Y here and also to the
++	  specific driver for your SoC below. You will also need to select the
++	  specific codec(s) attached to the SoC
++
++	  This SoC audio support can also be built as a module.  If so, the module
++	  will be called snd-soc-core.
++
++# All the supported Soc's
++menu "Soc Platforms"
++depends on SND_SOC
++source "sound/soc/pxa/Kconfig"
++source "sound/soc/at91/Kconfig"
++source "sound/soc/imx/Kconfig"
++source "sound/soc/s3c24xx/Kconfig"
++endmenu
++
++# Supported codecs
++menu "Soc Codecs"
++depends on SND_SOC
++source "sound/soc/codecs/Kconfig"
++endmenu
++
++endmenu
+Index: linux-2.6-pxa-new/sound/soc/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/Makefile
+@@ -0,0 +1,4 @@
++snd-soc-core-objs := soc-core.o soc-dapm.o
++
++obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
++obj-$(CONFIG_SND_SOC)	+= pxa/ at91/ imx/ s3c24xx/ codecs/
+Index: linux-2.6-pxa-new/sound/soc/codecs/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/Kconfig
+@@ -0,0 +1,90 @@
++config SND_SOC_AC97_CODEC
++	tristate "SoC generic AC97 support"
++	depends SND_SOC
++	help
++	  Say Y or M if you want generic AC97 support. This is not required
++	  for the AC97 codecs listed below.
++
++config SND_SOC_WM8711
++	tristate "SoC driver for the WM8711 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8711 codec.
++
++config SND_SOC_WM8510
++	tristate "SoC driver for the WM8510 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8711 codec.
++
++config SND_SOC_WM8731
++	tristate "SoC driver for the WM8731 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8731 codec.
++
++config SND_SOC_WM8750
++	tristate "SoC driver for the WM8750 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8750 codec.
++
++config SND_SOC_WM8753
++	tristate "SoC driver for the WM8753 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8753 codec.
++
++config SND_SOC_WM8772
++	tristate "SoC driver for the WM8772 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8772 codec.
++
++config SND_SOC_WM8971
++	tristate "SoC driver for the WM8971 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8971 codec.
++
++config SND_SOC_WM8976
++	tristate "SoC driver for the WM8976 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8976 codec.
++
++config SND_SOC_WM8974
++	tristate "SoC driver for the WM8974 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8974 codec.
++
++config SND_SOC_WM8980
++	tristate "SoC driver for the WM8980 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM8980 codec.
++
++config SND_SOC_WM9713
++	tristate "SoC driver for the WM9713 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM9713 codec.
++
++config SND_SOC_WM9712
++	tristate "SoC driver for the WM9712 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the WM9712 codec.
++
++config SND_SOC_UDA1380
++	tristate "SoC driver for the UDA1380 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the UDA1380 codec.
++
++config SND_SOC_AK4535
++	tristate "SoC driver for the AK4535 codec"
++	depends SND_SOC
++	help
++	  Say Y or M if you want to support the AK4535 codec.
+Index: linux-2.6-pxa-new/sound/soc/codecs/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/Makefile
+@@ -0,0 +1,31 @@
++snd-soc-ac97-objs := ac97.o
++snd-soc-wm8711-objs := wm8711.o
++snd-soc-wm8510-objs := wm8510.o
++snd-soc-wm8731-objs := wm8731.o
++snd-soc-wm8750-objs := wm8750.o
++snd-soc-wm8753-objs := wm8753.o
++snd-soc-wm8772-objs := wm8772.o
++snd-soc-wm8971-objs := wm8971.o
++snd-soc-wm8974-objs := wm8974.o
++snd-soc-wm8976-objs := wm8976.o
++snd-soc-wm8980-objs := wm8980.o
++snd-soc-uda1380-objs := uda1380.o
++snd-soc-ak4535-objs := ak4535.o
++snd-soc-wm9713-objs := wm9713.o
++snd-soc-wm9712-objs := wm9712.o
++
++obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
++obj-$(CONFIG_SND_SOC_WM8711)	+= snd-soc-wm8711.o
++obj-$(CONFIG_SND_SOC_WM8510)	+= snd-soc-wm8510.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_WM8772)	+= snd-soc-wm8772.o
++obj-$(CONFIG_SND_SOC_WM8971)	+= snd-soc-wm8971.o
++obj-$(CONFIG_SND_SOC_WM8974)	+= snd-soc-wm8974.o
++obj-$(CONFIG_SND_SOC_WM8976)	+= snd-soc-wm8976.o
++obj-$(CONFIG_SND_SOC_WM8980)	+= snd-soc-wm8980.o
++obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
++obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
++obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
++obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
+Index: linux-2.6-pxa-new/sound/soc/codecs/ac97.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/ac97.c
+@@ -0,0 +1,167 @@
++/*
++ * ac97.c  --  ALSA Soc AC97 codec support
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    17th Oct 2005   Initial version.
++ *
++ * Generic AC97 support.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#define AC97_VERSION "0.5"
++
++#define AC97_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define AC97_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)
++
++/* may need to expand this */
++static struct snd_soc_dai_mode soc_ac97[] = {
++	{0, 0,	SNDRV_PCM_FMTBIT_S16_LE,	AC97_RATES},
++	{0, 0,	SNDRV_PCM_FMTBIT_S18_3LE,	AC97_RATES},
++	{0, 0,	SNDRV_PCM_FMTBIT_S20_3LE,	AC97_RATES},
++};
++
++static int ac97_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++
++	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
++	return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
++}
++
++static struct snd_soc_codec_dai ac97_dai = {
++	.name = "AC97 HiFi",
++	.playback = {
++		.stream_name = "AC97 Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "AC97 Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.prepare = ac97_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(soc_ac97),
++		.mode = soc_ac97,},
++};
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	return soc_ac97_ops.read(codec->ac97, reg);
++}
++
++static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int val)
++{
++	soc_ac97_ops.write(codec->ac97, reg, val);
++	return 0;
++}
++
++static int ac97_soc_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec;
++	struct snd_ac97_bus *ac97_bus;
++	struct snd_ac97_template ac97_template;
++	int ret = 0;
++
++	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
++
++	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++	if (socdev->codec == NULL)
++		return -ENOMEM;
++	codec = socdev->codec;
++	mutex_init(&codec->mutex);
++
++	codec->name = "AC97";
++	codec->owner = THIS_MODULE;
++	codec->dai = &ac97_dai;
++	codec->num_dai = 1;
++	codec->write = ac97_write;
++	codec->read = ac97_read;
++	INIT_LIST_HEAD(&codec->dapm_widgets);
++	INIT_LIST_HEAD(&codec->dapm_paths);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0)
++		goto err;
++
++	/* add codec as bus device for standard ac97 */
++	ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
++	if(ret < 0)
++		goto bus_err;
++
++	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
++	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
++	if(ret < 0)
++		goto bus_err;
++
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0)
++		goto bus_err;
++	return 0;
++
++bus_err:
++	snd_soc_free_pcms(socdev);
++
++err:
++	kfree(socdev->codec->reg_cache);
++	kfree(socdev->codec);
++	socdev->codec = NULL;
++	return ret;
++}
++
++static int ac97_soc_remove(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++
++	if(codec == NULL)
++		return 0;
++
++	snd_soc_free_pcms(socdev);
++	kfree(socdev->codec->reg_cache);
++	kfree(socdev->codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_ac97= {
++	.probe = 	ac97_soc_probe,
++	.remove = 	ac97_soc_remove,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
++
++MODULE_DESCRIPTION("Soc Generic AC97 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/ac97.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/ac97.h
+@@ -0,0 +1,18 @@
++/*
++ * linux/sound/codecs/ac97.h -- ALSA SoC Layer
++ *
++ * Author:		Liam Girdwood
++ * Created:		Dec 1st 2005
++ * Copyright:	Wolfson Microelectronics. PLC.
++ *
++ * 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_AC97_H
++#define __LINUX_SND_SOC_AC97_H
++
++extern struct snd_soc_codec_device soc_codec_dev_ac97;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/ak4535.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/ak4535.c
+@@ -0,0 +1,701 @@
++/*
++ * ak4535.c  --  AK4535 ALSA Soc Audio driver
++ *
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on wm8753.c by Liam Girdwood
++ *
++ * 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/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "ak4535.h"
++
++#define AUDIO_NAME "ak4535"
++#define AK4535_VERSION "0.3"
++
++struct snd_soc_codec_device soc_codec_dev_ak4535;
++
++/*
++ * ak4535 register cache
++ */
++static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
++    0x0000, 0x0080, 0x0000, 0x0003,
++    0x0002, 0x0000, 0x0011, 0x0001,
++    0x0000, 0x0040, 0x0036, 0x0010,
++    0x0000, 0x0000, 0x0057, 0x0000,
++};
++
++#define AK4535_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS | \
++	SND_SOC_DAIFMT_NB_NF)
++
++#define AK4535_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define AK4535_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)
++
++static struct snd_soc_dai_mode ak4535_modes[] = {
++	/* codec frame and clock slave modes */
++	{
++		.fmt = AK4535_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = AK4535_RATES,
++		.pcmdir = AK4535_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = AK4535_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = AK4535_RATES,
++		.pcmdir = AK4535_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 32,
++	},
++};
++
++/*
++ * read ak4535 register cache
++ */
++static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= AK4535_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write ak4535 register cache
++ */
++static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= AK4535_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the AK4535 register space
++ */
++static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D8 AK4535 register offset
++	 *   D7...D0 register data
++	 */
++	data[0] = reg & 0xff;
++	data[1] = value & 0xff;
++
++	ak4535_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
++static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
++static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
++static const char *ak4535_deemp[] = {"44.1kHz", "Off", "48kHz", "32kHz"};
++static const char *ak4535_mic_select[] = {"Internal", "External"};
++
++static const struct soc_enum ak4535_enum[] = {
++	SOC_ENUM_SINGLE(AK4535_SIG1, 7, 2, ak4535_mono_gain),
++	SOC_ENUM_SINGLE(AK4535_SIG1, 6, 2, ak4535_mono_out),
++	SOC_ENUM_SINGLE(AK4535_MODE2, 2, 2, ak4535_hp_out),
++	SOC_ENUM_SINGLE(AK4535_DAC, 0, 4, ak4535_deemp),
++	SOC_ENUM_SINGLE(AK4535_MIC, 1, 2, ak4535_mic_select),
++};
++
++static const struct snd_kcontrol_new ak4535_snd_controls[] = {
++	SOC_SINGLE("ALC2 Switch", AK4535_SIG1, 1, 1, 0),
++	SOC_ENUM("Mono 1 Output", ak4535_enum[1]),
++	SOC_ENUM("Mono 1 Gain", ak4535_enum[0]),
++	SOC_ENUM("Headphone Output", ak4535_enum[2]),
++	SOC_ENUM("Playback Deemphasis", ak4535_enum[3]),
++	SOC_SINGLE("Bass Volume", AK4535_DAC, 2, 3, 0),
++	SOC_SINGLE("Mic Boost (+20dB) Switch", AK4535_MIC, 0, 1, 0),
++	SOC_ENUM("Mic Select", ak4535_enum[4]),
++	SOC_SINGLE("ALC Operation Time", AK4535_TIMER, 0, 3, 0),
++	SOC_SINGLE("ALC Recovery Time", AK4535_TIMER, 2, 3, 0),
++	SOC_SINGLE("ALC ZC Time", AK4535_TIMER, 4, 3, 0),
++	SOC_SINGLE("ALC 1 Switch", AK4535_ALC1, 5, 1, 0),
++	SOC_SINGLE("ALC 2 Switch", AK4535_ALC1, 6, 1, 0),
++	SOC_SINGLE("ALC Volume", AK4535_ALC2, 0, 127, 0),
++	SOC_SINGLE("Capture Volume", AK4535_PGA, 0, 127, 0),
++	SOC_SINGLE("Left Playback Volume", AK4535_LATT, 0, 127, 1),
++	SOC_SINGLE("Right Playback Volume", AK4535_RATT, 0, 127, 1),
++	SOC_SINGLE("AUX Bypass Volume", AK4535_VOL, 0, 15, 0),
++	SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0),
++};
++
++/* add non dapm controls */
++static int ak4535_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++			snd_soc_cnew(&ak4535_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Mono 1 Mixer */
++static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = {
++	SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0),
++	SOC_DAPM_SINGLE("Mono Playback Switch", AK4535_SIG1, 5, 1, 0),
++};
++
++/* Stereo Mixer */
++static const struct snd_kcontrol_new ak4535_stereo_mixer_controls[] = {
++	SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG2, 4, 1, 0),
++	SOC_DAPM_SINGLE("Playback Switch", AK4535_SIG2, 7, 1, 0),
++	SOC_DAPM_SINGLE("Aux Bypass Switch", AK4535_SIG2, 5, 1, 0),
++};
++
++/* Input Mixer */
++static const struct snd_kcontrol_new ak4535_input_mixer_controls[] = {
++	SOC_DAPM_SINGLE("Mic Capture Switch", AK4535_MIC, 2, 1, 0),
++	SOC_DAPM_SINGLE("Aux Capture Switch", AK4535_MIC, 5, 1, 0),
++};
++
++/* Input mux */
++static const struct snd_kcontrol_new ak4535_input_mux_control =
++	SOC_DAPM_ENUM("Input Select", ak4535_enum[0]);
++
++/* HP L switch */
++static const struct snd_kcontrol_new ak4535_hpl_control =
++	SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 1, 1, 1);
++
++/* HP R switch */
++static const struct snd_kcontrol_new ak4535_hpr_control =
++	SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 0, 1, 1);
++
++/* Speaker switch */
++static const struct snd_kcontrol_new ak4535_spk_control =
++	SOC_DAPM_SINGLE("Switch", AK4535_MODE2, 0, 0, 0);
++
++/* mono 2 switch */
++static const struct snd_kcontrol_new ak4535_mono2_control =
++	SOC_DAPM_SINGLE("Switch", AK4535_SIG1, 0, 1, 0);
++
++/* Line out switch */
++static const struct snd_kcontrol_new ak4535_line_control =
++	SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 6, 1, 0);
++
++/* ak4535 dapm widgets */
++static const struct snd_soc_dapm_widget ak4535_dapm_widgets[] = {
++	SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0,
++		&ak4535_stereo_mixer_controls[0],
++		ARRAY_SIZE(ak4535_stereo_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0,
++		&ak4535_mono1_mixer_controls[0],
++		ARRAY_SIZE(ak4535_mono1_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0,
++		&ak4535_input_mixer_controls[0],
++		ARRAY_SIZE(ak4535_mono1_mixer_controls)),
++	SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
++		&ak4535_input_mux_control),
++	SND_SOC_DAPM_DAC("DAC", "Playback", AK4535_PM2, 0, 0),
++	SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0,
++		&ak4535_mono2_control),
++	SND_SOC_DAPM_SWITCH("Speaker Enable", SND_SOC_NOPM, 0, 0,
++		&ak4535_spk_control),
++	SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0,
++		&ak4535_line_control),
++	SND_SOC_DAPM_SWITCH("Left HP Enable", SND_SOC_NOPM, 0, 0,
++		&ak4535_hpl_control),
++	SND_SOC_DAPM_SWITCH("Right HP Enable", SND_SOC_NOPM, 0, 0,
++		&ak4535_hpr_control),
++	SND_SOC_DAPM_OUTPUT("LOUT"),
++	SND_SOC_DAPM_OUTPUT("HPL"),
++	SND_SOC_DAPM_OUTPUT("ROUT"),
++	SND_SOC_DAPM_OUTPUT("HPR"),
++	SND_SOC_DAPM_OUTPUT("SPP"),
++	SND_SOC_DAPM_OUTPUT("SPN"),
++	SND_SOC_DAPM_OUTPUT("MOUT1"),
++	SND_SOC_DAPM_OUTPUT("MOUT2"),
++	SND_SOC_DAPM_OUTPUT("MICOUT"),
++	SND_SOC_DAPM_ADC("ADC", "Capture", AK4535_PM1, 0, 1),
++	SND_SOC_DAPM_PGA("Spk Amp", AK4535_PM2, 3, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("HP R Amp", AK4535_PM2, 1, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("HP L Amp", AK4535_PM2, 2, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Mic", AK4535_PM1, 1, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Line Out", AK4535_PM1, 4, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Mono Out", AK4535_PM1, 3, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("AUX In", AK4535_PM1, 2, 0, NULL, 0),
++
++	SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4535_MIC, 3, 0),
++	SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4535_MIC, 4, 0),
++	SND_SOC_DAPM_INPUT("MICIN"),
++	SND_SOC_DAPM_INPUT("MICEXT"),
++	SND_SOC_DAPM_INPUT("AUX"),
++	SND_SOC_DAPM_INPUT("MIN"),
++	SND_SOC_DAPM_INPUT("AIN"),
++};
++
++static const char *audio_map[][3] = {
++	/*stereo mixer */
++	{"Stereo Mixer", "Playback Switch", "DAC"},
++	{"Stereo Mixer", "Mic Sidetone Switch", "Mic"},
++	{"Stereo Mixer", "Aux Bypass Switch", "AUX In"},
++
++	/* mono1 mixer */
++	{"Mono1 Mixer", "Mic Sidetone Switch", "Mic"},
++	{"Mono1 Mixer", "Mono Playback Switch", "DAC"},
++
++	/* mono2 mixer */
++	{"Mono2 Mixer", "Mono Playback Switch", "Stereo Mixer"},
++
++	/* Mic */
++	{"AIN", NULL, "Mic"},
++	{"Input Mux", "Internal", "Mic Int Bias"},
++	{"Input Mux", "External", "Mic Ext Bias"},
++	{"Mic Int Bias", NULL, "MICIN"},
++	{"Mic Ext Bias", NULL, "MICEXT"},
++	{"MICOUT", NULL, "Input Mux"},
++
++	/* line out */
++	{"LOUT", "Switch", "Line"},
++	{"ROUT", "Switch", "Line Out Enable"},
++	{"Line Out Enable", NULL, "Line Out"},
++	{"Line Out", NULL, "Stereo Mixer"},
++
++	/* mono1 out */
++	{"MOUT1", NULL, "Mono Out"},
++	{"Mono Out", NULL, "Mono Mixer"},
++
++	/* left HP */
++	{"HPL", "Switch", "Left HP Enable"},
++	{"Left HP Enable", NULL, "HP L Amp"},
++	{"HP L Amp", NULL, "Stereo Mixer"},
++
++	/* right HP */
++	{"HPR", "Switch", "Right HP Enable"},
++	{"Right HP Enable", NULL, "HP R Amp"},
++	{"HP R Amp", NULL, "Stereo Mixer"},
++
++	/* speaker */
++	{"SPP", "Switch", "Speaker Enable"},
++	{"SPN", "Switch", "Speaker Enable"},
++	{"Speaker Enable", NULL, "Spk Amp"},
++	{"Spk Amp", NULL, "MIN"},
++
++	/* mono 2 */
++	{"MOUT2", "Switch", "Mono 2 Enable"},
++	{"Mono 2 Enable", NULL, "Stereo Mixer"},
++
++	/* Aux In */
++	{"Aux In", NULL, "AUX"},
++
++	/* ADC */
++	{"ADC", NULL, "Input Mixer"},
++	{"Input Mixer", "Mic Capture Switch", "Mic"},
++	{"Input Mixer", "Aux Capture Switch", "Aux In"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int ak4535_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(ak4535_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &ak4535_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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 ak4535_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u8 mode = 0, mode2;
++	int bfs;
++
++	mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2);
++	bfs = SND_SOC_FSBW_REAL(rtd->codec_dai->dai_runtime.bfs);
++	snd_assert(bfs, return -ENODEV);
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		mode = 0x0002;
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		mode = 0x0001;
++		break;
++	}
++
++	/* set fs */
++	switch (rtd->codec_dai->dai_runtime.fs) {
++	case 1024:
++		mode2 |= (0x3 << 5);
++		break;
++	case 512:
++		mode2 |= (0x2 << 5);
++		break;
++	case 256:
++		mode2 |= (0x1 << 5);
++		break;
++	}
++
++	/* bfs */
++	if (bfs == 64)
++		mode |= 0x4;
++
++	/* set rate */
++	ak4535_write(codec, AK4535_MODE1, mode);
++	ak4535_write(codec, AK4535_MODE2, mode2);
++
++	return 0;
++}
++
++static unsigned int ak4535_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	if (info->fs != 256)
++		return 0;
++
++	/* we only support 256 FS atm */
++	if (info->rate * info->fs == clk) {
++		dai->mclk = clk;
++		return clk;
++	}
++
++	return 0;
++}
++
++static int ak4535_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
++	if (mute)
++		ak4535_write(codec, AK4535_DAC, mute_reg);
++	else
++		ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
++	return 0;
++}
++
++static int ak4535_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++	/* vref/mid, clk and osc on, dac unmute, active */
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, dac mute, inactive */
++		ak4535_write(codec, AK4535_PM1, 0x80);
++		ak4535_write(codec, AK4535_PM2, 0x0);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, inactive */
++		ak4535_write(codec, AK4535_PM1, 0x0);
++		ak4535_write(codec, AK4535_PM2, 0x80);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai ak4535_dai = {
++	.name = "AK4535",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = ak4535_config_sysclk,
++	.digital_mute = ak4535_mute,
++	.ops = {
++		.prepare = ak4535_pcm_prepare,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(ak4535_modes),
++		.mode = ak4535_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(ak4535_dai);
++
++static int ak4535_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;
++
++	ak4535_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int ak4535_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(ak4535_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	ak4535_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	ak4535_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the AK4535 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int ak4535_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "AK4535";
++	codec->owner = THIS_MODULE;
++	codec->read = ak4535_read_reg_cache;
++	codec->write = ak4535_write;
++	codec->dapm_event = ak4535_dapm_event;
++	codec->dai = &ak4535_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(ak4535_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, ak4535_reg,
++		sizeof(u16) * ARRAY_SIZE(ak4535_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ak4535_reg);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	ak4535_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	ak4535_add_controls(codec);
++	ak4535_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 struct snd_soc_device *ak4535_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++#define I2C_DRIVERID_AK4535 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver ak4535_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = ak4535_socdev;
++	struct ak4535_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		printk(KERN_ERR "failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = ak4535_init(socdev);
++	if (ret < 0) {
++		printk(KERN_ERR "failed to initialise AK4535\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int ak4535_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++
++	return 0;
++}
++
++static int ak4535_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, ak4535_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver ak4535_i2c_driver = {
++	.driver = {
++		.name = "AK4535 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_AK4535,
++	.attach_adapter = ak4535_i2c_attach,
++	.detach_client =  ak4535_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "AK4535",
++	.driver = &ak4535_i2c_driver,
++};
++#endif
++
++static int ak4535_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct ak4535_setup_data *setup;
++	struct snd_soc_codec* codec;
++	int ret = 0;
++
++	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_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);
++
++	ak4535_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&ak4535_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int ak4535_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)
++		ak4535_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&ak4535_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_ak4535 = {
++	.probe = 	ak4535_probe,
++	.remove = 	ak4535_remove,
++	.suspend = 	ak4535_suspend,
++	.resume =	ak4535_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
++
++MODULE_DESCRIPTION("Soc AK4535 driver");
++MODULE_AUTHOR("Richard Purdie");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/ak4535.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/ak4535.h
+@@ -0,0 +1,46 @@
++/*
++ * ak4535.h  --  AK4535 Soc Audio driver
++ *
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on wm8753.h
++ *
++ * 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 _AK4535_H
++#define _AK4535_H
++
++/* AK4535 register space */
++
++#define AK4535_PM1		0x0
++#define AK4535_PM2		0x1
++#define AK4535_SIG1		0x2
++#define AK4535_SIG2		0x3
++#define AK4535_MODE1	0x4
++#define AK4535_MODE2	0x5
++#define AK4535_DAC		0x6
++#define AK4535_MIC		0x7
++#define AK4535_TIMER	0x8
++#define AK4535_ALC1		0x9
++#define AK4535_ALC2		0xa
++#define AK4535_PGA		0xb
++#define AK4535_LATT		0xc
++#define AK4535_RATT		0xd
++#define AK4535_VOL		0xe
++#define AK4535_STATUS	0xf
++
++#define AK4535_CACHEREGNUM 	0x10
++
++struct ak4535_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai ak4535_dai;
++extern struct snd_soc_codec_device soc_codec_dev_ak4535;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/uda1380.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/uda1380.c
+@@ -0,0 +1,582 @@
++/*
++ * uda1380.c - Philips UDA1380 ALSA SoC audio driver
++ *
++ * 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.
++ *
++ * Modified by Richard Purdie <richard at openedhand.com> to fit into SoC
++ * codec model.
++ *
++ * Copyright (c) 2005 Giorgio Padrin <giorgio at mandarinlogiq.org>
++ * Copyright 2005 Openedhand Ltd.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/ioctl.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/initval.h>
++#include <sound/info.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include "uda1380.h"
++
++#define UDA1380_VERSION "0.4"
++
++/*
++ * uda1380 register cache
++ */
++static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = {
++    0x0502, 0x0000, 0x0000, 0x3f3f,
++    0x0202, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0000, 0xff00, 0x0000, 0x4800,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x8000, 0x0002, 0x0000,
++};
++
++#define UDA1380_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS | \
++	 SND_SOC_DAIFMT_NB_NF)
++
++#define UDA1380_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define UDA1380_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)
++
++static struct snd_soc_dai_mode uda1380_modes[] = {
++	/* slave rates capture & playback */
++	{
++		.fmt = UDA1380_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = UDA1380_RATES,
++		.pcmdir = UDA1380_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++
++	/* slave rates playback */
++	{
++		.fmt = UDA1380_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++};
++
++/*
++ * read uda1380 register cache
++ */
++static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == UDA1380_RESET)
++		return 0;
++	if (reg >= UDA1380_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write uda1380 register cache
++ */
++static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= UDA1380_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the UDA1380 register space
++ */
++static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[3];
++
++	/* data is
++	 *   data[0] is register offset
++	 *   data[1] is MS byte
++	 *   data[2] is LS byte
++	 */
++	data[0] = reg;
++	data[1] = (value & 0xff00) >> 8;
++	data[2] = value & 0x00ff;
++
++	uda1380_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 3) == 3)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define uda1380_reset(c)	uda1380_write(c, UDA1380_RESET, 0)
++
++/* declarations of ALSA reg_elem_REAL controls */
++static const char *uda1380_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz",
++	"96kHz"};
++static const char *uda1380_input_sel[] = {"Line", "Mic"};
++
++static const struct soc_enum uda1380_enum[] = {
++	SOC_ENUM_DOUBLE(UDA1380_DEEMP, 0, 8, 5, uda1380_deemp),
++	SOC_ENUM_SINGLE(UDA1380_ADC, 3, 2, uda1380_input_sel),
++};
++
++static const struct snd_kcontrol_new uda1380_snd_controls[] = {
++	SOC_DOUBLE("Playback Volume", UDA1380_MVOL, 0, 8, 127, 0),
++	SOC_DOUBLE("Treble Volume", UDA1380_MODE, 4, 12, 3, 0),
++	SOC_DOUBLE("Bass Volume", UDA1380_MODE, 0, 8, 15, 0),
++	SOC_ENUM("Playback De-emphasis", uda1380_enum[0]),
++	SOC_DOUBLE("Capture Volume", UDA1380_DEC, 0, 8, 127, 0),
++	SOC_DOUBLE("Line Capture Volume", UDA1380_PGA, 0, 8, 15, 0),
++	SOC_SINGLE("Mic Capture Volume", UDA1380_PGA, 8, 11, 0),
++	SOC_DOUBLE("Playback Switch", UDA1380_DEEMP, 3, 11, 1, 0),
++	SOC_SINGLE("Capture Switch", UDA1380_PGA, 15, 1, 0),
++	SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0),
++	SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1),
++	SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0),
++};
++
++/* add non dapm controls */
++static int uda1380_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++			snd_soc_cnew(&uda1380_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Input mux */
++static const struct snd_kcontrol_new uda1380_input_mux_control =
++	SOC_DAPM_ENUM("Input Select", uda1380_enum[1]);
++
++static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
++	SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
++		&uda1380_input_mux_control),
++	SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0),
++	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0),
++	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0),
++	SND_SOC_DAPM_INPUT("VINM"),
++	SND_SOC_DAPM_INPUT("VINL"),
++	SND_SOC_DAPM_INPUT("VINR"),
++	SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0),
++	SND_SOC_DAPM_OUTPUT("VOUTLHP"),
++	SND_SOC_DAPM_OUTPUT("VOUTRHP"),
++	SND_SOC_DAPM_OUTPUT("VOUTL"),
++	SND_SOC_DAPM_OUTPUT("VOUTR"),
++	SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0),
++	SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0),
++};
++
++static const char *audio_map[][3] = {
++
++	/* analog mixer setup is different from diagram for dapm */
++	{"HeadPhone Driver", NULL, "Analog Mixer"},
++	{"VOUTR", NULL, "Analog Mixer"},
++	{"VOUTL", NULL, "Analog Mixer"},
++	{"Analog Mixer", NULL, "VINR"},
++	{"Analog Mixer", NULL, "VINL"},
++	{"Analog Mixer", NULL, "DAC"},
++
++	/* headphone driver */
++	{"VOUTLHP", NULL, "HeadPhone Driver"},
++	{"VOUTRHP", NULL, "HeadPhone Driver"},
++
++	/* input mux */
++	{"Left ADC", NULL, "Input Mux"},
++	{"Input Mux", "Mic", "Mic LNA"},
++	{"Input Mux", "Line", "Left PGA"},
++
++	/* right input */
++	{"Right ADC", NULL, "Right PGA"},
++
++	/* inputs */
++	{"Mic LNA", NULL, "VINM"},
++	{"Left PGA", NULL, "VINL"},
++	{"Right PGA", NULL, "VINR"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int uda1380_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(uda1380_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &uda1380_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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 uda1380_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		uda1380_write(codec, UDA1380_CLK, R00_EN_DAC | R00_EN_INT | clk);
++	else
++		uda1380_write(codec, UDA1380_CLK, R00_EN_ADC | R00_EN_DEC | clk);
++
++	return 0;
++}
++
++static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		uda1380_write(codec, UDA1380_CLK, ~(R00_EN_DAC | R00_EN_INT) & clk);
++	else
++		uda1380_write(codec, UDA1380_CLK, ~(R00_EN_ADC | R00_EN_DEC) & clk);
++}
++
++static unsigned int uda1380_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	if(info->fs != 256)
++		return 0;
++
++	/* we only support 256 FS atm */
++	if(info->rate * info->fs == clk) {
++		dai->mclk = clk;
++		return clk;
++	}
++
++	return 0;
++}
++
++static int uda1380_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & 0xbfff;
++	if(mute)
++		uda1380_write(codec, UDA1380_DEEMP, mute_reg | 0x4000);
++	else
++		uda1380_write(codec, UDA1380_DEEMP, mute_reg);
++	return 0;
++}
++
++static int uda1380_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	switch (event) {
++		case SNDRV_CTL_POWER_D0: /* full On */
++		case SNDRV_CTL_POWER_D1: /* partial On */
++		case SNDRV_CTL_POWER_D2: /* partial On */
++		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++			/* everything off except internal bias */
++			uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
++			break;
++		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++			/* everything off, inactive */
++			uda1380_write(codec, UDA1380_PM, 0x0);
++			break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai uda1380_dai = {
++	.name = "UDA1380",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = uda1380_config_sysclk,
++	.digital_mute = uda1380_mute,
++	.ops = {
++		.prepare = uda1380_pcm_prepare,
++		.shutdown = uda1380_pcm_shutdown,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(uda1380_modes),
++		.mode = uda1380_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(uda1380_dai);
++
++static int uda1380_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;
++
++	uda1380_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int uda1380_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	uda1380_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	uda1380_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the UDA1380 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int uda1380_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "UDA1380";
++	codec->owner = THIS_MODULE;
++	codec->read = uda1380_read_reg_cache;
++	codec->write = uda1380_write;
++	codec->dapm_event = uda1380_dapm_event;
++	codec->dai = &uda1380_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(uda1380_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, uda1380_reg,
++		sizeof(u16) * ARRAY_SIZE(uda1380_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(uda1380_reg);
++	uda1380_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	uda1380_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	uda1380_write(codec, UDA1380_CLK, 0);
++
++	/* uda1380 init */
++	uda1380_add_controls(codec);
++	uda1380_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 struct snd_soc_device *uda1380_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++#define I2C_DRIVERID_UDA1380 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver uda1380_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = uda1380_socdev;
++	struct uda1380_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if(ret < 0) {
++		printk(KERN_ERR "failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = uda1380_init(socdev);
++	if(ret < 0) {
++		printk(KERN_ERR "failed to initialise UDA1380\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int uda1380_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int uda1380_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, uda1380_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver uda1380_i2c_driver = {
++	.driver = {
++		.name =  "UDA1380 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_UDA1380,
++	.attach_adapter = uda1380_i2c_attach,
++	.detach_client =  uda1380_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "UDA1380",
++	.driver = &uda1380_i2c_driver,
++};
++#endif
++
++static int uda1380_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct uda1380_setup_data *setup;
++	struct snd_soc_codec* codec;
++	int ret = 0;
++
++	printk(KERN_INFO "UDA1380 Audio Codec %s", UDA1380_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);
++
++	uda1380_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&uda1380_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int uda1380_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)
++		uda1380_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&uda1380_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_uda1380 = {
++	.probe = 	uda1380_probe,
++	.remove = 	uda1380_remove,
++	.suspend = 	uda1380_suspend,
++	.resume =	uda1380_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
++
++MODULE_AUTHOR("Giorgio Padrin");
++MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/uda1380.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/uda1380.h
+@@ -0,0 +1,56 @@
++/*
++ * Audio support for Philips UDA1380
++ *
++ * 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.
++ *
++ * Copyright (c) 2005 Giorgio Padrin <giorgio at mandarinlogiq.org>
++ */
++
++#define UDA1380_CLK		0x00
++#define UDA1380_IFACE	0x01
++#define UDA1380_PM		0x02
++#define UDA1380_AMIX	0x03
++#define UDA1380_HP		0x04
++#define UDA1380_MVOL	0x10
++#define UDA1380_MIXVOL	0x11
++#define UDA1380_MODE	0x12
++#define UDA1380_DEEMP	0x13
++#define UDA1380_MIXER	0x14
++#define UDA1380_INTSTAT	0x18
++#define UDA1380_DEC		0x20
++#define UDA1380_PGA		0x21
++#define UDA1380_ADC		0x22
++#define UDA1380_AGC		0x23
++#define UDA1380_DECSTAT	0x28
++#define UDA1380_RESET	0x7f
++
++#define UDA1380_CACHEREGNUM 0x24
++
++/* Register flags */
++#define R00_EN_ADC	0x0800
++#define R00_EN_DEC	0x0400
++#define R00_EN_DAC	0x0200
++#define R00_EN_INT	0x0100
++#define R02_PON_HP	0x2000
++#define R02_PON_DAC	0x0400
++#define R02_PON_BIAS	0x0100
++#define R02_PON_LNA	0x0010
++#define R02_PON_PGAL	0x0008
++#define R02_PON_ADCL	0x0004
++#define R02_PON_PGAR	0x0002
++#define R02_PON_ADCR	0x0001
++#define R13_MTM		0x4000
++#define R21_MT_ADC	0x8000
++#define R22_SEL_LNA	0x0008
++#define R22_SEL_MIC	0x0004
++#define R22_SKIP_DCFIL	0x0002
++#define R23_AGC_EN	0x0001
++
++struct uda1380_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai uda1380_dai;
++extern struct snd_soc_codec_device soc_codec_dev_uda1380;
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8731.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8731.c
+@@ -0,0 +1,886 @@
++/*
++ * wm8731.c  --  WM8731 ALSA SoC Audio driver
++ *
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on wm8753.c by Liam Girdwood
++ *
++ * 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/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8731.h"
++
++#define AUDIO_NAME "wm8731"
++#define WM8731_VERSION "0.12"
++
++/*
++ * Debug
++ */
++
++#define WM8731_DEBUG 0
++
++#ifdef WM8731_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8731;
++
++/*
++ * wm8731 register cache
++ * We can't read the WM8731 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ * There is no point in caching the reset register
++ */
++static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
++    0x0097, 0x0097, 0x0079, 0x0079,
++    0x000a, 0x0008, 0x009f, 0x000a,
++    0x0000, 0x0000
++};
++
++#define WM8731_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8731_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8731_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++#define WM8731_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8731_modes[] = {
++	/* codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 1536,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 2304,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 1408,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 2112,
++		.bfs = 64,
++	},
++
++	/* 32k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 576,
++		.bfs = 64,
++	},
++
++	/* 44.1k & 48k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++
++	/* 88.2 & 96k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++
++	/* USB codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 44.1k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 48k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 88.2k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 136,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 96k */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 125,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8731_HIFI_BITS,
++		.pcmrate = WM8731_RATES,
++		.pcmdir = WM8731_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8731 register cache
++ */
++static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8731_RESET)
++		return 0;
++	if (reg >= WM8731_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8731 register cache
++ */
++static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8731_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8731 register space
++ */
++static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8731 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8731_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8731_reset(c)	wm8731_write(c, WM8731_RESET, 0)
++
++static const char *wm8731_input_select[] = {"Line In", "Mic"};
++static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
++
++static const struct soc_enum wm8731_enum[] = {
++	SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
++	SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
++};
++
++static const struct snd_kcontrol_new wm8731_snd_controls[] = {
++
++SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
++	0, 127, 0),
++SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
++	7, 1, 0),
++
++SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0),
++SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
++
++SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
++SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1),
++
++SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
++
++SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
++SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
++
++SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
++};
++
++/* add non dapm controls */
++static int wm8731_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
++		if ((err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Output Mixer */
++static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
++SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
++SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
++};
++
++/* Input mux */
++static const struct snd_kcontrol_new wm8731_input_mux_controls =
++SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
++
++static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
++SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
++	&wm8731_output_mixer_controls[0],
++	ARRAY_SIZE(wm8731_output_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1),
++SND_SOC_DAPM_OUTPUT("LOUT"),
++SND_SOC_DAPM_OUTPUT("LHPOUT"),
++SND_SOC_DAPM_OUTPUT("ROUT"),
++SND_SOC_DAPM_OUTPUT("RHPOUT"),
++SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1),
++SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls),
++SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0),
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1),
++SND_SOC_DAPM_INPUT("MICIN"),
++SND_SOC_DAPM_INPUT("RLINEIN"),
++SND_SOC_DAPM_INPUT("LLINEIN"),
++};
++
++static const char *intercon[][3] = {
++	/* output mixer */
++	{"Output Mixer", "Line Bypass Switch", "Line Input"},
++	{"Output Mixer", "HiFi Playback Switch", "DAC"},
++	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
++
++	/* outputs */
++	{"RHPOUT", NULL, "Output Mixer"},
++	{"ROUT", NULL, "Output Mixer"},
++	{"LHPOUT", NULL, "Output Mixer"},
++	{"LOUT", NULL, "Output Mixer"},
++
++	/* input mux */
++	{"Input Mux", "Line In", "Line Input"},
++	{"Input Mux", "Mic", "Mic Bias"},
++	{"ADC", NULL, "Input Mux"},
++
++	/* inputs */
++	{"Line Input", NULL, "LLINEIN"},
++	{"Line Input", NULL, "RLINEIN"},
++	{"Mic Bias", NULL, "MICIN"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8731_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
++	}
++
++	/* set up audio path interconnects */
++	for(i = 0; intercon[i][0] != NULL; i++) {
++		snd_soc_dapm_connect_input(codec, intercon[i][0],
++			intercon[i][1], intercon[i][2]);
++	}
++
++	snd_soc_dapm_new_widgets(codec);
++	return 0;
++}
++
++struct _coeff_div {
++	u32 mclk;
++	u32 rate;
++	u16 fs;
++	u8 sr:4;
++	u8 bosr:1;
++	u8 usb:1;
++};
++
++/* codec mclk clock divider coefficients */
++static const struct _coeff_div coeff_div[] = {
++	/* 48k */
++	{12288000, 48000, 256, 0x0, 0x0, 0x0},
++	{18432000, 48000, 384, 0x0, 0x1, 0x0},
++	{12000000, 48000, 250, 0x0, 0x0, 0x1},
++
++	/* 32k */
++	{12288000, 32000, 384, 0x6, 0x0, 0x0},
++	{18432000, 32000, 576, 0x6, 0x1, 0x0},
++
++	/* 8k */
++	{12288000, 8000, 1536, 0x3, 0x0, 0x0},
++	{18432000, 8000, 2304, 0x3, 0x1, 0x0},
++	{11289600, 8000, 1408, 0xb, 0x0, 0x0},
++	{16934400, 8000, 2112, 0xb, 0x1, 0x0},
++	{12000000, 8000, 1500, 0x3, 0x0, 0x1},
++
++	/* 96k */
++	{12288000, 96000, 128, 0x7, 0x0, 0x0},
++	{18432000, 96000, 192, 0x7, 0x1, 0x0},
++	{12000000, 96000, 125, 0x7, 0x0, 0x1},
++
++	/* 44.1k */
++	{11289600, 44100, 256, 0x8, 0x0, 0x0},
++	{16934400, 44100, 384, 0x8, 0x1, 0x0},
++	{12000000, 44100, 272, 0x8, 0x1, 0x1},
++
++	/* 88.2k */
++	{11289600, 88200, 128, 0xf, 0x0, 0x0},
++	{16934400, 88200, 192, 0xf, 0x1, 0x0},
++	{12000000, 88200, 136, 0xf, 0x1, 0x1},
++};
++
++static inline int get_coeff(int mclk, int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
++		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
++			return i;
++	}
++	return 0;
++}
++
++/* WM8731 supports numerous clocks per sample rate */
++static unsigned int wm8731_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	dai->mclk = 0;
++
++	/* check that the calculated FS and rate actually match a clock from
++	 * the machine driver */
++	if (info->fs * info->rate == clk)
++		dai->mclk = clk;
++
++	return dai->mclk;
++}
++
++static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 iface = 0, srate;
++	int i = get_coeff(rtd->codec_dai->mclk,
++		snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate));
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		iface |= 0x0040;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++	srate = (coeff_div[i].sr << 2) |
++		(coeff_div[i].bosr << 1) | coeff_div[i].usb;
++	wm8731_write(codec, WM8731_SRATE, srate);
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		iface |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x000c;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0010;
++		break;
++	}
++
++	/* set iface */
++	wm8731_write(codec, WM8731_IFACE, iface);
++
++	/* set active */
++	wm8731_write(codec, WM8731_ACTIVE, 0x0001);
++	return 0;
++}
++
++static void wm8731_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++
++	/* deactivate */
++	if (!codec->active) {
++		udelay(50);
++		wm8731_write(codec, WM8731_ACTIVE, 0x0);
++	}
++}
++
++static int wm8731_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
++	if (mute)
++		wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8);
++	else
++		wm8731_write(codec, WM8731_APDIGI, mute_reg);
++	return 0;
++}
++
++static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, osc on, dac unmute */
++		wm8731_write(codec, WM8731_PWR, reg);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, */
++		wm8731_write(codec, WM8731_PWR, reg | 0x0040);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8731_write(codec, WM8731_ACTIVE, 0x0);
++		wm8731_write(codec, WM8731_PWR, 0xffff);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8731_dai = {
++	.name = "WM8731",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8731_config_sysclk,
++	.digital_mute = wm8731_mute,
++	.ops = {
++		.prepare = wm8731_pcm_prepare,
++		.shutdown = wm8731_shutdown,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8731_modes),
++		.mode = wm8731_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8731_dai);
++
++static int wm8731_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;
++
++	wm8731_write(codec, WM8731_ACTIVE, 0x0);
++	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8731_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8731_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8731 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8731_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8731";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8731_read_reg_cache;
++	codec->write = wm8731_write;
++	codec->dapm_event = wm8731_dapm_event;
++	codec->dai = &wm8731_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8731_reg);
++
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8731_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache,
++		wm8731_reg, sizeof(u16) * ARRAY_SIZE(wm8731_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8731_reg);
++
++	wm8731_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* set the update bits */
++	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
++	wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
++	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
++	wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
++	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
++	wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
++	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
++	wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
++
++	wm8731_add_controls(codec);
++	wm8731_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 struct snd_soc_device *wm8731_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8731 2 wire address is determined by GPIO5
++ * state during powerup.
++ *    low  = 0x1a
++ *    high = 0x1b
++ */
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8731_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8731_socdev;
++	struct wm8731_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8731_init(socdev);
++	if (ret < 0) {
++		err("failed to initialise WM8731\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8731_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8731_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8731_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8731_i2c_driver = {
++	.driver = {
++		.name = "WM8731 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8731,
++	.attach_adapter = wm8731_i2c_attach,
++	.detach_client =  wm8731_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8731",
++	.driver = &wm8731_i2c_driver,
++};
++#endif
++
++static int wm8731_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8731_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8731 Audio Codec %s", WM8731_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);
++
++	wm8731_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8731_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8731_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)
++		wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8731_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8731 = {
++	.probe = 	wm8731_probe,
++	.remove = 	wm8731_remove,
++	.suspend = 	wm8731_suspend,
++	.resume =	wm8731_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
++
++MODULE_DESCRIPTION("ASoC WM8731 driver");
++MODULE_AUTHOR("Richard Purdie");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8731.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8731.h
+@@ -0,0 +1,41 @@
++/*
++ * wm8731.h  --  WM8731 Soc Audio driver
++ *
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on wm8753.h
++ *
++ * 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 _WM8731_H
++#define _WM8731_H
++
++/* WM8731 register space */
++
++#define WM8731_LINVOL   0x00
++#define WM8731_RINVOL   0x01
++#define WM8731_LOUT1V   0x02
++#define WM8731_ROUT1V   0x03
++#define WM8731_APANA    0x04
++#define WM8731_APDIGI   0x05
++#define WM8731_PWR      0x06
++#define WM8731_IFACE    0x07
++#define WM8731_SRATE    0x08
++#define WM8731_ACTIVE   0x09
++#define WM8731_RESET	0x0f
++
++#define WM8731_CACHEREGNUM 	10
++
++struct wm8731_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8731_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8731;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8750.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8750.c
+@@ -0,0 +1,1282 @@
++/*
++ * wm8750.c -- WM8750 ALSA SoC audio driver
++ *
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on WM8753.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.
++ */
++
++#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/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 "wm8750.h"
++
++#define AUDIO_NAME "WM8750"
++#define WM8750_VERSION "0.11"
++
++/*
++ * Debug
++ */
++
++#define WM8750_DEBUG 0
++
++#ifdef WM8750_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++static struct workqueue_struct *wm8750_workq = NULL;
++static struct work_struct wm8750_dapm_work;
++
++/*
++ * wm8750 register cache
++ * We can't read the WM8750 register space when we
++ * are using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8750_reg[] = {
++	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
++	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
++	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
++	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
++	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
++	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
++	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
++	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
++	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
++	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
++	0x0079, 0x0079, 0x0079,          /* 40 */
++};
++
++#define WM8750_HIFI_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8750_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8750_HIFI_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++#define WM8750_HIFI_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++#define WM8750_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8750_modes[] = {
++	/* common codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1408,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2304,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2112,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 11.025k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1024,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1088,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 16k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1152,
++		.bfs = WM8750_HIFI_FSB
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 750,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 22.05k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 512,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 544,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 32k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 576,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 375,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 44.1k & 48k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* 88.2k & 96k */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 128,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 192,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 136,
++		.bfs = WM8750_HIFI_FSB,
++	},
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 125,
++		.bfs = WM8750_HIFI_FSB,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8750_HIFI_BITS,
++		.pcmrate = WM8750_HIFI_RATES,
++		.pcmdir = WM8750_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8750 register cache
++ */
++static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg > WM8750_CACHE_REGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8750 register cache
++ */
++static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg > WM8750_CACHE_REGNUM)
++		return;
++	cache[reg] = value;
++}
++
++static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8753 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8750_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8750_reset(c)	wm8750_write(c, WM8750_RESET, 0)
++
++/*
++ * WM8750 Controls
++ */
++static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
++static const char *wm8750_treble[] = {"8kHz", "4kHz"};
++static const char *wm8750_3d_lc[] = {"200Hz", "500Hz"};
++static const char *wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"};
++static const char *wm8750_3d_func[] = {"Capture", "Playback"};
++static const char *wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"};
++static const char *wm8750_ng_type[] = {"Constant PGA Gain",
++	"Mute ADC Output"};
++static const char *wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA",
++	"Differential"};
++static const char *wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3",
++	"Differential"};
++static const char *wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut",
++	"ROUT1"};
++static const char *wm8750_diff_sel[] = {"Line 1", "Line 2"};
++static const char *wm8750_adcpol[] = {"Normal", "L Invert", "R Invert",
++	"L + R Invert"};
++static const char *wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
++static const char *wm8750_mono_mux[] = {"Stereo", "Mono (Left)",
++	"Mono (Right)", "Digital Mono"};
++
++static const struct soc_enum wm8750_enum[] = {
++SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass),
++SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter),
++SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble),
++SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc),
++SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc),
++SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func),
++SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func),
++SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type),
++SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux),
++SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux),
++SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */
++SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel),
++SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3),
++SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel),
++SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol),
++SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph),
++SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
++
++};
++
++static const struct snd_kcontrol_new wm8750_snd_controls[] = {
++
++SOC_DOUBLE_R("Capture Volume", WM8750_LINVOL, WM8750_RINVOL, 0, 63, 0),
++SOC_DOUBLE_R("Capture ZC Switch", WM8750_LINVOL, WM8750_RINVOL, 6, 1, 0),
++SOC_DOUBLE_R("Capture Switch", WM8750_LINVOL, WM8750_RINVOL, 7, 1, 1),
++
++SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8750_LOUT1V,
++	WM8750_ROUT1V, 7, 1, 0),
++SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8750_LOUT2V,
++	WM8750_ROUT2V, 7, 1, 0),
++
++SOC_ENUM("Playback De-emphasis", wm8750_enum[15]),
++
++SOC_ENUM("Capture Polarity", wm8750_enum[14]),
++SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
++SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
++
++SOC_DOUBLE_R("PCM Volume", WM8750_LDAC, WM8750_RDAC, 0, 255, 0),
++
++SOC_ENUM("Bass Boost", wm8750_enum[0]),
++SOC_ENUM("Bass Filter", wm8750_enum[1]),
++SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
++
++SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 0),
++SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
++
++SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
++SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0),
++SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]),
++SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
++SOC_ENUM("3D Mode", wm8750_enum[5]),
++
++SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0),
++SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0),
++SOC_ENUM("ALC Capture Function", wm8750_enum[6]),
++SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0),
++SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0),
++SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0),
++SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0),
++SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0),
++SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]),
++SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0),
++
++SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0),
++SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0),
++
++SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0),
++SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
++
++SOC_SINGLE("Right Speaker Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
++
++/* Unimplemented */
++/* ADCDAC Bit 0 - ADCHPD */
++/* ADCDAC Bit 4 - HPOR */
++/* ADCTL1 Bit 2,3 - DATSEL */
++/* ADCTL1 Bit 4,5 - DMONOMIX */
++/* ADCTL1 Bit 6,7 - VSEL */
++/* ADCTL2 Bit 2 - LRCM */
++/* ADCTL2 Bit 3 - TRI */
++/* ADCTL3 Bit 5 - HPFLREN */
++/* ADCTL3 Bit 6 - VROI */
++/* ADCTL3 Bit 7,8 - ADCLRM */
++/* ADCIN Bit 4 - LDCM */
++/* ADCIN Bit 5 - RDCM */
++
++SOC_DOUBLE_R("Mic Boost", WM8750_LADCIN, WM8750_RADCIN, 4, 3, 0),
++
++SOC_DOUBLE_R("Bypass Left Playback Volume", WM8750_LOUTM1,
++	WM8750_LOUTM2, 4, 7, 1),
++SOC_DOUBLE_R("Bypass Right Playback Volume", WM8750_ROUTM1,
++	WM8750_ROUTM2, 4, 7, 1),
++SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8750_MOUTM1,
++	WM8750_MOUTM2, 4, 7, 1),
++
++SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
++
++SOC_DOUBLE_R("Headphone Playback Volume", WM8750_LOUT1V, WM8750_ROUT1V,
++	0, 127, 0),
++SOC_DOUBLE_R("Speaker Playback Volume", WM8750_LOUT2V, WM8750_ROUT2V,
++	0, 127, 0),
++
++SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
++
++};
++
++/* add non dapm controls */
++static int wm8750_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/*
++ * DAPM Controls
++ */
++
++/* Left Mixer */
++static const struct snd_kcontrol_new wm8750_left_mixer_controls[] = {
++SOC_DAPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0),
++};
++
++/* Right Mixer */
++static const struct snd_kcontrol_new wm8750_right_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0),
++};
++
++/* Mono Mixer */
++static const struct snd_kcontrol_new wm8750_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0),
++};
++
++/* Left Line Mux */
++static const struct snd_kcontrol_new wm8750_left_line_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[8]);
++
++/* Right Line Mux */
++static const struct snd_kcontrol_new wm8750_right_line_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[9]);
++
++/* Left PGA Mux */
++static const struct snd_kcontrol_new wm8750_left_pga_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[10]);
++
++/* Right PGA Mux */
++static const struct snd_kcontrol_new wm8750_right_pga_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[11]);
++
++/* Out 3 Mux */
++static const struct snd_kcontrol_new wm8750_out3_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[12]);
++
++/* Differential Mux */
++static const struct snd_kcontrol_new wm8750_diffmux_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[13]);
++
++/* Mono ADC Mux */
++static const struct snd_kcontrol_new wm8750_monomux_controls =
++SOC_DAPM_ENUM("Route", wm8750_enum[16]);
++
++static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
++	SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
++		&wm8750_left_mixer_controls[0],
++		ARRAY_SIZE(wm8750_left_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
++		&wm8750_right_mixer_controls[0],
++		ARRAY_SIZE(wm8750_right_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0,
++		&wm8750_mono_mixer_controls[0],
++		ARRAY_SIZE(wm8750_mono_mixer_controls)),
++
++	SND_SOC_DAPM_PGA("Right Out 2", WM8750_PWR2, 3, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Left Out 2", WM8750_PWR2, 4, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Right Out 1", WM8750_PWR2, 5, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Left Out 1", WM8750_PWR2, 6, 0, NULL, 0),
++	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0),
++	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0),
++
++	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8750_PWR1, 1, 0),
++	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0),
++	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0),
++
++	SND_SOC_DAPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0,
++		&wm8750_left_pga_controls),
++	SND_SOC_DAPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0,
++		&wm8750_right_pga_controls),
++	SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
++		&wm8750_left_line_controls),
++	SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
++		&wm8750_right_line_controls),
++
++	SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8750_out3_controls),
++	SND_SOC_DAPM_PGA("Out 3", WM8750_PWR2, 1, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Mono Out 1", WM8750_PWR2, 2, 0, NULL, 0),
++
++	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
++		&wm8750_diffmux_controls),
++	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
++		&wm8750_monomux_controls),
++	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
++		&wm8750_monomux_controls),
++
++	SND_SOC_DAPM_OUTPUT("LOUT1"),
++	SND_SOC_DAPM_OUTPUT("ROUT1"),
++	SND_SOC_DAPM_OUTPUT("LOUT2"),
++	SND_SOC_DAPM_OUTPUT("ROUT2"),
++	SND_SOC_DAPM_OUTPUT("MONO"),
++	SND_SOC_DAPM_OUTPUT("OUT3"),
++
++	SND_SOC_DAPM_INPUT("LINPUT1"),
++	SND_SOC_DAPM_INPUT("LINPUT2"),
++	SND_SOC_DAPM_INPUT("LINPUT3"),
++	SND_SOC_DAPM_INPUT("RINPUT1"),
++	SND_SOC_DAPM_INPUT("RINPUT2"),
++	SND_SOC_DAPM_INPUT("RINPUT3"),
++};
++
++static const char *audio_map[][3] = {
++	/* left mixer */
++	{"Left Mixer", "Playback Switch", "Left DAC"},
++	{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Left Mixer", "Right Playback Switch", "Right DAC"},
++	{"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* right mixer */
++	{"Right Mixer", "Left Playback Switch", "Left DAC"},
++	{"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Right Mixer", "Playback Switch", "Right DAC"},
++	{"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* left out 1 */
++	{"Left Out 1", NULL, "Left Mixer"},
++	{"LOUT1", NULL, "Left Out 1"},
++
++	/* left out 2 */
++	{"Left Out 2", NULL, "Left Mixer"},
++	{"LOUT2", NULL, "Left Out 2"},
++
++	/* right out 1 */
++	{"Right Out 1", NULL, "Right Mixer"},
++	{"ROUT1", NULL, "Right Out 1"},
++
++	/* right out 2 */
++	{"Right Out 2", NULL, "Right Mixer"},
++	{"ROUT2", NULL, "Right Out 2"},
++
++	/* mono mixer */
++	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
++	{"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
++	{"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* mono out */
++	{"Mono Out 1", NULL, "Mono Mixer"},
++	{"MONO1", NULL, "Mono Out 1"},
++
++	/* out 3 */
++	{"Out3 Mux", "VREF", "VREF"},
++	{"Out3 Mux", "ROUT1 + Vol", "ROUT1"},
++	{"Out3 Mux", "ROUT1", "Right Mixer"},
++	{"Out3 Mux", "MonoOut", "MONO1"},
++	{"Out 3", NULL, "Out3 Mux"},
++	{"OUT3", NULL, "Out 3"},
++
++	/* Left Line Mux */
++	{"Left Line Mux", "Line 1", "LINPUT1"},
++	{"Left Line Mux", "Line 2", "LINPUT2"},
++	{"Left Line Mux", "Line 3", "LINPUT3"},
++	{"Left Line Mux", "PGA", "Left PGA Mux"},
++	{"Left Line Mux", "Differential", "Differential Mux"},
++
++	/* Right Line Mux */
++	{"Right Line Mux", "Line 1", "RINPUT1"},
++	{"Right Line Mux", "Line 2", "RINPUT2"},
++	{"Right Line Mux", "Line 3", "RINPUT3"},
++	{"Right Line Mux", "PGA", "Right PGA Mux"},
++	{"Right Line Mux", "Differential", "Differential Mux"},
++
++	/* Left PGA Mux */
++	{"Left PGA Mux", "Line 1", "LINPUT1"},
++	{"Left PGA Mux", "Line 2", "LINPUT2"},
++	{"Left PGA Mux", "Line 3", "LINPUT3"},
++	{"Left PGA Mux", "Differential", "Differential Mux"},
++
++	/* Right PGA Mux */
++	{"Right PGA Mux", "Line 1", "RINPUT1"},
++	{"Right PGA Mux", "Line 2", "RINPUT2"},
++	{"Right PGA Mux", "Line 3", "RINPUT3"},
++	{"Right PGA Mux", "Differential", "Differential Mux"},
++
++	/* Differential Mux */
++	{"Differential Mux", "Line 1", "LINPUT1"},
++	{"Differential Mux", "Line 1", "RINPUT1"},
++	{"Differential Mux", "Line 2", "LINPUT2"},
++	{"Differential Mux", "Line 2", "RINPUT2"},
++
++	/* Left ADC Mux */
++	{"Left ADC Mux", "Stereo", "Left PGA Mux"},
++	{"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
++	{"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
++
++	/* Right ADC Mux */
++	{"Right ADC Mux", "Stereo", "Right PGA Mux"},
++	{"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
++	{"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
++
++	/* ADC */
++	{"Left ADC", NULL, "Left ADC Mux"},
++	{"Right ADC", NULL, "Right ADC Mux"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8750_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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;
++}
++
++struct _coeff_div {
++	u32 mclk;
++	u32 rate;
++	u16 fs;
++	u8 sr:5;
++	u8 usb:1;
++};
++
++/* codec hifi mclk clock divider coefficients */
++static const struct _coeff_div coeff_div[] = {
++	/* 8k */
++	{12288000, 8000, 1536, 0x6, 0x0},
++	{11289600, 8000, 1408, 0x16, 0x0},
++	{18432000, 8000, 2304, 0x7, 0x0},
++	{16934400, 8000, 2112, 0x17, 0x0},
++	{12000000, 8000, 1500, 0x6, 0x1},
++
++	/* 11.025k */
++	{11289600, 11025, 1024, 0x18, 0x0},
++	{16934400, 11025, 1536, 0x19, 0x0},
++	{12000000, 11025, 1088, 0x19, 0x1},
++
++	/* 16k */
++	{12288000, 16000, 768, 0xa, 0x0},
++	{18432000, 16000, 1152, 0xb, 0x0},
++	{12000000, 16000, 750, 0xa, 0x1},
++
++	/* 22.05k */
++	{11289600, 22050, 512, 0x1a, 0x0},
++	{16934400, 22050, 768, 0x1b, 0x0},
++	{12000000, 22050, 544, 0x1b, 0x1},
++
++	/* 32k */
++	{12288000, 32000, 384, 0xc, 0x0},
++	{18432000, 32000, 576, 0xd, 0x0},
++	{12000000, 32000, 375, 0xa, 0x1},
++
++	/* 44.1k */
++	{11289600, 44100, 256, 0x10, 0x0},
++	{16934400, 44100, 384, 0x11, 0x0},
++	{12000000, 44100, 272, 0x11, 0x1},
++
++	/* 48k */
++	{12288000, 48000, 256, 0x0, 0x0},
++	{18432000, 48000, 384, 0x1, 0x0},
++	{12000000, 48000, 250, 0x0, 0x1},
++
++	/* 88.2k */
++	{11289600, 88200, 128, 0x1e, 0x0},
++	{16934400, 88200, 192, 0x1f, 0x0},
++	{12000000, 88200, 136, 0x1f, 0x1},
++
++	/* 96k */
++	{12288000, 96000, 128, 0xe, 0x0},
++	{18432000, 96000, 192, 0xf, 0x0},
++	{12000000, 96000, 125, 0xe, 0x1},
++};
++
++static inline int get_coeff(int mclk, int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
++		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
++			return i;
++	}
++
++	printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
++		mclk, rate);
++	return -EINVAL;
++}
++
++/* WM8750 supports numerous input clocks per sample rate */
++static unsigned int wm8750_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	dai->mclk = clk;
++	return dai->mclk;
++}
++
++static int wm8750_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 iface = 0, bfs, srate = 0;
++	int i = get_coeff(rtd->codec_dai->mclk,
++		snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate));
++
++	/* is coefficient valid ? */
++	if (i < 0)
++		return i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		iface = 0x0040;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		iface |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x000c;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0010;
++		break;
++	}
++
++	/* set bclk divisor rate */
++	switch (bfs) {
++	case 1:
++		break;
++	case 4:
++		srate |= (0x1 << 7);
++		break;
++	case 8:
++		srate |= (0x2 << 7);
++		break;
++	case 16:
++		srate |= (0x3 << 7);
++		break;
++	}
++
++	/* set iface & srate */
++	wm8750_write(codec, WM8750_IFACE, iface);
++	wm8750_write(codec, WM8750_SRATE, srate |
++		(coeff_div[i].sr << 1) | coeff_div[i].usb);
++
++	return 0;
++}
++
++static int wm8750_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
++	if (mute)
++		wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
++	else
++		wm8750_write(codec, WM8750_ADCDAC, mute_reg);
++	return 0;
++}
++
++static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* set vmid to 50k and unmute dac */
++		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		/* set vmid to 5k for quick power up */
++		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* mute dac and set vmid to 500k, enable VREF */
++		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		wm8750_write(codec, WM8750_PWR1, 0x0001);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8750_dai = {
++	.name = "WM8750",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8750_config_sysclk,
++	.digital_mute = wm8750_mute,
++	.ops = {
++		.prepare = wm8750_pcm_prepare,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8750_modes),
++		.mode = wm8750_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8750_dai);
++
++static void wm8750_work(void *data)
++{
++	struct snd_soc_codec *codec = (struct snd_soc_codec *)data;
++	wm8750_dapm_event(codec, codec->dapm_state);
++}
++
++static int wm8750_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;
++
++	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8750_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
++		if (i == WM8750_RESET)
++			continue;
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++
++	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* charge wm8750 caps */
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
++		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
++		codec->dapm_state = SNDRV_CTL_POWER_D0;
++		queue_delayed_work(wm8750_workq, &wm8750_dapm_work,
++			 msecs_to_jiffies(1000));
++	}
++
++	return 0;
++}
++
++/*
++ * initialise the WM8750 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8750_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8750";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8750_read_reg_cache;
++	codec->write = wm8750_write;
++	codec->dapm_event = wm8750_dapm_event;
++	codec->dai = &wm8750_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8750_reg);
++
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8750_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8750_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8750_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8750_reg);
++
++	wm8750_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* charge output caps */
++	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
++	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
++	queue_delayed_work(wm8750_workq, &wm8750_dapm_work,
++		msecs_to_jiffies(1000));
++
++	/* set the update bits */
++	reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
++	wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_RDAC);
++	wm8750_write(codec, WM8750_RDAC, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V);
++	wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V);
++	wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V);
++	wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V);
++	wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_LINVOL);
++	wm8750_write(codec, WM8750_LINVOL, reg | 0x0100);
++	reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
++	wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
++
++	wm8750_add_controls(codec);
++	wm8750_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0) {
++		snd_soc_free_pcms(socdev);
++		snd_soc_dapm_free(socdev);
++	}
++
++	return ret;
++}
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++static struct snd_soc_device *wm8750_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8731 2 wire address is determined by GPIO5
++ * state during powerup.
++ *    low  = 0x1a
++ *    high = 0x1b
++ */
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8750_i2c_driver;
++static struct i2c_client client_template;
++
++static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8750_socdev;
++	struct wm8750_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8750_init(socdev);
++	if (ret < 0) {
++	err("failed to initialise WM8750\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8750_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8750_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8750_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8750_i2c_driver = {
++	.driver = {
++		.name = "WM8750 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8750,
++	.attach_adapter = wm8750_i2c_attach,
++	.detach_client =  wm8750_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8750",
++	.driver = &wm8750_i2c_driver,
++};
++#endif
++
++static int wm8750_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8750_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8750 Audio Codec %s", WM8750_VERSION);
++	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);
++	wm8750_socdev = socdev;
++	INIT_WORK(&wm8750_dapm_work, wm8750_work, codec);
++	wm8750_workq = create_workqueue("wm8750");
++	if (wm8750_workq == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8750_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++		/* Add other interfaces here */
++#endif
++
++	return ret;
++}
++
++/* power down chip */
++static int wm8750_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)
++		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	if (wm8750_workq)
++		destroy_workqueue(wm8750_workq);
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8750_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8750 = {
++	.probe = 	wm8750_probe,
++	.remove = 	wm8750_remove,
++	.suspend = 	wm8750_suspend,
++	.resume =	wm8750_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
++
++MODULE_DESCRIPTION("ASoC WM8750 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8750.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8750.h
+@@ -0,0 +1,66 @@
++/*
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Author: Richard Purdie <richard at openedhand.com>
++ *
++ * Based on WM8753.h
++ *
++ * 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 _WM8750_H
++#define _WM8750_H
++
++/* WM8750 register space */
++
++#define WM8750_LINVOL    0x00
++#define WM8750_RINVOL    0x01
++#define WM8750_LOUT1V    0x02
++#define WM8750_ROUT1V    0x03
++#define WM8750_ADCDAC    0x05
++#define WM8750_IFACE     0x07
++#define WM8750_SRATE     0x08
++#define WM8750_LDAC      0x0a
++#define WM8750_RDAC      0x0b
++#define WM8750_BASS      0x0c
++#define WM8750_TREBLE    0x0d
++#define WM8750_RESET     0x0f
++#define WM8750_3D        0x10
++#define WM8750_ALC1      0x11
++#define WM8750_ALC2      0x12
++#define WM8750_ALC3      0x13
++#define WM8750_NGATE     0x14
++#define WM8750_LADC      0x15
++#define WM8750_RADC      0x16
++#define WM8750_ADCTL1    0x17
++#define WM8750_ADCTL2    0x18
++#define WM8750_PWR1      0x19
++#define WM8750_PWR2      0x1a
++#define WM8750_ADCTL3    0x1b
++#define WM8750_ADCIN     0x1f
++#define WM8750_LADCIN    0x20
++#define WM8750_RADCIN    0x21
++#define WM8750_LOUTM1    0x22
++#define WM8750_LOUTM2    0x23
++#define WM8750_ROUTM1    0x24
++#define WM8750_ROUTM2    0x25
++#define WM8750_MOUTM1    0x26
++#define WM8750_MOUTM2    0x27
++#define WM8750_LOUT2V    0x28
++#define WM8750_ROUT2V    0x29
++#define WM8750_MOUTV     0x2a
++
++#define WM8750_CACHE_REGNUM 0x2a
++
++struct wm8750_setup_data {
++	unsigned short i2c_address;
++	unsigned int mclk;
++};
++
++extern struct snd_soc_codec_dai wm8750_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8750;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8753.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8753.c
+@@ -0,0 +1,2128 @@
++/*
++ * wm8753.c  --  WM8753 ALSA Soc Audio driver
++ *
++ * Copyright 2003 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ * Notes:
++ *  The WM8753 is a low power, high quality stereo codec with integrated PCM
++ *  codec designed for portable digital telephony applications.
++ *
++ * Dual DAI:-
++ *
++ * This driver support 2 DAI PCM's. This makes the default PCM available for
++ * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for
++ * voice.
++ *
++ * Please note that the voice PCM can be connected directly to a Bluetooth
++ * codec or GSM modem and thus cannot be read or written to, although it is
++ * available to be configured with snd_hw_params(), etc and kcontrols in the
++ * normal alsa manner.
++ *
++ * Fast DAI switching:-
++ *
++ * The driver can now fast switch between the DAI configurations via a
++ * an alsa kcontrol. This allows the PCM to remain open.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8753.h"
++
++#define AUDIO_NAME "wm8753"
++#define WM8753_VERSION "0.16"
++
++/*
++ * Debug
++ */
++
++#define WM8753_DEBUG 0
++
++#ifdef WM8753_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++static int caps_charge = 2000;
++module_param(caps_charge, int, 0);
++MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
++
++static struct workqueue_struct *wm8753_workq = NULL;
++static struct work_struct wm8753_dapm_work;
++static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
++	unsigned int mode);
++
++/*
++ * wm8753 register cache
++ * We can't read the WM8753 register space when we
++ * are using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8753_reg[] = {
++	0x0008, 0x0000, 0x000a, 0x000a,
++	0x0033, 0x0000, 0x0007, 0x00ff,
++	0x00ff, 0x000f, 0x000f, 0x007b,
++	0x0000, 0x0032, 0x0000, 0x00c3,
++	0x00c3, 0x00c0, 0x0000, 0x0000,
++	0x0000, 0x0000, 0x0000, 0x0000,
++	0x0000, 0x0000, 0x0000, 0x0000,
++	0x0000, 0x0000, 0x0000, 0x0055,
++	0x0005, 0x0050, 0x0055, 0x0050,
++	0x0055, 0x0050, 0x0055, 0x0079,
++	0x0079, 0x0079, 0x0079, 0x0079,
++	0x0000, 0x0000, 0x0000, 0x0000,
++	0x0097, 0x0097, 0x0000, 0x0004,
++	0x0000, 0x0083, 0x0024, 0x01ba,
++	0x0000, 0x0083, 0x0024, 0x01ba,
++	0x0000, 0x0000
++};
++
++#define WM8753_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_DSP_B |  SND_SOC_DAIFMT_NB_NF | \
++	SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_IB_IF)
++
++#define WM8753_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8753_HIFI_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++#define WM8753_HIFI_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++#define WM8753_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++/*
++ * HiFi modes
++ */
++static struct snd_soc_dai_mode wm8753_hifi_modes[] = {
++	/* codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1408,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2304,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2112,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* 11.025k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1024,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1088,
++		.bfs = WM8753_HIFI_FSB,
++		},
++
++	/* 16k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt= WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1152,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 750,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* 22.05k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 512,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 544,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* 32k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 576,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 375,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* 44.1k & 48k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* 88.2k & 96k */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 128,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 192,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 136,
++		.bfs = WM8753_HIFI_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 125,
++		.bfs = WM8753_HIFI_FSB,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = WM8753_HIFI_RATES,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++#define WM8753_VOICE_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++#define WM8753_VOICE_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)
++
++#define WM8753_VOICE_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++/*
++ * Voice modes
++ */
++static struct snd_soc_dai_mode wm8753_voice_modes[] = {
++
++	/* master modes */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_VOICE_BITS,
++		.pcmrate = WM8753_VOICE_RATES,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8753_VOICE_FSB,
++	},
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = WM8753_VOICE_BITS,
++		.pcmrate = WM8753_VOICE_RATES,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8753_VOICE_FSB,
++	},
++
++	/* slave modes */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8753_VOICE_BITS,
++		.pcmrate = WM8753_VOICE_RATES,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++
++/*
++ * Mode 4
++ */
++static struct snd_soc_dai_mode wm8753_mixed_modes[] = {
++	/* slave modes */
++	{
++		.fmt = WM8753_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8753_HIFI_BITS,
++		.pcmrate = WM8753_HIFI_RATES,
++		.pcmdir = WM8753_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8753 register cache
++ */
++static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
++		return -1;
++	return cache[reg - 1];
++}
++
++/*
++ * write wm8753 register cache
++ */
++static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < 1 || reg > 0x3f)
++		return;
++	cache[reg - 1] = value;
++}
++
++/*
++ * write to the WM8753 register space
++ */
++static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8753 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8753_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
++
++/*
++ * WM8753 Controls
++ */
++static const char *wm8753_base[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm8753_base_filter[] =
++	{"130Hz @ 48kHz", "200Hz @ 48kHz", "100Hz @ 16kHz", "400Hz @ 48kHz",
++	"100Hz @ 8kHz", "200Hz @ 8kHz"};
++static const char *wm8753_treble[] = {"8kHz", "4kHz"};
++static const char *wm8753_alc_func[] = {"Off", "Right", "Left", "Stereo"};
++static const char *wm8753_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"};
++static const char *wm8753_3d_func[] = {"Capture", "Playback"};
++static const char *wm8753_3d_uc[] = {"2.2kHz", "1.5kHz"};
++static const char *wm8753_3d_lc[] = {"200Hz", "500Hz"};
++static const char *wm8753_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz"};
++static const char *wm8753_mono_mix[] = {"Stereo", "Left", "Right", "Mono"};
++static const char *wm8753_dac_phase[] = {"Non Inverted", "Inverted"};
++static const char *wm8753_line_mix[] = {"Line 1 + 2", "Line 1 - 2",
++	"Line 1", "Line 2"};
++static const char *wm8753_mono_mux[] = {"Line Mix", "Rx Mix"};
++static const char *wm8753_right_mux[] = {"Line 2", "Rx Mix"};
++static const char *wm8753_left_mux[] = {"Line 1", "Rx Mix"};
++static const char *wm8753_rxmsel[] = {"RXP - RXN", "RXP + RXN", "RXP", "RXN"};
++static const char *wm8753_sidetone_mux[] = {"Left PGA", "Mic 1", "Mic 2",
++	"Right PGA"};
++static const char *wm8753_mono2_src[] = {"Inverted Mono 1", "Left", "Right",
++	"Left + Right"};
++static const char *wm8753_out3[] = {"VREF", "ROUT2", "Left + Right"};
++static const char *wm8753_out4[] = {"VREF", "Capture ST", "LOUT2"};
++static const char *wm8753_radcsel[] = {"PGA", "Line or RXP-RXN", "Sidetone"};
++static const char *wm8753_ladcsel[] = {"PGA", "Line or RXP-RXN", "Line"};
++static const char *wm8753_mono_adc[] = {"Stereo", "Analogue Mix Left",
++	"Analogue Mix Right", "Digital Mono Mix"};
++static const char *wm8753_adc_hp[] = {"3.4Hz @ 48kHz", "82Hz @ 16k",
++	"82Hz @ 8kHz", "170Hz @ 8kHz"};
++static const char *wm8753_adc_filter[] = {"HiFi", "Voice"};
++static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
++static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
++
++static const struct soc_enum wm8753_enum[] = {
++SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),		// 0
++SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter),	// 1
++SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble), 	// 2
++SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func),	// 3
++SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type),	// 4
++SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func),		// 5
++SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc),			// 6
++SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc),			// 7
++SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp),		// 8
++SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix),		// 9
++SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase),	// 10
++SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix),	// 11
++SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux),	// 12
++SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux),	// 13
++SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux),	// 14
++SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel),	// 15
++SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux),// 16
++SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src),	// 17
++SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3),		// 18
++SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4),		// 19
++SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel),	// 20
++SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel),	// 21
++SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc),	// 22
++SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp),		// 23
++SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),	// 24
++SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),	// 25
++SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode), // 26
++};
++
++
++static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
++
++	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
++	return 0;
++}
++
++static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
++
++	if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0])
++		return 0;
++
++	mode &= 0xfff3;
++	mode |= (ucontrol->value.integer.value[0] << 2);
++
++	wm8753_write(codec, WM8753_IOCTL, mode);
++	wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
++	return 1;
++}
++
++static const struct snd_kcontrol_new wm8753_snd_controls[] = {
++SOC_DOUBLE_R("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0),
++
++SOC_DOUBLE_R("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 63, 0),
++SOC_DOUBLE_R("ADC Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 0),
++SOC_DOUBLE_R("ADC Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
++
++SOC_DOUBLE_R("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, 0, 127, 0),
++SOC_DOUBLE_R("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, 127, 0),
++
++SOC_SINGLE("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0),
++
++SOC_DOUBLE_R("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, 1),
++SOC_DOUBLE_R("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, 7, 1),
++SOC_DOUBLE_R("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, 1),
++
++SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, 1, 0),
++SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0),
++
++SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
++SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
++SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
++SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
++
++SOC_ENUM("Bass Boost", wm8753_enum[0]),
++SOC_ENUM("Bass Filter", wm8753_enum[1]),
++SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 7, 1),
++
++SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 7, 0),
++SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
++
++SOC_DOUBLE("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1),
++SOC_SINGLE("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1),
++
++SOC_DOUBLE_R("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0),
++SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
++SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 0),
++
++SOC_ENUM("Capture Filter Select", wm8753_enum[23]),
++SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]),
++SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1),
++
++SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0),
++SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0),
++SOC_ENUM("ALC Capture Function", wm8753_enum[3]),
++SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0),
++SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1),
++SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1),
++SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0),
++SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0),
++SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]),
++SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0),
++
++SOC_ENUM("3D Function", wm8753_enum[5]),
++SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]),
++SOC_ENUM("3D Lower Cut-off", wm8753_enum[7]),
++SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0),
++SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0),
++
++SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0),
++SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0),
++
++SOC_ENUM("De-emphasis", wm8753_enum[8]),
++SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
++SOC_ENUM("Playback Phase", wm8753_enum[10]),
++
++SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0),
++SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
++
++SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
++};
++
++/* add non dapm controls */
++static int wm8753_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/*
++ * _DAPM_ Controls
++ */
++
++/* Left Mixer */
++static const struct snd_kcontrol_new wm8753_left_mixer_controls[] = {
++SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0),
++SOC_DAPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0),
++};
++
++/* Right mixer */
++static const struct snd_kcontrol_new wm8753_right_mixer_controls[] = {
++SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0),
++};
++
++/* Mono mixer */
++static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 3, 1, 0),
++SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_MOUTM1, 7, 1, 0),
++};
++
++/* Mono 2 Mux */
++static const struct snd_kcontrol_new wm8753_mono2_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[17]);
++
++/* Out 3 Mux */
++static const struct snd_kcontrol_new wm8753_out3_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[18]);
++
++/* Out 4 Mux */
++static const struct snd_kcontrol_new wm8753_out4_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[19]);
++
++/* ADC Mono Mix */
++static const struct snd_kcontrol_new wm8753_adc_mono_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[22]);
++
++/* Record mixer */
++static const struct snd_kcontrol_new wm8753_record_mixer_controls[] = {
++SOC_DAPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0),
++SOC_DAPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0),
++SOC_DAPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0),
++};
++
++/* Left ADC mux */
++static const struct snd_kcontrol_new wm8753_adc_left_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[21]);
++
++/* Right ADC mux */
++static const struct snd_kcontrol_new wm8753_adc_right_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[20]);
++
++/* MIC mux */
++static const struct snd_kcontrol_new wm8753_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[16]);
++
++/* ALC mixer */
++static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0),
++SOC_DAPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0),
++SOC_DAPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0),
++SOC_DAPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0),
++};
++
++/* Left Line mux */
++static const struct snd_kcontrol_new wm8753_line_left_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[14]);
++
++/* Right Line mux */
++static const struct snd_kcontrol_new wm8753_line_right_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[13]);
++
++/* Mono Line mux */
++static const struct snd_kcontrol_new wm8753_line_mono_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[12]);
++
++/* Line mux and mixer */
++static const struct snd_kcontrol_new wm8753_line_mux_mix_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[11]);
++
++/* Rx mux and mixer */
++static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[15]);
++
++/* Mic Selector Mux */
++static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm8753_enum[25]);
++
++static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8753_PWR1, 5, 0),
++SND_SOC_DAPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0,
++	&wm8753_left_mixer_controls[0], ARRAY_SIZE(wm8753_left_mixer_controls)),
++SND_SOC_DAPM_PGA("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Left Out 2", WM8753_PWR3, 6, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", WM8753_PWR1, 3, 0),
++SND_SOC_DAPM_OUTPUT("LOUT1"),
++SND_SOC_DAPM_OUTPUT("LOUT2"),
++SND_SOC_DAPM_MIXER("Right Mixer", WM8753_PWR4, 1, 0,
++	&wm8753_right_mixer_controls[0], ARRAY_SIZE(wm8753_right_mixer_controls)),
++SND_SOC_DAPM_PGA("Right Out 1", WM8753_PWR3, 7, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Right Out 2", WM8753_PWR3, 5, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", WM8753_PWR1, 2, 0),
++SND_SOC_DAPM_OUTPUT("ROUT1"),
++SND_SOC_DAPM_OUTPUT("ROUT2"),
++SND_SOC_DAPM_MIXER("Mono Mixer", WM8753_PWR4, 2, 0,
++	&wm8753_mono_mixer_controls[0], ARRAY_SIZE(wm8753_mono_mixer_controls)),
++SND_SOC_DAPM_PGA("Mono Out 1", WM8753_PWR3, 2, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out 2", WM8753_PWR3, 1, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", WM8753_PWR1, 4, 0),
++SND_SOC_DAPM_OUTPUT("MONO1"),
++SND_SOC_DAPM_MUX("Mono 2 Mux", SND_SOC_NOPM, 0, 0, &wm8753_mono2_controls),
++SND_SOC_DAPM_OUTPUT("MONO2"),
++SND_SOC_DAPM_MIXER("Out3 Left + Right", -1, 0, 0, NULL, 0),
++SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out3_controls),
++SND_SOC_DAPM_PGA("Out 3", WM8753_PWR3, 4, 0, NULL, 0),
++SND_SOC_DAPM_OUTPUT("OUT3"),
++SND_SOC_DAPM_MUX("Out4 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out4_controls),
++SND_SOC_DAPM_PGA("Out 4", WM8753_PWR3, 3, 0, NULL, 0),
++SND_SOC_DAPM_OUTPUT("OUT4"),
++SND_SOC_DAPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0,
++	&wm8753_record_mixer_controls[0],
++	ARRAY_SIZE(wm8753_record_mixer_controls)),
++SND_SOC_DAPM_ADC("Left ADC", "Left Voice Capture", WM8753_PWR2, 3, 0),
++SND_SOC_DAPM_ADC("Right ADC", "Right Voice Capture", WM8753_PWR2, 2, 0),
++SND_SOC_DAPM_MUX("Capture Left Mixer", SND_SOC_NOPM, 0, 0,
++	&wm8753_adc_mono_controls),
++SND_SOC_DAPM_MUX("Capture Right Mixer", SND_SOC_NOPM, 0, 0,
++	&wm8753_adc_mono_controls),
++SND_SOC_DAPM_MUX("Capture Left Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_adc_left_controls),
++SND_SOC_DAPM_MUX("Capture Right Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_adc_right_controls),
++SND_SOC_DAPM_MUX("Mic Sidetone Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_mic_mux_controls),
++SND_SOC_DAPM_PGA("Left Capture Volume", WM8753_PWR2, 5, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Right Capture Volume", WM8753_PWR2, 4, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("ALC Mixer", WM8753_PWR2, 6, 0,
++	&wm8753_alc_mixer_controls[0], ARRAY_SIZE(wm8753_alc_mixer_controls)),
++SND_SOC_DAPM_MUX("Line Left Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_line_left_controls),
++SND_SOC_DAPM_MUX("Line Right Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_line_right_controls),
++SND_SOC_DAPM_MUX("Line Mono Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_line_mono_controls),
++SND_SOC_DAPM_MUX("Line Mixer", SND_SOC_NOPM, 0, 0,
++	&wm8753_line_mux_mix_controls),
++SND_SOC_DAPM_MUX("Rx Mixer", SND_SOC_NOPM, 0, 0,
++	&wm8753_rx_mux_mix_controls),
++SND_SOC_DAPM_PGA("Mic 1 Volume", WM8753_PWR2, 8, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mic 2 Volume", WM8753_PWR2, 7, 0, NULL, 0),
++SND_SOC_DAPM_MUX("Mic Selection Mux", SND_SOC_NOPM, 0, 0,
++	&wm8753_mic_sel_mux_controls),
++SND_SOC_DAPM_INPUT("LINE1"),
++SND_SOC_DAPM_INPUT("LINE2"),
++SND_SOC_DAPM_INPUT("RXP"),
++SND_SOC_DAPM_INPUT("RXN"),
++SND_SOC_DAPM_INPUT("ACIN"),
++SND_SOC_DAPM_INPUT("ACOP"),
++SND_SOC_DAPM_INPUT("MIC1N"),
++SND_SOC_DAPM_INPUT("MIC1"),
++SND_SOC_DAPM_INPUT("MIC2N"),
++SND_SOC_DAPM_INPUT("MIC2"),
++SND_SOC_DAPM_VMID("VREF"),
++};
++
++static const char *audio_map[][3] = {
++	/* left mixer */
++	{"Left Mixer", "Left Playback Switch", "Left DAC"},
++	{"Left Mixer", "Voice Playback Switch", "Voice DAC"},
++	{"Left Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
++	{"Left Mixer", "Bypass Playback Switch", "Line Left Mux"},
++
++	/* right mixer */
++	{"Right Mixer", "Right Playback Switch", "Right DAC"},
++	{"Right Mixer", "Voice Playback Switch", "Voice DAC"},
++	{"Right Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
++	{"Right Mixer", "Bypass Playback Switch", "Line Right Mux"},
++
++	/* mono mixer */
++	{"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
++	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
++	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
++	{"Mono Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
++	{"Mono Mixer", "Bypass Playback Switch", "Line Mono Mux"},
++
++	/* left out */
++	{"Left Out 1", NULL, "Left Mixer"},
++	{"Left Out 2", NULL, "Left Mixer"},
++	{"LOUT1", NULL, "Left Out 1"},
++	{"LOUT2", NULL, "Left Out 2"},
++
++	/* right out */
++	{"Right Out 1", NULL, "Right Mixer"},
++	{"Right Out 2", NULL, "Right Mixer"},
++	{"ROUT1", NULL, "Right Out 1"},
++	{"ROUT2", NULL, "Right Out 2"},
++
++	/* mono 1 out */
++	{"Mono Out 1", NULL, "Mono Mixer"},
++	{"MONO1", NULL, "Mono Out 1"},
++
++	/* mono 2 out */
++	{"Mono 2 Mux", "Left + Right", "Out3 Left + Right"},
++	{"Mono 2 Mux", "Inverted Mono 1", "MONO1"},
++	{"Mono 2 Mux", "Left", "Left Mixer"},
++	{"Mono 2 Mux", "Right", "Right Mixer"},
++	{"Mono Out 2", NULL, "Mono 2 Mux"},
++	{"MONO2", NULL, "Mono Out 2"},
++
++	/* out 3 */
++	{"Out3 Left + Right", NULL, "Left Mixer"},
++	{"Out3 Left + Right", NULL, "Right Mixer"},
++	{"Out3 Mux", "VREF", "VREF"},
++	{"Out3 Mux", "Left + Right", "Out3 Left + Right"},
++	{"Out3 Mux", "ROUT2", "ROUT2"},
++	{"Out 3", NULL, "Out3 Mux"},
++	{"OUT3", NULL, "Out 3"},
++
++	/* out 4 */
++	{"Out4 Mux", "VREF", "VREF"},
++	{"Out4 Mux", "Capture ST", "Capture ST Mixer"},
++	{"Out4 Mux", "LOUT2", "LOUT2"},
++	{"Out 4", NULL, "Out4 Mux"},
++	{"OUT4", NULL, "Out 4"},
++
++	/* record mixer  */
++	{"Playback Mixer", "Left Capture Switch", "Left Mixer"},
++	{"Playback Mixer", "Voice Capture Switch", "Mono Mixer"},
++	{"Playback Mixer", "Right Capture Switch", "Right Mixer"},
++
++	/* Mic/SideTone Mux */
++	{"Mic Sidetone Mux", "Left PGA", "Left Capture Volume"},
++	{"Mic Sidetone Mux", "Right PGA", "Right Capture Volume"},
++	{"Mic Sidetone Mux", "Mic 1", "Mic 1 Volume"},
++	{"Mic Sidetone Mux", "Mic 2", "Mic 2 Volume"},
++
++	/* Capture Left Mux */
++	{"Capture Left Mux", "PGA", "Left Capture Volume"},
++	{"Capture Left Mux", "Line or RXP-RXN", "Line Left Mux"},
++	{"Capture Left Mux", "Line", "LINE1"},
++
++	/* Capture Right Mux */
++	{"Capture Right Mux", "PGA", "Right Capture Volume"},
++	{"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"},
++	{"Capture Right Mux", "Sidetone", "Capture ST Mixer"},
++
++	/* Mono Capture mixer-mux */
++	{"Capture Right Mixer", "Stereo", "Capture Right Mux"},
++	{"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"},
++	{"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"},
++	{"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"},
++	{"Capture Right Mixer", "Analogue Mix Right", "Capture Right Mux"},
++	{"Capture Left Mixer", "Digital Mono Mix", "Capture Left Mux"},
++	{"Capture Left Mixer", "Digital Mono Mix", "Capture Right Mux"},
++	{"Capture Right Mixer", "Digital Mono Mix", "Capture Left Mux"},
++	{"Capture Right Mixer", "Digital Mono Mix", "Capture Right Mux"},
++
++	/* ADC */
++	{"Left ADC", NULL, "Capture Left Mixer"},
++	{"Right ADC", NULL, "Capture Right Mixer"},
++
++	/* Left Capture Volume */
++	{"Left Capture Volume", NULL, "ACIN"},
++
++	/* Right Capture Volume */
++	{"Right Capture Volume", NULL, "Mic 2 Volume"},
++
++	/* ALC Mixer */
++	{"ALC Mixer", "Line Capture Switch", "Line Mixer"},
++	{"ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume"},
++	{"ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume"},
++	{"ALC Mixer", "Rx Capture Switch", "Rx Mixer"},
++
++	/* Line Left Mux */
++	{"Line Left Mux", "Line 1", "LINE1"},
++	{"Line Left Mux", "Rx Mix", "Rx Mixer"},
++
++	/* Line Right Mux */
++	{"Line Right Mux", "Line 2", "LINE2"},
++	{"Line Right Mux", "Rx Mix", "Rx Mixer"},
++
++	/* Line Mono Mux */
++	{"Line Mono Mux", "Line Mix", "Line Mixer"},
++	{"Line Mono Mux", "Rx Mix", "Rx Mixer"},
++
++	/* Line Mixer/Mux */
++	{"Line Mixer", "Line 1 + 2", "LINE1"},
++	{"Line Mixer", "Line 1 - 2", "LINE1"},
++	{"Line Mixer", "Line 1 + 2", "LINE2"},
++	{"Line Mixer", "Line 1 - 2", "LINE2"},
++	{"Line Mixer", "Line 1", "LINE1"},
++	{"Line Mixer", "Line 2", "LINE2"},
++
++	/* Rx Mixer/Mux */
++	{"Rx Mixer", "RXP - RXN", "RXP"},
++	{"Rx Mixer", "RXP + RXN", "RXP"},
++	{"Rx Mixer", "RXP - RXN", "RXN"},
++	{"Rx Mixer", "RXP + RXN", "RXN"},
++	{"Rx Mixer", "RXP", "RXP"},
++	{"Rx Mixer", "RXN", "RXN"},
++
++	/* Mic 1 Volume */
++	{"Mic 1 Volume", NULL, "MIC1N"},
++	{"Mic 1 Volume", NULL, "Mic Selection Mux"},
++
++	/* Mic 2 Volume */
++	{"Mic 2 Volume", NULL, "MIC2N"},
++	{"Mic 2 Volume", NULL, "MIC2"},
++
++	/* Mic Selector Mux */
++	{"Mic Selection Mux", "Mic 1", "MIC1"},
++	{"Mic Selection Mux", "Mic 2", "MIC2N"},
++	{"Mic Selection Mux", "Mic 3", "MIC2"},
++
++	/* ACOP */
++	{"ACOP", NULL, "ALC Mixer"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8753_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
++	}
++
++	/* set up the WM8753 audio map */
++	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;
++}
++
++/* PLL divisors */
++struct _pll_div {
++	u32 pll_in;		/* ext clock input */
++	u32 pll_out;	/* pll out freq */
++	u32 div2:1;
++	u32 n:4;
++	u32 k:24;
++};
++
++/*
++ * PLL divisors -
++ */
++static const struct _pll_div pll_div[] = {
++   {13000000,	12288000,	0,	0x7,    0x23F54A},
++   {13000000,	11289600,	0,	0x6,    0x3CA2F5},
++   {12000000,	12288000,	0,	0x8,    0x0C49BA},
++   {12000000,	11289600,	0,	0x7,    0x21B08A},
++   {24000000,	12288000,	1,	0x8,    0x0C49BA},
++   {24000000,	11289600,	1,	0x7,    0x21B08A},
++   {12288000,	11289600,	0,	0x7,	0x166667},
++   {26000000,	11289600,	1,	0x6,	0x3CA2F5},
++   {26000000,	12288000,	1,	0x7,	0x23F54A},
++};
++
++static u32 wm8753_config_pll(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int pll)
++{
++	u16 reg;
++	int found = 0;
++
++    if (pll == 1) {
++		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
++        if (!dai->pll_in || !dai->mclk) {
++            /* disable PLL1  */
++            wm8753_write(codec, WM8753_PLL1CTL1, 0x0026);
++			wm8753_write(codec, WM8753_CLOCK, reg);
++			return 0;
++        } else {
++            u16 value = 0;
++            int i = 0;
++
++            /* if we cant match, then use good values for N and K */
++            for (;i < ARRAY_SIZE(pll_div); i++) {
++                if (pll_div[i].pll_out == dai->pll_out &&
++                	pll_div[i].pll_in == dai->pll_in) {
++                	found = 1;
++                    break;
++                }
++            }
++
++			if (!found)
++				goto err;
++
++            /* set up N and K PLL divisor ratios */
++            /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
++            value = (pll_div[i].n << 5) + ((pll_div[i].k & 0x3c0000) >> 18);
++            wm8753_write(codec, WM8753_PLL1CTL2, value);
++
++            /* bits 8:0 = PLL_K[17:9] */
++            value = (pll_div[i].k & 0x03fe00) >> 9;
++            wm8753_write(codec, WM8753_PLL1CTL3, value);
++
++            /* bits 8:0 = PLL_K[8:0] */
++            value = pll_div[i].k & 0x0001ff;
++            wm8753_write(codec, WM8753_PLL1CTL4, value);
++
++            /* set PLL1 as input and enable */
++            wm8753_write(codec, WM8753_PLL1CTL1, 0x0027 |
++            	(pll_div[i].div2 << 3));
++			wm8753_write(codec, WM8753_CLOCK, reg | 0x0010);
++        }
++    } else {
++		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
++        if (!dai->pll_in || !dai->mclk) {
++            /* disable PLL2  */
++            wm8753_write(codec, WM8753_PLL2CTL1, 0x0026);
++			wm8753_write(codec, WM8753_CLOCK, reg);
++			return 0;
++        } else {
++            u16 value = 0;
++            int i = 0;
++
++            /* if we cant match, then use good values for N and K */
++            for (;i < ARRAY_SIZE(pll_div); i++) {
++                if (pll_div[i].pll_out == dai->pll_out &&
++                	pll_div[i].pll_in == dai->pll_in) {
++                		found = 1;
++                		break;
++                }
++            }
++
++			if (!found)
++				goto err;
++
++            /* set up N and K PLL divisor ratios */
++            /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
++            value = (pll_div[i].n << 5) + ((pll_div[i].k & 0x3c0000) >> 18);
++            wm8753_write(codec, WM8753_PLL2CTL2, value);
++
++            /* bits 8:0 = PLL_K[17:9] */
++            value = (pll_div[i].k & 0x03fe00) >> 9;
++            wm8753_write(codec, WM8753_PLL2CTL3, value);
++
++            /* bits 8:0 = PLL_K[8:0] */
++            value = pll_div[i].k & 0x0001ff;
++            wm8753_write(codec, WM8753_PLL2CTL4, value);
++
++            /* set PLL1 as input and enable */
++            wm8753_write(codec, WM8753_PLL2CTL1, 0x0027 |
++            	(pll_div[i].div2 << 3));
++			wm8753_write(codec, WM8753_CLOCK, reg | 0x0008);
++        }
++    }
++
++    return dai->pll_in;
++err:
++	return 0;
++}
++
++struct _coeff_div {
++	u32 mclk;
++	u32 rate;
++	u16 fs;
++	u8 sr:5;
++	u8 usb:1;
++};
++
++/* codec hifi mclk (after PLL) clock divider coefficients */
++static const struct _coeff_div coeff_div[] = {
++	/* 8k */
++	{12288000, 8000, 1536, 0x6, 0x0},
++	{11289600, 8000, 1408, 0x16, 0x0},
++	{18432000, 8000, 2304, 0x7, 0x0},
++	{16934400, 8000, 2112, 0x17, 0x0},
++	{12000000, 8000, 1500, 0x6, 0x1},
++
++	/* 11.025k */
++	{11289600, 11025, 1024, 0x18, 0x0},
++	{16934400, 11025, 1536, 0x19, 0x0},
++	{12000000, 11025, 1088, 0x19, 0x1},
++
++	/* 16k */
++	{12288000, 16000, 768, 0xa, 0x0},
++	{18432000, 16000, 1152, 0xb, 0x0},
++	{12000000, 16000, 750, 0xa, 0x1},
++
++	/* 22.05k */
++	{11289600, 22050, 512, 0x1a, 0x0},
++	{16934400, 22050, 768, 0x1b, 0x0},
++	{12000000, 22050, 544, 0x1b, 0x1},
++
++	/* 32k */
++	{12288000, 32000, 384, 0xc, 0x0},
++	{18432000, 32000, 576, 0xd, 0x0},
++	{12000000, 32000, 375, 0xa, 0x1},
++
++	/* 44.1k */
++	{11289600, 44100, 256, 0x10, 0x0},
++	{16934400, 44100, 384, 0x11, 0x0},
++	{12000000, 44100, 272, 0x11, 0x1},
++
++	/* 48k */
++	{12288000, 48000, 256, 0x0, 0x0},
++	{18432000, 48000, 384, 0x1, 0x0},
++	{12000000, 48000, 250, 0x0, 0x1},
++
++	/* 88.2k */
++	{11289600, 88200, 128, 0x1e, 0x0},
++	{16934400, 88200, 192, 0x1f, 0x0},
++	{12000000, 88200, 136, 0x1f, 0x1},
++
++	/* 96k */
++	{12288000, 96000, 128, 0xe, 0x0},
++	{18432000, 96000, 192, 0xf, 0x0},
++	{12000000, 96000, 125, 0xe, 0x1},
++};
++
++static int get_coeff(int mclk, int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
++		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
++			return i;
++	}
++	return -EINVAL;
++}
++
++/* supported HiFi input clocks (that don't use PLL) */
++const static int hifi_clks[] = {11289600, 12000000, 12288000,
++	16934400, 18432000};
++
++/* The HiFi interface can be clocked in one of two ways:-
++ *  o No PLL - MCLK is used directly.
++ *  o PLL    - PLL is used to generate audio MCLK from input clock.
++ *
++ * We use the direct method if we can as it saves power.
++ */
++static unsigned int wm8753_config_i2s_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, pll_out;
++
++	/* is clk supported without the PLL */
++	for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) {
++		if (clk == hifi_clks[i]) {
++			dai->mclk = clk;
++			dai->pll_in = dai->pll_out = 0;
++			dai->clk_div = 1;
++			return clk;
++		}
++	}
++
++	/* determine best PLL output speed */
++	if (info->bclk_master &
++		(SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
++		pll_out = info->fs * info->rate;
++	} else {
++		/* calc slave clock */
++		switch (info->rate){
++			case 11025:
++			case 22050:
++			case 44100:
++			case 88200:
++				pll_out = 11289600;
++				break;
++			default:
++				pll_out = 12288000;
++				break;
++		}
++	}
++
++	/* are input & output clocks supported by PLL */
++	for (i = 0;i < ARRAY_SIZE(pll_div); i++) {
++		if (pll_div[i].pll_in == clk && pll_div[i].pll_out == pll_out) {
++			dai->pll_in = clk;
++			dai->pll_out = dai->mclk = pll_out;
++			return pll_out;
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++/* valid PCM clock dividers * 2 */
++static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16};
++
++/* The Voice interface can be clocked in one of four ways:-
++ *  o No PLL - MCLK is used directly.
++ *  o Div    - MCLK is directly divided.
++ *  o PLL    - PLL is used to generate audio MCLK from input clock.
++ *  o PLL & Div - PLL and post divider are used.
++ *
++ * We use the non PLL methods if we can, as it saves power.
++ */
++
++static unsigned int wm8753_config_pcm_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) {
++		if ((best_clk >> 1) * pcm_divs[i] == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = pcm_divs[i];
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll_div); i++) {
++		if (pll_div[i].pll_in == clk) {
++			for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) {
++				if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) {
++					dai->pll_in = clk;
++					dai->pll_out = pll_div[i].pll_out;
++					dai->clk_div = pcm_divs[j];
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++/* set the format and bit size for ADC and Voice DAC */
++static void wm8753_adc_vdac_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01e0;
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		voice |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		voice |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		voice |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		voice |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		voice |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		voice |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		voice |= 0x000c;
++		break;
++	}
++
++	wm8753_write(codec, WM8753_PCM, voice);
++}
++
++/* configure PCM DAI */
++static int wm8753_pcm_dai_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 voice, ioctl, srate, srate2, fs, bfs, clock;
++	unsigned int rate;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	fs = rtd->codec_dai->dai_runtime.fs;
++	rate = snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate);
++	voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x001f;
++
++	/* set master/slave audio interface */
++	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x01fd;
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		ioctl |= 0x0002;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		voice |= 0x0040;
++		break;
++	}
++
++	/* do we need to enable the PLL */
++	if (rtd->codec_dai->pll_in) {
++		if (wm8753_config_pll(codec, rtd->codec_dai, 2) !=
++			rtd->codec_dai->pll_in) {
++			err("could not set pll to %d --> %d",
++				rtd->codec_dai->pll_in, rtd->codec_dai->pll_out);
++			return -ENODEV;
++		}
++	}
++
++	/* set up PCM divider */
++	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
++	switch (rtd->codec_dai->clk_div) {
++	case 2: /* 1 */
++		break;
++	case 6: /* 3 */
++		clock |= (0x2 << 6);
++		break;
++	case 11: /* 5.5 */
++		clock |= (0x3 << 6);
++		break;
++	case 4: /* 2 */
++		clock |= (0x4 << 6);
++		break;
++	case 8: /* 4 */
++		clock |= (0x5 << 6);
++		break;
++	case 12: /* 6 */
++		clock |= (0x6 << 6);
++		break;
++	case 16: /* 8 */
++		clock |= (0x7 << 6);
++		break;
++	default:
++		printk(KERN_ERR "wm8753: invalid PCM clk divider %d\n",
++			rtd->codec_dai->clk_div);
++		break;
++	}
++	wm8753_write(codec, WM8753_CLOCK, clock);
++
++	/* set bclk divisor rate */
++	srate2 = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
++	switch (bfs) {
++	case 1:
++		break;
++	case 2:
++		srate2 |= (0x1 << 6);
++		break;
++	case 4:
++		srate2 |= (0x2 << 6);
++		break;
++	case 8:
++		srate2 |= (0x3 << 6);
++		break;
++	case 16:
++		srate2 |= (0x4 << 6);
++		break;
++	}
++	wm8753_write(codec, WM8753_SRATE2, srate2);
++
++	srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
++	if (rtd->codec_dai->dai_runtime.fs == 384)
++		srate |= 0x80;
++	wm8753_write(codec, WM8753_SRATE1, srate);
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		voice |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		voice |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		voice |= 0x0010;
++		break;
++	}
++	//printk("voice %x %x ioctl %x %x srate2 %x %x srate1 %x %x\n",
++	//WM8753_PCM, voice, WM8753_IOCTL, ioctl, WM8753_SRATE2,
++	//srate2, WM8753_SRATE1, srate);
++
++	wm8753_write(codec, WM8753_IOCTL, ioctl);
++	wm8753_write(codec, WM8753_PCM, voice);
++	return 0;
++}
++
++/* configure hifi DAC wordlength and format */
++static void wm8753_hdac_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		hifi |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		hifi |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		hifi |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		hifi |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		hifi |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		hifi |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		hifi |= 0x000c;
++		break;
++	}
++
++	wm8753_write(codec, WM8753_HIFI, hifi);
++}
++
++/* configure i2s (hifi) DAI clocking */
++static int wm8753_i2s_dai_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 srate, bfs, hifi, ioctl;
++	unsigned int rate;
++	int i = 0;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	rate = snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate);
++	hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x001f;
++
++	/* is coefficient valid ? */
++	if ((i = get_coeff(rtd->codec_dai->mclk, rate)) < 0)
++		return i;
++
++	srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
++	wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[i].sr << 1) |
++		coeff_div[i].usb);
++
++	/* do we need to enable the PLL */
++	if (rtd->codec_dai->pll_in) {
++		if (wm8753_config_pll(codec, rtd->codec_dai, 1) !=
++			rtd->codec_dai->pll_in) {
++			err("could not set pll to %d --> %d",
++				rtd->codec_dai->pll_in, rtd->codec_dai->pll_out);
++			return -ENODEV;
++		}
++	}
++
++	/* set bclk divisor rate */
++	srate = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
++	switch (bfs) {
++	case 1:
++		break;
++	case 2:
++		srate |= (0x1 << 3);
++		break;
++	case 4:
++		srate |= (0x2 << 3);
++		break;
++	case 8:
++		srate |= (0x3 << 3);
++		break;
++	case 16:
++		srate |= (0x4 << 3);
++		break;
++	}
++	wm8753_write(codec, WM8753_SRATE2, srate);
++
++	/* set master/slave audio interface */
++	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00fe;
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		ioctl |= 0x0001;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		hifi |= 0x0040;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		hifi |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		hifi |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		hifi |= 0x0010;
++		break;
++	}
++	wm8753_write(codec, WM8753_IOCTL, ioctl);
++	wm8753_write(codec, WM8753_HIFI, hifi);
++	return 0;
++}
++
++static int wm8753_mode1v_prepare (struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clock;
++
++	/* set clk source as pcmclk */
++	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
++	wm8753_write(codec, WM8753_CLOCK, clock);
++
++	wm8753_adc_vdac_prepare(substream);
++	return wm8753_pcm_dai_prepare(substream);
++}
++
++static int wm8753_mode1h_prepare (struct snd_pcm_substream *substream)
++{
++	wm8753_hdac_prepare(substream);
++	return wm8753_i2s_dai_prepare(substream);
++}
++
++static int wm8753_mode2_prepare (struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clock;
++
++	/* set clk source as pcmclk */
++	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
++	wm8753_write(codec, WM8753_CLOCK, clock);
++
++	wm8753_adc_vdac_prepare(substream);
++	return wm8753_i2s_dai_prepare(substream);
++}
++
++static int wm8753_mode3_prepare (struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clock;
++
++	/* set clk source as mclk */
++	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
++	wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
++
++	wm8753_hdac_prepare(substream);
++	wm8753_adc_vdac_prepare(substream);
++	return wm8753_i2s_dai_prepare(substream);
++}
++
++static int wm8753_mode4_prepare (struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 clock;
++
++	/* set clk source as mclk */
++	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
++	wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
++
++	wm8753_hdac_prepare(substream);
++	wm8753_adc_vdac_prepare(substream);
++	return wm8753_i2s_dai_prepare(substream);
++}
++
++static int wm8753_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
++
++	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
++	 * make sure we check if they are not both active when we mute */
++	if (mute && dai->id == 1) {
++		if (!wm8753_dai[WM8753_DAI_VOICE].playback.active ||
++			!wm8753_dai[WM8753_DAI_HIFI].playback.active)
++			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
++	} else {
++		if (mute)
++			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
++		else
++			wm8753_write(codec, WM8753_DAC, mute_reg);
++	}
++
++	return 0;
++}
++
++static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* set vmid to 50k and unmute dac */
++		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		/* set vmid to 5k for quick power up */
++		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* mute dac and set vmid to 500k, enable VREF */
++		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		wm8753_write(codec, WM8753_PWR1, 0x0001);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++/*
++ * The WM8753 supports upto 4 different and mutually exclusive DAI
++ * configurations. This gives 2 PCM's available for use, hifi and voice.
++ * NOTE: The Voice PCM cannot play or caputure audio to the CPU as it's DAI
++ * is connected between the wm8753 and a BT codec or GSM modem.
++ *
++ * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI
++ * 2. Voice over HIFI DAI - HIFI disabled
++ * 3. Voice disabled - HIFI over HIFI
++ * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
++ */
++static const struct snd_soc_codec_dai wm8753_all_dai[] = {
++/* DAI HiFi mode 1 */
++{	.name = "WM8753 HiFi",
++	.id = 1,
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = { /* dummy for fast DAI switching */
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm8753_config_i2s_sysclk,
++	.digital_mute = wm8753_mute,
++	.ops = {
++		.prepare = wm8753_mode1h_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8753_hifi_modes),
++		.mode = wm8753_hifi_modes,},
++},
++/* DAI Voice mode 1 */
++{	.name = "WM8753 Voice",
++	.id = 1,
++	.playback = {
++		.stream_name = "Voice Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.capture = {
++		.stream_name = "Voice Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm8753_config_pcm_sysclk,
++	.digital_mute = wm8753_mute,
++	.ops = {
++		.prepare = wm8753_mode1v_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8753_voice_modes),
++		.mode = wm8753_voice_modes,},
++},
++/* DAI HiFi mode 2 - dummy */
++{	.name = "WM8753 HiFi",
++	.id = 2,
++},
++/* DAI Voice mode 2 */
++{	.name = "WM8753 Voice",
++	.id = 2,
++	.playback = {
++		.stream_name = "Voice Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.capture = {
++		.stream_name = "Voice Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm8753_config_i2s_sysclk,
++	.digital_mute = wm8753_mute,
++	.ops = {
++		.prepare = wm8753_mode2_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8753_voice_modes),
++		.mode = wm8753_voice_modes,},
++},
++/* DAI HiFi mode 3 */
++{	.name = "WM8753 HiFi",
++	.id = 3,
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm8753_config_i2s_sysclk,
++	.digital_mute = wm8753_mute,
++	.ops = {
++		.prepare = wm8753_mode3_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8753_hifi_modes),
++		.mode = wm8753_hifi_modes,},
++},
++/* DAI Voice mode 3 - dummy */
++{	.name = "WM8753 Voice",
++	.id = 3,
++},
++/* DAI HiFi mode 4 */
++{	.name = "WM8753 HiFi",
++	.id = 4,
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm8753_config_i2s_sysclk,
++	.digital_mute = wm8753_mute,
++	.ops = {
++		.prepare = wm8753_mode4_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8753_mixed_modes),
++		.mode = wm8753_mixed_modes,},
++},
++/* DAI Voice mode 4 - dummy */
++{	.name = "WM8753 Voice",
++	.id = 4,
++},
++};
++
++struct snd_soc_codec_dai wm8753_dai[2];
++EXPORT_SYMBOL_GPL(wm8753_dai);
++
++static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
++{
++	if (mode < 4) {
++		wm8753_dai[0] = wm8753_all_dai[mode << 1];
++		wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
++	}
++}
++
++static void wm8753_work(void *data)
++{
++	struct snd_soc_codec *codec = (struct snd_soc_codec *)data;
++	wm8753_dapm_event(codec, codec->dapm_state);
++}
++
++static int wm8753_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;
++
++	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8753_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
++		if (i + 1 == WM8753_RESET)
++			continue;
++		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++
++	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* charge wm8753 caps */
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
++		wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
++		codec->dapm_state = SNDRV_CTL_POWER_D0;
++		queue_delayed_work(wm8753_workq, &wm8753_dapm_work,
++			msecs_to_jiffies(caps_charge));
++	}
++
++	return 0;
++}
++
++/*
++ * initialise the WM8753 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8753_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8753";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8753_read_reg_cache;
++	codec->write = wm8753_write;
++	codec->dapm_event = wm8753_dapm_event;
++	codec->dai = wm8753_dai;
++	codec->num_dai = 2;
++	codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
++
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8753_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8753_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8753_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8753_reg);
++	wm8753_set_dai_mode(codec, 0);
++
++	wm8753_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* charge output caps */
++	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
++	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
++	queue_delayed_work(wm8753_workq,
++		&wm8753_dapm_work, msecs_to_jiffies(caps_charge));
++
++	/* set the update bits */
++	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
++	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
++	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
++	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
++	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
++	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
++	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
++	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
++	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
++	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
++
++	wm8753_add_controls(codec);
++	wm8753_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0) {
++		snd_soc_free_pcms(socdev);
++		snd_soc_dapm_free(socdev);
++	}
++
++	return ret;
++}
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++static struct snd_soc_device *wm8753_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8753 2 wire address is determined by GPIO5
++ * state during powerup.
++ *    low  = 0x1a
++ *    high = 0x1b
++ */
++#define I2C_DRIVERID_WM8753 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8753_i2c_driver;
++static struct i2c_client client_template;
++
++static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8753_socdev;
++	struct wm8753_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8753_init(socdev);
++	if (ret < 0) {
++		err("failed to initialise WM8753\n");
++		goto err;
++	}
++
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8753_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8753_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8753_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8753_i2c_driver = {
++	.driver = {
++		.name = "WM8753 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8753,
++	.attach_adapter = wm8753_i2c_attach,
++	.detach_client =  wm8753_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8753",
++	.driver = &wm8753_i2c_driver,
++};
++#endif
++
++static int wm8753_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8753_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8753 Audio Codec %s", WM8753_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);
++	wm8753_socdev = socdev;
++	INIT_WORK(&wm8753_dapm_work, wm8753_work, codec);
++	wm8753_workq = create_workqueue("wm8753");
++	if (wm8753_workq == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8753_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++		/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8753_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)
++		wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	if (wm8753_workq)
++		destroy_workqueue(wm8753_workq);
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8753_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8753 = {
++	.probe = 	wm8753_probe,
++	.remove = 	wm8753_remove,
++	.suspend = 	wm8753_suspend,
++	.resume =	wm8753_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
++
++MODULE_DESCRIPTION("ASoC WM8753 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8753.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8753.h
+@@ -0,0 +1,91 @@
++/*
++ * wm8753.h  --  audio driver for WM8753
++ *
++ * Copyright 2003 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ */
++
++#ifndef _WM8753_H
++#define _WM8753_H
++
++/* WM8753 register space */
++
++#define WM8753_DAC		0x01
++#define WM8753_ADC		0x02
++#define WM8753_PCM		0x03
++#define WM8753_HIFI		0x04
++#define WM8753_IOCTL	0x05
++#define WM8753_SRATE1	0x06
++#define WM8753_SRATE2	0x07
++#define WM8753_LDAC		0x08
++#define WM8753_RDAC		0x09
++#define WM8753_BASS		0x0a
++#define WM8753_TREBLE	0x0b
++#define WM8753_ALC1		0x0c
++#define WM8753_ALC2		0x0d
++#define WM8753_ALC3		0x0e
++#define WM8753_NGATE	0x0f
++#define WM8753_LADC		0x10
++#define WM8753_RADC		0x11
++#define WM8753_ADCTL1	0x12
++#define WM8753_3D		0x13
++#define WM8753_PWR1		0x14
++#define WM8753_PWR2		0x15
++#define WM8753_PWR3		0x16
++#define WM8753_PWR4		0x17
++#define WM8753_ID		0x18
++#define WM8753_INTPOL	0x19
++#define WM8753_INTEN	0x1a
++#define WM8753_GPIO1	0x1b
++#define WM8753_GPIO2	0x1c
++#define WM8753_RESET	0x1f
++#define WM8753_RECMIX1	0x20
++#define WM8753_RECMIX2	0x21
++#define WM8753_LOUTM1	0x22
++#define WM8753_LOUTM2	0x23
++#define WM8753_ROUTM1	0x24
++#define WM8753_ROUTM2	0x25
++#define WM8753_MOUTM1	0x26
++#define WM8753_MOUTM2	0x27
++#define WM8753_LOUT1V	0x28
++#define WM8753_ROUT1V	0x29
++#define WM8753_LOUT2V	0x2a
++#define WM8753_ROUT2V	0x2b
++#define WM8753_MOUTV	0x2c
++#define WM8753_OUTCTL	0x2d
++#define WM8753_ADCIN	0x2e
++#define WM8753_INCTL1	0x2f
++#define WM8753_INCTL2	0x30
++#define WM8753_LINVOL	0x31
++#define WM8753_RINVOL	0x32
++#define WM8753_MICBIAS	0x33
++#define WM8753_CLOCK	0x34
++#define WM8753_PLL1CTL1	0x35
++#define WM8753_PLL1CTL2	0x36
++#define WM8753_PLL1CTL3	0x37
++#define WM8753_PLL1CTL4	0x38
++#define WM8753_PLL2CTL1	0x39
++#define WM8753_PLL2CTL2	0x3a
++#define WM8753_PLL2CTL3	0x3b
++#define WM8753_PLL2CTL4	0x3c
++#define WM8753_BIASCTL	0x3d
++#define WM8753_ADCTL2	0x3f
++
++struct wm8753_setup_data {
++	unsigned short i2c_address;
++};
++
++#define WM8753_DAI_HIFI		0
++#define WM8753_DAI_VOICE	1
++
++extern struct snd_soc_codec_dai wm8753_dai[2];
++extern struct snd_soc_codec_device soc_codec_dev_wm8753;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8772.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8772.c
+@@ -0,0 +1,806 @@
++/*
++ * wm8772.c  --  WM8772 ALSA Soc Audio driver
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8772.h"
++
++#define AUDIO_NAME "WM8772"
++#define WM8772_VERSION "0.3"
++
++/*
++ * wm8772 register cache
++ * We can't read the WM8772 register space when we
++ * are using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8772_reg[] = {
++	0x00ff, 0x00ff, 0x0120, 0x0000,  /*  0 */
++	0x00ff, 0x00ff, 0x00ff, 0x00ff,  /*  4 */
++	0x00ff, 0x0000, 0x0080, 0x0040,  /*  8 */
++	0x0000
++};
++
++#define WM8772_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_IB_NF)
++
++#define WM8772_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8772_PRATES \
++	(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
++	 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
++
++#define WM8772_CRATES \
++	(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
++	 SNDRV_PCM_RATE_96000)
++
++static struct snd_soc_dai_mode wm8772_modes[] = {
++	/* common codec frame and clock master modes */
++	/* 32k */
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 768,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 512,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++
++	/* 	44.1k */
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 768,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 512,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++
++	/* 48k */
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 768,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 512,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++
++	/* 96k */
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8772_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8772_DIR,
++		.pcmrate = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++
++	/* 192k */
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_192000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8772_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_192000,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++	},
++
++	/* slave mode */
++	{
++		.fmt = WM8772_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = WM8772_PRATES,
++		.pcmdir = SND_SOC_DAIDIR_PLAYBACK,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++	{
++		.fmt = WM8772_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = WM8772_CRATES,
++		.pcmdir = SND_SOC_DAIDIR_CAPTURE,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8772 register cache
++ */
++static inline unsigned int wm8772_read_reg_cache(struct snd_soc_codec * codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg > WM8772_CACHE_REGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8772 register cache
++ */
++static inline void wm8772_write_reg_cache(struct snd_soc_codec * codec,
++	unsigned int reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg > WM8772_CACHE_REGNUM)
++		return;
++	cache[reg] = value;
++}
++
++static int wm8772_write(struct snd_soc_codec * codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8772 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8772_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -1;
++}
++
++#define wm8772_reset(c)	wm8772_write(c, WM8772_RESET, 0)
++
++/*
++ * WM8772 Controls
++ */
++static const char *wm8772_zero_flag[] = {"All Ch", "Ch 1", "Ch 2", "Ch3"};
++
++static const struct soc_enum wm8772_enum[] = {
++SOC_ENUM_SINGLE(WM8772_DACCTRL, 0, 4, wm8772_zero_flag),
++};
++
++static const struct snd_kcontrol_new wm8772_snd_controls[] = {
++
++SOC_SINGLE("Left1 Playback Volume", WM8772_LDAC1VOL, 0, 255, 0),
++SOC_SINGLE("Left2 Playback Volume", WM8772_LDAC2VOL, 0, 255, 0),
++SOC_SINGLE("Left3 Playback Volume", WM8772_LDAC3VOL, 0, 255, 0),
++SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC1VOL, 0, 255, 0),
++SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC2VOL, 0, 255, 0),
++SOC_SINGLE("Right1 Playback Volume", WM8772_RDAC3VOL, 0, 255, 0),
++SOC_SINGLE("Master Playback Volume", WM8772_MDACVOL, 0, 255, 0),
++
++SOC_SINGLE("Playback Switch", WM8772_DACCH, 0, 1, 0),
++SOC_SINGLE("Capture Switch", WM8772_ADCCTRL, 2, 1, 0),
++
++SOC_SINGLE("Demp1 Playback Switch", WM8772_DACCTRL, 6, 1, 0),
++SOC_SINGLE("Demp2 Playback Switch", WM8772_DACCTRL, 7, 1, 0),
++SOC_SINGLE("Demp3 Playback Switch", WM8772_DACCTRL, 8, 1, 0),
++
++SOC_SINGLE("Phase Invert 1 Switch", WM8772_IFACE, 6, 1, 0),
++SOC_SINGLE("Phase Invert 2 Switch", WM8772_IFACE, 7, 1, 0),
++SOC_SINGLE("Phase Invert 3 Switch", WM8772_IFACE, 8, 1, 0),
++
++SOC_SINGLE("Playback ZC Switch", WM8772_DACCTRL, 0, 1, 0),
++
++SOC_SINGLE("Capture High Pass Switch", WM8772_ADCCTRL, 3, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm8772_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8772_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8772_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/* valid wm8772 mclk frequencies */
++static const int freq_table[5][6] = {
++	{4096000, 6144000, 8192000, 12288000, 16384000, 24576000},
++	{5644800, 8467000, 11289600, 16934000, 22579200, 33868800},
++	{6144000, 9216000, 12288000, 18432000, 24576000, 36864000},
++	{12288000, 18432000, 24576000, 36864000, 0, 0},
++	{24576000, 36864000, 0, 0, 0},
++};
++
++static unsigned int check_freq(int rate, unsigned int freq)
++{
++	int i;
++
++	for(i = 0; i < 6; i++) {
++		if(freq == freq_table[i][rate])
++			return freq;
++	}
++	return 0;
++}
++
++static unsigned int wm8772_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	switch (info->rate){
++	case 32000:
++		dai->mclk = check_freq(0, clk);
++		break;
++	case 44100:
++		dai->mclk = check_freq(1, clk);
++		break;
++	case 48000:
++		dai->mclk = check_freq(2, clk);
++		break;
++	case 96000:
++		dai->mclk = check_freq(3, clk);
++		break;
++	case 192000:
++		dai->mclk = check_freq(4, clk);
++		break;
++	default:
++		dai->mclk = 0;
++	}
++	return dai->mclk;
++}
++
++static int wm8772_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 diface = wm8772_read_reg_cache(codec, WM8772_IFACE) & 0xffc0;
++	u16 diface_ctrl = wm8772_read_reg_cache(codec, WM8772_DACRATE) & 0xfe1f;
++	u16 aiface = 0;
++	u16 aiface_ctrl = wm8772_read_reg_cache(codec, WM8772_ADCCTRL) & 0xfcff;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++
++		/* set master/slave audio interface */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++		case SND_SOC_DAIFMT_CBM_CFM:
++			diface_ctrl |= 0x0010;
++			break;
++		case SND_SOC_DAIFMT_CBS_CFS:
++			break;
++		}
++
++		/* interface format */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++		case SND_SOC_DAIFMT_I2S:
++			diface |= 0x0002;
++			break;
++		case SND_SOC_DAIFMT_RIGHT_J:
++			break;
++		case SND_SOC_DAIFMT_LEFT_J:
++			diface |= 0x0001;
++			break;
++		case SND_SOC_DAIFMT_DSP_A:
++			diface |= 0x0003;
++			break;
++		case SND_SOC_DAIFMT_DSP_B:
++			diface |= 0x0007;
++			break;
++		}
++
++		/* bit size */
++		switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++		case SNDRV_PCM_FMTBIT_S16_LE:
++			break;
++		case SNDRV_PCM_FORMAT_S20_3LE:
++			diface |= 0x0010;
++			break;
++		case SNDRV_PCM_FORMAT_S24_3LE:
++			diface |= 0x0020;
++			break;
++		case SNDRV_PCM_FORMAT_S32_LE:
++			diface |= 0x0030;
++			break;
++		}
++
++		/* clock inversion */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++		case SND_SOC_DAIFMT_NB_NF:
++			break;
++		case SND_SOC_DAIFMT_IB_NF:
++			diface |= 0x0008;
++			break;
++		}
++
++		/* set rate */
++		switch (rtd->codec_dai->dai_runtime.fs) {
++		case 768:
++			diface_ctrl |= (0x5 << 6);
++			break;
++		case 512:
++			diface_ctrl |= (0x4 << 6);
++			break;
++		case 384:
++			diface_ctrl |= (0x3 << 6);
++			break;
++		case 256:
++			diface_ctrl |= (0x2 << 6);
++			break;
++		case 192:
++			diface_ctrl |= (0x1 << 6);
++			break;
++		}
++
++		wm8772_write(codec, WM8772_DACRATE, diface_ctrl);
++		wm8772_write(codec, WM8772_IFACE, diface);
++
++	} else {
++
++		/* set master/slave audio interface */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++		case SND_SOC_DAIFMT_CBM_CFM:
++			aiface |= 0x0010;
++			break;
++		case SND_SOC_DAIFMT_CBS_CFS:
++			break;
++		}
++
++		/* interface format */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++		case SND_SOC_DAIFMT_I2S:
++			aiface |= 0x0002;
++			break;
++		case SND_SOC_DAIFMT_RIGHT_J:
++			break;
++		case SND_SOC_DAIFMT_LEFT_J:
++			aiface |= 0x0001;
++			break;
++		case SND_SOC_DAIFMT_DSP_A:
++			aiface |= 0x0003;
++			break;
++		case SND_SOC_DAIFMT_DSP_B:
++			aiface |= 0x0003;
++			aiface_ctrl |= 0x0010;
++			break;
++		}
++
++		/* bit size */
++		switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++		case SNDRV_PCM_FMTBIT_S16_LE:
++			break;
++		case SNDRV_PCM_FMTBIT_S20_3LE:
++			aiface |= 0x0004;
++			break;
++		case SNDRV_PCM_FMTBIT_S24_LE:
++			aiface |= 0x0008;
++			break;
++		case SNDRV_PCM_FMTBIT_S32_LE:
++			aiface |= 0x000c;
++			break;
++		}
++
++		/* clock inversion */
++		switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++		case SND_SOC_DAIFMT_NB_NF:
++			break;
++		case SND_SOC_DAIFMT_IB_NF:
++			aiface_ctrl |= 0x0020;
++			break;
++		}
++
++		/* set rate */
++		switch (rtd->codec_dai->dai_runtime.fs) {
++		case 768:
++			aiface |= (0x5 << 5);
++			break;
++		case 512:
++			aiface |= (0x4 << 5);
++			break;
++		case 384:
++			aiface |= (0x3 << 5);
++			break;
++		case 256:
++			aiface |= (0x2 << 5);
++			break;
++		}
++
++		wm8772_write(codec, WM8772_ADCCTRL, aiface_ctrl);
++		wm8772_write(codec, WM8772_ADCRATE, aiface);
++	}
++
++	return 0;
++}
++
++static int wm8772_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 master = wm8772_read_reg_cache(codec, WM8772_DACRATE) & 0xffe0;
++
++	switch (event) {
++		case SNDRV_CTL_POWER_D0: /* full On */
++			/* vref/mid, clk and osc on, dac unmute, active */
++			wm8772_write(codec, WM8772_DACRATE, master);
++			break;
++		case SNDRV_CTL_POWER_D1: /* partial On */
++		case SNDRV_CTL_POWER_D2: /* partial On */
++			break;
++		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++			/* everything off except vref/vmid, dac mute, inactive */
++			wm8772_write(codec, WM8772_DACRATE, master | 0x0f);
++			break;
++		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++			/* everything off, dac mute, inactive */
++			wm8772_write(codec, WM8772_DACRATE, master | 0x1f);
++			break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8772_dai = {
++	.name = "WM8772",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 6,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8772_config_sysclk,
++	.ops = {
++		.prepare = wm8772_pcm_prepare,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8772_modes),
++		.mode = wm8772_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8772_dai);
++
++static int wm8772_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;
++
++	wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8772_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8772_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8772_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8772 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8772_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8772";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8772_read_reg_cache;
++	codec->write = wm8772_write;
++	codec->dapm_event = wm8772_dapm_event;
++	codec->dai = &wm8772_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8772_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8772_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8772_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8772_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8772_reg);
++
++	wm8772_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* set the update bits */
++	reg = wm8772_read_reg_cache(codec, WM8772_MDACVOL);
++	wm8772_write(codec, WM8772_MDACVOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_LDAC1VOL);
++	wm8772_write(codec, WM8772_LDAC1VOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_LDAC2VOL);
++	wm8772_write(codec, WM8772_LDAC2VOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_LDAC3VOL);
++	wm8772_write(codec, WM8772_LDAC3VOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_RDAC1VOL);
++	wm8772_write(codec, WM8772_RDAC1VOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_RDAC2VOL);
++	wm8772_write(codec, WM8772_RDAC2VOL, reg | 0x0100);
++	reg = wm8772_read_reg_cache(codec, WM8772_RDAC3VOL);
++	wm8772_write(codec, WM8772_RDAC3VOL, reg | 0x0100);
++
++	wm8772_add_controls(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0) {
++		snd_soc_free_pcms(socdev);
++		snd_soc_dapm_free(socdev);
++	}
++
++	return ret;
++}
++
++static struct snd_soc_device *wm8772_socdev;
++
++static int wm8772_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8772_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	printk(KERN_INFO "WM8772 Audio Codec %s", WM8772_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);
++
++	wm8772_socdev = socdev;
++
++	/* Add other interfaces here */
++#warning do SPI device probe here and then call wm8772_init()
++
++	return ret;
++}
++
++/* power down chip */
++static int wm8772_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)
++		wm8772_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8772 = {
++	.probe = 	wm8772_probe,
++	.remove = 	wm8772_remove,
++	.suspend = 	wm8772_suspend,
++	.resume =	wm8772_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8772);
++
++MODULE_DESCRIPTION("ASoC WM8772 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8772.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8772.h
+@@ -0,0 +1,40 @@
++/*
++ * wm8772.h  --  audio driver for WM8772
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ */
++
++#ifndef _WM8772_H
++#define _WM8772_H
++
++/* WM8772 register space */
++
++#define WM8772_LDAC1VOL   0x00
++#define WM8772_RDAC1VOL   0x01
++#define WM8772_DACCH      0x02
++#define WM8772_IFACE      0x03
++#define WM8772_LDAC2VOL   0x04
++#define WM8772_RDAC2VOL   0x05
++#define WM8772_LDAC3VOL   0x06
++#define WM8772_RDAC3VOL   0x07
++#define WM8772_MDACVOL    0x08
++#define WM8772_DACCTRL    0x09
++#define WM8772_DACRATE    0x0a
++#define WM8772_ADCRATE    0x0b
++#define WM8772_ADCCTRL    0x0c
++#define WM8772_RESET	  0x1f
++
++#define WM8772_CACHE_REGNUM 	10
++
++extern struct snd_soc_codec_dai wm8772_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8772;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8971.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8971.c
+@@ -0,0 +1,1214 @@
++/*
++ * wm8971.c  --  WM8971 ALSA SoC Audio driver
++ *
++ * Copyright 2005 Lab126, Inc.
++ *
++ * Author: Kenneth Kiraly <kiraly at lab126.com>
++ *
++ * Based on wm8753.c by Liam Girdwood
++ *
++ *  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/i2c.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 "wm8971.h"
++
++#define AUDIO_NAME "wm8971"
++#define WM8971_VERSION "0.8"
++
++#undef	WM8971_DEBUG
++
++#ifdef WM8971_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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	WM8971_REG_COUNT		43
++
++static struct workqueue_struct *wm8971_workq = NULL;
++static struct work_struct wm8971_dapm_work;
++
++/*
++ * wm8971 register cache
++ * We can't read the WM8971 register space when we
++ * are using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8971_reg[] = {
++	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
++	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
++	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
++	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
++	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
++	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
++	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
++	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
++	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
++	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
++	0x0079, 0x0079, 0x0079,          /* 40 */
++};
++
++#define WM8971_HIFI_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8971_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8971_HIFI_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++#define WM8971_HIFI_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++#define WM8971_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8971_modes[] = {
++	/* common codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1408,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2304,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 2112,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 11.025k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1024,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1536,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1088,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 16k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1152,
++		.bfs = WM8971_HIFI_FSB
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 750,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 22.05k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 512,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 768,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 544,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 32k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 576,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 375,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 44.1k & 48k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 384,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* 88.2k & 96k */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 128,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 192,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 136,
++		.bfs = WM8971_HIFI_FSB,
++	},
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 125,
++		.bfs = WM8971_HIFI_FSB,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8971_HIFI_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8971_HIFI_BITS,
++		.pcmrate = WM8971_HIFI_RATES,
++		.pcmdir = WM8971_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < WM8971_REG_COUNT)
++		return cache[reg];
++
++	return -1;
++}
++
++static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < WM8971_REG_COUNT)
++		cache[reg] = value;
++}
++
++static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8753 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8971_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8971_reset(c)	wm8971_write(c, WM8971_RESET, 0)
++
++/* WM8971 Controls */
++static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
++static const char *wm8971_bass_filter[] = { "130Hz @ 48kHz",
++	"200Hz @ 48kHz" };
++static const char *wm8971_treble[] = { "8kHz", "4kHz" };
++static const char *wm8971_alc_func[] = { "Off", "Right", "Left", "Stereo" };
++static const char *wm8971_ng_type[] = { "Constant PGA Gain",
++	"Mute ADC Output" };
++static const char *wm8971_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
++static const char *wm8971_mono_mux[] = {"Stereo", "Mono (Left)",
++	"Mono (Right)", "Digital Mono"};
++static const char *wm8971_dac_phase[] = { "Non Inverted", "Inverted" };
++static const char *wm8971_lline_mux[] = {"Line", "NC", "NC", "PGA",
++	"Differential"};
++static const char *wm8971_rline_mux[] = {"Line", "Mic", "NC", "PGA",
++	"Differential"};
++static const char *wm8971_lpga_sel[] = {"Line", "NC", "NC", "Differential"};
++static const char *wm8971_rpga_sel[] = {"Line", "Mic", "NC", "Differential"};
++static const char *wm8971_adcpol[] = {"Normal", "L Invert", "R Invert",
++	"L + R Invert"};
++
++static const struct soc_enum wm8971_enum[] = {
++	SOC_ENUM_SINGLE(WM8971_BASS, 7, 2, wm8971_bass),			/* 0 */
++	SOC_ENUM_SINGLE(WM8971_BASS, 6, 2, wm8971_bass_filter),
++	SOC_ENUM_SINGLE(WM8971_TREBLE, 6, 2, wm8971_treble),
++	SOC_ENUM_SINGLE(WM8971_ALC1, 7, 4, wm8971_alc_func),
++	SOC_ENUM_SINGLE(WM8971_NGATE, 1, 2, wm8971_ng_type),        /* 4 */
++	SOC_ENUM_SINGLE(WM8971_ADCDAC, 1, 4, wm8971_deemp),
++	SOC_ENUM_SINGLE(WM8971_ADCTL1, 4, 4, wm8971_mono_mux),
++	SOC_ENUM_SINGLE(WM8971_ADCTL1, 1, 2, wm8971_dac_phase),
++	SOC_ENUM_SINGLE(WM8971_LOUTM1, 0, 5, wm8971_lline_mux),     /* 8 */
++	SOC_ENUM_SINGLE(WM8971_ROUTM1, 0, 5, wm8971_rline_mux),
++	SOC_ENUM_SINGLE(WM8971_LADCIN, 6, 4, wm8971_lpga_sel),
++	SOC_ENUM_SINGLE(WM8971_RADCIN, 6, 4, wm8971_rpga_sel),
++	SOC_ENUM_SINGLE(WM8971_ADCDAC, 5, 4, wm8971_adcpol),        /* 12 */
++	SOC_ENUM_SINGLE(WM8971_ADCIN, 6, 4, wm8971_mono_mux),
++};
++
++static const struct snd_kcontrol_new wm8971_snd_controls[] = {
++	SOC_DOUBLE_R("Capture Volume", WM8971_LINVOL, WM8971_RINVOL, 0, 63, 0),
++	SOC_DOUBLE_R("Capture ZC Switch", WM8971_LINVOL, WM8971_RINVOL, 6, 1, 0),
++	SOC_DOUBLE_R("Capture Switch", WM8971_LINVOL, WM8971_RINVOL, 7, 1, 1),
++
++	SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8971_LOUT1V,
++		WM8971_ROUT1V, 7, 1, 0),
++	SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8971_LOUT2V,
++		WM8971_ROUT2V, 7, 1, 0),
++	SOC_SINGLE("Mono Playback ZC Switch", WM8971_MOUTV, 7, 1, 0),
++
++	SOC_DOUBLE_R("PCM Volume", WM8971_LDAC, WM8971_RDAC, 0, 255, 0),
++
++	SOC_DOUBLE_R("Bypass Left Playback Volume", WM8971_LOUTM1,
++		WM8971_LOUTM2, 4, 7, 1),
++	SOC_DOUBLE_R("Bypass Right Playback Volume", WM8971_ROUTM1,
++		WM8971_ROUTM2, 4, 7, 1),
++	SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8971_MOUTM1,
++		WM8971_MOUTM2, 4, 7, 1),
++
++	SOC_DOUBLE_R("Headphone Playback Volume", WM8971_LOUT1V,
++		WM8971_ROUT1V, 0, 127, 0),
++	SOC_DOUBLE_R("Speaker Playback Volume", WM8971_LOUT2V,
++		WM8971_ROUT2V, 0, 127, 0),
++
++	SOC_ENUM("Bass Boost", wm8971_enum[0]),
++	SOC_ENUM("Bass Filter", wm8971_enum[1]),
++	SOC_SINGLE("Bass Volume", WM8971_BASS, 0, 7, 1),
++
++	SOC_SINGLE("Treble Volume", WM8971_TREBLE, 0, 7, 0),
++	SOC_ENUM("Treble Cut-off", wm8971_enum[2]),
++
++	SOC_SINGLE("Capture Filter Switch", WM8971_ADCDAC, 0, 1, 1),
++
++	SOC_SINGLE("ALC Target Volume", WM8971_ALC1, 0, 7, 0),
++	SOC_SINGLE("ALC Max Volume", WM8971_ALC1, 4, 7, 0),
++
++	SOC_SINGLE("ALC Capture Target Volume", WM8971_ALC1, 0, 7, 0),
++	SOC_SINGLE("ALC Capture Max Volume", WM8971_ALC1, 4, 7, 0),
++	SOC_ENUM("ALC Capture Function", wm8971_enum[3]),
++	SOC_SINGLE("ALC Capture ZC Switch", WM8971_ALC2, 7, 1, 0),
++	SOC_SINGLE("ALC Capture Hold Time", WM8971_ALC2, 0, 15, 0),
++	SOC_SINGLE("ALC Capture Decay Time", WM8971_ALC3, 4, 15, 0),
++	SOC_SINGLE("ALC Capture Attack Time", WM8971_ALC3, 0, 15, 0),
++	SOC_SINGLE("ALC Capture NG Threshold", WM8971_NGATE, 3, 31, 0),
++	SOC_ENUM("ALC Capture NG Type", wm8971_enum[4]),
++	SOC_SINGLE("ALC Capture NG Switch", WM8971_NGATE, 0, 1, 0),
++
++	SOC_SINGLE("Capture 6dB Attenuate", WM8971_ADCDAC, 8, 1, 0),
++	SOC_SINGLE("Playback 6dB Attenuate", WM8971_ADCDAC, 7, 1, 0),
++
++    SOC_ENUM("Playback De-emphasis", wm8971_enum[5]),
++	SOC_ENUM("Playback Function", wm8971_enum[6]),
++	SOC_ENUM("Playback Phase", wm8971_enum[7]),
++
++	SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0),
++};
++
++/* add non-DAPM controls */
++static int wm8971_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8971_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/*
++ * DAPM Controls
++ */
++
++/* Left Mixer */
++static const struct snd_kcontrol_new wm8971_left_mixer_controls[] = {
++SOC_DAPM_SINGLE("Playback Switch", WM8971_LOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_LOUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8971_LOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_LOUTM2, 7, 1, 0),
++};
++
++/* Right Mixer */
++static const struct snd_kcontrol_new wm8971_right_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left Playback Switch", WM8971_ROUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_ROUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Playback Switch", WM8971_ROUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_ROUTM2, 7, 1, 0),
++};
++
++/* Mono Mixer */
++static const struct snd_kcontrol_new wm8971_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left Playback Switch", WM8971_MOUTM1, 8, 1, 0),
++SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_MOUTM1, 7, 1, 0),
++SOC_DAPM_SINGLE("Right Playback Switch", WM8971_MOUTM2, 8, 1, 0),
++SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_MOUTM2, 7, 1, 0),
++};
++
++/* Left Line Mux */
++static const struct snd_kcontrol_new wm8971_left_line_controls =
++SOC_DAPM_ENUM("Route", wm8971_enum[8]);
++
++/* Right Line Mux */
++static const struct snd_kcontrol_new wm8971_right_line_controls =
++SOC_DAPM_ENUM("Route", wm8971_enum[9]);
++
++/* Left PGA Mux */
++static const struct snd_kcontrol_new wm8971_left_pga_controls =
++SOC_DAPM_ENUM("Route", wm8971_enum[10]);
++
++/* Right PGA Mux */
++static const struct snd_kcontrol_new wm8971_right_pga_controls =
++SOC_DAPM_ENUM("Route", wm8971_enum[11]);
++
++/* Mono ADC Mux */
++static const struct snd_kcontrol_new wm8971_monomux_controls =
++SOC_DAPM_ENUM("Route", wm8971_enum[13]);
++
++static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
++	SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
++		&wm8971_left_mixer_controls[0],
++		ARRAY_SIZE(wm8971_left_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
++		&wm8971_right_mixer_controls[0],
++		ARRAY_SIZE(wm8971_right_mixer_controls)),
++	SND_SOC_DAPM_MIXER("Mono Mixer", WM8971_PWR2, 2, 0,
++		&wm8971_mono_mixer_controls[0],
++		ARRAY_SIZE(wm8971_mono_mixer_controls)),
++
++	SND_SOC_DAPM_PGA("Right Out 2", WM8971_PWR2, 3, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Left Out 2", WM8971_PWR2, 4, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Right Out 1", WM8971_PWR2, 5, 0, NULL, 0),
++	SND_SOC_DAPM_PGA("Left Out 1", WM8971_PWR2, 6, 0, NULL, 0),
++	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8971_PWR2, 7, 0),
++	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0),
++	SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0),
++
++	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8971_PWR1, 1, 0),
++	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0),
++	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0),
++
++	SND_SOC_DAPM_MUX("Left PGA Mux", WM8971_PWR1, 5, 0,
++		&wm8971_left_pga_controls),
++	SND_SOC_DAPM_MUX("Right PGA Mux", WM8971_PWR1, 4, 0,
++		&wm8971_right_pga_controls),
++	SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
++		&wm8971_left_line_controls),
++	SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
++		&wm8971_right_line_controls),
++
++	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
++		&wm8971_monomux_controls),
++	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
++		&wm8971_monomux_controls),
++
++	SND_SOC_DAPM_OUTPUT("LOUT1"),
++	SND_SOC_DAPM_OUTPUT("ROUT1"),
++	SND_SOC_DAPM_OUTPUT("LOUT2"),
++	SND_SOC_DAPM_OUTPUT("ROUT2"),
++	SND_SOC_DAPM_OUTPUT("MONO"),
++
++	SND_SOC_DAPM_INPUT("LINPUT1"),
++	SND_SOC_DAPM_INPUT("RINPUT1"),
++	SND_SOC_DAPM_INPUT("MIC"),
++};
++
++static const char *audio_map[][3] = {
++	/* left mixer */
++	{"Left Mixer", "Playback Switch", "Left DAC"},
++	{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Left Mixer", "Right Playback Switch", "Right DAC"},
++	{"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* right mixer */
++	{"Right Mixer", "Left Playback Switch", "Left DAC"},
++	{"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Right Mixer", "Playback Switch", "Right DAC"},
++	{"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* left out 1 */
++	{"Left Out 1", NULL, "Left Mixer"},
++	{"LOUT1", NULL, "Left Out 1"},
++
++	/* left out 2 */
++	{"Left Out 2", NULL, "Left Mixer"},
++	{"LOUT2", NULL, "Left Out 2"},
++
++	/* right out 1 */
++	{"Right Out 1", NULL, "Right Mixer"},
++	{"ROUT1", NULL, "Right Out 1"},
++
++	/* right out 2 */
++	{"Right Out 2", NULL, "Right Mixer"},
++	{"ROUT2", NULL, "Right Out 2"},
++
++	/* mono mixer */
++	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
++	{"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
++	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
++	{"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
++
++	/* mono out */
++	{"Mono Out", NULL, "Mono Mixer"},
++	{"MONO1", NULL, "Mono Out"},
++
++	/* Left Line Mux */
++	{"Left Line Mux", "Line", "LINPUT1"},
++	{"Left Line Mux", "PGA", "Left PGA Mux"},
++	{"Left Line Mux", "Differential", "Differential Mux"},
++
++	/* Right Line Mux */
++	{"Right Line Mux", "Line", "RINPUT1"},
++	{"Right Line Mux", "Mic", "MIC"},
++	{"Right Line Mux", "PGA", "Right PGA Mux"},
++	{"Right Line Mux", "Differential", "Differential Mux"},
++
++	/* Left PGA Mux */
++	{"Left PGA Mux", "Line", "LINPUT1"},
++	{"Left PGA Mux", "Differential", "Differential Mux"},
++
++	/* Right PGA Mux */
++	{"Right PGA Mux", "Line", "RINPUT1"},
++	{"Right PGA Mux", "Differential", "Differential Mux"},
++
++	/* Differential Mux */
++	{"Differential Mux", "Line", "LINPUT1"},
++	{"Differential Mux", "Line", "RINPUT1"},
++
++	/* Left ADC Mux */
++	{"Left ADC Mux", "Stereo", "Left PGA Mux"},
++	{"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
++	{"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
++
++	/* Right ADC Mux */
++	{"Right ADC Mux", "Stereo", "Right PGA Mux"},
++	{"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
++	{"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
++
++	/* ADC */
++	{"Left ADC", NULL, "Left ADC Mux"},
++	{"Right ADC", NULL, "Right ADC Mux"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8971_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8971_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8971_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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;
++}
++
++struct _coeff_div {
++	u32 mclk;
++	u32 rate;
++	u16 fs;
++	u8 sr:5;
++	u8 usb:1;
++};
++
++/* codec hifi mclk clock divider coefficients */
++static const struct _coeff_div coeff_div[] = {
++	/* 8k */
++	{12288000, 8000, 1536, 0x6, 0x0},
++	{11289600, 8000, 1408, 0x16, 0x0},
++	{18432000, 8000, 2304, 0x7, 0x0},
++	{16934400, 8000, 2112, 0x17, 0x0},
++	{12000000, 8000, 1500, 0x6, 0x1},
++
++	/* 11.025k */
++	{11289600, 11025, 1024, 0x18, 0x0},
++	{16934400, 11025, 1536, 0x19, 0x0},
++	{12000000, 11025, 1088, 0x19, 0x1},
++
++	/* 16k */
++	{12288000, 16000, 768, 0xa, 0x0},
++	{18432000, 16000, 1152, 0xb, 0x0},
++	{12000000, 16000, 750, 0xa, 0x1},
++
++	/* 22.05k */
++	{11289600, 22050, 512, 0x1a, 0x0},
++	{16934400, 22050, 768, 0x1b, 0x0},
++	{12000000, 22050, 544, 0x1b, 0x1},
++
++	/* 32k */
++	{12288000, 32000, 384, 0xc, 0x0},
++	{18432000, 32000, 576, 0xd, 0x0},
++	{12000000, 32000, 375, 0xa, 0x1},
++
++	/* 44.1k */
++	{11289600, 44100, 256, 0x10, 0x0},
++	{16934400, 44100, 384, 0x11, 0x0},
++	{12000000, 44100, 272, 0x11, 0x1},
++
++	/* 48k */
++	{12288000, 48000, 256, 0x0, 0x0},
++	{18432000, 48000, 384, 0x1, 0x0},
++	{12000000, 48000, 250, 0x0, 0x1},
++
++	/* 88.2k */
++	{11289600, 88200, 128, 0x1e, 0x0},
++	{16934400, 88200, 192, 0x1f, 0x0},
++	{12000000, 88200, 136, 0x1f, 0x1},
++
++	/* 96k */
++	{12288000, 96000, 128, 0xe, 0x0},
++	{18432000, 96000, 192, 0xf, 0x0},
++	{12000000, 96000, 125, 0xe, 0x1},
++};
++
++static int get_coeff(int mclk, int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
++		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
++			return i;
++	}
++	return -EINVAL;
++}
++
++/* WM8971 supports numerous input clocks per sample rate */
++static unsigned int wm8971_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	dai->mclk = 0;
++
++	/* check that the calculated FS and rate actually match a clock from
++	 * the machine driver */
++	if (info->fs * info->rate == clk)
++		dai->mclk = clk;
++
++	return dai->mclk;
++}
++
++static int wm8971_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 iface = 0, bfs, srate = 0;
++	int i = get_coeff(rtd->codec_dai->mclk,
++		snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate));
++
++	/* is coefficient valid ? */
++	if (i < 0)
++		return i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		iface |= 0x0040;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		iface |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x000c;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0010;
++		break;
++	}
++
++	/* set bclk divisor rate */
++	switch (bfs) {
++	case 1:
++		break;
++	case 4:
++		srate |= (0x1 << 7);
++		break;
++	case 8:
++		srate |= (0x2 << 7);
++		break;
++	case 16:
++		srate |= (0x3 << 7);
++		break;
++	}
++
++	/* set iface & srate */
++	wm8971_write(codec, WM8971_AUDIO, iface);
++	wm8971_write(codec, WM8971_SRATE, srate |
++		(coeff_div[i].sr << 1) | coeff_div[i].usb);
++	return 0;
++}
++
++static int wm8971_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7;
++	if (mute)
++		wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
++	else
++		wm8971_write(codec, WM8971_ADCDAC, mute_reg);
++	return 0;
++}
++
++static int wm8971_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* set vmid to 50k and unmute dac */
++		wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		/* set vmid to 5k for quick power up */
++		wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x01c0);
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* mute dac and set vmid to 500k, enable VREF */
++		wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		wm8971_write(codec, WM8971_PWR1, 0x0001);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8971_dai = {
++	.name = "WM8971",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8971_config_sysclk,
++	.digital_mute = wm8971_mute,
++	.ops = {
++		.prepare = wm8971_pcm_prepare,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8971_modes),
++		.mode = wm8971_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8971_dai);
++
++static void wm8971_work(void *data)
++{
++	struct snd_soc_codec *codec = (struct snd_soc_codec *)data;
++	wm8971_dapm_event(codec, codec->dapm_state);
++}
++
++static int wm8971_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;
++
++	wm8971_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8971_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
++		if (i + 1 == WM8971_RESET)
++			continue;
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++
++	wm8971_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* charge wm8971 caps */
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
++		wm8971_dapm_event(codec, SNDRV_CTL_POWER_D2);
++		codec->dapm_state = SNDRV_CTL_POWER_D0;
++		queue_delayed_work(wm8971_workq, &wm8971_dapm_work,
++			msecs_to_jiffies(1000));
++	}
++
++	return 0;
++}
++
++static int wm8971_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8971";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8971_read_reg_cache;
++	codec->write = wm8971_write;
++	codec->dapm_event = wm8971_dapm_event;
++	codec->dai = &wm8971_dai;
++	codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
++	codec->num_dai = 1;
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8971_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8971_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8971_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8971_reg);
++
++	wm8971_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* charge output caps */
++	wm8971_dapm_event(codec, SNDRV_CTL_POWER_D2);
++	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
++	queue_delayed_work(wm8971_workq, &wm8971_dapm_work,
++		msecs_to_jiffies(1000));
++
++	/* set the update bits */
++	reg = wm8971_read_reg_cache(codec, WM8971_LDAC);
++	wm8971_write(codec, WM8971_LDAC, reg | 0x0100);
++	reg = wm8971_read_reg_cache(codec, WM8971_RDAC);
++	wm8971_write(codec, WM8971_RDAC, reg | 0x0100);
++
++	reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V);
++	wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100);
++	reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V);
++	wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100);
++
++	reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V);
++	wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100);
++	reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V);
++	wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100);
++
++	reg = wm8971_read_reg_cache(codec, WM8971_LINVOL);
++	wm8971_write(codec, WM8971_LINVOL, reg | 0x0100);
++	reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
++	wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
++
++	wm8971_add_controls(codec);
++	wm8971_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0) {
++		snd_soc_free_pcms(socdev);
++		snd_soc_dapm_free(socdev);
++	}
++
++	return ret;
++}
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++static struct snd_soc_device *wm8971_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8731 2 wire address is determined by GPIO5
++ * state during powerup.
++ *    low  = 0x1a
++ *    high = 0x1b
++ */
++#define I2C_DRIVERID_WM8971 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8971_i2c_driver;
++static struct i2c_client client_template;
++
++static int wm8971_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8971_socdev;
++	struct wm8971_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++
++	i2c_set_clientdata(i2c, codec);
++
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8971_init(socdev);
++	if (ret < 0) {
++		err("failed to initialise WM8971\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8971_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8971_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8971_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8971_i2c_driver = {
++	.driver = {
++		.name = "WM8971 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8971,
++	.attach_adapter = wm8971_i2c_attach,
++	.detach_client =  wm8971_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8971",
++	.driver = &wm8971_i2c_driver,
++};
++#endif
++
++static int wm8971_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8971_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8971 Audio Codec %s", WM8971_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);
++	wm8971_socdev = socdev;
++
++	INIT_WORK(&wm8971_dapm_work, wm8971_work, codec);
++	wm8971_workq = create_workqueue("wm8971");
++	if (wm8971_workq == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8971_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++		/* Add other interfaces here */
++#endif
++
++	return ret;
++}
++
++/* power down chip */
++static int wm8971_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)
++		wm8971_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	if (wm8971_workq)
++		destroy_workqueue(wm8971_workq);
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8971_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8971 = {
++	.probe = 	wm8971_probe,
++	.remove = 	wm8971_remove,
++	.suspend = 	wm8971_suspend,
++	.resume =	wm8971_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
++
++MODULE_DESCRIPTION("ASoC WM8971 driver");
++MODULE_AUTHOR("Lab126");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8971.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8971.h
+@@ -0,0 +1,61 @@
++/*
++ * wm8971.h  --  audio driver for WM8971
++ *
++ * Copyright 2005 Lab126, Inc.
++ *
++ * Author: Kenneth Kiraly <kiraly at lab126.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.
++ *
++ */
++
++#ifndef _WM8971_H
++#define _WM8971_H
++
++#define WM8971_LINVOL	0x00
++#define WM8971_RINVOL	0x01
++#define WM8971_LOUT1V	0x02
++#define WM8971_ROUT1V	0x03
++#define WM8971_ADCDAC	0x05
++#define WM8971_AUDIO	0x07
++#define WM8971_SRATE	0x08
++#define WM8971_LDAC		0x0a
++#define WM8971_RDAC		0x0b
++#define WM8971_BASS		0x0c
++#define WM8971_TREBLE	0x0d
++#define WM8971_RESET	0x0f
++#define WM8971_ALC1		0x11
++#define	WM8971_ALC2		0x12
++#define	WM8971_ALC3		0x13
++#define WM8971_NGATE	0x14
++#define WM8971_LADC		0x15
++#define WM8971_RADC		0x16
++#define	WM8971_ADCTL1	0x17
++#define	WM8971_ADCTL2	0x18
++#define WM8971_PWR1		0x19
++#define WM8971_PWR2		0x1a
++#define	WM8971_ADCTL3	0x1b
++#define WM8971_ADCIN	0x1f
++#define	WM8971_LADCIN	0x20
++#define	WM8971_RADCIN	0x21
++#define WM8971_LOUTM1	0x22
++#define WM8971_LOUTM2	0x23
++#define WM8971_ROUTM1	0x24
++#define WM8971_ROUTM2	0x25
++#define WM8971_MOUTM1	0x26
++#define WM8971_MOUTM2	0x27
++#define WM8971_LOUT2V	0x28
++#define WM8971_ROUT2V	0x29
++#define WM8971_MOUTV	0x2A
++
++struct wm8971_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8971_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8971;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8974.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8974.c
+@@ -0,0 +1,935 @@
++/*
++ * wm8974.c  --  WM8974 ALSA Soc Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ *
++ * Author: Liam Girdwood <liam.girdwood at wolfsonmicro.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/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8974.h"
++
++#define AUDIO_NAME "wm8974"
++#define WM8974_VERSION "0.5"
++
++/*
++ * Debug
++ */
++
++#define WM8974_DEBUG 0
++
++#ifdef WM8974_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8974;
++
++/*
++ * wm8974 register cache
++ * We can't read the WM8974 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0050, 0x0000, 0x0140, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x00ff,
++    0x0000, 0x0000, 0x0100, 0x00ff,
++    0x0000, 0x0000, 0x012c, 0x002c,
++    0x002c, 0x002c, 0x002c, 0x0000,
++    0x0032, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0038, 0x000b, 0x0032, 0x0000,
++    0x0008, 0x000c, 0x0093, 0x00e9,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0003, 0x0010, 0x0000, 0x0000,
++    0x0000, 0x0002, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0039, 0x0000,
++    0x0000,
++};
++
++#define WM8974_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8974_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8974_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)
++
++#define WM8794_BCLK \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | SND_SOC_FSBD(8) |\
++	 SND_SOC_FSBD(16) | SND_SOC_FSBD(32))
++
++#define WM8794_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8974_modes[] = {
++	/* codec frame and clock master modes */
++	{
++		.fmt = WM8974_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8794_HIFI_BITS,
++		.pcmrate = WM8974_RATES,
++		.pcmdir = WM8974_DIR,
++		.fs = 256,
++		.bfs = WM8794_BCLK,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8974_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8794_HIFI_BITS,
++		.pcmrate = WM8974_RATES,
++		.pcmdir = WM8974_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8974 register cache
++ */
++static inline unsigned int wm8974_read_reg_cache(struct snd_soc_codec * codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8974_RESET)
++		return 0;
++	if (reg >= WM8974_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8974 register cache
++ */
++static inline void wm8974_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8974_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8974 register space
++ */
++static int wm8974_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8974 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8974_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8974_reset(c)	wm8974_write(c, WM8974_RESET, 0)
++
++static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
++static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
++static const char *wm8974_eqmode[] = {"Capture", "Playback" };
++static const char *wm8974_bw[] = {"Narrow", "Wide" };
++static const char *wm8974_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" };
++static const char *wm8974_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" };
++static const char *wm8974_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" };
++static const char *wm8974_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" };
++static const char *wm8974_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" };
++static const char *wm8974_alc[] = {"ALC", "Limiter" };
++
++static const struct soc_enum wm8974_enum[] = {
++	SOC_ENUM_SINGLE(WM8974_COMP, 1, 4, wm8974_companding), /* adc */
++	SOC_ENUM_SINGLE(WM8974_COMP, 3, 4, wm8974_companding), /* dac */
++	SOC_ENUM_SINGLE(WM8974_DAC,  4, 4, wm8974_deemp),
++	SOC_ENUM_SINGLE(WM8974_EQ1,  8, 2, wm8974_eqmode),
++
++	SOC_ENUM_SINGLE(WM8974_EQ1,  5, 4, wm8974_eq1),
++	SOC_ENUM_SINGLE(WM8974_EQ2,  8, 2, wm8974_bw),
++	SOC_ENUM_SINGLE(WM8974_EQ2,  5, 4, wm8974_eq2),
++	SOC_ENUM_SINGLE(WM8974_EQ3,  8, 2, wm8974_bw),
++
++	SOC_ENUM_SINGLE(WM8974_EQ3,  5, 4, wm8974_eq3),
++	SOC_ENUM_SINGLE(WM8974_EQ4,  8, 2, wm8974_bw),
++	SOC_ENUM_SINGLE(WM8974_EQ4,  5, 4, wm8974_eq4),
++	SOC_ENUM_SINGLE(WM8974_EQ5,  8, 2, wm8974_bw),
++
++	SOC_ENUM_SINGLE(WM8974_EQ5,  5, 4, wm8974_eq5),
++	SOC_ENUM_SINGLE(WM8974_ALC3,  8, 2, wm8974_alc),
++};
++
++static const struct snd_kcontrol_new wm8974_snd_controls[] = {
++
++SOC_SINGLE("Digital Loopback Switch", WM8974_COMP, 0, 1, 0),
++
++SOC_ENUM("DAC Companding", wm8974_enum[1]),
++SOC_ENUM("ADC Companding", wm8974_enum[0]),
++
++SOC_ENUM("Playback De-emphasis", wm8974_enum[2]),
++SOC_SINGLE("DAC Inversion Switch", WM8974_DAC, 0, 1, 0),
++
++SOC_SINGLE("PCM Volume", WM8974_DACVOL, 0, 127, 0),
++
++SOC_SINGLE("High Pass Filter Switch", WM8974_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Cut Off", WM8974_ADC, 4, 7, 0),
++SOC_SINGLE("ADC Inversion Switch", WM8974_COMP, 0, 1, 0),
++
++SOC_SINGLE("Capture Volume", WM8974_ADCVOL,  0, 127, 0),
++
++SOC_ENUM("Equaliser Function", wm8974_enum[3]),
++SOC_ENUM("EQ1 Cut Off", wm8974_enum[4]),
++SOC_SINGLE("EQ1 Volume", WM8974_EQ1,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ2 Bandwith", wm8974_enum[5]),
++SOC_ENUM("EQ2 Cut Off", wm8974_enum[6]),
++SOC_SINGLE("EQ2 Volume", WM8974_EQ2,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ3 Bandwith", wm8974_enum[7]),
++SOC_ENUM("EQ3 Cut Off", wm8974_enum[8]),
++SOC_SINGLE("EQ3 Volume", WM8974_EQ3,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ4 Bandwith", wm8974_enum[9]),
++SOC_ENUM("EQ4 Cut Off", wm8974_enum[10]),
++SOC_SINGLE("EQ4 Volume", WM8974_EQ4,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ5 Bandwith", wm8974_enum[11]),
++SOC_ENUM("EQ5 Cut Off", wm8974_enum[12]),
++SOC_SINGLE("EQ5 Volume", WM8974_EQ5,  0, 31, 1),
++
++SOC_SINGLE("DAC Playback Limiter Switch", WM8974_DACLIM1,  8, 1, 0),
++SOC_SINGLE("DAC Playback Limiter Decay", WM8974_DACLIM1,  4, 15, 0),
++SOC_SINGLE("DAC Playback Limiter Attack", WM8974_DACLIM1,  0, 15, 0),
++
++SOC_SINGLE("DAC Playback Limiter Threshold", WM8974_DACLIM2,  4, 7, 0),
++SOC_SINGLE("DAC Playback Limiter Boost", WM8974_DACLIM2,  0, 15, 0),
++
++SOC_SINGLE("ALC Enable Switch", WM8974_ALC1,  8, 1, 0),
++SOC_SINGLE("ALC Capture Max Gain", WM8974_ALC1,  3, 7, 0),
++SOC_SINGLE("ALC Capture Min Gain", WM8974_ALC1,  0, 7, 0),
++
++SOC_SINGLE("ALC Capture ZC Switch", WM8974_ALC2,  8, 1, 0),
++SOC_SINGLE("ALC Capture Hold", WM8974_ALC2,  4, 7, 0),
++SOC_SINGLE("ALC Capture Target", WM8974_ALC2,  0, 15, 0),
++
++SOC_ENUM("ALC Capture Mode", wm8974_enum[13]),
++SOC_SINGLE("ALC Capture Decay", WM8974_ALC3,  4, 15, 0),
++SOC_SINGLE("ALC Capture Attack", WM8974_ALC3,  0, 15, 0),
++
++SOC_SINGLE("ALC Capture Noise Gate Switch", WM8974_NGATE,  3, 1, 0),
++SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8974_NGATE,  0, 7, 0),
++
++SOC_SINGLE("Capture PGA ZC Switch", WM8974_INPPGA,  7, 1, 0),
++SOC_SINGLE("Capture PGA Volume", WM8974_INPPGA,  0, 63, 0),
++
++SOC_SINGLE("Speaker Playback ZC Switch", WM8974_SPKVOL,  7, 1, 0),
++SOC_SINGLE("Speaker Playback Switch", WM8974_SPKVOL,  6, 1, 1),
++SOC_SINGLE("Speaker Playback Volume", WM8974_SPKVOL,  0, 63, 0),
++
++SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST,  8, 1, 0),
++SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm8974_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8974_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8974_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Speaker Output Mixer */
++static const struct snd_kcontrol_new wm8974_speaker_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_SPKMIX, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_SPKMIX, 5, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_SPKMIX, 0, 1, 1),
++};
++
++/* Mono Output Mixer */
++static const struct snd_kcontrol_new wm8974_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_MONOMIX, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_MONOMIX, 2, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 1),
++};
++
++/* AUX Input boost vol */
++static const struct snd_kcontrol_new wm8974_aux_boost_controls =
++SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0);
++
++/* Mic Input boost vol */
++static const struct snd_kcontrol_new wm8974_mic_boost_controls =
++SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0);
++
++/* Capture boost switch */
++static const struct snd_kcontrol_new wm8974_capture_boost_controls =
++SOC_DAPM_SINGLE("Capture Boost Switch", WM8974_INPPGA,  6, 1, 0);
++
++/* Aux In to PGA */
++static const struct snd_kcontrol_new wm8974_aux_capture_boost_controls =
++SOC_DAPM_SINGLE("Aux Capture Boost Switch", WM8974_INPPGA,  2, 1, 0);
++
++/* Mic P In to PGA */
++static const struct snd_kcontrol_new wm8974_micp_capture_boost_controls =
++SOC_DAPM_SINGLE("Mic P Capture Boost Switch", WM8974_INPPGA,  0, 1, 0);
++
++/* Mic N In to PGA */
++static const struct snd_kcontrol_new wm8974_micn_capture_boost_controls =
++SOC_DAPM_SINGLE("Mic N Capture Boost Switch", WM8974_INPPGA,  1, 1, 0);
++
++static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = {
++SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0,
++	&wm8974_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm8974_speaker_mixer_controls)),
++SND_SOC_DAPM_MIXER("Mono Mixer", WM8974_POWER3, 3, 0,
++	&wm8974_mono_mixer_controls[0],
++	ARRAY_SIZE(wm8974_mono_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8974_POWER3, 0, 0),
++SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8974_POWER3, 0, 0),
++SND_SOC_DAPM_PGA("Aux Input", WM8974_POWER1, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkN Out", WM8974_POWER3, 5, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkP Out", WM8974_POWER3, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", WM8974_POWER3, 7, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mic PGA", WM8974_POWER2, 2, 0, NULL, 0),
++
++SND_SOC_DAPM_PGA("Aux Boost", SND_SOC_NOPM, 0, 0,
++	&wm8974_aux_boost_controls, 1),
++SND_SOC_DAPM_PGA("Mic Boost", SND_SOC_NOPM, 0, 0,
++	&wm8974_mic_boost_controls, 1),
++SND_SOC_DAPM_SWITCH("Capture Boost", SND_SOC_NOPM, 0, 0,
++	&wm8974_capture_boost_controls),
++
++SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0, NULL, 0),
++
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
++
++SND_SOC_DAPM_INPUT("MICN"),
++SND_SOC_DAPM_INPUT("MICP"),
++SND_SOC_DAPM_INPUT("AUX"),
++SND_SOC_DAPM_OUTPUT("MONOOUT"),
++SND_SOC_DAPM_OUTPUT("SPKOUTP"),
++SND_SOC_DAPM_OUTPUT("SPKOUTN"),
++};
++
++static const char *audio_map[][3] = {
++	/* Mono output mixer */
++	{"Mono Mixer", "PCM Playback Switch", "DAC"},
++	{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Speaker output mixer */
++	{"Speaker Mixer", "PCM Playback Switch", "DAC"},
++	{"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Outputs */
++	{"Mono Out", NULL, "Mono Mixer"},
++	{"MONOOUT", NULL, "Mono Out"},
++	{"SpkN Out", NULL, "Speaker Mixer"},
++	{"SpkP Out", NULL, "Speaker Mixer"},
++	{"SPKOUTN", NULL, "SpkN Out"},
++	{"SPKOUTP", NULL, "SpkP Out"},
++
++	/* Boost Mixer */
++	{"Boost Mixer", NULL, "ADC"},
++    {"Capture Boost Switch", "Aux Capture Boost Switch", "AUX"},
++	{"Aux Boost", "Aux Volume", "Boost Mixer"},
++    {"Capture Boost", "Capture Switch", "Boost Mixer"},
++	{"Mic Boost", "Mic Volume", "Boost Mixer"},
++
++	/* Inputs */
++	{"MICP", NULL, "Mic Boost"},
++	{"MICN", NULL, "Mic PGA"},
++	{"Mic PGA", NULL, "Capture Boost"},
++	{"AUX", NULL, "Aux Input"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8974_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8974_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8974_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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;
++}
++
++struct pll_ {
++	unsigned int in_hz, out_hz;
++	unsigned int pre:4; /* prescale - 1 */
++	unsigned int n:4;
++	unsigned int k;
++};
++
++struct pll_ pll[] = {
++	{12000000, 11289600, 0, 7, 0x86c220},
++	{12000000, 12288000, 0, 8, 0x3126e8},
++	{13000000, 11289600, 0, 6, 0xf28bd4},
++	{13000000, 12288000, 0, 7, 0x8fd525},
++	{12288000, 11289600, 0, 7, 0x59999a},
++	{11289600, 12288000, 0, 8, 0x80dee9},
++	/* liam - add more entries */
++};
++
++static int set_pll(struct snd_soc_codec *codec, unsigned int in,
++	unsigned int out)
++{
++	int i;
++	u16 reg;
++
++	if(out == 0) {
++		reg = wm8974_read_reg_cache(codec, WM8974_POWER1);
++		wm8974_write(codec, WM8974_POWER1, reg & 0x1df);
++		return 0;
++	}
++
++	for(i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (in == pll[i].in_hz && out == pll[i].out_hz) {
++			wm8974_write(codec, WM8974_PLLN, (pll[i].pre << 4) | pll[i].n);
++			wm8974_write(codec, WM8974_PLLK1, pll[i].k >> 18);
++			wm8974_write(codec, WM8974_PLLK1, (pll[i].k >> 9) && 0x1ff);
++			wm8974_write(codec, WM8974_PLLK1, pll[i].k && 0x1ff);
++			reg = wm8974_read_reg_cache(codec, WM8974_POWER1);
++			wm8974_write(codec, WM8974_POWER1, reg | 0x020);
++			return 0;
++		}
++	}
++	return -EINVAL;
++}
++
++/* mclk dividers * 2 */
++static unsigned char mclk_div[] = {2, 3, 4, 6, 8, 12, 16, 24};
++
++/* we need 256FS to drive the DAC's and ADC's */
++static unsigned int wm8974_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if ((best_clk >> 1) * mclk_div[i] == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = mclk_div[i];
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == clk) {
++			for (j = 0; j < ARRAY_SIZE(mclk_div); j++) {
++				if (pll[i].out_hz == mclk_div[j] * (best_clk >> 1)) {
++					dai->pll_in = clk;
++					dai->pll_out = pll[i].out_hz;
++					dai->clk_div = mclk_div[j];
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++static int wm8974_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *dai = rtd->codec_dai;
++	u16 iface = 0, bfs, clk = 0, adn;
++	int fs = 48000 << 7, i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	switch (bfs) {
++	case 2:
++		clk |= 0x1 << 2;
++		break;
++	case 4:
++		clk |= 0x2 << 2;
++		break;
++	case 8:
++		clk |= 0x3 << 2;
++		break;
++	case 16:
++		clk |= 0x4 << 2;
++		break;
++	case 32:
++		clk |= 0x5 << 2;
++		break;
++	}
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		clk |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0010;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0008;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x00018;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0020;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0040;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x0060;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0180;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0100;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0080;
++		break;
++	}
++
++	/* filter coefficient */
++	adn = wm8974_read_reg_cache(codec, WM8974_ADD) & 0x1f1;
++	switch (rtd->codec_dai->dai_runtime.pcmrate) {
++	case SNDRV_PCM_RATE_8000:
++		adn |= 0x5 << 1;
++		fs = 8000 << 7;
++		break;
++	case SNDRV_PCM_RATE_11025:
++		adn |= 0x4 << 1;
++		fs = 11025 << 7;
++		break;
++	case SNDRV_PCM_RATE_16000:
++		adn |= 0x3 << 1;
++		fs = 16000 << 7;
++		break;
++	case SNDRV_PCM_RATE_22050:
++		adn |= 0x2 << 1;
++		fs = 22050 << 7;
++		break;
++	case SNDRV_PCM_RATE_32000:
++		adn |= 0x1 << 1;
++		fs = 32000 << 7;
++		break;
++	case SNDRV_PCM_RATE_44100:
++		fs = 44100 << 7;
++		break;
++	}
++
++	/* do we need to enable the PLL */
++	if(dai->pll_in)
++		set_pll(codec, dai->pll_in, dai->pll_out);
++
++	/* divide the clock to 256 fs */
++	for(i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if (dai->clk_div == mclk_div[i]) {
++			clk |= i << 5;
++			clk &= 0xff;
++			goto set;
++		}
++	}
++
++set:
++	/* set iface */
++	wm8974_write(codec, WM8974_IFACE, iface);
++	wm8974_write(codec, WM8974_CLOCK, clk);
++
++	return 0;
++}
++
++static int wm8974_hw_free(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	set_pll(codec, 0, 0);
++	return 0;
++}
++
++static int wm8974_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
++	if(mute)
++		wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
++	else
++		wm8974_write(codec, WM8974_DAC, mute_reg);
++	return 0;
++}
++
++/* liam need to make this lower power with dapm */
++static int wm8974_dapm_event(struct snd_soc_codec *codec, int event)
++{
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, clk and osc on, dac unmute, active */
++		wm8974_write(codec, WM8974_POWER1, 0x1ff);
++		wm8974_write(codec, WM8974_POWER2, 0x1ff);
++		wm8974_write(codec, WM8974_POWER3, 0x1ff);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, dac mute, inactive */
++
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8974_write(codec, WM8974_POWER1, 0x0);
++		wm8974_write(codec, WM8974_POWER2, 0x0);
++		wm8974_write(codec, WM8974_POWER3, 0x0);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8974_dai = {
++	.name = "WM8974 HiFi",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 1,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 1,
++	},
++	.config_sysclk = wm8974_config_sysclk,
++	.digital_mute = wm8974_mute,
++	.ops = {
++		.prepare = wm8974_pcm_prepare,
++		.hw_free = wm8974_hw_free,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8974_modes),
++		.mode = wm8974_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8974_dai);
++
++static int wm8974_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;
++
++	wm8974_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8974_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8974_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8974_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8974 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8974_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "WM8974";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8974_read_reg_cache;
++	codec->write = wm8974_write;
++	codec->dapm_event = wm8974_dapm_event;
++	codec->dai = &wm8974_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8974_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8974_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8974_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8974_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8974_reg);
++
++	wm8974_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8974_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8974_add_controls(codec);
++	wm8974_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 struct snd_soc_device *wm8974_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8974 2 wire address is 0x1a
++ */
++#define I2C_DRIVERID_WM8974 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8974_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8974_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8974_socdev;
++	struct wm8974_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL) {
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if(ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8974_init(socdev);
++	if(ret < 0) {
++		err("failed to initialise WM8974\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8974_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8974_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8974_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8974_i2c_driver = {
++	.driver = {
++		.name = "WM8974 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8974,
++	.attach_adapter = wm8974_i2c_attach,
++	.detach_client =  wm8974_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8974",
++	.driver = &wm8974_i2c_driver,
++};
++#endif
++
++static int wm8974_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8974_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8974 Audio Codec %s", WM8974_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);
++
++	wm8974_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8974_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8974_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)
++		wm8974_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8974_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8974 = {
++	.probe = 	wm8974_probe,
++	.remove = 	wm8974_remove,
++	.suspend = 	wm8974_suspend,
++	.resume =	wm8974_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974);
++
++MODULE_DESCRIPTION("ASoC WM8974 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8974.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8974.h
+@@ -0,0 +1,64 @@
++/*
++ * wm8974.h  --  WM8974 Soc Audio driver
++ *
++ * 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 _WM8974_H
++#define _WM8974_H
++
++/* WM8974 register space */
++
++#define WM8974_RESET		0x0
++#define WM8974_POWER1		0x1
++#define WM8974_POWER2		0x2
++#define WM8974_POWER3		0x3
++#define WM8974_IFACE		0x4
++#define WM8974_COMP			0x5
++#define WM8974_CLOCK		0x6
++#define WM8974_ADD			0x7
++#define WM8974_GPIO			0x8
++#define WM8974_DAC			0xa
++#define WM8974_DACVOL		0xb
++#define WM8974_ADC			0xe
++#define WM8974_ADCVOL		0xf
++#define WM8974_EQ1			0x12
++#define WM8974_EQ2			0x13
++#define WM8974_EQ3			0x14
++#define WM8974_EQ4			0x15
++#define WM8974_EQ5			0x16
++#define WM8974_DACLIM1		0x18
++#define WM8974_DACLIM2		0x19
++#define WM8974_NOTCH1		0x1b
++#define WM8974_NOTCH2		0x1c
++#define WM8974_NOTCH3		0x1d
++#define WM8974_NOTCH4		0x1e
++#define WM8974_ALC1			0x20
++#define WM8974_ALC2			0x21
++#define WM8974_ALC3			0x22
++#define WM8974_NGATE		0x23
++#define WM8974_PLLN			0x24
++#define WM8974_PLLK1		0x25
++#define WM8974_PLLK2		0x26
++#define WM8974_PLLK3		0x27
++#define WM8974_ATTEN		0x28
++#define WM8974_INPUT		0x2c
++#define WM8974_INPPGA		0x2d
++#define WM8974_ADCBOOST		0x2f
++#define WM8974_OUTPUT		0x31
++#define WM8974_SPKMIX		0x32
++#define WM8974_SPKVOL		0x36
++#define WM8974_MONOMIX		0x38
++
++#define WM8974_CACHEREGNUM 	57
++
++struct wm8974_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8974_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8974;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm9712.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm9712.c
+@@ -0,0 +1,781 @@
++/*
++ * wm9712.c  --  ALSA Soc WM9712 codec support
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    4th Feb 2006   Initial version.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#define WM9712_VERSION "0.4"
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg);
++static int ac97_write(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int val);
++
++#define AC97_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define AC97_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)
++
++/* may need to expand this */
++static struct snd_soc_dai_mode ac97_modes[] = {
++	{
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE,
++		.pcmrate = AC97_RATES,
++		.pcmdir = AC97_DIR,
++	},
++};
++
++/*
++ * WM9712 register cache
++ */
++static const u16 wm9712_reg[] = {
++	0x6174, 0x8000, 0x8000, 0x8000, // 6
++	0xf0f0, 0xaaa0, 0xc008, 0x6808, // e
++	0xe808, 0xaaa0, 0xad00, 0x8000, // 16
++	0xe808, 0x3000, 0x8000, 0x0000, // 1e
++	0x0000, 0x0000, 0x0000, 0x000f, // 26
++	0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
++	0x0000, 0xbb80, 0x0000, 0x0000, // 36
++	0x0000, 0x2000, 0x0000, 0x0000, // 3e
++	0x0000, 0x0000, 0x0000, 0x0000, // 46
++	0x0000, 0x0000, 0xf83e, 0xffff, // 4e
++	0x0000, 0x0000, 0x0000, 0xf83e, // 56
++	0x0008, 0x0000, 0x0000, 0x0000, // 5e
++	0xb032, 0x3e00, 0x0000, 0x0000, // 66
++	0x0000, 0x0000, 0x0000, 0x0000, // 6e
++	0x0000, 0x0000, 0x0000, 0x0006, // 76
++	0x0001, 0x0000, 0x574d, 0x4c12, // 7e
++	0x0000, 0x0000 // virtual hp mixers
++};
++
++/* virtual HP mixers regs */
++#define HPL_MIXER	0x80
++#define HPR_MIXER	0x82
++
++static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"};
++static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"};
++static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right",
++	"Mono"};
++static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"};
++static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
++static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
++static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2",
++	"Stereo"};
++static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
++	"Line", "Headphone Mixer", "Phone Mixer", "Phone"};
++static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
++static const char *wm9712_diff_sel[] = {"Mic", "Line"};
++
++static const struct soc_enum wm9712_enum[] = {
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
++SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
++SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src),
++SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src),
++SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc),
++SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base),
++SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain),
++SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic),
++SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel),
++SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel),
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type),
++SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel),
++};
++
++static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
++SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
++SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
++SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
++SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
++
++SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
++SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),
++SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0),
++SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
++SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 0),
++
++SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
++SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
++SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
++SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
++SOC_ENUM("ALC Function", wm9712_enum[0]),
++SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
++SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
++SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
++SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
++SOC_ENUM("ALC NG Type", wm9712_enum[10]),
++SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
++
++SOC_SINGLE("Mic Headphone  Volume", AC97_VIDEO, 12, 7, 1),
++SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
++
++SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
++SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
++SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
++
++SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
++SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1),
++SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1),
++
++SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1),
++SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1),
++SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1),
++
++SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 0),
++SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1),
++
++SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
++SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
++
++SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
++SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
++SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0),
++
++SOC_ENUM("Bass Control", wm9712_enum[5]),
++SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
++SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
++SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
++SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 0),
++SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 0),
++
++SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
++SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
++SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
++SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
++
++SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
++SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
++SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm9712_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/* We have to create a fake left and right HP mixers because
++ * the codec only has a single control that is shared by both channels.
++ * This makes it impossible to determine the audio path.
++ */
++static int mixer_event (struct snd_soc_dapm_widget *w, int event)
++{
++	u16 l, r, beep, line, phone, mic, pcm, aux;
++
++	l = ac97_read(w->codec, HPL_MIXER);
++	r = ac97_read(w->codec, HPR_MIXER);
++	beep = ac97_read(w->codec, AC97_PC_BEEP);
++	mic = ac97_read(w->codec, AC97_VIDEO);
++	phone = ac97_read(w->codec, AC97_PHONE);
++	line = ac97_read(w->codec, AC97_LINE);
++	pcm = ac97_read(w->codec, AC97_PCM);
++	aux = ac97_read(w->codec, AC97_CD);
++
++	if (l & 0x1 || r & 0x1)
++		ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_VIDEO, mic | 0x8000);
++
++	if (l & 0x2 || r & 0x2)
++		ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
++
++	if (l & 0x4 || r & 0x4)
++		ac97_write(w->codec, AC97_LINE, line & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_LINE, line | 0x8000);
++
++	if (l & 0x8 || r & 0x8)
++		ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
++
++	if (l & 0x10 || r & 0x10)
++		ac97_write(w->codec, AC97_CD, aux & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_CD, aux | 0x8000);
++
++	if (l & 0x20 || r & 0x20)
++		ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
++
++	return 0;
++}
++
++/* Left Headphone Mixers */
++static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = {
++	SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0),
++	SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0),
++	SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0),
++	SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0),
++	SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0),
++	SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0),
++};
++
++/* Right Headphone Mixers */
++static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = {
++	SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0),
++	SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0),
++	SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0),
++	SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0),
++	SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0),
++	SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0),
++};
++
++/* Speaker Mixer */
++static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = {
++	SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1),
++	SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1),
++	SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1),
++	SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1),
++	SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1),
++};
++
++/* Phone Mixer */
++static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = {
++	SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1),
++	SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1),
++	SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1),
++	SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1),
++	SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1),
++	SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1),
++};
++
++/* ALC headphone mux */
++static const struct snd_kcontrol_new wm9712_alc_mux_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[1]);
++
++/* out 3 mux */
++static const struct snd_kcontrol_new wm9712_out3_mux_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[2]);
++
++/* spk mux */
++static const struct snd_kcontrol_new wm9712_spk_mux_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[3]);
++
++/* Capture to Phone mux */
++static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[4]);
++
++/* Capture left select */
++static const struct snd_kcontrol_new wm9712_capture_selectl_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[8]);
++
++/* Capture right select */
++static const struct snd_kcontrol_new wm9712_capture_selectr_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[9]);
++
++/* Mic select */
++static const struct snd_kcontrol_new wm9712_mic_src_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[7]);
++
++/* diff select */
++static const struct snd_kcontrol_new wm9712_diff_sel_controls =
++SOC_DAPM_ENUM("Route", wm9712_enum[11]);
++
++static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = {
++SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9712_alc_mux_controls),
++SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0,
++	&wm9712_out3_mux_controls),
++SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0,
++	&wm9712_spk_mux_controls),
++SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9712_capture_phone_mux_controls),
++SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
++	&wm9712_capture_selectl_controls),
++SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
++	&wm9712_capture_selectr_controls),
++SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
++	&wm9712_mic_src_controls),
++SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
++	&wm9712_diff_sel_controls),
++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1,
++	&wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls),
++	mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1,
++	&wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls),
++	 mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1,
++	&wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)),
++SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1,
++	&wm9712_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm9712_speaker_mixer_controls)),
++SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1),
++SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1),
++SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0),
++SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1),
++SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1),
++SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
++SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
++SND_SOC_DAPM_OUTPUT("MONOOUT"),
++SND_SOC_DAPM_OUTPUT("HPOUTL"),
++SND_SOC_DAPM_OUTPUT("HPOUTR"),
++SND_SOC_DAPM_OUTPUT("LOUT2"),
++SND_SOC_DAPM_OUTPUT("ROUT2"),
++SND_SOC_DAPM_OUTPUT("OUT3"),
++SND_SOC_DAPM_INPUT("LINEINL"),
++SND_SOC_DAPM_INPUT("LINEINR"),
++SND_SOC_DAPM_INPUT("PHONE"),
++SND_SOC_DAPM_INPUT("PCBEEP"),
++SND_SOC_DAPM_INPUT("MIC1"),
++SND_SOC_DAPM_INPUT("MIC2"),
++};
++
++static const char *audio_map[][3] = {
++	/* virtual mixer - mixes left & right channels for spk and mono */
++	{"AC97 Mixer", NULL, "Left DAC"},
++	{"AC97 Mixer", NULL, "Right DAC"},
++
++	/* Left HP mixer */
++	{"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
++	{"Left HP Mixer", "Aux Playback Switch",  "Aux DAC"},
++	{"Left HP Mixer", "Phone Bypass Switch",  "Phone PGA"},
++	{"Left HP Mixer", "Line Bypass Switch",   "Line PGA"},
++	{"Left HP Mixer", "PCM Playback Switch",  "Left DAC"},
++	{"Left HP Mixer", "Mic Sidetone Switch",  "Mic PGA"},
++	{"Left HP Mixer", NULL,  "ALC Sidetone Mux"},
++	//{"Right HP Mixer", NULL, "HP Mixer"},
++
++	/* Right HP mixer */
++	{"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
++	{"Right HP Mixer", "Aux Playback Switch",  "Aux DAC"},
++	{"Right HP Mixer", "Phone Bypass Switch",  "Phone PGA"},
++	{"Right HP Mixer", "Line Bypass Switch",   "Line PGA"},
++	{"Right HP Mixer", "PCM Playback Switch",  "Right DAC"},
++	{"Right HP Mixer", "Mic Sidetone Switch",  "Mic PGA"},
++	{"Right HP Mixer", NULL,  "ALC Sidetone Mux"},
++
++	/* speaker mixer */
++	{"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"},
++	{"Speaker Mixer", "Line Bypass Switch",   "Line PGA"},
++	{"Speaker Mixer", "PCM Playback Switch",  "AC97 Mixer"},
++	{"Speaker Mixer", "Phone Bypass Switch",  "Phone PGA"},
++	{"Speaker Mixer", "Aux Playback Switch",  "Aux DAC"},
++
++	/* Phone mixer */
++	{"Phone Mixer", "PCBeep Bypass Switch",  "PCBEEP"},
++	{"Phone Mixer", "Line Bypass Switch",    "Line PGA"},
++	{"Phone Mixer", "Aux Playback Switch",   "Aux DAC"},
++	{"Phone Mixer", "PCM Playback Switch",   "AC97 Mixer"},
++	{"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"},
++	{"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"},
++
++	/* inputs */
++	{"Line PGA", NULL, "LINEINL"},
++	{"Line PGA", NULL, "LINEINR"},
++	{"Phone PGA", NULL, "PHONE"},
++	{"Mic PGA", NULL, "MIC1"},
++	{"Mic PGA", NULL, "MIC2"},
++
++	/* left capture selector */
++	{"Left Capture Select", "Mic", "MIC1"},
++	{"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
++	{"Left Capture Select", "Line", "LINEINL"},
++	{"Left Capture Select", "Headphone Mixer", "Left HP Mixer"},
++	{"Left Capture Select", "Phone Mixer", "Phone Mixer"},
++	{"Left Capture Select", "Phone", "PHONE"},
++
++	/* right capture selector */
++	{"Right Capture Select", "Mic", "MIC2"},
++	{"Right Capture Select", "Speaker Mixer", "Speaker Mixer"},
++	{"Right Capture Select", "Line", "LINEINR"},
++	{"Right Capture Select", "Headphone Mixer", "Right HP Mixer"},
++	{"Right Capture Select", "Phone Mixer", "Phone Mixer"},
++	{"Right Capture Select", "Phone", "PHONE"},
++
++	/* ALC Sidetone */
++	{"ALC Sidetone Mux", "Stereo", "Left Capture Select"},
++	{"ALC Sidetone Mux", "Stereo", "Right Capture Select"},
++	{"ALC Sidetone Mux", "Left", "Left Capture Select"},
++	{"ALC Sidetone Mux", "Right", "Right Capture Select"},
++
++	/* ADC's */
++	{"Left ADC", NULL, "Left Capture Select"},
++	{"Right ADC", NULL, "Right Capture Select"},
++
++	/* outputs */
++	{"MONOOUT", NULL, "Phone Mixer"},
++	{"HPOUTL", NULL, "Headphone PGA"},
++	{"Headphone PGA", NULL, "Left HP Mixer"},
++	{"HPOUTR", NULL, "Headphone PGA"},
++	{"Headphone PGA", NULL, "Right HP Mixer"},
++
++	/* mono hp mixer */
++	{"Mono HP Mixer", NULL, "Left HP Mixer"},
++	{"Mono HP Mixer", NULL, "Right HP Mixer"},
++
++	/* Out3 Mux */
++	{"Out3 Mux", "Left", "Left HP Mixer"},
++	{"Out3 Mux", "Mono", "Phone Mixer"},
++	{"Out3 Mux", "Left + Right", "Mono HP Mixer"},
++	{"Out 3 PGA", NULL, "Out3 Mux"},
++	{"OUT3", NULL, "Out 3 PGA"},
++
++	/* speaker Mux */
++	{"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
++	{"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
++	{"Speaker PGA", NULL, "Speaker Mux"},
++	{"LOUT2", NULL, "Speaker PGA"},
++	{"ROUT2", NULL, "Speaker PGA"},
++
++	{NULL, NULL, NULL},
++};
++
++static int wm9712_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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 unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++
++	if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
++		reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
++		reg == AC97_REC_GAIN)
++		return soc_ac97_ops.read(codec->ac97, reg);
++	else {
++		reg = reg >> 1;
++
++		if (reg > (ARRAY_SIZE(wm9712_reg)))
++			return -EIO;
++
++		return cache[reg];
++	}
++}
++
++static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int val)
++{
++	u16 *cache = codec->reg_cache;
++
++	soc_ac97_ops.write(codec->ac97, reg, val);
++	reg = reg >> 1;
++	if (reg <= (ARRAY_SIZE(wm9712_reg)))
++		cache[reg] = val;
++
++	return 0;
++}
++
++static int ac97_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg;
++	u16 vra;
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		reg = AC97_PCM_FRONT_DAC_RATE;
++	else
++		reg = AC97_PCM_LR_ADC_RATE;
++
++	return ac97_write(codec, reg, runtime->rate);
++}
++
++static int ac97_aux_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 vra, xsle;
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++	xsle = ac97_read(codec, AC97_PCI_SID);
++	ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
++
++	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++		return -ENODEV;
++
++	return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
++}
++
++struct snd_soc_codec_dai wm9712_dai[] = {
++{
++	.name = "AC97 HiFi",
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.prepare = ac97_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(ac97_modes),
++		.mode = ac97_modes,},
++	},
++	{
++	.name = "AC97 Aux",
++	.playback = {
++		.stream_name = "Aux Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.ops = {
++		.prepare = ac97_aux_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(ac97_modes),
++		.mode = ac97_modes,},
++	},
++};
++EXPORT_SYMBOL_GPL(wm9712_dai);
++
++static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 reg;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* liam - maybe enable thermal shutdown */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* enable master bias and vmid */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		ac97_write(codec, AC97_POWERDOWN, 0x0000);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* disable everything including AC link */
++		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
++		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++		ac97_write(codec, AC97_POWERDOWN, 0xffff);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
++{
++	if (try_warm && soc_ac97_ops.warm_reset) {
++		soc_ac97_ops.warm_reset(codec->ac97);
++		if (!(ac97_read(codec, 0) & 0x8000))
++			return 1;
++	}
++
++	soc_ac97_ops.reset(codec->ac97);
++	if (ac97_read(codec, 0) & 0x8000)
++		goto err;
++	return 0;
++
++err:
++	printk(KERN_ERR "WM9712 AC97 reset failed\n");
++	return -EIO;
++}
++
++static int wm9712_soc_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;
++
++	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm9712_soc_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i, ret;
++	u16 *cache = codec->reg_cache;
++
++	ret = wm9712_reset(codec, 1);
++	if (ret < 0){
++		printk(KERN_ERR "could not reset AC97 codec\n");
++		return ret;
++	}
++
++	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	if (ret == 0) {
++		/* Sync reg_cache with the hardware after cold reset */
++		for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
++			if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
++				(i > 0x58 && i != 0x5c))
++				continue;
++			soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
++		}
++	}
++
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
++		wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
++
++	return ret;
++}
++
++static int wm9712_soc_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
++
++	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++	if (socdev->codec == NULL)
++		return -ENOMEM;
++	codec = socdev->codec;
++	mutex_init(&codec->mutex);
++
++	codec->reg_cache =
++		kzalloc(sizeof(u16) * ARRAY_SIZE(wm9712_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL) {
++		kfree(codec->ac97);
++		kfree(socdev->codec);
++		socdev->codec = NULL;
++		return -ENOMEM;
++	}
++	memcpy(codec->reg_cache, wm9712_reg, sizeof(u16) * ARRAY_SIZE(wm9712_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9712_reg);
++	codec->reg_cache_step = 2;
++
++	codec->name = "WM9712";
++	codec->owner = THIS_MODULE;
++	codec->dai = wm9712_dai;
++	codec->num_dai = ARRAY_SIZE(wm9712_dai);
++	codec->write = ac97_write;
++	codec->read = ac97_read;
++	codec->dapm_event = wm9712_dapm_event;
++	INIT_LIST_HEAD(&codec->dapm_widgets);
++	INIT_LIST_HEAD(&codec->dapm_paths);
++
++	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
++	if (ret < 0)
++		goto err;
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0)
++		goto pcm_err;
++
++	ret = wm9712_reset(codec, 0);
++	if (ret < 0) {
++		printk(KERN_ERR "AC97 link error\n");
++		goto reset_err;
++	}
++
++	/* set alc mux to none */
++	ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
++
++	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm9712_add_controls(codec);
++	wm9712_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0)
++		goto reset_err;
++
++	return 0;
++
++reset_err:
++	snd_soc_free_pcms(socdev);
++
++pcm_err:
++	snd_soc_free_ac97_codec(codec);
++
++err:
++	kfree(socdev->codec->reg_cache);
++	kfree(socdev->codec);
++	socdev->codec = NULL;
++	return ret;
++}
++
++static int wm9712_soc_remove(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++
++	if (codec == NULL)
++		return 0;
++
++	snd_soc_dapm_free(socdev);
++	snd_soc_free_pcms(socdev);
++	snd_soc_free_ac97_codec(codec);
++	kfree(codec->reg_cache);
++	kfree(codec);
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm9712 = {
++	.probe = 	wm9712_soc_probe,
++	.remove = 	wm9712_soc_remove,
++	.suspend =	wm9712_soc_suspend,
++	.resume =	wm9712_soc_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
++
++MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm9712.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm9712.h
+@@ -0,0 +1,14 @@
++/*
++ * wm9712.h  --  WM9712 Soc Audio driver
++ */
++
++#ifndef _WM9712_H
++#define _WM9712_H
++
++#define WM9712_DAI_AC97_HIFI	0
++#define WM9712_DAI_AC97_AUX		1
++
++extern struct snd_soc_codec_dai wm9712_dai[2];
++extern struct snd_soc_codec_device soc_codec_dev_wm9712;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm9713.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm9713.c
+@@ -0,0 +1,1313 @@
++/*
++ * wm9713.c  --  ALSA Soc WM9713 codec support
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    4th Feb 2006   Initial version.
++ *
++ *  Features:-
++ *
++ *   o Support for AC97 Codec, Voice DAC and Aux DAC
++ *   o Support for DAPM
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#define WM9713_VERSION "0.12"
++
++struct wm9713 {
++	u32 pll; /* current PLL frequency */
++	u32 pll_resume; /* PLL resume frequency */
++};
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg);
++static int ac97_write(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int val);
++
++#define AC97_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define AC97_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)
++
++/* may need to expand this */
++static struct snd_soc_dai_mode ac97_modes[] = {
++	{
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE,
++		.pcmrate = AC97_RATES,
++	},
++};
++
++#define WM9713_VOICE_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | \
++	SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_DSP_A | \
++	SND_SOC_DAIFMT_DSP_B |  SND_SOC_DAIFMT_NB_NF | \
++	SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM9713_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM9713_VOICE_FSB \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
++	SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
++
++#define WM9713_VOICE_RATES \
++	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
++	SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | \
++	SNDRV_PCM_RATE_96000)
++
++#define WM9713_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++/*
++ * Voice modes
++ */
++static struct snd_soc_dai_mode wm9713_voice_modes[] = {
++	/* master modes */
++	{
++		.fmt = WM9713_VOICE_DAIFMT | SND_SOC_DAIFMT_CBM_CFM | \
++			SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt =  WM9713_HIFI_BITS,
++		.pcmrate = WM9713_VOICE_RATES,
++		.pcmdir = WM9713_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM9713_VOICE_FSB,
++	},
++
++	/* slave modes */
++	{
++		.fmt = WM9713_VOICE_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM9713_HIFI_BITS,
++		.pcmrate = WM9713_VOICE_RATES,
++		.pcmdir = WM9713_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * WM9713 register cache
++ * Reg 0x3c bit 15 is used by touch driver.
++ */
++static const u16 wm9713_reg[] = {
++	0x6174, 0x8080, 0x8080, 0x8080, // 6
++	0xc880, 0xe808, 0xe808, 0x0808, // e
++	0x00da, 0x8000, 0xd600, 0xaaa0, // 16
++	0xaaa0, 0xaaa0, 0x0000, 0x0000, // 1e
++	0x0f0f, 0x0040, 0x0000, 0x7f00, // 26
++	0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
++	0x0000, 0xbb80, 0x0000, 0x4523, // 36
++	0x0000, 0x2000, 0x7eff, 0xffff, // 3e
++	0x0000, 0x0000, 0x0080, 0x0000, // 46
++	0x0000, 0x0000, 0xfffe, 0xffff, // 4e
++	0x0000, 0x0000, 0x0000, 0xfffe, // 56
++	0x4000, 0x0000, 0x0000, 0x0000, // 5e
++	0xb032, 0x3e00, 0x0000, 0x0000, // 66
++	0x0000, 0x0000, 0x0000, 0x0000, // 6e
++	0x0000, 0x0000, 0x0000, 0x0006, // 76
++	0x0001, 0x0000, 0x574d, 0x4c13, // 7e
++	0x0000, 0x0000, 0x0000 // virtual hp & mic mixers
++};
++
++/* virtual HP mixers regs */
++#define HPL_MIXER	0x80
++#define HPR_MIXER	0x82
++#define MICB_MUX	0x82
++
++static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
++static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
++static const char *wm9713_rec_src[] =
++	{"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
++	"Mono Out", "Zh"};
++static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
++static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
++static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
++	"Mono Vmid", "Inv Vmid"};
++static const char *wm9713_spk_pga[] =
++	{"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
++	"Speaker Vmid", "Inv Vmid"};
++static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
++	"Headphone Vmid"};
++static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
++static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
++static const char *wm9713_dac_inv[] =
++	{"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
++	"Headphone Mono", "NC", "Vmid"};
++static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
++static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
++static const char *wm9713_micb_select[] = {"MPB", "MPA"};
++
++static const struct soc_enum wm9713_enum[] = {
++SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),  /* record mux mono 2 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src),  /* record mux left 3 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src),  /* record mux right 4*/
++SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
++SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
++SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
++SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */
++};
++
++static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
++SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
++SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
++SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
++SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE,15, 7, 1, 1),
++SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
++SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
++SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
++SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
++
++SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
++SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
++
++SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
++SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
++SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 63, 0),
++SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
++
++SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
++SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
++SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
++
++SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
++SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
++SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
++SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
++SOC_ENUM("ALC Function", wm9713_enum[6]),
++SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
++SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
++SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
++SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
++SOC_ENUM("ALC NG Type", wm9713_enum[17]),
++SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
++
++SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
++SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
++
++SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
++SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
++SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1),
++
++SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
++SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
++SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1),
++
++SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1),
++SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
++SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
++SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
++
++SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
++SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
++SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
++
++SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
++SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
++SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
++
++SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
++SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
++SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1),
++
++SOC_ENUM("Bass Control", wm9713_enum[16]),
++SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
++SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
++SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
++SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
++SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
++
++SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
++SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
++SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
++};
++
++/* add non dapm controls */
++static int wm9713_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm9713_snd_ac97_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/* We have to create a fake left and right HP mixers because
++ * the codec only has a single control that is shared by both channels.
++ * This makes it impossible to determine the audio path using the current
++ * register map, thus we add a new (virtual) register to help determine the
++ * audio route within the device.
++ */
++static int mixer_event (struct snd_soc_dapm_widget *w, int event)
++{
++	u16 l, r, beep, tone, phone, rec, pcm, aux;
++
++	l = ac97_read(w->codec, HPL_MIXER);
++	r = ac97_read(w->codec, HPR_MIXER);
++	beep = ac97_read(w->codec, AC97_PC_BEEP);
++	tone = ac97_read(w->codec, AC97_MASTER_TONE);
++	phone = ac97_read(w->codec, AC97_PHONE);
++	rec = ac97_read(w->codec, AC97_REC_SEL);
++	pcm = ac97_read(w->codec, AC97_PCM);
++	aux = ac97_read(w->codec, AC97_AUX);
++
++	if (event & SND_SOC_DAPM_PRE_REG)
++		return 0;
++	if (l & 0x1 || r & 0x1)
++		ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
++
++	if (l & 0x2 || r & 0x2)
++		ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
++
++	if (l & 0x4 || r & 0x4)
++		ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
++
++	if (l & 0x8 || r & 0x8)
++		ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000);
++
++	if (l & 0x10 || r & 0x10)
++		ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
++
++	if (l & 0x20 || r & 0x20)
++		ac97_write(w->codec, AC97_AUX, aux & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_AUX, aux | 0x8000);
++
++	return 0;
++}
++
++/* Left Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
++};
++
++/* Right Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0),
++};
++
++/* headphone capture mux */
++static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[1]);
++
++/* headphone mic mux */
++static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[0]);
++
++/* Speaker Mixer */
++static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
++};
++
++/* Mono Mixer */
++static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
++SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
++SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
++};
++
++/* mono mic mux */
++static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[2]);
++
++/* mono output mux */
++static const struct snd_kcontrol_new wm9713_mono_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[7]);
++
++/* speaker left output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[8]);
++
++/* speaker right output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[9]);
++
++/* headphone left output mux */
++static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[10]);
++
++/* headphone right output mux */
++static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[11]);
++
++/* Out3 mux */
++static const struct snd_kcontrol_new wm9713_out3_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[12]);
++
++/* Out4 mux */
++static const struct snd_kcontrol_new wm9713_out4_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[13]);
++
++/* DAC inv mux 1 */
++static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[14]);
++
++/* DAC inv mux 2 */
++static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[15]);
++
++/* Capture source left */
++static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[3]);
++
++/* Capture source right */
++static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[4]);
++
++/* mic source */
++static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[18]);
++
++/* mic source B virtual control */
++static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[19]);
++
++static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
++SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_rec_mux_controls),
++SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_mic_mux_controls),
++SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_mono_mic_mux_controls),
++SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_mono_mux_controls),
++SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_spkl_mux_controls),
++SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_spkr_mux_controls),
++SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hpl_out_mux_controls),
++SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hpr_out_mux_controls),
++SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_out3_mux_controls),
++SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_out4_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
++	&wm9713_dac_inv1_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
++	&wm9713_dac_inv2_mux_controls),
++SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_rec_srcl_mux_controls),
++SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_rec_srcr_mux_controls),
++SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_mic_sel_mux_controls ),
++SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_micb_sel_mux_controls ),
++SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
++	&wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls),
++	mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
++	&wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
++	mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
++	&wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
++SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
++	&wm9713_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm9713_speaker_mixer_controls)),
++SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
++SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
++SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
++SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1),
++SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1),
++SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
++SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
++SND_SOC_DAPM_OUTPUT("MONO"),
++SND_SOC_DAPM_OUTPUT("HPL"),
++SND_SOC_DAPM_OUTPUT("HPR"),
++SND_SOC_DAPM_OUTPUT("SPKL"),
++SND_SOC_DAPM_OUTPUT("SPKR"),
++SND_SOC_DAPM_OUTPUT("OUT3"),
++SND_SOC_DAPM_OUTPUT("OUT4"),
++SND_SOC_DAPM_INPUT("LINEL"),
++SND_SOC_DAPM_INPUT("LINER"),
++SND_SOC_DAPM_INPUT("MONOIN"),
++SND_SOC_DAPM_INPUT("PCBEEP"),
++SND_SOC_DAPM_INPUT("MIC1"),
++SND_SOC_DAPM_INPUT("MIC2A"),
++SND_SOC_DAPM_INPUT("MIC2B"),
++SND_SOC_DAPM_VMID("VMID"),
++};
++
++static const char *audio_map[][3] = {
++	/* left HP mixer */
++	{"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Left HP Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Left HP Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Left HP Mixer", "Bypass Playback Switch",  "Left Line In"},
++	{"Left HP Mixer", "PCM Playback Switch",     "Left DAC"},
++	{"Left HP Mixer", "MonoIn Playback Switch",  "Mono In"},
++	{"Left HP Mixer", NULL,  "Capture Headphone Mux"},
++
++	/* right HP mixer */
++	{"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Right HP Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Right HP Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Right HP Mixer", "Bypass Playback Switch",  "Right Line In"},
++	{"Right HP Mixer", "PCM Playback Switch",     "Right DAC"},
++	{"Right HP Mixer", "MonoIn Playback Switch",  "Mono In"},
++	{"Right HP Mixer", NULL,  "Capture Headphone Mux"},
++
++	/* virtual mixer - mixes left & right channels for spk and mono */
++	{"AC97 Mixer", NULL, "Left DAC"},
++	{"AC97 Mixer", NULL, "Right DAC"},
++	{"Line Mixer", NULL, "Right Line In"},
++	{"Line Mixer", NULL, "Left Line In"},
++	{"HP Mixer", NULL, "Left HP Mixer"},
++	{"HP Mixer", NULL, "Right HP Mixer"},
++	{"Capture Mixer", NULL, "Left Capture Source"},
++	{"Capture Mixer", NULL, "Right Capture Source"},
++
++	/* speaker mixer */
++	{"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Speaker Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Speaker Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Speaker Mixer", "Bypass Playback Switch",  "Line Mixer"},
++	{"Speaker Mixer", "PCM Playback Switch",     "AC97 Mixer"},
++	{"Speaker Mixer", "MonoIn Playback Switch",  "Mono In"},
++
++	/* mono mixer */
++	{"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Mono Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Mono Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Mono Mixer", "Bypass Playback Switch",  "Line Mixer"},
++	{"Mono Mixer", "PCM Playback Switch",     "AC97 Mixer"},
++	{"Mono Mixer", NULL,  "Capture Mono Mux"},
++
++	/* DAC inv mux 1 */
++	{"DAC Inv Mux 1", "Mono", "Mono Mixer"},
++	{"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
++	{"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
++	{"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
++	{"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
++
++	/* DAC inv mux 2 */
++	{"DAC Inv Mux 2", "Mono", "Mono Mixer"},
++	{"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
++	{"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
++	{"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
++	{"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
++
++	/* headphone left mux */
++	{"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
++
++	/* headphone right mux */
++	{"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
++
++	/* speaker left mux */
++	{"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
++	{"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
++	{"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
++
++	/* speaker right mux */
++	{"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
++	{"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
++	{"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
++
++	/* mono mux */
++	{"Mono Out Mux", "Mono", "Mono Mixer"},
++	{"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
++
++	/* out 3 mux */
++	{"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
++
++	/* out 4 mux */
++	{"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
++
++	/* output pga */
++	{"HPL", NULL, "Left Headphone"},
++	{"Left Headphone", NULL, "Left Headphone Out Mux"},
++	{"HPR", NULL, "Right Headphone"},
++	{"Right Headphone", NULL, "Right Headphone Out Mux"},
++	{"OUT3", NULL, "Out 3"},
++	{"Out 3", NULL, "Out 3 Mux"},
++	{"OUT4", NULL, "Out 4"},
++	{"Out 4", NULL, "Out 4 Mux"},
++	{"SPKL", NULL, "Left Speaker"},
++	{"Left Speaker", NULL, "Left Speaker Out Mux"},
++	{"SPKR", NULL, "Right Speaker"},
++	{"Right Speaker", NULL, "Right Speaker Out Mux"},
++	{"MONO", NULL, "Mono Out"},
++	{"Mono Out", NULL, "Mono Out Mux"},
++
++	/* input pga */
++	{"Left Line In", NULL, "LINEL"},
++	{"Right Line In", NULL, "LINER"},
++	{"Mono In", NULL, "MONOIN"},
++	{"Mic A PGA", NULL, "Mic A Pre Amp"},
++	{"Mic B PGA", NULL, "Mic B Pre Amp"},
++
++	/* left capture select */
++	{"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
++	{"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
++	{"Left Capture Source", "Line", "LINEL"},
++	{"Left Capture Source", "Mono In", "MONOIN"},
++	{"Left Capture Source", "Headphone", "Left HP Mixer"},
++	{"Left Capture Source", "Speaker", "Speaker Mixer"},
++	{"Left Capture Source", "Mono Out", "Mono Mixer"},
++
++	/* right capture select */
++	{"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
++	{"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
++	{"Right Capture Source", "Line", "LINER"},
++	{"Right Capture Source", "Mono In", "MONOIN"},
++	{"Right Capture Source", "Headphone", "Right HP Mixer"},
++	{"Right Capture Source", "Speaker", "Speaker Mixer"},
++	{"Right Capture Source", "Mono Out", "Mono Mixer"},
++
++	/* left ADC */
++	{"Left ADC", NULL, "Left Capture Source"},
++
++	/* right ADC */
++	{"Right ADC", NULL, "Right Capture Source"},
++
++	/* mic */
++	{"Mic A Pre Amp", NULL, "Mic A Source"},
++	{"Mic A Source", "Mic 1", "MIC1"},
++	{"Mic A Source", "Mic 2 A", "MIC2A"},
++	{"Mic A Source", "Mic 2 B", "Mic B Source"},
++	{"Mic B Pre Amp", "MPB", "Mic B Source"},
++	{"Mic B Source", NULL, "MIC2B"},
++
++	/* headphone capture */
++	{"Capture Headphone Mux", "Stereo", "Capture Mixer"},
++	{"Capture Headphone Mux", "Left", "Left Capture Source"},
++	{"Capture Headphone Mux", "Right", "Right Capture Source"},
++
++	/* mono capture */
++	{"Capture Mono Mux", "Stereo", "Capture Mixer"},
++	{"Capture Mono Mux", "Left", "Left Capture Source"},
++	{"Capture Mono Mux", "Right", "Right Capture Source"},
++
++	{NULL, NULL, NULL},
++};
++
++static int wm9713_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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 unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++
++	if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
++		reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
++		reg == AC97_CD)
++		return soc_ac97_ops.read(codec->ac97, reg);
++	else {
++		reg = reg >> 1;
++
++		if (reg > (ARRAY_SIZE(wm9713_reg)))
++			return -EIO;
++
++		return cache[reg];
++	}
++}
++
++static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int val)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < 0x7c)
++		soc_ac97_ops.write(codec->ac97, reg, val);
++	reg = reg >> 1;
++	if (reg <= (ARRAY_SIZE(wm9713_reg)))
++		cache[reg] = val;
++
++	return 0;
++}
++
++struct pll_ {
++	unsigned int in_hz;
++	unsigned int lf:1; /* allows low frequency use */
++	unsigned int sdm:1; /* allows fraction n div */
++	unsigned int divsel:1; /* enables input clock div */
++	unsigned int divctl:1; /* input clock divider */
++	unsigned int n:4;
++	unsigned int k;
++};
++
++struct pll_ pll[] = {
++	{13000000, 0, 1, 0, 0, 7, 0x23f488},
++	{2048000,  1, 0, 0, 0, 12, 0x0},
++	{4096000,  1, 0, 0, 0, 6, 0x0},
++	{12288000, 0, 0, 0, 0, 8, 0x0},
++	/* liam - add more entries */
++};
++
++/* we must have either 24.576MHz or a PLL freq */
++static unsigned int wm9713_config_ac97sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i;
++	dai->mclk = 0;
++
++	/* first check if we can get away witout burning any PLL power */
++	if (24576000 == clk) {
++		/* standard AC97 clock */
++		dai->mclk = clk;
++		goto out;
++	}
++
++	/* ok no standard clock, so we must now try the PLL */
++	for(i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (clk == pll[i].in_hz) {
++			dai->mclk = clk; /* clock out */
++			goto out;
++		}
++	}
++
++out:
++	return dai->mclk;
++}
++
++/* The WM9713 voice DAC can only run at 256FS. This interface and DAC are
++ * clocked by the main AC97 clock divided down to 256 FS.
++ */
++static unsigned int wm9713_config_vsysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 1; i <= 16; i++) {
++		if (best_clk * i == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = i << 1;
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == clk) {
++			for (j = 1; j <= 16; j++) {
++				if (24576000 == j * best_clk) {
++					dai->pll_in = clk;
++					dai->pll_out = 24576000;
++					dai->clk_div = j << 1;
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++u32 wm9713_set_pll(struct snd_soc_codec *codec, u32 in)
++{
++	struct wm9713 *wm = (struct wm9713*)codec->private_data;
++	int i;
++	u16 reg, reg2;
++
++	/* turn PLL off ? */
++	if (in == 0) {
++		/* disable PLL power and select ext source */
++		reg = ac97_read(codec, AC97_HANDSET_RATE);
++		ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
++		reg = ac97_read(codec, AC97_EXTENDED_MID);
++		ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
++		wm->pll = 0;
++		return 0;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == in)
++			goto found;
++	}
++	return -EINVAL;
++
++found:
++	if (pll[i].sdm == 0) {
++		reg = (pll[i].n << 12) | (pll[i].lf << 11) |
++			(pll[i].divsel << 9) | (pll[i].divctl << 8);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++	} else {
++		/* write the fractional k to the reg 0x46 pages */
++		reg2 = (pll[i].n << 12) | (pll[i].lf << 11) | (pll[i].sdm << 10) |
++			(pll[i].divsel << 9) | (pll[i].divctl << 8);
++
++		reg = reg2 | (0x5 << 4) | (pll[i].k >> 20); /* K [21:20] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x4 << 4) | ((pll[i].k >> 16) & 0xf); /* K [19:16] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x3 << 4) | ((pll[i].k >> 12) & 0xf); /* K [15:12] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x2 << 4) | ((pll[i].k >> 8) & 0xf); /* K [11:8] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x1 << 4) | ((pll[i].k >> 4) & 0xf); /* K [7:4] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x0 << 4) | (pll[i].k & 0xf); /* K [3:0] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++	}
++
++	/* turn PLL on and select as source */
++	reg = ac97_read(codec, AC97_EXTENDED_MID);
++	ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
++	reg = ac97_read(codec, AC97_HANDSET_RATE);
++	ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
++	/* wait 10ms AC97 link frames for the link to stabilise */
++	schedule_timeout_interruptible(msecs_to_jiffies(10));
++	wm->pll = in;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(wm9713_set_pll);
++
++static int wm9713_voice_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 reg = 0x8000, bfs, div, gpio;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffe2;
++
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK){
++	case SND_SOC_DAIFMT_CBM_CFM:
++		reg |= 0x4000;
++		gpio |= 0x0008;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		reg |= 0x6000;
++		gpio |= 0x000c;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		reg |= 0x0200;
++		gpio |= 0x000d;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		gpio |= 0x0009;
++		break;
++	}
++	ac97_write(codec, AC97_GPIO_CFG, gpio);
++
++	/* enable PLL if needed */
++	if (rtd->codec_dai->pll_in)
++		wm9713_set_pll(codec, rtd->codec_dai->pll_in);
++
++	/* set the PCM divider */
++	div = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
++	ac97_write(codec, AC97_HANDSET_RATE, div |
++		((rtd->codec_dai->clk_div >> 1) -1) << 8);
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		reg |= 0x00c0;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		reg |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		reg |= 0x0040;
++		break;
++	}
++
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		reg |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		reg |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		reg |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		reg |= 0x0043;
++		break;
++	}
++
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		reg |= 0x0004;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		reg |= 0x0008;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		reg |= 0x000c;
++		break;
++	}
++
++	switch (bfs) {
++	case 2:
++		reg |= (0x1 << 9);
++		break;
++	case 4:
++		reg |= (0x2 << 9);
++		break;
++	case 8:
++		reg |= (0x3 << 9);
++		break;
++	case 16:
++		reg |= (0x4 << 9);
++		break;
++	}
++
++	/* enable PCM interface in master mode */
++	ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++	return 0;
++}
++
++static void wm9713_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++
++	if (!codec->active)
++		wm9713_set_pll(codec, 0);
++}
++
++static void wm9713_voiceshutdown(snd_pcm_substream_t *substream)
++{
++    struct snd_soc_pcm_runtime *rtd = substream->private_data;
++    struct snd_soc_device *socdev = rtd->socdev;
++    struct snd_soc_codec *codec = socdev->codec;
++    u16 status;
++
++    wm9713_shutdown(substream);
++
++    /* Gracefully shut down the voice interface. */
++    status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
++    ac97_write(codec,AC97_HANDSET_RATE,0x0280);
++    schedule_timeout_interruptible(msecs_to_jiffies(1));
++    ac97_write(codec,AC97_HANDSET_RATE,0x0F80);
++    ac97_write(codec,AC97_EXTENDED_MID,status);
++}
++
++static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg;
++	u16 vra;
++
++	/* we need a 24576000Hz clock to run at the correct speed */
++	if (rtd->codec_dai->mclk != 24576000)
++		wm9713_set_pll(codec, rtd->codec_dai->mclk);
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		reg = AC97_PCM_FRONT_DAC_RATE;
++	else
++		reg = AC97_PCM_LR_ADC_RATE;
++
++	return ac97_write(codec, reg, runtime->rate);
++}
++
++static int ac97_aux_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 vra, xsle;
++
++	/* we need a 24576000Hz clock to run at the correct speed */
++	if (rtd->codec_dai->mclk != 24576000)
++		wm9713_set_pll(codec, rtd->codec_dai->mclk);
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++	xsle = ac97_read(codec, AC97_PCI_SID);
++	ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
++
++	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++		return -ENODEV;
++
++	return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
++}
++
++struct snd_soc_codec_dai wm9713_dai[] = {
++{
++	.name = "AC97 HiFi",
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm9713_config_ac97sysclk,
++	.ops = {
++		.shutdown = wm9713_shutdown,
++		.prepare = ac97_hifi_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(ac97_modes),
++		.mode = ac97_modes,},},
++	{
++	.name = "AC97 Aux",
++	.playback = {
++		.stream_name = "Aux Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.config_sysclk = wm9713_config_ac97sysclk,
++	.ops = {
++		.shutdown = wm9713_shutdown,
++		.prepare = ac97_aux_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(ac97_modes),
++		.mode = ac97_modes,}
++	},
++	{
++	.name = "WM9713 Voice",
++	.playback = {
++		.stream_name = "Voice Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.capture = {
++		.stream_name = "Voice Capture",
++		.channels_min = 1,
++		.channels_max = 2,},
++	.config_sysclk = wm9713_config_vsysclk,
++	.ops = {
++		.prepare = wm9713_voice_prepare,
++		.shutdown = wm9713_voiceshutdown,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm9713_voice_modes),
++		.mode = wm9713_voice_modes,},
++	},
++};
++EXPORT_SYMBOL_GPL(wm9713_dai);
++
++int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
++{
++	if (try_warm && soc_ac97_ops.warm_reset) {
++		soc_ac97_ops.warm_reset(codec->ac97);
++		if (!(ac97_read(codec, 0) & 0x8000))
++			return 1;
++	}
++
++	soc_ac97_ops.reset(codec->ac97);
++	if (ac97_read(codec, 0) & 0x8000)
++		return -EIO;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(wm9713_reset);
++
++static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 reg;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* enable thermal shutdown */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* enable master bias and vmid */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		ac97_write(codec, AC97_POWERDOWN, 0x0000);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* disable everything including AC link */
++		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
++		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++		ac97_write(codec, AC97_POWERDOWN, 0xffff);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++static int wm9713_soc_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;
++	struct wm9713 *wm = (struct wm9713*)codec->private_data;
++
++	if (wm->pll) {
++		wm->pll_resume = wm->pll;
++		wm9713_set_pll(codec, 0);
++	}
++	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm9713_soc_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	struct wm9713 *wm = (struct wm9713*)codec->private_data;
++	int i, ret;
++	u16 *cache = codec->reg_cache;
++
++	if ((ret = wm9713_reset(codec, 1)) < 0){
++		printk(KERN_ERR "could not reset AC97 codec\n");
++		return ret;
++	}
++
++	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* only synchronise the codec if warm reset failed */
++	if (ret == 0) {
++		for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i+=2) {
++			if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
++				i == AC97_EXTENDED_MSTATUS || i > 0x66)
++				continue;
++			soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
++		}
++	}
++
++	if (wm->pll_resume) {
++		wm9713_set_pll(codec, wm->pll_resume);
++		wm->pll_resume = 0;
++	}
++
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
++		wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
++
++	return ret;
++}
++
++static int wm9713_soc_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec;
++	int ret = 0, reg;
++
++	printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION);
++
++	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++	if (socdev->codec == NULL)
++		return -ENOMEM;
++	codec = socdev->codec;
++	mutex_init(&codec->mutex);
++
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm9713_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL){
++		kfree(socdev->codec);
++		socdev->codec = NULL;
++		return -ENOMEM;
++	}
++	memcpy(codec->reg_cache, wm9713_reg,
++		sizeof(u16) * ARRAY_SIZE(wm9713_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9713_reg);
++	codec->reg_cache_step = 2;
++
++	codec->private_data = kzalloc(sizeof(struct wm9713), GFP_KERNEL);
++	if (codec->private_data == NULL) {
++		kfree(codec->reg_cache);
++		kfree(socdev->codec);
++		socdev->codec = NULL;
++		return -ENOMEM;
++	}
++
++	codec->name = "WM9713";
++	codec->owner = THIS_MODULE;
++	codec->dai = wm9713_dai;
++	codec->num_dai = ARRAY_SIZE(wm9713_dai);
++	codec->write = ac97_write;
++	codec->read = ac97_read;
++	codec->dapm_event = wm9713_dapm_event;
++	INIT_LIST_HEAD(&codec->dapm_widgets);
++	INIT_LIST_HEAD(&codec->dapm_paths);
++
++	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
++	if (ret < 0)
++		goto err;
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0)
++		goto pcm_err;
++
++	/* do a cold reset for the controller and then try
++	 * a warm reset followed by an optional cold reset for codec */
++	wm9713_reset(codec, 0);
++	ret = wm9713_reset(codec, 1);
++	if (ret < 0)	{
++		printk(KERN_ERR "AC97 link error\n");
++		goto reset_err;
++	}
++
++	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* unmute the adc - move to kcontrol */
++	reg = ac97_read(codec, AC97_CD) & 0x7fff;
++	ac97_write(codec, AC97_CD, reg);
++
++	wm9713_add_controls(codec);
++	wm9713_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0)
++		goto reset_err;
++	return 0;
++
++reset_err:
++	snd_soc_free_pcms(socdev);
++
++pcm_err:
++	snd_soc_free_ac97_codec(codec);
++
++err:
++	kfree(socdev->codec->private_data);
++	kfree(socdev->codec->reg_cache);
++	kfree(socdev->codec);
++	socdev->codec = NULL;
++	return ret;
++}
++
++static int wm9713_soc_remove(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++
++	if (codec == NULL)
++		return 0;
++
++	snd_soc_dapm_free(socdev);
++	snd_soc_free_pcms(socdev);
++	snd_soc_free_ac97_codec(codec);
++	kfree(codec->private_data);
++	kfree(codec->reg_cache);
++	kfree(codec);
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm9713= {
++	.probe = 	wm9713_soc_probe,
++	.remove = 	wm9713_soc_remove,
++	.suspend =	wm9713_soc_suspend,
++	.resume = 	wm9713_soc_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
++
++MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm9713.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm9713.h
+@@ -0,0 +1,18 @@
++/*
++ * wm9713.h  --  WM9713 Soc Audio driver
++ */
++
++#ifndef _WM9713_H
++#define _WM9713_H
++
++#define WM9713_DAI_AC97_HIFI	0
++#define WM9713_DAI_AC97_AUX		1
++#define WM9713_DAI_PCM_VOICE	2
++
++extern struct snd_soc_codec_device soc_codec_dev_wm9713;
++extern struct snd_soc_codec_dai wm9713_dai[3];
++
++u32 wm9713_set_pll(struct snd_soc_codec *codec, u32 in);
++int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/pxa/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/Kconfig
+@@ -0,0 +1,125 @@
++menu "SoC Audio for the Intel PXA2xx"
++
++config SND_PXA2xx_SOC
++	tristate "SoC Audio for the Intel PXA2xx chip"
++	depends on ARCH_PXA && SND
++	select SND_PCM
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the PXA2xx AC97, I2S or SSP interface. You will also need
++	  to select the audio interfaces to support below.
++
++config SND_PXA2xx_AC97
++	tristate
++	select SND_AC97_CODEC
++
++config SND_PXA2xx_SOC_AC97
++	tristate
++	select SND_AC97_BUS
++	select SND_SOC_AC97_BUS
++
++config SND_PXA2xx_SOC_I2S
++	tristate
++
++config SND_PXA2xx_SOC_SSP
++	tristate
++	select PXA_SSP
++
++config SND_PXA2xx_SOC_MAINSTONE
++	tristate "SoC AC97 Audio support for Intel Mainstone"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_AC97
++	help
++	  Say Y if you want to add support for generic AC97 SoC audio on Mainstone.
++
++config SND_PXA2xx_SOC_MAINSTONE_WM8731
++	tristate "SoC I2S Audio support for Intel Mainstone - WM8731"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC audio on Mainstone
++	  with the WM8731.
++
++config SND_PXA2xx_SOC_MAINSTONE_WM8753
++	tristate "SoC I2S/SSP Audio support for Intel Mainstone - WM8753"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_I2S
++	select SND_PXA2xx_SOC_SSP
++	help
++	  Say Y if you want to add support for SoC audio on Mainstone
++	  with the WM8753.
++
++config SND_PXA2xx_SOC_MAINSTONE_WM8974
++	tristate "SoC I2S Audio support for Intel Mainstone - WM8974"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC audio on Mainstone
++	  with the WM8974.
++
++config SND_PXA2xx_SOC_MAINSTONE_WM9713
++	tristate "SoC I2S/SSP Audio support for Intel Mainstone - WM9713"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_AC97
++	select SND_PXA2xx_SOC_SSP
++	help
++	  Say Y if you want to add support for SoC voice audio on Mainstone
++	  with the WM9713.
++
++config SND_MAINSTONE_BASEBAND
++	tristate "Example SoC Baseband Audio support for Intel Mainstone"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_AC97
++	help
++	  Say Y if you want to add support for SoC baseband on Mainstone
++	  with the WM9713 and example Baseband modem.
++
++config SND_MAINSTONE_BLUETOOTH
++	tristate "Example SoC Bluetooth Audio support for Intel Mainstone"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC bluetooth on Mainstone
++	  with the WM8753 and example Bluetooth codec.
++
++config SND_PXA2xx_SOC_MAINSTONE_WM9712
++	tristate "SoC I2S/SSP Audio support for Intel Mainstone - WM9712"
++	depends on SND_PXA2xx_SOC && MACH_MAINSTONE
++	select SND_PXA2xx_SOC_AC97
++	help
++	  Say Y if you want to add support for SoC voice audio on Mainstone
++	  with the WM9712.
++
++config SND_PXA2xx_SOC_CORGI
++	tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
++	depends on SND_PXA2xx_SOC && PXA_SHARP_C7xx
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC audio on Sharp
++	  Zaurus SL-C7x0 models (Corgi, Shepherd, Husky).
++
++config SND_PXA2xx_SOC_SPITZ
++	tristate "SoC Audio support for Sharp Zaurus SL-Cxx00"
++	depends on SND_PXA2xx_SOC && PXA_SHARP_Cxx00
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC audio on Sharp
++	  Zaurus SL-Cxx00 models (Spitz, Borzoi and Akita).
++
++config SND_PXA2xx_SOC_POODLE
++	tristate "SoC Audio support for Poodle"
++	depends on SND_PXA2xx_SOC && MACH_POODLE
++	select SND_PXA2xx_SOC_I2S
++	help
++	  Say Y if you want to add support for SoC audio on Sharp
++	  Zaurus SL-5600 model (Poodle).
++
++config SND_PXA2xx_SOC_TOSA
++	tristate "SoC AC97 Audio support for Tosa"
++	depends on SND_PXA2xx_SOC && MACH_TOSA
++	select SND_PXA2xx_SOC_AC97
++	help
++	  Say Y if you want to add support for SoC audio on Sharp
++	  Zaurus SL-C6000x models (Tosa).
++
++endmenu
+Index: linux-2.6-pxa-new/sound/soc/pxa/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/Makefile
+@@ -0,0 +1,36 @@
++# PXA Platform Support
++snd-soc-pxa2xx-objs := pxa2xx-pcm.o
++snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
++snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
++snd-soc-pxa2xx-ssp-objs := pxa2xx-ssp.o
++
++obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-pxa2xx.o
++obj-$(CONFIG_SND_PXA2xx_SOC_AC97) += snd-soc-pxa2xx-ac97.o
++obj-$(CONFIG_SND_PXA2xx_SOC_I2S) += snd-soc-pxa2xx-i2s.o
++obj-$(CONFIG_SND_PXA2xx_SOC_SSP) += snd-soc-pxa2xx-ssp.o
++
++# PXA Machine Support
++snd-soc-corgi-objs := corgi.o
++snd-soc-mainstone-wm8731-objs := mainstone_wm8731.o
++snd-soc-mainstone-wm8753-objs := mainstone_wm8753.o
++snd-soc-mainstone-wm8974-objs := mainstone_wm8974.o
++snd-soc-mainstone-wm9713-objs := mainstone_wm9713.o
++snd-soc-mainstone-wm9712-objs := mainstone_wm9712.o
++snd-soc-mainstone-baseband-objs := mainstone_baseband.o
++snd-soc-mainstone-bluetooth-objs := mainstone_bluetooth.o
++snd-soc-poodle-objs := poodle.o
++snd-soc-tosa-objs := tosa.o
++snd-soc-spitz-objs := spitz.o
++
++obj-$(CONFIG_SND_PXA2xx_SOC_CORGI) += snd-soc-corgi.o
++obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8731) += snd-soc-mainstone-wm8731.o
++obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8753) += snd-soc-mainstone-wm8753.o
++obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8974) += snd-soc-mainstone-wm8974.o
++obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9713) += snd-soc-mainstone-wm9713.o
++obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9712) += snd-soc-mainstone-wm9712.o
++obj-$(CONFIG_SND_MAINSTONE_BASEBAND) += snd-soc-mainstone-baseband.o
++obj-$(CONFIG_SND_MAINSTONE_BLUETOOTH) += snd-soc-mainstone-bluetooth.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
++
+Index: linux-2.6-pxa-new/sound/soc/pxa/corgi.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/corgi.c
+@@ -0,0 +1,361 @@
++/*
++ * corgi.c  --  SoC audio for Corgi
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Authors: Liam Girdwood <liam.girdwood at wolfsonmicro.com>
++ *          Richard Purdie <richard at openedhand.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.
++ *
++ *  Revision history
++ *    30th Nov 2005   Initial 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/hardware/scoop.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/corgi.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm8731.h"
++#include "pxa2xx-pcm.h"
++
++#define CORGI_HP        0
++#define CORGI_MIC       1
++#define CORGI_LINE      2
++#define CORGI_HEADSET   3
++#define CORGI_HP_OFF    4
++#define CORGI_SPK_ON    0
++#define CORGI_SPK_OFF   1
++
++ /* audio clock in Hz - rounded from 12.235MHz */
++#define CORGI_AUDIO_CLOCK 12288000
++
++static int corgi_jack_func;
++static int corgi_spk_func;
++
++static void corgi_ext_control(struct snd_soc_codec *codec)
++{
++	int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
++
++	/* set up jack connection */
++	switch (corgi_jack_func) {
++	case CORGI_HP:
++		hp = 1;
++		/* set = unmute headphone */
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
++		break;
++	case CORGI_MIC:
++		mic = 1;
++		/* reset = mute headphone */
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
++		break;
++	case CORGI_LINE:
++		line = 1;
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
++		break;
++	case CORGI_HEADSET:
++		hs = 1;
++		mic = 1;
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
++		break;
++	}
++
++	if (corgi_spk_func == CORGI_SPK_ON)
++		spk = 1;
++
++	/* set the enpoints to their new connetion states */
++	snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
++	snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
++	snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
++	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
++	snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
++
++	/* signal a DAPM event */
++	snd_soc_dapm_sync_endpoints(codec);
++}
++
++static int corgi_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 */
++	corgi_ext_control(codec);
++	return 0;
++}
++
++/* we need to unmute the HP at shutdown as the mute burns power on corgi */
++static int corgi_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_codec *codec = rtd->socdev->codec;
++
++	/* set = unmute headphone */
++	set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
++	set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
++	return 0;
++}
++
++static struct snd_soc_ops corgi_ops = {
++	.startup = corgi_startup,
++	.shutdown = corgi_shutdown,
++};
++
++static int corgi_get_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = corgi_jack_func;
++	return 0;
++}
++
++static int corgi_set_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++	if (corgi_jack_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	corgi_jack_func = ucontrol->value.integer.value[0];
++	corgi_ext_control(codec);
++	return 1;
++}
++
++static int corgi_get_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = corgi_spk_func;
++	return 0;
++}
++
++static int corgi_set_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (corgi_spk_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	corgi_spk_func = ucontrol->value.integer.value[0];
++	corgi_ext_control(codec);
++	return 1;
++}
++
++static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
++{
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
++	else
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
++
++	return 0;
++}
++
++static int corgi_mic_event(struct snd_soc_dapm_widget *w, int event)
++{
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
++	else
++		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
++
++	return 0;
++}
++
++/* corgi machine dapm widgets */
++static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
++SND_SOC_DAPM_HP("Headphone Jack", NULL),
++SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
++SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
++SND_SOC_DAPM_LINE("Line Jack", NULL),
++SND_SOC_DAPM_HP("Headset Jack", NULL),
++};
++
++/* Corgi machine audio map (connections to the codec pins) */
++static const char *audio_map[][3] = {
++
++	/* headset Jack  - in = micin, out = LHPOUT*/
++	{"Headset Jack", NULL, "LHPOUT"},
++
++	/* headphone connected to LHPOUT1, RHPOUT1 */
++	{"Headphone Jack", NULL, "LHPOUT"},
++	{"Headphone Jack", NULL, "RHPOUT"},
++
++	/* speaker connected to LOUT, ROUT */
++	{"Ext Spk", NULL, "ROUT"},
++	{"Ext Spk", NULL, "LOUT"},
++
++	/* mic is connected to MICIN (via right channel of headphone jack) */
++	{"MICIN", NULL, "Mic Jack"},
++
++	/* Same as the above but no mic bias for line signals */
++	{"MICIN", NULL, "Line Jack"},
++
++	{NULL, NULL, NULL},
++};
++
++static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
++	"Off"};
++static const char *spk_function[] = {"On", "Off"};
++static const struct soc_enum corgi_enum[] = {
++	SOC_ENUM_SINGLE_EXT(5, jack_function),
++	SOC_ENUM_SINGLE_EXT(2, spk_function),
++};
++
++static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
++	SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
++		corgi_set_jack),
++	SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
++		corgi_set_spk),
++};
++
++/*
++ * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
++ */
++static int corgi_wm8731_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
++	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
++
++	/* Add corgi specific controls */
++	for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
++		err = snd_ctl_add(codec->card,
++			snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	/* Add corgi specific widgets */
++	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
++	}
++
++	/* Set up corgi specific audio path audio_map */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++static unsigned int corgi_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	if (info->bclk_master & SND_SOC_DAIFMT_CBS_CFS) {
++		/* pxa2xx is i2s master  */
++		switch (info->rate) {
++		case 44100:
++		case 88200:
++			/* configure codec digital filters for 44.1, 88.2 */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				11289600);
++		break;
++		default:
++			/* configure codec digital filters for all other rates */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				CORGI_AUDIO_CLOCK);
++		break;
++		}
++		/* config pxa i2s as master */
++		return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info,
++			CORGI_AUDIO_CLOCK);
++	} else {
++		/* codec is i2s master -
++		 * only configure codec DAI clock and filters */
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++			CORGI_AUDIO_CLOCK);
++	}
++}
++
++/* corgi digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link corgi_dai = {
++	.name = "WM8731",
++	.stream_name = "WM8731",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8731_dai,
++	.init = corgi_wm8731_init,
++	.config_sysclk = corgi_config_sysclk,
++};
++
++/* corgi audio machine driver */
++static struct snd_soc_machine snd_soc_machine_corgi = {
++	.name = "Corgi",
++	.dai_link = &corgi_dai,
++	.num_links = 1,
++	.ops = &corgi_ops,
++};
++
++/* corgi audio private data */
++static struct wm8731_setup_data corgi_wm8731_setup = {
++	.i2c_address = 0x1b,
++};
++
++/* corgi audio subsystem */
++static struct snd_soc_device corgi_snd_devdata = {
++	.machine = &snd_soc_machine_corgi,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8731,
++	.codec_data = &corgi_wm8731_setup,
++};
++
++static struct platform_device *corgi_snd_device;
++
++static int __init corgi_init(void)
++{
++	int ret;
++
++	if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
++		return -ENODEV;
++
++	corgi_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!corgi_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata);
++	corgi_snd_devdata.dev = &corgi_snd_device->dev;
++	ret = platform_device_add(corgi_snd_device);
++
++	if (ret)
++		platform_device_put(corgi_snd_device);
++
++	return ret;
++}
++
++static void __exit corgi_exit(void)
++{
++	platform_device_unregister(corgi_snd_device);
++}
++
++module_init(corgi_init);
++module_exit(corgi_exit);
++
++/* Module information */
++MODULE_AUTHOR("Richard Purdie");
++MODULE_DESCRIPTION("ALSA SoC Corgi");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone.c
+@@ -0,0 +1,126 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    30th Oct 2005   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/ac97.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++static long mst_audio_suspend_mask;
++
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	mst_audio_suspend_mask = MST_MSCWR2;
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static struct snd_soc_machine_config codecs[] = {
++{
++	.name = "AC97",
++	.sname = "AC97 HiFi",
++	.iface = &pxa_ac97_interface[0],
++},
++{
++	.name = "AC97 Aux",
++	.sname = "AC97 Aux",
++	.iface = &pxa_ac97_interface[1],
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.config = codecs,
++	.nconfigs = ARRAY_SIZE(codecs),
++};
++
++static struct snd_soc_device mainstone_snd_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_ac97,
++};
++
++static struct platform_device *mainstone_snd_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_device, &mainstone_snd_devdata);
++	mainstone_snd_devdata.dev = &mainstone_snd_device->dev;
++	ret = platform_device_add(mainstone_snd_device);
++
++	if (ret)
++		platform_device_put(mainstone_snd_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_baseband.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_baseband.c
+@@ -0,0 +1,249 @@
++/*
++ * mainstone_baseband.c
++ * Mainstone Example Baseband modem  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    15th Apr 2006   Initial version.
++ *
++ * This is example code to demonstrate connecting a baseband modem to the PCM
++ * DAI on the WM9713 codec on the Intel Mainstone platform. It is by no means
++ * complete as it requires code to control the modem.
++ *
++ * The architecture consists of the WM9713 AC97 DAI connected to the PXA27x
++ * AC97 controller and the WM9713 PCM DAI connected to the basebands DAI. The
++ * baseband is controlled via a serial port. Audio is routed between the PXA27x
++ * and the baseband via internal WM9713 analog paths.
++ *
++ * This driver is not the baseband modem driver. This driver only calls
++ * functions from the Baseband driver to set up it's PCM DAI.
++ *
++ * It's intended to use this driver as follows:-
++ *
++ *  1. open() WM9713 PCM audio device.
++ *  2. open() serial device (for AT commands).
++ *  3. configure PCM audio device (rate etc) - sets up WM9713 PCM DAI,
++ *      this will also set up the baseband PCM DAI (via calling baseband driver).
++ *  4. send any further AT commands to set up baseband.
++ *  5. configure codec audio mixer paths.
++ *  6. open(), configure and read/write AC97 audio device - to Tx/Rx voice
++ *
++ * The PCM audio device is opened but IO is never performed on it as the IO is
++ * directly between the codec and the baseband (and not the CPU).
++ *
++ * TODO:
++ *  o Implement callbacks
++ */
++
++#include <linux/init.h>
++#include <linux/module.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/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++#include <asm/arch/ssp.h>
++
++#include "../codecs/wm9713.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++#define BASEBAND_XXX_DAIFMT \
++	(SND_SOC_DAIFMT_DSP_B  | SND_SOC_DAIFMT_CBS_CFS |\
++	 SND_SOC_DAIFMT_NB_NF)
++
++#define BASEBAND_XXX_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++/*
++ * PCM modes - 8k 16bit mono baseband modem is master
++ */
++static struct snd_soc_dai_mode mainstone_example_modes[] = {
++	/* port master clk & frame modes */
++	{BASEBAND_XXX_DAIFMT, SND_SOC_DAITDM_LRDW(0,0), SNDRV_PCM_FORMAT_S16_LE,
++		SNDRV_PCM_RATE_8000, BASEBAND_XXX_DIR, SND_SOC_DAI_BFS_RATE, 256, 64},
++};
++
++/* Do specific baseband PCM voice startup here */
++static int mainstone_baseband_startup(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++/* Do specific baseband PCM voice shutdown here */
++static void mainstone_baseband_shutdown (struct snd_pcm_substream *substream)
++{
++}
++
++/* Do specific baseband modem PCM voice hw params init here */
++static int mainstone_baseband_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	return 0;
++}
++
++/* Do specific baseband modem PCM voice hw params free here */
++static int mainstone_baseband_hw_free(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++static struct snd_soc_cpu_dai mainstone_example_dai[] = {
++	{	.name = "Baseband",
++		.id = 0,
++		.type = SND_SOC_DAI_PCM,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 1,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 1,},
++		.ops = {
++			.startup = mainstone_baseband_startup,
++			.shutdown = mainstone_baseband_shutdown,
++			.hw_params = mainstone_baseband_hw_params,
++			.hw_free = mainstone_baseband_hw_free,
++			},
++		.caps = {
++			.mode = mainstone_example_modes,
++			.num_modes = ARRAY_SIZE(mainstone_example_modes),},
++	},
++};
++
++/* do we need to do any thing on the mainstone when the stream is
++ * started and stopped
++ */
++static int mainstone_startup(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++static void mainstone_shutdown(struct snd_pcm_substream *substream)
++{
++}
++
++static struct snd_soc_ops mainstone_ops = {
++	.startup = mainstone_startup,
++	.shutdown = mainstone_shutdown,
++};
++
++/* PM */
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static int mainstone_wm9713_init(struct snd_soc_codec *codec)
++{
++	return 0;
++}
++
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	/* wm8753 has pll that generates mclk from 13MHz xtal */
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
++}
++
++/* the physical audio connections between the WM9713, Baseband and pxa2xx */
++static struct snd_soc_dai_link mainstone_dai[] = {
++{
++	.name = "AC97",
++	.stream_name = "AC97 HiFi",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
++	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
++	.init = mainstone_wm9713_init,
++},
++{
++	.name = "AC97 Aux",
++	.stream_name = "AC97 Aux",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
++	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
++},
++{
++	.name = "Baseband",
++	.stream_name = "Voice",
++	.cpu_dai = mainstone_example_dai,
++	.codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.ops = &mainstone_ops,
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct snd_soc_device mainstone_snd_ac97_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm9713,
++};
++
++static struct platform_device *mainstone_snd_ac97_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_ac97_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_ac97_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_ac97_device, &mainstone_snd_ac97_devdata);
++	mainstone_snd_ac97_devdata.dev = &mainstone_snd_ac97_device->dev;
++
++	if((ret = platform_device_add(mainstone_snd_ac97_device)) != 0)
++		platform_device_put(mainstone_snd_ac97_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_ac97_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("Mainstone Example Baseband PCM Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_bluetooth.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_bluetooth.c
+@@ -0,0 +1,399 @@
++/*
++ * mainstone_bluetooth.c
++ * Mainstone Example Bluetooth  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    15th May 2006   Initial version.
++ *
++ * This is example code to demonstrate connecting a bluetooth codec to the PCM
++ * DAI on the WM8753 codec on the Intel Mainstone platform. It is by no means
++ * complete as it requires code to control the BT codec.
++ *
++ * The architecture consists of the WM8753 HIFI DAI connected to the PXA27x
++ * I2S controller and the WM8753 PCM DAI connected to the bluetooth DAI. The
++ * bluetooth codec and wm8753 are controlled via I2C. Audio is routed between
++ * the PXA27x and the bluetooth via internal WM8753 analog paths.
++ *
++ * This example supports the following audio input/outputs.
++ *
++ *  o Board mounted Mic and Speaker (spk has amplifier)
++ *  o Headphones via jack socket
++ *  o BT source and sink
++ *
++ * This driver is not the bluetooth codec driver. This driver only calls
++ * functions from the Bluetooth driver to set up it's PCM DAI.
++ *
++ * It's intended to use the driver as follows:-
++ *
++ *  1. open() WM8753 PCM audio device.
++ *  2. configure PCM audio device (rate etc) - sets up WM8753 PCM DAI,
++ *      this should also set up the BT codec DAI (via calling bt driver).
++ *  3. configure codec audio mixer paths.
++ *  4. open(), configure and read/write HIFI audio device - to Tx/Rx voice
++ *
++ * The PCM audio device is opened but IO is never performed on it as the IO is
++ * directly between the codec and the BT codec (and not the CPU).
++ *
++ * TODO:
++ *  o Implement callbacks
++ */
++
++#include <linux/init.h>
++#include <linux/module.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/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++#include <asm/arch/ssp.h>
++
++#include "../codecs/wm8753.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++#define BLUETOOTH_DAIFMT \
++	(SND_SOC_DAIFMT_DSP_B  | SND_SOC_DAIFMT_CBS_CFS |\
++	 SND_SOC_DAIFMT_NB_NF)
++
++#define BLUETOOTH_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++/*
++ * PCM modes - 8k 16bit mono BT codec is master
++ */
++static struct snd_soc_dai_mode mainstone_bt_modes[] = {
++	/* port master clk & frame modes */
++	{BLUETOOTH_DAIFMT, SND_SOC_DAITDM_LRDW(0,0), SNDRV_PCM_FORMAT_S16_LE,
++		SNDRV_PCM_RATE_8000, BLUETOOTH_DIR, SND_SOC_DAI_BFS_RATE, 256, 64},
++};
++
++/* Do specific bluetooth PCM startup here */
++static int mainstone_bt_startup(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++/* Do specific bluetooth PCM shutdown here */
++static void mainstone_bt_shutdown (struct snd_pcm_substream *substream)
++{
++}
++
++/* Do pecific bluetooth PCM hw params init here */
++static int mainstone_bt_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	return 0;
++}
++
++/* Do specific bluetooth PCM hw params free here */
++static int mainstone_bt_hw_free(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++static struct snd_soc_cpu_dai mainstone_bt_dai[] = {
++	{	.name = "Bluetooth",
++		.id = 0,
++		.type = SND_SOC_DAI_PCM,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 1,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 1,},
++		.ops = {
++			.startup = mainstone_bt_startup,
++			.shutdown = mainstone_bt_shutdown,
++			.hw_params = mainstone_bt_hw_params,
++			.hw_free = mainstone_bt_hw_free,
++			},
++		.caps = {
++			.mode = mainstone_bt_modes,
++			.num_modes = ARRAY_SIZE(mainstone_bt_modes),},
++	},
++};
++
++/* do we need to do any thing on the mainstone when the stream is
++ * started and stopped
++ */
++static int mainstone_startup(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++static void mainstone_shutdown(struct snd_pcm_substream *substream)
++{
++}
++
++static struct snd_soc_ops mainstone_ops = {
++	.startup = mainstone_startup,
++	.shutdown = mainstone_shutdown,
++};
++
++/* PM */
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	return 0;
++}
++
++/*
++ * Machine audio functions.
++ *
++ * The machine now has 3 extra audio controls.
++ *
++ * Jack function: Sets function (device plugged into Jack) to nothing (Off)
++ *                or Headphones.
++ *
++ * Mic function: Set the on board Mic to On or Off
++ * Spk function: Set the on board Spk to On or Off
++ *
++ * example: BT playback (of far end) and capture (of near end)
++ *  Set Mic and Speaker to On, open BT alsa interface as above and set up
++ *  internal audio paths.
++ */
++
++static int machine_jack_func = 0;
++static int machine_spk_func = 0;
++static int machine_mic_func = 0;
++
++static int machine_get_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = machine_jack_func;
++	return 0;
++}
++
++static int machine_set_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++	machine_jack_func = ucontrol->value.integer.value[0];
++	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", machine_jack_func);
++	return 0;
++}
++
++static int machine_get_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = machine_spk_func;
++	return 0;
++}
++
++static int machine_set_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++	machine_spk_func = ucontrol->value.integer.value[0];
++	snd_soc_dapm_set_endpoint(codec, "Spk", machine_spk_func);
++	return 0;
++}
++
++static int machine_get_mic(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = machine_spk_func;
++	return 0;
++}
++
++static int machine_set_mic(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++	machine_spk_func = ucontrol->value.integer.value[0];
++	snd_soc_dapm_set_endpoint(codec, "Mic", machine_mic_func);
++	return 0;
++}
++
++/* turns on board speaker amp on/off */
++static int machine_amp_event(struct snd_soc_dapm_widget *w, int event)
++{
++#if 0
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		/* on */
++	else
++		/* off */
++#endif
++	return 0;
++}
++
++/* machine dapm widgets */
++static const struct snd_soc_dapm_widget machine_dapm_widgets[] = {
++SND_SOC_DAPM_HP("Headphone Jack", NULL),
++SND_SOC_DAPM_SPK("Spk", machine_amp_event),
++SND_SOC_DAPM_MIC("Mic", NULL),
++};
++
++/* machine connections to the codec pins */
++static const char* audio_map[][3] = {
++
++	/* headphone connected to LOUT1, ROUT1 */
++	{"Headphone Jack", NULL, "LOUT"},
++	{"Headphone Jack", NULL, "ROUT"},
++
++	/* speaker connected to LOUT2, ROUT2 */
++	{"Spk", NULL, "ROUT2"},
++	{"Spk", NULL, "LOUT2"},
++
++	/* mic is connected to MIC1 (via Mic Bias) */
++	{"MIC1", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic"},
++
++	{NULL, NULL, NULL},
++};
++
++static const char* jack_function[] = {"Off", "Headphone"};
++static const char* spk_function[] = {"Off", "On"};
++static const char* mic_function[] = {"Off", "On"};
++static const struct soc_enum machine_ctl_enum[] = {
++	SOC_ENUM_SINGLE_EXT(2, jack_function),
++	SOC_ENUM_SINGLE_EXT(2, spk_function),
++	SOC_ENUM_SINGLE_EXT(2, mic_function),
++};
++
++static const struct snd_kcontrol_new wm8753_machine_controls[] = {
++	SOC_ENUM_EXT("Jack Function", machine_ctl_enum[0], machine_get_jack, machine_set_jack),
++	SOC_ENUM_EXT("Speaker Function", machine_ctl_enum[1], machine_get_spk, machine_set_spk),
++	SOC_ENUM_EXT("Mic Function", machine_ctl_enum[2], machine_get_mic, machine_set_mic),
++};
++
++static int mainstone_wm8753_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	/* not used on this machine - e.g. will never be powered up */
++	snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
++	snd_soc_dapm_set_endpoint(codec, "OUT4", 0);
++	snd_soc_dapm_set_endpoint(codec, "MONO2", 0);
++	snd_soc_dapm_set_endpoint(codec, "MONO1", 0);
++	snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
++	snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
++	snd_soc_dapm_set_endpoint(codec, "RXP", 0);
++	snd_soc_dapm_set_endpoint(codec, "RXN", 0);
++	snd_soc_dapm_set_endpoint(codec, "MIC2", 0);
++
++	/* Add machine specific controls */
++	for (i = 0; i < ARRAY_SIZE(wm8753_machine_controls); i++) {
++		if ((err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8753_machine_controls[i],codec, NULL))) < 0)
++			return err;
++	}
++
++	/* Add machine specific widgets */
++	for(i = 0; i < ARRAY_SIZE(machine_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &machine_dapm_widgets[i]);
++	}
++
++	/* Set up machine specific audio path audio_mapnects */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++/* this configures the clocking between the WM8753 and the BT codec */
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	/* wm8753 has pll that generates mclk from 13MHz xtal */
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{ /* Hifi Playback - for similatious use with voice below */
++	.name = "WM8753",
++	.stream_name = "WM8753 HiFi",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
++	.init = mainstone_wm8753_init,
++	.config_sysclk = mainstone_config_sysclk,
++},
++{ /* Voice via BT */
++	.name = "Bluetooth",
++	.stream_name = "Voice",
++	.cpu_dai = mainstone_bt_dai,
++	.codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.ops = &mainstone_ops,
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct snd_soc_device mainstone_snd_wm8753_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8753,
++};
++
++static struct platform_device *mainstone_snd_wm8753_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_wm8753_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_wm8753_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_wm8753_device, &mainstone_snd_wm8753_devdata);
++	mainstone_snd_wm8753_devdata.dev = &mainstone_snd_wm8753_device->dev;
++
++	if((ret = platform_device_add(mainstone_snd_wm8753_device)) != 0)
++		platform_device_put(mainstone_snd_wm8753_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_wm8753_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("Mainstone Example Bluetooth PCM Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8731.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8731.c
+@@ -0,0 +1,156 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    5th June 2006   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm8731.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++
++static const struct snd_soc_dapm_widget dapm_widgets[] = {
++	SND_SOC_DAPM_MIC("Int Mic", NULL),
++	SND_SOC_DAPM_SPK("Ext Spk", NULL),
++};
++
++static const char* intercon[][3] = {
++
++	/* speaker connected to LHPOUT */
++	{"Ext Spk", NULL, "LHPOUT"},
++
++	/* mic is connected to Mic Jack, with WM8731 Mic Bias */
++	{"MICIN", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Int Mic"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++/*
++ * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
++ */
++static int mainstone_wm8731_init(struct snd_soc_codec *codec)
++{
++	int i;
++
++
++	/* Add specific widgets */
++	for(i = 0; i < ARRAY_SIZE(dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &dapm_widgets[i]);
++	}
++
++	/* Set up specific audio path interconnects */
++	for(i = 0; intercon[i][0] != NULL; i++) {
++		snd_soc_dapm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
++	}
++
++	/* not connected */
++	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
++	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
++
++	/* always connected */
++	snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
++	snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
++
++	snd_soc_dapm_sync_endpoints(codec);
++
++	return 0;
++}
++
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	/* we have a 12.288MHz crystal */
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 12288000);
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{
++	.name = "WM8731",
++	.stream_name = "WM8731 HiFi",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8731_dai,
++	.init = mainstone_wm8731_init,
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct wm8731_setup_data corgi_wm8731_setup = {
++	.i2c_address = 0x1b,
++};
++
++static struct snd_soc_device mainstone_snd_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8731,
++	.codec_data = &corgi_wm8731_setup,
++};
++
++static struct platform_device *mainstone_snd_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_device, &mainstone_snd_devdata);
++	mainstone_snd_devdata.dev = &mainstone_snd_device->dev;
++	ret = platform_device_add(mainstone_snd_device);
++
++	if (ret)
++		platform_device_put(mainstone_snd_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC WM8731 Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8753.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8753.c
+@@ -0,0 +1,226 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    30th Oct 2005   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm8753.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++static int mainstone_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if(rtd->cpu_dai->type == SND_SOC_DAI_PCM && rtd->cpu_dai->id == 1) {
++		/* enable USB on the go MUX so we can use SSPFRM2 */
++		MST_MSCWR2 |= MST_MSCWR2_USB_OTG_SEL;
++		MST_MSCWR2 &= ~MST_MSCWR2_USB_OTG_RST;
++	}
++	return 0;
++}
++
++static void mainstone_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if(rtd->cpu_dai->type == SND_SOC_DAI_PCM && rtd->cpu_dai->id == 1) {
++		/* disable USB on the go MUX so we can use ttyS0 */
++		MST_MSCWR2 &= ~MST_MSCWR2_USB_OTG_SEL;
++		MST_MSCWR2 |= MST_MSCWR2_USB_OTG_RST;
++	}
++}
++
++static struct snd_soc_ops mainstone_ops = {
++	.startup = mainstone_startup,
++	.shutdown = mainstone_shutdown,
++};
++
++static long mst_audio_suspend_mask;
++
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	mst_audio_suspend_mask = MST_MSCWR2;
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++/* example machine audio_mapnections */
++static const char* audio_map[][3] = {
++
++	/* mic is connected to mic1 - with bias */
++	{"MIC1", NULL, "Mic Bias"},
++	{"MIC1N", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic1 Jack"},
++	{"Mic Bias", NULL, "Mic1 Jack"},
++
++	{"ACIN", NULL, "ACOP"},
++	{NULL, NULL, NULL},
++};
++
++/* headphone detect support on my board */
++static const char * hp_pol[] = {"Headphone", "Speaker"};
++static const struct soc_enum wm8753_enum =
++	SOC_ENUM_SINGLE(WM8753_OUTCTL, 1, 2, hp_pol);
++
++static const struct snd_kcontrol_new wm8753_mainstone_controls[] = {
++	SOC_SINGLE("Headphone Detect Switch", WM8753_OUTCTL, 6, 1, 0),
++	SOC_ENUM("Headphone Detect Polarity", wm8753_enum),
++};
++
++/*
++ * This is an example machine initialisation for a wm8753 connected to a
++ * Mainstone II. It is missing logic to detect hp/mic insertions and logic
++ * to re-route the audio in such an event.
++ */
++static int mainstone_wm8753_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	/* set up mainstone codec pins */
++	snd_soc_dapm_set_endpoint(codec, "RXP", 0);
++	snd_soc_dapm_set_endpoint(codec, "RXN", 0);
++	snd_soc_dapm_set_endpoint(codec, "MIC2", 0);
++
++	/* add mainstone specific controls */
++	for (i = 0; i < ARRAY_SIZE(wm8753_mainstone_controls); i++) {
++		if ((err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8753_mainstone_controls[i],codec, NULL))) < 0)
++			return err;
++	}
++
++	/* set up mainstone specific audio path audio_mapnects */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	/* wm8753 has pll that generates mclk from 13MHz xtal */
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{ /* Hifi Playback - for similatious use with voice below */
++	.name = "WM8753",
++	.stream_name = "WM8753 HiFi",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
++	.init = mainstone_wm8753_init,
++	.config_sysclk = mainstone_config_sysclk,
++},
++{ /* Voice via BT */
++	.name = "Bluetooth",
++	.stream_name = "Voice",
++	.cpu_dai = &pxa_ssp_dai[1],
++	.codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.ops = &mainstone_ops,
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct wm8753_setup_data mainstone_wm8753_setup = {
++	.i2c_address = 0x1a,
++};
++
++static struct snd_soc_device mainstone_snd_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8753,
++	.codec_data = &mainstone_wm8753_setup,
++};
++
++static struct platform_device *mainstone_snd_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_device, &mainstone_snd_devdata);
++	mainstone_snd_devdata.dev = &mainstone_snd_device->dev;
++	ret = platform_device_add(mainstone_snd_device);
++
++	if (ret)
++		platform_device_put(mainstone_snd_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC WM8753 Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8974.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm8974.c
+@@ -0,0 +1,112 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    30th Oct 2005   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm8974.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++static int mainstone_wm8974_init(struct snd_soc_codec *codec)
++{
++	return 0;
++}
++
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	/* we have a PLL */
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 12288000);
++
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{
++	.name = "WM8974",
++	.stream_name = "WM8974 HiFi",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8974_dai,
++	.init = mainstone_wm8974_init,
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct wm8974_setup_data mainstone_wm8974_setup = {
++	.i2c_address = 0x1a,
++};
++
++static struct snd_soc_device mainstone_snd_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8974,
++	.codec_data = &mainstone_wm8974_setup,
++};
++
++static struct platform_device *mainstone_snd_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_device, &mainstone_snd_devdata);
++	mainstone_snd_devdata.dev = &mainstone_snd_device->dev;
++	ret = platform_device_add(mainstone_snd_device);
++
++	if (ret)
++		platform_device_put(mainstone_snd_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm9712.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm9712.c
+@@ -0,0 +1,171 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    29th Jan 2006   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm9712.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++static long mst_audio_suspend_mask;
++
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	mst_audio_suspend_mask = MST_MSCWR2;
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++/* mainstone machine dapm widgets */
++static const struct snd_soc_dapm_widget mainstone_dapm_widgets[] = {
++	SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
++};
++
++/* example machine interconnections */
++static const char* intercon[][3] = {
++
++	/* mic is connected to mic1 - with bias */
++	{"MIC1", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic (Internal)"},
++
++	{NULL, NULL, NULL},
++};
++
++/*
++ * This is an example machine initialisation for a wm8753 connected to a
++ * Mainstone II. It is missing logic to detect hp/mic insertions and logic
++ * to re-route the audio in such an event.
++ */
++static int mainstone_wm9712_init(struct snd_soc_codec *codec)
++{
++	int i;
++
++	/* set up mainstone codec pins */
++	snd_soc_dapm_set_endpoint(codec, "RXP", 0);
++	snd_soc_dapm_set_endpoint(codec, "RXN", 0);
++	//snd_soc_dapm_set_endpoint(codec, "MIC2", 0);
++
++	/* Add mainstone specific widgets */
++	for(i = 0; i < ARRAY_SIZE(mainstone_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &mainstone_dapm_widgets[i]);
++	}
++
++	/* set up mainstone specific audio path interconnects */
++	for(i = 0; intercon[i][0] != NULL; i++) {
++		snd_soc_dapm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
++	}
++
++	snd_soc_dapm_sync_endpoints(codec);
++	return 0;
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{
++	.name = "AC97",
++	.stream_name = "AC97 HiFi",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
++	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
++	.init = mainstone_wm9712_init,
++},
++{
++	.name = "AC97 Aux",
++	.stream_name = "AC97 Aux",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
++	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct snd_soc_device mainstone_snd_ac97_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm9712,
++};
++
++static struct platform_device *mainstone_snd_ac97_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_ac97_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_ac97_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_ac97_device, &mainstone_snd_ac97_devdata);
++	mainstone_snd_ac97_devdata.dev = &mainstone_snd_ac97_device->dev;
++
++	if((ret = platform_device_add(mainstone_snd_ac97_device)) != 0)
++		platform_device_put(mainstone_snd_ac97_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_ac97_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC WM9712 Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm9713.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/mainstone_wm9713.c
+@@ -0,0 +1,263 @@
++/*
++ * mainstone.c  --  SoC audio for Mainstone
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Mainstone audio amplifier code taken from arch/arm/mach-pxa/mainstone.c
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    29th Jan 2006   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mainstone.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm9713.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine mainstone;
++
++static int mainstone_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if(rtd->cpu_dai->type == SND_SOC_DAI_PCM && rtd->cpu_dai->id == 1) {
++		/* enable USB on the go MUX so we can use SSPFRM2 */
++		MST_MSCWR2 |= MST_MSCWR2_USB_OTG_SEL;
++		MST_MSCWR2 &= ~MST_MSCWR2_USB_OTG_RST;
++	}
++	return 0;
++}
++
++static void mainstone_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if(rtd->cpu_dai->type == SND_SOC_DAI_PCM && rtd->cpu_dai->id == 1) {
++		/* disable USB on the go MUX so we can use ttyS0 */
++		MST_MSCWR2 &= ~MST_MSCWR2_USB_OTG_SEL;
++		MST_MSCWR2 |= MST_MSCWR2_USB_OTG_RST;
++	}
++}
++
++static struct snd_soc_ops mainstone_ops = {
++	.startup = mainstone_startup,
++	.shutdown = mainstone_shutdown,
++};
++
++static int test = 0;
++static int get_test(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = test;
++	return 0;
++}
++
++static int set_test(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++	test = ucontrol->value.integer.value[0];
++	if(test) {
++
++	} else {
++
++	}
++	return 0;
++}
++
++static long mst_audio_suspend_mask;
++
++static int mainstone_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	mst_audio_suspend_mask = MST_MSCWR2;
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_resume(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_probe(struct platform_device *pdev)
++{
++	MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static int mainstone_remove(struct platform_device *pdev)
++{
++	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
++	return 0;
++}
++
++static const char* test_function[] = {"Off", "On"};
++static const struct soc_enum mainstone_enum[] = {
++	SOC_ENUM_SINGLE_EXT(2, test_function),
++};
++
++static const struct snd_kcontrol_new mainstone_controls[] = {
++	SOC_ENUM_EXT("ATest Function", mainstone_enum[0], get_test, set_test),
++};
++
++/* mainstone machine dapm widgets */
++static const struct snd_soc_dapm_widget mainstone_dapm_widgets[] = {
++	SND_SOC_DAPM_MIC("Mic 1", NULL),
++	SND_SOC_DAPM_MIC("Mic 2", NULL),
++	SND_SOC_DAPM_MIC("Mic 3", NULL),
++};
++
++/* example machine audio_mapnections */
++static const char* audio_map[][3] = {
++
++	/* mic is connected to mic1 - with bias */
++	{"MIC1", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic 1"},
++	/* mic is connected to mic2A - with bias */
++	{"MIC2A", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic 2"},
++	/* mic is connected to mic2B - with bias */
++	{"MIC2B", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic 3"},
++
++	{NULL, NULL, NULL},
++};
++
++/*
++ * This is an example machine initialisation for a wm9713 connected to a
++ * Mainstone II. It is missing logic to detect hp/mic insertions and logic
++ * to re-route the audio in such an event.
++ */
++static int mainstone_wm9713_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	/* set up mainstone codec pins */
++	snd_soc_dapm_set_endpoint(codec, "RXP", 0);
++	snd_soc_dapm_set_endpoint(codec, "RXN", 0);
++	//snd_soc_dapm_set_endpoint(codec, "MIC2", 0);
++
++	/* Add test specific controls */
++	for (i = 0; i < ARRAY_SIZE(mainstone_controls); i++) {
++		if ((err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&mainstone_controls[i],codec, NULL))) < 0)
++			return err;
++	}
++
++	/* Add mainstone specific widgets */
++	for(i = 0; i < ARRAY_SIZE(mainstone_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &mainstone_dapm_widgets[i]);
++	}
++
++	/* set up mainstone specific audio path audio_mapnects */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++/* configure the system audio clock */
++unsigned int mainstone_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 24576000);
++}
++
++static struct snd_soc_dai_link mainstone_dai[] = {
++{
++	.name = "AC97",
++	.stream_name = "AC97 HiFi",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
++	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
++	.init = mainstone_wm9713_init,
++	.config_sysclk = mainstone_config_sysclk,
++},
++{
++	.name = "AC97 Aux",
++	.stream_name = "AC97 Aux",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
++	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
++	.config_sysclk = mainstone_config_sysclk,
++},
++{
++	.name = "WM9713",
++	.stream_name = "WM9713 Voice",
++	.cpu_dai = &pxa_ssp_dai[PXA2XX_DAI_SSP2],
++	.codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
++	.config_sysclk = mainstone_config_sysclk,
++},
++};
++
++static struct snd_soc_machine mainstone = {
++	.name = "Mainstone",
++	.probe = mainstone_probe,
++	.remove = mainstone_remove,
++	.suspend_pre = mainstone_suspend,
++	.resume_post = mainstone_resume,
++	.ops = &mainstone_ops,
++	.dai_link = mainstone_dai,
++	.num_links = ARRAY_SIZE(mainstone_dai),
++};
++
++static struct snd_soc_device mainstone_snd_ac97_devdata = {
++	.machine = &mainstone,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm9713,
++};
++
++static struct platform_device *mainstone_snd_ac97_device;
++
++static int __init mainstone_init(void)
++{
++	int ret;
++
++	mainstone_snd_ac97_device = platform_device_alloc("soc-audio", -1);
++	if (!mainstone_snd_ac97_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(mainstone_snd_ac97_device, &mainstone_snd_ac97_devdata);
++	mainstone_snd_ac97_devdata.dev = &mainstone_snd_ac97_device->dev;
++
++	if((ret = platform_device_add(mainstone_snd_ac97_device)) != 0)
++		platform_device_put(mainstone_snd_ac97_device);
++
++	return ret;
++}
++
++static void __exit mainstone_exit(void)
++{
++	platform_device_unregister(mainstone_snd_ac97_device);
++}
++
++module_init(mainstone_init);
++module_exit(mainstone_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC WM9713 Mainstone");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/poodle.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/poodle.c
+@@ -0,0 +1,329 @@
++/*
++ * poodle.c  --  SoC audio for Poodle
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Authors: Liam Girdwood <liam.girdwood at wolfsonmicro.com>
++ *          Richard Purdie <richard at openedhand.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/hardware/locomo.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/poodle.h>
++#include <asm/arch/audio.h>
++
++#include "../codecs/wm8731.h"
++#include "pxa2xx-pcm.h"
++
++#define POODLE_HP        1
++#define POODLE_HP_OFF    0
++#define POODLE_SPK_ON    1
++#define POODLE_SPK_OFF   0
++
++ /* audio clock in Hz - rounded from 12.235MHz */
++#define POODLE_AUDIO_CLOCK 12288000
++
++static int poodle_jack_func;
++static int poodle_spk_func;
++
++static void poodle_ext_control(struct snd_soc_codec *codec)
++{
++	int spk = 0;
++
++	/* set up jack connection */
++	if (poodle_jack_func == POODLE_HP) {
++		/* set = unmute headphone */
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_MUTE_L, 1);
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_MUTE_R, 1);
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
++	} else {
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_MUTE_L, 0);
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_MUTE_R, 0);
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
++	}
++
++	if (poodle_spk_func == POODLE_SPK_ON)
++		spk = 1;
++
++	/* set the enpoints to their new connetion states */
++	snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
++
++	/* signal a DAPM event */
++	snd_soc_dapm_sync_endpoints(codec);
++}
++
++static int poodle_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 */
++	poodle_ext_control(codec);
++	return 0;
++}
++
++/* we need to unmute the HP at shutdown as the mute burns power on poodle */
++static int poodle_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_codec *codec = rtd->socdev->codec;
++
++	/* set = unmute headphone */
++	locomo_gpio_write(&poodle_locomo_device.dev,
++		POODLE_LOCOMO_GPIO_MUTE_L, 1);
++	locomo_gpio_write(&poodle_locomo_device.dev,
++		POODLE_LOCOMO_GPIO_MUTE_R, 1);
++	return 0;
++}
++
++static struct snd_soc_ops poodle_ops = {
++	.startup = poodle_startup,
++	.shutdown = poodle_shutdown,
++};
++
++static int poodle_get_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = poodle_jack_func;
++	return 0;
++}
++
++static int poodle_set_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (poodle_jack_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	poodle_jack_func = ucontrol->value.integer.value[0];
++	poodle_ext_control(codec);
++	return 1;
++}
++
++static int poodle_get_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = poodle_spk_func;
++	return 0;
++}
++
++static int poodle_set_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (poodle_spk_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	poodle_spk_func = ucontrol->value.integer.value[0];
++	poodle_ext_control(codec);
++	return 1;
++}
++
++static int poodle_amp_event(struct snd_soc_dapm_widget *w, int event)
++{
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_AMP_ON, 0);
++	else
++		locomo_gpio_write(&poodle_locomo_device.dev,
++			POODLE_LOCOMO_GPIO_AMP_ON, 1);
++
++	return 0;
++}
++
++/* poodle machine dapm widgets */
++static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
++SND_SOC_DAPM_HP("Headphone Jack", NULL),
++SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
++};
++
++/* Corgi machine audio_mapnections to the codec pins */
++static const char *audio_map[][3] = {
++
++	/* headphone connected to LHPOUT1, RHPOUT1 */
++	{"Headphone Jack", NULL, "LHPOUT"},
++	{"Headphone Jack", NULL, "RHPOUT"},
++
++	/* speaker connected to LOUT, ROUT */
++	{"Ext Spk", NULL, "ROUT"},
++	{"Ext Spk", NULL, "LOUT"},
++
++	{NULL, NULL, NULL},
++};
++
++static const char *jack_function[] = {"Off", "Headphone"};
++static const char *spk_function[] = {"Off", "On"};
++static const struct soc_enum poodle_enum[] = {
++	SOC_ENUM_SINGLE_EXT(2, jack_function),
++	SOC_ENUM_SINGLE_EXT(2, spk_function),
++};
++
++static const snd_kcontrol_new_t wm8731_poodle_controls[] = {
++	SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
++		poodle_set_jack),
++	SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
++		poodle_set_spk),
++};
++
++/*
++ * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
++ */
++static int poodle_wm8731_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
++	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
++	snd_soc_dapm_set_endpoint(codec, "MICIN", 1);
++
++	/* Add poodle specific controls */
++	for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
++		err = snd_ctl_add(codec->card,
++			snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	/* Add poodle specific widgets */
++	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
++	}
++
++	/* Set up poodle specific audio path audio_map */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++static unsigned int poodle_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	if (info->bclk_master & SND_SOC_DAIFMT_CBS_CFS) {
++		/* pxa2xx is i2s master  */
++		switch (info->rate) {
++		case 44100:
++		case 88200:
++			/* configure codec digital filters for 44.1, 88.2 */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				11289600);
++		break;
++		default:
++			/* configure codec digital filters for all other rates */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				POODLE_AUDIO_CLOCK);
++		break;
++		}
++		return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info,
++			POODLE_AUDIO_CLOCK);
++	} else {
++		/* codec is i2s master -
++		 * only configure codec DAI clock and filters */
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++			POODLE_AUDIO_CLOCK);
++	}
++}
++
++/* poodle digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link poodle_dai = {
++	.name = "WM8731",
++	.stream_name = "WM8731",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8731_dai,
++	.init = poodle_wm8731_init,
++	.config_sysclk = poodle_config_sysclk,
++};
++
++/* poodle audio machine driver */
++static struct snd_soc_machine snd_soc_machine_poodle = {
++	.name = "Poodle",
++	.dai_link = &poodle_dai,
++	.num_links = 1,
++	.ops = &poodle_ops,
++};
++
++/* poodle audio private data */
++static struct wm8731_setup_data poodle_wm8731_setup = {
++	.i2c_address = 0x1b,
++};
++
++/* poodle audio subsystem */
++static struct snd_soc_device poodle_snd_devdata = {
++	.machine = &snd_soc_machine_poodle,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8731,
++	.codec_data = &poodle_wm8731_setup,
++};
++
++static struct platform_device *poodle_snd_device;
++
++static int __init poodle_init(void)
++{
++	int ret;
++
++	if (!machine_is_poodle())
++		return -ENODEV;
++
++	locomo_gpio_set_dir(&poodle_locomo_device.dev,
++		POODLE_LOCOMO_GPIO_AMP_ON, 0);
++	/* should we mute HP at startup - burning power ?*/
++	locomo_gpio_set_dir(&poodle_locomo_device.dev,
++		POODLE_LOCOMO_GPIO_MUTE_L, 0);
++	locomo_gpio_set_dir(&poodle_locomo_device.dev,
++		POODLE_LOCOMO_GPIO_MUTE_R, 0);
++
++	poodle_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!poodle_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata);
++	poodle_snd_devdata.dev = &poodle_snd_device->dev;
++	ret = platform_device_add(poodle_snd_device);
++
++	if (ret)
++		platform_device_put(poodle_snd_device);
++
++	return ret;
++}
++
++static void __exit poodle_exit(void)
++{
++	platform_device_unregister(poodle_snd_device);
++}
++
++module_init(poodle_init);
++module_exit(poodle_exit);
++
++/* Module information */
++MODULE_AUTHOR("Richard Purdie");
++MODULE_DESCRIPTION("ALSA SoC Poodle");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-ac97.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-ac97.c
+@@ -0,0 +1,437 @@
++/*
++ * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
++ *
++ * Author:	Nicolas Pitre
++ * Created:	Dec 02, 2004
++ * Copyright:	MontaVista Software 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.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include <linux/delay.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/irq.h>
++#include <linux/mutex.h>
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++
++#include "pxa2xx-pcm.h"
++
++static DEFINE_MUTEX(car_mutex);
++static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
++static volatile long gsr_bits;
++
++#define AC97_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define AC97_RATES \
++	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
++	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
++
++/* may need to expand this */
++static struct snd_soc_dai_mode pxa2xx_ac97_modes[] = {
++	{
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = AC97_RATES,
++		.pcmdir = AC97_DIR,
++	},
++};
++
++/*
++ * Beware PXA27x bugs:
++ *
++ *   o Slot 12 read from modem space will hang controller.
++ *   o CDONE, SDONE interrupt fails after any slot 12 IO.
++ *
++ * We therefore have an hybrid approach for waiting on SDONE (interrupt or
++ * 1 jiffy timeout if interrupt never comes).
++ */
++
++static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
++	unsigned short reg)
++{
++	unsigned short val = -1;
++	volatile u32 *reg_addr;
++
++	mutex_lock(&car_mutex);
++
++	/* set up primary or secondary codec/modem space */
++#ifdef CONFIG_PXA27x
++	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
++#else
++	if (reg == AC97_GPIO_STATUS)
++		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
++	else
++		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
++#endif
++	reg_addr += (reg >> 1);
++
++#ifndef CONFIG_PXA27x
++	if (reg == AC97_GPIO_STATUS) {
++		/* read from controller cache */
++		val = *reg_addr;
++		goto out;
++	}
++#endif
++
++	/* start read access across the ac97 link */
++	GSR = GSR_CDONE | GSR_SDONE;
++	gsr_bits = 0;
++	val = *reg_addr;
++
++	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
++	if (!((GSR | gsr_bits) & GSR_SDONE)) {
++		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
++				__FUNCTION__, reg, GSR | gsr_bits);
++		val = -1;
++		goto out;
++	}
++
++	/* valid data now */
++	GSR = GSR_CDONE | GSR_SDONE;
++	gsr_bits = 0;
++	val = *reg_addr;
++	/* but we've just started another cycle... */
++	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
++
++out:	mutex_unlock(&car_mutex);
++	return val;
++}
++
++static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
++	unsigned short val)
++{
++	volatile u32 *reg_addr;
++
++	mutex_lock(&car_mutex);
++
++	/* set up primary or secondary codec/modem space */
++#ifdef CONFIG_PXA27x
++	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
++#else
++	if (reg == AC97_GPIO_STATUS)
++		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
++	else
++		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
++#endif
++	reg_addr += (reg >> 1);
++
++	GSR = GSR_CDONE | GSR_SDONE;
++	gsr_bits = 0;
++	*reg_addr = val;
++	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
++	if (!((GSR | gsr_bits) & GSR_CDONE))
++		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
++				__FUNCTION__, reg, GSR | gsr_bits);
++
++	mutex_unlock(&car_mutex);
++}
++
++static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
++{
++	gsr_bits = 0;
++
++#ifdef CONFIG_PXA27x
++	/* warm reset broken on Bulverde,
++	   so manually keep AC97 reset high */
++	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
++	udelay(10);
++	GCR |= GCR_WARM_RST;
++	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++	udelay(500);
++#else
++	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
++	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
++#endif
++
++	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
++		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
++				 __FUNCTION__, gsr_bits);
++
++	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
++}
++
++static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
++{
++	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
++	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
++
++	gsr_bits = 0;
++#ifdef CONFIG_PXA27x
++	/* PXA27x Developers Manual section 13.5.2.2.1 */
++	pxa_set_cken(1 << 31, 1);
++	udelay(5);
++	pxa_set_cken(1 << 31, 0);
++	GCR = GCR_COLD_RST;
++	udelay(50);
++#else
++	GCR = GCR_COLD_RST;
++	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
++	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
++#endif
++
++	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
++		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
++				 __FUNCTION__, gsr_bits);
++
++	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
++}
++
++static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
++{
++	long status;
++
++	status = GSR;
++	if (status) {
++		GSR = status;
++		gsr_bits |= status;
++		wake_up(&gsr_wq);
++
++#ifdef CONFIG_PXA27x
++		/* Although we don't use those we still need to clear them
++		   since they tend to spuriously trigger when MMC is used
++		   (hardware bug? go figure)... */
++		MISR = MISR_EOC;
++		PISR = PISR_EOC;
++		MCSR = MCSR_EOC;
++#endif
++
++		return IRQ_HANDLED;
++	}
++
++	return IRQ_NONE;
++}
++
++struct snd_ac97_bus_ops soc_ac97_ops = {
++	.read	= pxa2xx_ac97_read,
++	.write	= pxa2xx_ac97_write,
++	.warm_reset	= pxa2xx_ac97_warm_reset,
++	.reset	= pxa2xx_ac97_cold_reset,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
++	.name			= "AC97 PCM Stereo out",
++	.dev_addr		= __PREG(PCDR),
++	.drcmr			= &DRCMRTXPCDR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST32 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
++	.name			= "AC97 PCM Stereo in",
++	.dev_addr		= __PREG(PCDR),
++	.drcmr			= &DRCMRRXPCDR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST32 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
++	.name			= "AC97 Aux PCM (Slot 5) Mono out",
++	.dev_addr		= __PREG(MODR),
++	.drcmr			= &DRCMRTXMODR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
++	.name			= "AC97 Aux PCM (Slot 5) Mono in",
++	.dev_addr		= __PREG(MODR),
++	.drcmr			= &DRCMRRXMODR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
++	.name			= "AC97 Mic PCM (Slot 6) Mono in",
++	.dev_addr		= __PREG(MCDR),
++	.drcmr			= &DRCMRRXMCDR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++#ifdef CONFIG_PM
++static int pxa2xx_ac97_suspend(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	GCR |= GCR_ACLINK_OFF;
++	pxa_set_cken(CKEN2_AC97, 0);
++	return 0;
++}
++
++static int pxa2xx_ac97_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
++	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
++	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
++	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
++#ifdef CONFIG_PXA27x
++	/* Use GPIO 113 as AC97 Reset on Bulverde */
++	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++#endif
++	pxa_set_cken(CKEN2_AC97, 1);
++	return 0;
++}
++
++#else
++#define pxa2xx_ac97_suspend	NULL
++#define pxa2xx_ac97_resume	NULL
++#endif
++
++static int pxa2xx_ac97_probe(struct platform_device *pdev)
++{
++	int ret;
++
++	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
++	if (ret < 0)
++		goto err;
++
++	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
++	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
++	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
++	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
++#ifdef CONFIG_PXA27x
++	/* Use GPIO 113 as AC97 Reset on Bulverde */
++	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++#endif
++	pxa_set_cken(CKEN2_AC97, 1);
++	return 0;
++
++ err:
++	if (CKEN & CKEN2_AC97) {
++		GCR |= GCR_ACLINK_OFF;
++		free_irq(IRQ_AC97, NULL);
++		pxa_set_cken(CKEN2_AC97, 0);
++	}
++	return ret;
++}
++
++static void pxa2xx_ac97_remove(struct platform_device *pdev)
++{
++	GCR |= GCR_ACLINK_OFF;
++	free_irq(IRQ_AC97, NULL);
++	pxa_set_cken(CKEN2_AC97, 0);
++}
++
++static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		rtd->cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
++	else
++		rtd->cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
++
++	return 0;
++}
++
++static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		rtd->cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
++	else
++		rtd->cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
++
++	return 0;
++}
++
++static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		return -ENODEV;
++	else
++		rtd->cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
++
++	return 0;
++}
++
++/*
++ * There is only 1 physical AC97 interface for pxa2xx, but it
++ * has extra fifo's that can be used for aux DACs and ADCs.
++ */
++struct snd_soc_cpu_dai pxa_ac97_dai[] = {
++{
++	.name = "pxa2xx-ac97",
++	.id = 0,
++	.type = SND_SOC_DAI_AC97,
++	.probe = pxa2xx_ac97_probe,
++	.remove = pxa2xx_ac97_remove,
++	.suspend = pxa2xx_ac97_suspend,
++	.resume = pxa2xx_ac97_resume,
++	.playback = {
++		.stream_name = "AC97 Playback",
++		.channels_min = 2,
++		.channels_max = 2,},
++	.capture = {
++		.stream_name = "AC97 Capture",
++		.channels_min = 2,
++		.channels_max = 2,},
++	.ops = {
++		.hw_params = pxa2xx_ac97_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(pxa2xx_ac97_modes),
++		.mode = pxa2xx_ac97_modes,},
++},
++{
++	.name = "pxa2xx-ac97-aux",
++	.id = 1,
++	.type = SND_SOC_DAI_AC97,
++	.playback = {
++		.stream_name = "AC97 Aux Playback",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.capture = {
++		.stream_name = "AC97 Aux Capture",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.ops = {
++		.hw_params = pxa2xx_ac97_hw_aux_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(pxa2xx_ac97_modes),
++		.mode = pxa2xx_ac97_modes,},
++},
++{
++	.name = "pxa2xx-ac97-mic",
++	.id = 2,
++	.type = SND_SOC_DAI_AC97,
++	.capture = {
++		.stream_name = "AC97 Mic Capture",
++		.channels_min = 1,
++		.channels_max = 1,},
++	.ops = {
++		.hw_params = pxa2xx_ac97_hw_mic_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(pxa2xx_ac97_modes),
++		.mode = pxa2xx_ac97_modes,},},
++};
++
++EXPORT_SYMBOL_GPL(pxa_ac97_dai);
++EXPORT_SYMBOL_GPL(soc_ac97_ops);
++
++MODULE_AUTHOR("Nicolas Pitre");
++MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-i2s.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-i2s.c
+@@ -0,0 +1,354 @@
++/*
++ * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    12th Aug 2005   Initial version.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++
++#include "pxa2xx-pcm.h"
++
++/* used to disable sysclk if external crystal is used */
++static int extclk;
++module_param(extclk, int, 0);
++MODULE_PARM_DESC(extclk, "set to 1 to disable pxa2xx i2s sysclk");
++
++struct pxa_i2s_port {
++	u32 sadiv;
++	u32 sacr0;
++	u32 sacr1;
++	u32 saimr;
++	int master;
++};
++static struct pxa_i2s_port pxa_i2s;
++
++#define PXA_I2S_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
++
++#define PXA_I2S_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define PXA_I2S_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++/* priv is divider */
++static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
++	/* pxa2xx I2S frame and clock master modes */
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x48,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x34,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x24,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0x1a,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0xd,
++	},
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = PXA_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = SND_SOC_FSBD(4),
++		.priv = 0xc,
++	},
++
++	/* pxa2xx I2S frame master and clock slave mode */
++	{
++		.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = PXA_I2S_RATES,
++		.pcmdir = PXA_I2S_DIR,
++		.fs = SND_SOC_FS_ALL,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.bfs = 64,
++		.priv = 0x48,
++	},
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
++	.name			= "I2S PCM Stereo out",
++	.dev_addr		= __PREG(SADR),
++	.drcmr			= &DRCMRTXSADR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST32 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
++	.name			= "I2S PCM Stereo in",
++	.dev_addr		= __PREG(SADR),
++	.drcmr			= &DRCMRRXSADR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST32 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_gpio gpio_bus[] = {
++	{ /* I2S SoC Slave */
++		.rx = GPIO29_SDATA_IN_I2S_MD,
++		.tx = GPIO30_SDATA_OUT_I2S_MD,
++		.clk = GPIO28_BITCLK_IN_I2S_MD,
++		.frm = GPIO31_SYNC_I2S_MD,
++	},
++	{ /* I2S SoC Master */
++#ifdef CONFIG_PXA27x
++		.sys = GPIO113_I2S_SYSCLK_MD,
++#else
++		.sys = GPIO32_SYSCLK_I2S_MD,
++#endif
++		.rx = GPIO29_SDATA_IN_I2S_MD,
++		.tx = GPIO30_SDATA_OUT_I2S_MD,
++		.clk = GPIO28_BITCLK_OUT_I2S_MD,
++		.frm = GPIO31_SYNC_I2S_MD,
++	},
++};
++
++static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (!rtd->cpu_dai->active) {
++		SACR0 |= SACR0_RST;
++		SACR0 = 0;
++	}
++
++	return 0;
++}
++
++/* wait for I2S controller to be ready */
++static int pxa_i2s_wait(void)
++{
++	int i;
++
++	/* flush the Rx FIFO */
++	for(i = 0; i < 16; i++)
++		SADR;
++	return 0;
++}
++
++static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	pxa_i2s.master = 0;
++	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
++		pxa_i2s.master = 1;
++
++	if (pxa_i2s.master && !extclk)
++		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
++
++	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
++	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
++	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
++	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
++	pxa_set_cken(CKEN8_I2S, 1);
++	pxa_i2s_wait();
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
++	else
++		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
++
++	/* is port used by another stream */
++	if (!(SACR0 & SACR0_ENB)) {
++
++		SACR0 = 0;
++		SACR1 = 0;
++		if (pxa_i2s.master)
++			SACR0 |= SACR0_BCKD;
++
++		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
++
++		if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_LEFT_J)
++			SACR1 |= SACR1_AMSL;
++	}
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		SAIMR |= SAIMR_TFS;
++	else
++		SAIMR |= SAIMR_RFS;
++
++	SADIV = rtd->cpu_dai->dai_runtime.priv;
++	return 0;
++}
++
++static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		SACR0 |= SACR0_ENB;
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
++{
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		SACR1 |= SACR1_DRPL;
++		SAIMR &= ~SAIMR_TFS;
++	} else {
++		SACR1 |= SACR1_DREC;
++		SAIMR &= ~SAIMR_RFS;
++	}
++
++	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
++		SACR0 &= ~SACR0_ENB;
++		pxa_i2s_wait();
++		pxa_set_cken(CKEN8_I2S, 0);
++	}
++}
++
++#ifdef CONFIG_PM
++static int pxa2xx_i2s_suspend(struct platform_device *dev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if (!dai->active)
++		return 0;
++
++	/* store registers */
++	pxa_i2s.sacr0 = SACR0;
++	pxa_i2s.sacr1 = SACR1;
++	pxa_i2s.saimr = SAIMR;
++	pxa_i2s.sadiv = SADIV;
++
++	/* deactivate link */
++	SACR0 &= ~SACR0_ENB;
++	pxa_i2s_wait();
++	return 0;
++}
++
++static int pxa2xx_i2s_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if (!dai->active)
++		return 0;
++
++	pxa_i2s_wait();
++
++	SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
++	SACR1 = pxa_i2s.sacr1;
++	SAIMR = pxa_i2s.saimr;
++	SADIV = pxa_i2s.sadiv;
++	SACR0 |= SACR0_ENB;
++
++	return 0;
++}
++
++#else
++#define pxa2xx_i2s_suspend	NULL
++#define pxa2xx_i2s_resume	NULL
++#endif
++
++/* pxa2xx I2S sysclock is always 256 FS */
++static unsigned int pxa_i2s_config_sysclk(struct snd_soc_cpu_dai *iface,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	return info->rate << 8;
++}
++
++struct snd_soc_cpu_dai pxa_i2s_dai = {
++	.name = "pxa2xx-i2s",
++	.id = 0,
++	.type = SND_SOC_DAI_I2S,
++	.suspend = pxa2xx_i2s_suspend,
++	.resume = pxa2xx_i2s_resume,
++	.config_sysclk = pxa_i2s_config_sysclk,
++	.playback = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.ops = {
++		.startup = pxa2xx_i2s_startup,
++		.shutdown = pxa2xx_i2s_shutdown,
++		.trigger = pxa2xx_i2s_trigger,
++		.hw_params = pxa2xx_i2s_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(pxa2xx_i2s_modes),
++		.mode = pxa2xx_i2s_modes,},
++};
++
++EXPORT_SYMBOL_GPL(pxa_i2s_dai);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-pcm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-pcm.c
+@@ -0,0 +1,363 @@
++/*
++ * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
++ *
++ * Author:	Nicolas Pitre
++ * Created:	Nov 30, 2004
++ * Copyright:	(C) 2004 MontaVista Software, 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/dma.h>
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++
++#include "pxa2xx-pcm.h"
++
++static const struct snd_pcm_hardware pxa2xx_pcm_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_S24_LE |
++					SNDRV_PCM_FMTBIT_S32_LE,
++	.period_bytes_min	= 32,
++	.period_bytes_max	= 8192 - 32,
++	.periods_min		= 1,
++	.periods_max		= PAGE_SIZE/sizeof(pxa_dma_desc),
++	.buffer_bytes_max	= 128 * 1024,
++	.fifo_size		= 32,
++};
++
++struct pxa2xx_runtime_data {
++	int dma_ch;
++	struct pxa2xx_pcm_dma_params *params;
++	pxa_dma_desc *dma_desc_array;
++	dma_addr_t dma_desc_array_phys;
++};
++
++static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
++{
++	struct snd_pcm_substream *substream = dev_id;
++	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
++	int dcsr;
++
++	dcsr = DCSR(dma_ch);
++	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
++
++	if (dcsr & DCSR_ENDINTR) {
++		snd_pcm_period_elapsed(substream);
++	} else {
++		printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
++			prtd->params->name, dma_ch, dcsr );
++	}
++}
++
++static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct pxa2xx_runtime_data *prtd = runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct pxa2xx_pcm_dma_params *dma = rtd->cpu_dai->dma_data;
++	size_t totsize = params_buffer_bytes(params);
++	size_t period = params_period_bytes(params);
++	pxa_dma_desc *dma_desc;
++	dma_addr_t dma_buff_phys, next_desc_phys;
++	int ret;
++
++	/* this may get called several times by oss emulation
++	 * with different params */
++	if (prtd->params == NULL) {
++		prtd->params = dma;
++		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
++			      pxa2xx_pcm_dma_irq, substream);
++		if (ret < 0)
++			return ret;
++		prtd->dma_ch = ret;
++	} else if (prtd->params != dma) {
++		pxa_free_dma(prtd->dma_ch);
++		prtd->params = dma;
++		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
++			      pxa2xx_pcm_dma_irq, substream);
++		if (ret < 0)
++			return ret;
++		prtd->dma_ch = ret;
++	}
++
++	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
++	runtime->dma_bytes = totsize;
++
++	dma_desc = prtd->dma_desc_array;
++	next_desc_phys = prtd->dma_desc_array_phys;
++	dma_buff_phys = runtime->dma_addr;
++	do {
++		next_desc_phys += sizeof(pxa_dma_desc);
++		dma_desc->ddadr = next_desc_phys;
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++			dma_desc->dsadr = dma_buff_phys;
++			dma_desc->dtadr = prtd->params->dev_addr;
++		} else {
++			dma_desc->dsadr = prtd->params->dev_addr;
++			dma_desc->dtadr = dma_buff_phys;
++		}
++		if (period > totsize)
++			period = totsize;
++		dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
++		dma_desc++;
++		dma_buff_phys += period;
++	} while (totsize -= period);
++	dma_desc[-1].ddadr = prtd->dma_desc_array_phys;
++
++	return 0;
++}
++
++static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
++
++	if (prtd && prtd->params)
++		*prtd->params->drcmr = 0;
++
++	if (prtd->dma_ch) {
++		snd_pcm_set_runtime_buffer(substream, NULL);
++		pxa_free_dma(prtd->dma_ch);
++		prtd->dma_ch = 0;
++	}
++
++	return 0;
++}
++
++static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
++
++	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
++	DCSR(prtd->dma_ch) = 0;
++	DCMD(prtd->dma_ch) = 0;
++	*prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
++
++	return 0;
++}
++
++static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
++		DCSR(prtd->dma_ch) = DCSR_RUN;
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		DCSR(prtd->dma_ch) &= ~DCSR_RUN;
++		break;
++
++	case SNDRV_PCM_TRIGGER_RESUME:
++		DCSR(prtd->dma_ch) |= DCSR_RUN;
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
++		DCSR(prtd->dma_ch) |= DCSR_RUN;
++		break;
++
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t
++pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct pxa2xx_runtime_data *prtd = runtime->private_data;
++
++	dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++			 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
++	snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
++
++	if (x == runtime->buffer_size)
++		x = 0;
++	return x;
++}
++
++static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct pxa2xx_runtime_data *prtd;
++	int ret;
++
++	snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware);
++
++	/*
++	 * For mysterious reasons (and despite what the manual says)
++	 * playback samples are lost if the DMA count is not a multiple
++	 * of the DMA burst size.  Let's add a rule to enforce that.
++	 */
++	ret = snd_pcm_hw_constraint_step(runtime, 0,
++		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
++	if (ret)
++		goto out;
++
++	ret = snd_pcm_hw_constraint_step(runtime, 0,
++		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
++	if (ret)
++		goto out;
++
++	prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL);
++	if (prtd == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	prtd->dma_desc_array =
++		dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
++				       &prtd->dma_desc_array_phys, GFP_KERNEL);
++	if (!prtd->dma_desc_array) {
++		ret = -ENOMEM;
++		goto err1;
++	}
++
++	runtime->private_data = prtd;
++	return 0;
++
++ err1:
++	kfree(prtd);
++ out:
++	return ret;
++}
++
++static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct pxa2xx_runtime_data *prtd = runtime->private_data;
++
++	dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
++			      prtd->dma_desc_array, prtd->dma_desc_array_phys);
++	kfree(prtd);
++	return 0;
++}
++
++static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
++	struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++				     runtime->dma_area,
++				     runtime->dma_addr,
++				     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops pxa2xx_pcm_ops = {
++	.open		= pxa2xx_pcm_open,
++	.close		= pxa2xx_pcm_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= pxa2xx_pcm_hw_params,
++	.hw_free	= pxa2xx_pcm_hw_free,
++	.prepare	= pxa2xx_pcm_prepare,
++	.trigger	= pxa2xx_pcm_trigger,
++	.pointer	= pxa2xx_pcm_pointer,
++	.mmap		= pxa2xx_pcm_mmap,
++};
++
++static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
++{
++	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
++	struct snd_dma_buffer *buf = &substream->dma_buffer;
++	size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
++	buf->dev.type = SNDRV_DMA_TYPE_DEV;
++	buf->dev.dev = pcm->card->dev;
++	buf->private_data = NULL;
++	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
++					   &buf->addr, GFP_KERNEL);
++	if (!buf->area)
++		return -ENOMEM;
++	buf->bytes = size;
++	return 0;
++}
++
++static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_dma_buffer *buf;
++	int stream;
++
++	for (stream = 0; stream < 2; stream++) {
++		substream = pcm->streams[stream].substream;
++		if (!substream)
++			continue;
++
++		buf = &substream->dma_buffer;
++		if (!buf->area)
++			continue;
++
++		dma_free_writecombine(pcm->card->dev, buf->bytes,
++				      buf->area, buf->addr);
++		buf->area = NULL;
++	}
++}
++
++static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
++
++int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
++	struct snd_pcm *pcm)
++{
++	int ret = 0;
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &pxa2xx_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = DMA_32BIT_MASK;
++
++	if (dai->playback.channels_min) {
++		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			goto out;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			goto out;
++	}
++ out:
++	return ret;
++}
++
++struct snd_soc_platform pxa2xx_soc_platform = {
++	.name		= "pxa2xx-audio",
++	.pcm_ops 	= &pxa2xx_pcm_ops,
++	.pcm_new	= pxa2xx_pcm_new,
++	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
++};
++
++EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
++
++MODULE_AUTHOR("Nicolas Pitre");
++MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-pcm.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-pcm.h
+@@ -0,0 +1,48 @@
++/*
++ * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
++ *
++ * Author:	Nicolas Pitre
++ * Created:	Nov 30, 2004
++ * Copyright:	MontaVista Software, 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.
++ */
++
++#ifndef _PXA2XX_PCM_H
++#define _PXA2XX_PCM_H
++
++struct pxa2xx_pcm_dma_params {
++	char *name;			/* stream identifier */
++	u32 dcmd;			/* DMA descriptor dcmd field */
++	volatile u32 *drcmr;		/* the DMA request channel to use */
++	u32 dev_addr;			/* device physical address for DMA */
++};
++
++struct pxa2xx_gpio {
++	u32 sys;
++	u32	rx;
++	u32 tx;
++	u32 clk;
++	u32 frm;
++};
++
++/* pxa2xx DAI ID's */
++#define PXA2XX_DAI_AC97_HIFI	0
++#define PXA2XX_DAI_AC97_AUX		1
++#define PXA2XX_DAI_AC97_MIC		2
++#define PXA2XX_DAI_I2S			0
++#define PXA2XX_DAI_SSP1			0
++#define PXA2XX_DAI_SSP2			1
++#define PXA2XX_DAI_SSP3			2
++
++extern struct snd_soc_cpu_dai pxa_ac97_dai[3];
++extern struct snd_soc_cpu_dai pxa_i2s_dai;
++extern struct snd_soc_cpu_dai pxa_ssp_dai[3];
++
++/* platform data */
++extern struct snd_soc_platform pxa2xx_soc_platform;
++extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-ssp.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/pxa2xx-ssp.c
+@@ -0,0 +1,767 @@
++/*
++ * pxa2xx-ssp.c  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    12th Aug 2005   Initial version.
++ *
++ * TODO:
++ *  o Fix master mode (bug)
++ *  o Fix resume (bug)
++ *  o Add support for other clocks
++ *  o Test network mode for > 16bit sample size
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/audio.h>
++#include <asm/arch/ssp.h>
++
++#include "pxa2xx-pcm.h"
++
++/*
++ * SSP sysclock frequency in Hz
++ * Neither default pxa2xx PLL clocks are good for audio, hence pxa27x
++ * has audio clock. I would recommend using the pxa27x audio clock or an
++ * external clock or making the codec master to gurantee better sample rates.
++ */
++#ifdef CONFIG_PXA27x
++static int sysclk[3] = {13000000, 13000000, 13000000};
++#else
++static int sysclk[3] = {1843200, 1843200, 1843200};
++#endif
++module_param_array(sysclk, int, NULL, 0);
++MODULE_PARM_DESC(sysclk, "sysclk frequency in Hz");
++
++/*
++ * SSP sysclock source.
++ * sysclk is ignored if audio clock is used
++ */
++#ifdef CONFIG_PXA27x
++static int clksrc[3] = {0, 0, 0};
++#else
++static int clksrc[3] = {0, 0, 0};
++#endif
++module_param_array(clksrc, int, NULL, 0);
++MODULE_PARM_DESC(clksrc,
++	"sysclk source, 0 = internal PLL, 1 = ext, 2 = network, 3 = audio clock");
++
++/*
++ * SSP GPIO's
++ */
++#define GPIO26_SSP1RX_MD	(26 | GPIO_ALT_FN_1_IN)
++#define GPIO25_SSP1TX_MD	(25 | GPIO_ALT_FN_2_OUT)
++#define GPIO23_SSP1CLKS_MD	(23 | GPIO_ALT_FN_2_IN)
++#define GPIO24_SSP1FRMS_MD	(24 | GPIO_ALT_FN_2_IN)
++#define GPIO23_SSP1CLKM_MD	(23 | GPIO_ALT_FN_2_OUT)
++#define GPIO24_SSP1FRMM_MD	(24 | GPIO_ALT_FN_2_OUT)
++
++#define GPIO11_SSP2RX_MD	(11 | GPIO_ALT_FN_2_IN)
++#define GPIO13_SSP2TX_MD	(13 | GPIO_ALT_FN_1_OUT)
++#define GPIO22_SSP2CLKS_MD	(22 | GPIO_ALT_FN_3_IN)
++#define GPIO88_SSP2FRMS_MD	(88 | GPIO_ALT_FN_3_IN)
++#define GPIO22_SSP2CLKM_MD	(22 | GPIO_ALT_FN_3_OUT)
++#define GPIO88_SSP2FRMM_MD	(88 | GPIO_ALT_FN_3_OUT)
++
++#define GPIO82_SSP3RX_MD	(82 | GPIO_ALT_FN_1_IN)
++#define GPIO81_SSP3TX_MD	(81 | GPIO_ALT_FN_1_OUT)
++#define GPIO84_SSP3CLKS_MD	(84 | GPIO_ALT_FN_1_IN)
++#define GPIO83_SSP3FRMS_MD	(83 | GPIO_ALT_FN_1_IN)
++#define GPIO84_SSP3CLKM_MD	(84 | GPIO_ALT_FN_1_OUT)
++#define GPIO83_SSP3FRMM_MD	(83 | GPIO_ALT_FN_1_OUT)
++
++#define PXA_SSP_MDAIFMT \
++	(SND_SOC_DAIFMT_DSP_B  |SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_CBM_CFS | \
++	SND_SOC_DAIFMT_CBS_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF)
++
++#define PXA_SSP_SDAIFMT \
++	(SND_SOC_DAIFMT_DSP_B  |SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS | \
++	SND_SOC_DAIFMT_CBS_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF)
++
++#define PXA_SSP_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define PXA_SSP_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
++	SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
++
++#define PXA_SSP_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++/*
++ * SSP modes
++ */
++static struct snd_soc_dai_mode pxa2xx_ssp_modes[] = {
++	/* port slave clk & frame modes */
++	{
++		.fmt = PXA_SSP_SDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = PXA_SSP_RATES,
++		.pcmdir = PXA_SSP_DIR,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++
++	/* port master clk & frame modes */
++#ifdef CONFIG_PXA27x
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_11025,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_22050,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 256,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 128,
++		.bfs = SND_SOC_FSBW(1),
++	},
++	{
++		.fmt = PXA_SSP_MDAIFMT,
++		.pcmfmt = PXA_SSP_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = PXA_SSP_DIR,
++		.flags = SND_SOC_DAI_BFS_RCW,
++		.fs = 128,
++		.bfs = SND_SOC_FSBW(1),
++	},
++#endif
++};
++
++static struct ssp_dev ssp[3];
++#ifdef CONFIG_PM
++static struct ssp_state ssp_state[3];
++#endif
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_out = {
++	.name			= "SSP1 PCM Mono out",
++	.dev_addr		= __PREG(SSDR_P1),
++	.drcmr			= &DRCMRTXSSDR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_in = {
++	.name			= "SSP1 PCM Mono in",
++	.dev_addr		= __PREG(SSDR_P1),
++	.drcmr			= &DRCMRRXSSDR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_out = {
++	.name			= "SSP1 PCM Stereo out",
++	.dev_addr		= __PREG(SSDR_P1),
++	.drcmr			= &DRCMRTXSSDR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_in = {
++	.name			= "SSP1 PCM Stereo in",
++	.dev_addr		= __PREG(SSDR_P1),
++	.drcmr			= &DRCMRRXSSDR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_out = {
++	.name			= "SSP2 PCM Mono out",
++	.dev_addr		= __PREG(SSDR_P2),
++	.drcmr			= &DRCMRTXSS2DR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_in = {
++	.name			= "SSP2 PCM Mono in",
++	.dev_addr		= __PREG(SSDR_P2),
++	.drcmr			= &DRCMRRXSS2DR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_out = {
++	.name			= "SSP2 PCM Stereo out",
++	.dev_addr		= __PREG(SSDR_P2),
++	.drcmr			= &DRCMRTXSS2DR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_in = {
++	.name			= "SSP2 PCM Stereo in",
++	.dev_addr		= __PREG(SSDR_P2),
++	.drcmr			= &DRCMRRXSS2DR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_out = {
++	.name			= "SSP3 PCM Mono out",
++	.dev_addr		= __PREG(SSDR_P3),
++	.drcmr			= &DRCMRTXSS3DR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_in = {
++	.name			= "SSP3 PCM Mono in",
++	.dev_addr		= __PREG(SSDR_P3),
++	.drcmr			= &DRCMRRXSS3DR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH2,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_out = {
++	.name			= "SSP3 PCM Stereo out",
++	.dev_addr		= __PREG(SSDR_P3),
++	.drcmr			= &DRCMRTXSS3DR,
++	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_in = {
++	.name			= "SSP3 PCM Stereo in",
++	.dev_addr		= __PREG(SSDR_P3),
++	.drcmr			= &DRCMRRXSS3DR,
++	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
++				  DCMD_BURST16 | DCMD_WIDTH4,
++};
++
++static struct pxa2xx_pcm_dma_params *ssp_dma_params[3][4] = {
++	{&pxa2xx_ssp1_pcm_mono_out, &pxa2xx_ssp1_pcm_mono_in,
++	&pxa2xx_ssp1_pcm_stereo_out,&pxa2xx_ssp1_pcm_stereo_in,},
++	{&pxa2xx_ssp2_pcm_mono_out, &pxa2xx_ssp2_pcm_mono_in,
++	&pxa2xx_ssp2_pcm_stereo_out, &pxa2xx_ssp2_pcm_stereo_in,},
++	{&pxa2xx_ssp3_pcm_mono_out, &pxa2xx_ssp3_pcm_mono_in,
++	&pxa2xx_ssp3_pcm_stereo_out,&pxa2xx_ssp3_pcm_stereo_in,},
++};
++
++static struct pxa2xx_gpio ssp_gpios[3][4] = {
++	{{ /* SSP1 SND_SOC_DAIFMT_CBM_CFM */
++		.rx = GPIO26_SSP1RX_MD,
++		.tx = GPIO25_SSP1TX_MD,
++		.clk = (23 | GPIO_ALT_FN_2_IN),
++		.frm = (24 | GPIO_ALT_FN_2_IN),
++	},
++	{ /* SSP1 SND_SOC_DAIFMT_CBS_CFS */
++		.rx = GPIO26_SSP1RX_MD,
++		.tx = GPIO25_SSP1TX_MD,
++		.clk = (23 | GPIO_ALT_FN_2_OUT),
++		.frm = (24 | GPIO_ALT_FN_2_OUT),
++	},
++	{ /* SSP1 SND_SOC_DAIFMT_CBS_CFM */
++		.rx = GPIO26_SSP1RX_MD,
++		.tx = GPIO25_SSP1TX_MD,
++		.clk = (23 | GPIO_ALT_FN_2_OUT),
++		.frm = (24 | GPIO_ALT_FN_2_IN),
++	},
++	{ /* SSP1 SND_SOC_DAIFMT_CBM_CFS */
++		.rx = GPIO26_SSP1RX_MD,
++		.tx = GPIO25_SSP1TX_MD,
++		.clk = (23 | GPIO_ALT_FN_2_IN),
++		.frm = (24 | GPIO_ALT_FN_2_OUT),
++	}},
++	{{ /* SSP2 SND_SOC_DAIFMT_CBM_CFM */
++		.rx = GPIO11_SSP2RX_MD,
++		.tx = GPIO13_SSP2TX_MD,
++		.clk = (22 | GPIO_ALT_FN_3_IN),
++		.frm = (88 | GPIO_ALT_FN_3_IN),
++	},
++	{ /* SSP2 SND_SOC_DAIFMT_CBS_CFS */
++		.rx = GPIO11_SSP2RX_MD,
++		.tx = GPIO13_SSP2TX_MD,
++		.clk = (22 | GPIO_ALT_FN_3_OUT),
++		.frm = (88 | GPIO_ALT_FN_3_OUT),
++	},
++	{ /* SSP2 SND_SOC_DAIFMT_CBS_CFM */
++		.rx = GPIO11_SSP2RX_MD,
++		.tx = GPIO13_SSP2TX_MD,
++		.clk = (22 | GPIO_ALT_FN_3_OUT),
++		.frm = (88 | GPIO_ALT_FN_3_IN),
++	},
++	{ /* SSP2 SND_SOC_DAIFMT_CBM_CFS */
++		.rx = GPIO11_SSP2RX_MD,
++		.tx = GPIO13_SSP2TX_MD,
++		.clk = (22 | GPIO_ALT_FN_3_IN),
++		.frm = (88 | GPIO_ALT_FN_3_OUT),
++	}},
++	{{ /* SSP3 SND_SOC_DAIFMT_CBM_CFM */
++		.rx = GPIO82_SSP3RX_MD,
++		.tx = GPIO81_SSP3TX_MD,
++		.clk = (84 | GPIO_ALT_FN_3_IN),
++		.frm = (83 | GPIO_ALT_FN_3_IN),
++	},
++	{ /* SSP3 SND_SOC_DAIFMT_CBS_CFS */
++		.rx = GPIO82_SSP3RX_MD,
++		.tx = GPIO81_SSP3TX_MD,
++		.clk = (84 | GPIO_ALT_FN_3_OUT),
++		.frm = (83 | GPIO_ALT_FN_3_OUT),
++	},
++	{ /* SSP3 SND_SOC_DAIFMT_CBS_CFM */
++		.rx = GPIO82_SSP3RX_MD,
++		.tx = GPIO81_SSP3TX_MD,
++		.clk = (84 | GPIO_ALT_FN_3_OUT),
++		.frm = (83 | GPIO_ALT_FN_3_IN),
++	},
++	{ /* SSP3 SND_SOC_DAIFMT_CBM_CFS */
++		.rx = GPIO82_SSP3RX_MD,
++		.tx = GPIO81_SSP3TX_MD,
++		.clk = (84 | GPIO_ALT_FN_3_IN),
++		.frm = (83 | GPIO_ALT_FN_3_OUT),
++	}},
++};
++
++static int pxa2xx_ssp_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int ret = 0;
++
++	if (!rtd->cpu_dai->active) {
++		ret = ssp_init (&ssp[rtd->cpu_dai->id], rtd->cpu_dai->id + 1,
++			SSP_NO_IRQ);
++		if (ret < 0)
++			return ret;
++		ssp_disable(&ssp[rtd->cpu_dai->id]);
++	}
++	return ret;
++}
++
++static void pxa2xx_ssp_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (!rtd->cpu_dai->active) {
++		ssp_disable(&ssp[rtd->cpu_dai->id]);
++		ssp_exit(&ssp[rtd->cpu_dai->id]);
++	}
++}
++
++#ifdef CONFIG_PM
++
++#if defined (CONFIG_PXA27x)
++static int cken[3] = {CKEN23_SSP1, CKEN3_SSP2, CKEN4_SSP3};
++#else
++static int cken[3] = {CKEN3_SSP, CKEN9_NSSP, CKEN10_ASSP};
++#endif
++
++static int pxa2xx_ssp_suspend(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if (!dai->active)
++		return 0;
++
++	ssp_save_state(&ssp[dai->id], &ssp_state[dai->id]);
++	pxa_set_cken(cken[dai->id], 0);
++	return 0;
++}
++
++static int pxa2xx_ssp_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if (!dai->active)
++		return 0;
++
++	pxa_set_cken(cken[dai->id], 1);
++	ssp_restore_state(&ssp[dai->id], &ssp_state[dai->id]);
++	ssp_enable(&ssp[dai->id]);
++
++	return 0;
++}
++
++#else
++#define pxa2xx_ssp_suspend	NULL
++#define pxa2xx_ssp_resume	NULL
++#endif
++
++/* todo - check clk source and PLL before returning clock rate */
++static unsigned int pxa_ssp_config_sysclk(struct snd_soc_cpu_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	/* audio clock ? (divide by 1) */
++	if (clksrc[dai->id] == 3) {
++		switch(info->rate){
++		case 8000:
++		case 16000:
++		case 32000:
++		case 48000:
++		case 96000:
++			return 12288000;
++			break;
++		case 11025:
++		case 22050:
++		case 44100:
++		case 88200:
++			return 11289600;
++		break;
++		}
++	}
++
++	/* pll */
++	return sysclk[dai->id];
++}
++
++#ifdef CONFIG_PXA27x
++static u32 pxa27x_set_audio_clk(unsigned int rate, unsigned int fs)
++{
++	u32 aclk = 0, div = 0;
++
++	if (rate == 0 || fs == 0)
++		return 0;
++
++	switch(rate){
++	case 8000:
++	case 16000:
++	case 32000:
++	case 48000:
++	case 96000:
++		aclk = 0x2 << 4;
++		div = 12288000 / (rate * fs);
++		break;
++	case 11025:
++	case 22050:
++	case 44100:
++	case 88200:
++		aclk = 0x1 << 4;
++		div = 11289600 / (rate * fs);
++		break;
++	}
++
++	aclk |= ffs(div) - 1;
++	return aclk;
++}
++#endif
++
++static inline int get_scr(int srate, int id)
++{
++	if (srate == 0)
++		return 0;
++	return (sysclk[id] / srate) - 1;
++}
++
++static int pxa2xx_ssp_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int fmt = 0, dma = 0, fs, chn = params_channels(params);
++	u32 ssp_mode = 0, ssp_setup = 0, psp_mode = 0, rate = 0;
++
++	fs = rtd->cpu_dai->dai_runtime.fs;
++
++	/* select correct DMA params */
++	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++		dma = 1;
++	if (chn == 2 || rtd->cpu_dai->dai_runtime.pcmfmt != PXA_SSP_BITS)
++		dma += 2;
++	rtd->cpu_dai->dma_data = ssp_dma_params[rtd->cpu_dai->id][dma];
++
++	/* is port used by another stream */
++	if (SSCR0 & SSCR0_SSE)
++		return 0;
++
++	/* bit size */
++	switch(rtd->cpu_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		ssp_mode |=SSCR0_DataSize(16);
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		ssp_mode |=(SSCR0_EDSS | SSCR0_DataSize(8));
++		/* use network mode for stereo samples > 16 bits */
++		if (chn == 2) {
++			ssp_mode |= (SSCR0_MOD | SSCR0_SlotsPerFrm(2) << 24);
++			/* active slots 0,1 */
++			SSTSA_P(rtd->cpu_dai->id +1) = 0x3;
++			SSRSA_P(rtd->cpu_dai->id +1) = 0x3;
++		}
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		ssp_mode |= (SSCR0_EDSS | SSCR0_DataSize(16));
++		/* use network mode for stereo samples > 16 bits */
++		if (chn == 2) {
++			ssp_mode |= (SSCR0_MOD | SSCR0_SlotsPerFrm(2) << 24);
++			/* active slots 0,1 */
++			SSTSA_P(rtd->cpu_dai->id +1) = 0x3;
++			SSRSA_P(rtd->cpu_dai->id +1) = 0x3;
++		}
++		break;
++	}
++
++	ssp_mode |= SSCR0_PSP;
++	ssp_setup = SSCR1_RxTresh(14) | SSCR1_TxTresh(1) |
++		SSCR1_TRAIL | SSCR1_RWOT;
++
++	switch(rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		ssp_setup |= (SSCR1_SCLKDIR | SSCR1_SFRMDIR);
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		ssp_setup |= SSCR1_SCLKDIR;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		ssp_setup |= SSCR1_SFRMDIR;
++		break;
++	}
++
++	switch(rtd->cpu_dai->dai_runtime.fmt) {
++	case SND_SOC_DAIFMT_CBS_CFS:
++		fmt = 1;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		fmt = 2;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		fmt = 3;
++		break;
++	}
++
++	pxa_gpio_mode(ssp_gpios[rtd->cpu_dai->id][fmt].rx);
++	pxa_gpio_mode(ssp_gpios[rtd->cpu_dai->id][fmt].tx);
++	pxa_gpio_mode(ssp_gpios[rtd->cpu_dai->id][fmt].frm);
++	pxa_gpio_mode(ssp_gpios[rtd->cpu_dai->id][fmt].clk);
++
++	switch (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		psp_mode |= SSPSP_SFRMP | SSPSP_FSRT;
++		break;
++	}
++
++	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_DSP_A)
++		psp_mode |= SSPSP_SCMODE(2);
++	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_DSP_B)
++		psp_mode |= SSPSP_SCMODE(3);
++
++	switch(clksrc[rtd->cpu_dai->id]) {
++	case 2: /* network clock */
++		ssp_mode |= SSCR0_NCS | SSCR0_MOD;
++	case 1: /* external clock */
++		ssp_mode |= SSCR0_ECS;
++	case 0: /* internal clock */
++		rate = get_scr(snd_soc_get_rate(rtd->cpu_dai->dai_runtime.pcmrate),
++			rtd->cpu_dai->id);
++		break;
++#ifdef CONFIG_PXA27x
++	case 3: /* audio clock */
++		ssp_mode |= (1 << 30);
++		SSACD_P(rtd->cpu_dai->id) = (0x1 << 3) |
++			pxa27x_set_audio_clk(
++				snd_soc_get_rate(rtd->cpu_dai->dai_runtime.pcmrate), fs);
++	 	break;
++#endif
++	}
++
++	ssp_config(&ssp[rtd->cpu_dai->id], ssp_mode, ssp_setup, psp_mode,
++		SSCR0_SerClkDiv(rate));
++#if 0
++	printk("SSCR0 %x SSCR1 %x SSTO %x SSPSP %x SSSR %x\n",
++		SSCR0_P(rtd->cpu_dai->id+1), SSCR1_P(rtd->cpu_dai->id+1),
++		SSTO_P(rtd->cpu_dai->id+1), SSPSP_P(rtd->cpu_dai->id+1),
++		SSSR_P(rtd->cpu_dai->id+1));
++#endif
++	return 0;
++}
++
++static int pxa2xx_ssp_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_RESUME:
++		ssp_enable(&ssp[rtd->cpu_dai->id]);
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSCR1_P(rtd->cpu_dai->id+1) |= SSCR1_TSRE;
++		else
++			SSCR1_P(rtd->cpu_dai->id+1) |= SSCR1_RSRE;
++		SSSR_P(rtd->cpu_dai->id+1) |= SSSR_P(rtd->cpu_dai->id+1);
++		break;
++	case SNDRV_PCM_TRIGGER_START:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSCR1_P(rtd->cpu_dai->id+1) |= SSCR1_TSRE;
++		else
++			SSCR1_P(rtd->cpu_dai->id+1) |= SSCR1_RSRE;
++		ssp_enable(&ssp[rtd->cpu_dai->id]);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSCR1_P(rtd->cpu_dai->id+1) &= ~SSCR1_TSRE;
++		else
++			SSCR1_P(rtd->cpu_dai->id+1) &= ~SSCR1_RSRE;
++		break;
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++		ssp_disable(&ssp[rtd->cpu_dai->id]);
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSCR1_P(rtd->cpu_dai->id+1) &= ~SSCR1_TSRE;
++		else
++			SSCR1_P(rtd->cpu_dai->id+1) &= ~SSCR1_RSRE;
++		break;
++
++	default:
++		ret = -EINVAL;
++	}
++#if 0
++	printk("SSCR0 %x SSCR1 %x SSTO %x SSPSP %x SSSR %x\n",
++		SSCR0_P(rtd->cpu_dai->id+1), SSCR1_P(rtd->cpu_dai->id+1),
++		SSTO_P(rtd->cpu_dai->id+1), SSPSP_P(rtd->cpu_dai->id+1),
++		SSSR_P(rtd->cpu_dai->id+1));
++#endif
++	return ret;
++}
++
++struct snd_soc_cpu_dai pxa_ssp_dai[] = {
++	{	.name = "pxa2xx-ssp1",
++		.id = 0,
++		.type = SND_SOC_DAI_PCM,
++		.suspend = pxa2xx_ssp_suspend,
++		.resume = pxa2xx_ssp_resume,
++		.config_sysclk = pxa_ssp_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = pxa2xx_ssp_startup,
++			.shutdown = pxa2xx_ssp_shutdown,
++			.trigger = pxa2xx_ssp_trigger,
++			.hw_params = pxa2xx_ssp_hw_params,},
++		.caps = {
++			.mode = pxa2xx_ssp_modes,
++			.num_modes = ARRAY_SIZE(pxa2xx_ssp_modes),},
++	},
++	{	.name = "pxa2xx-ssp2",
++		.id = 1,
++		.type = SND_SOC_DAI_PCM,
++		.suspend = pxa2xx_ssp_suspend,
++		.resume = pxa2xx_ssp_resume,
++		.config_sysclk = pxa_ssp_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = pxa2xx_ssp_startup,
++			.shutdown = pxa2xx_ssp_shutdown,
++			.trigger = pxa2xx_ssp_trigger,
++			.hw_params = pxa2xx_ssp_hw_params,},
++		.caps = {
++			.mode = pxa2xx_ssp_modes,
++			.num_modes = ARRAY_SIZE(pxa2xx_ssp_modes),},
++	},
++	{	.name = "pxa2xx-ssp3",
++		.id = 2,
++		.type = SND_SOC_DAI_PCM,
++		.suspend = pxa2xx_ssp_suspend,
++		.resume = pxa2xx_ssp_resume,
++		.config_sysclk = pxa_ssp_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = pxa2xx_ssp_startup,
++			.shutdown = pxa2xx_ssp_shutdown,
++			.trigger = pxa2xx_ssp_trigger,
++			.hw_params = pxa2xx_ssp_hw_params,},
++		.caps = {
++			.mode = pxa2xx_ssp_modes,
++			.num_modes = ARRAY_SIZE(pxa2xx_ssp_modes),},
++	},
++};
++
++EXPORT_SYMBOL_GPL(pxa_ssp_dai);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("pxa2xx SSP/PCM SoC Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/spitz.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/spitz.c
+@@ -0,0 +1,374 @@
++/*
++ * spitz.c  --  SoC audio for Sharp SL-Cxx00 models Spitz, Borzoi and Akita
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Authors: Liam Girdwood <liam.girdwood at wolfsonmicro.com>
++ *          Richard Purdie <richard at openedhand.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.
++ *
++ *  Revision history
++ *    30th Nov 2005   Initial 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/hardware/scoop.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/akita.h>
++#include <asm/arch/spitz.h>
++#include <asm/mach-types.h>
++#include "../codecs/wm8750.h"
++#include "pxa2xx-pcm.h"
++
++#define SPITZ_HP        0
++#define SPITZ_MIC       1
++#define SPITZ_LINE      2
++#define SPITZ_HEADSET   3
++#define SPITZ_HP_OFF    4
++#define SPITZ_SPK_ON    0
++#define SPITZ_SPK_OFF   1
++
++ /* audio clock in Hz - rounded from 12.235MHz */
++#define SPITZ_AUDIO_CLOCK 12288000
++
++static int spitz_jack_func;
++static int spitz_spk_func;
++
++static void spitz_ext_control(struct snd_soc_codec *codec)
++{
++	if (spitz_spk_func == SPITZ_SPK_ON)
++		snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
++	else
++		snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0);
++
++	/* set up jack connection */
++	switch (spitz_jack_func) {
++	case SPITZ_HP:
++		/* enable and unmute hp jack, disable mic bias */
++		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
++		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
++		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
++		break;
++	case SPITZ_MIC:
++		/* enable mic jack and bias, mute hp */
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
++		break;
++	case SPITZ_LINE:
++		/* enable line jack, disable mic bias and mute hp */
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Line Jack", 1);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
++		break;
++	case SPITZ_HEADSET:
++		/* enable and unmute headset jack enable mic bias, mute L hp */
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
++		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
++		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
++		break;
++	case SPITZ_HP_OFF:
++
++		/* jack removed, everything off */
++		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
++		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
++		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
++		break;
++	}
++	snd_soc_dapm_sync_endpoints(codec);
++}
++
++static int spitz_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 */
++	spitz_ext_control(codec);
++	return 0;
++}
++
++static struct snd_soc_ops spitz_ops = {
++	.startup = spitz_startup,
++};
++
++static int spitz_get_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = spitz_jack_func;
++	return 0;
++}
++
++static int spitz_set_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++	if (spitz_jack_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	spitz_jack_func = ucontrol->value.integer.value[0];
++	spitz_ext_control(codec);
++	return 1;
++}
++
++static int spitz_get_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = spitz_spk_func;
++	return 0;
++}
++
++static int spitz_set_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (spitz_spk_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	spitz_spk_func = ucontrol->value.integer.value[0];
++	spitz_ext_control(codec);
++	return 1;
++}
++
++static int spitz_mic_bias(struct snd_soc_dapm_widget *w, int event)
++{
++	if (machine_is_borzoi() || machine_is_spitz()) {
++		if (SND_SOC_DAPM_EVENT_ON(event))
++			set_scoop_gpio(&spitzscoop2_device.dev,
++				SPITZ_SCP2_MIC_BIAS);
++		else
++			reset_scoop_gpio(&spitzscoop2_device.dev,
++				SPITZ_SCP2_MIC_BIAS);
++	}
++
++	if (machine_is_akita()) {
++		if (SND_SOC_DAPM_EVENT_ON(event))
++			akita_set_ioexp(&akitaioexp_device.dev,
++				AKITA_IOEXP_MIC_BIAS);
++		else
++			akita_reset_ioexp(&akitaioexp_device.dev,
++				AKITA_IOEXP_MIC_BIAS);
++	}
++	return 0;
++}
++
++/* spitz machine dapm widgets */
++static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
++	SND_SOC_DAPM_HP("Headphone Jack", NULL),
++	SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
++	SND_SOC_DAPM_SPK("Ext Spk", NULL),
++	SND_SOC_DAPM_LINE("Line Jack", NULL),
++
++	/* headset is a mic and mono headphone */
++	SND_SOC_DAPM_HP("Headset Jack", NULL),
++};
++
++/* Spitz machine audio_map */
++static const char *audio_map[][3] = {
++
++	/* headphone connected to LOUT1, ROUT1 */
++	{"Headphone Jack", NULL, "LOUT1"},
++	{"Headphone Jack", NULL, "ROUT1"},
++
++	/* headset connected to ROUT1 and LINPUT1 with bias (def below) */
++	{"Headset Jack", NULL, "ROUT1"},
++
++	/* ext speaker connected to LOUT2, ROUT2  */
++	{"Ext Spk", NULL , "ROUT2"},
++	{"Ext Spk", NULL , "LOUT2"},
++
++	/* mic is connected to input 1 - with bias */
++	{"LINPUT1", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic Jack"},
++
++	/* line is connected to input 1 - no bias */
++	{"LINPUT1", NULL, "Line Jack"},
++
++	{NULL, NULL, NULL},
++};
++
++static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
++	"Off"};
++static const char *spk_function[] = {"On", "Off"};
++static const struct soc_enum spitz_enum[] = {
++	SOC_ENUM_SINGLE_EXT(5, jack_function),
++	SOC_ENUM_SINGLE_EXT(2, spk_function),
++};
++
++static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
++	SOC_ENUM_EXT("Jack Function", spitz_enum[0], spitz_get_jack,
++		spitz_set_jack),
++	SOC_ENUM_EXT("Speaker Function", spitz_enum[1], spitz_get_spk,
++		spitz_set_spk),
++};
++
++/*
++ * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
++ */
++static int spitz_wm8750_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	/* NC codec pins */
++	snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0);
++	snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0);
++	snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0);
++	snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0);
++	snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0);
++	snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
++	snd_soc_dapm_set_endpoint(codec, "MONO", 0);
++
++	/* Add spitz specific controls */
++	for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
++		err = snd_ctl_add(codec->card,
++			snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	/* Add spitz specific widgets */
++	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
++	}
++
++	/* Set up spitz specific audio path audio_map */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++static unsigned int spitz_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	if (info->bclk_master & SND_SOC_DAIFMT_CBS_CFS) {
++		/* pxa2xx is i2s master  */
++		switch (info->rate) {
++		case 11025:
++		case 22050:
++		case 44100:
++		case 88200:
++			/* configure codec digital filters
++			 * for 11.025, 22.05, 44.1, 88.2 */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				11289600);
++		break;
++		default:
++			/* configure codec digital filters for all other rates */
++			rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++				SPITZ_AUDIO_CLOCK);
++		break;
++		}
++		/* configure pxa2xx i2s interface clocks as master */
++		return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info,
++			SPITZ_AUDIO_CLOCK);
++	} else {
++		/* codec is i2s master - only configure codec DAI clock */
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info,
++			SPITZ_AUDIO_CLOCK);
++	}
++}
++
++/* spitz digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link spitz_dai = {
++	.name = "wm8750",
++	.stream_name = "WM8750",
++	.cpu_dai = &pxa_i2s_dai,
++	.codec_dai = &wm8750_dai,
++	.init = spitz_wm8750_init,
++	.config_sysclk = spitz_config_sysclk,
++};
++
++/* spitz audio machine driver */
++static struct snd_soc_machine snd_soc_machine_spitz = {
++	.name = "Spitz",
++	.dai_link = &spitz_dai,
++	.num_links = 1,
++	.ops = &spitz_ops,
++};
++
++/* spitz audio private data */
++static struct wm8750_setup_data spitz_wm8750_setup = {
++	.i2c_address = 0x1b,
++};
++
++/* spitz audio subsystem */
++static struct snd_soc_device spitz_snd_devdata = {
++	.machine = &snd_soc_machine_spitz,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8750,
++	.codec_data = &spitz_wm8750_setup,
++};
++
++static struct platform_device *spitz_snd_device;
++
++static int __init spitz_init(void)
++{
++	int ret;
++
++	if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))
++		return -ENODEV;
++
++	spitz_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!spitz_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata);
++	spitz_snd_devdata.dev = &spitz_snd_device->dev;
++	ret = platform_device_add(spitz_snd_device);
++
++	if (ret)
++		platform_device_put(spitz_snd_device);
++
++	return ret;
++}
++
++static void __exit spitz_exit(void)
++{
++	platform_device_unregister(spitz_snd_device);
++}
++
++module_init(spitz_init);
++module_exit(spitz_exit);
++
++MODULE_AUTHOR("Richard Purdie");
++MODULE_DESCRIPTION("ALSA SoC Spitz");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/pxa/tosa.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/pxa/tosa.c
+@@ -0,0 +1,287 @@
++/*
++ * tosa.c  --  SoC audio for Tosa
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Authors: Liam Girdwood <liam.girdwood at wolfsonmicro.com>
++ *          Richard Purdie <richard at openedhand.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.
++ *
++ *  Revision history
++ *    30th Nov 2005   Initial version.
++ *
++ * GPIO's
++ *  1 - Jack Insertion
++ *  5 - Hookswitch (headset answer/hang up switch)
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/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/hardware/tmio.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/audio.h>
++#include <asm/arch/tosa.h>
++
++#include "../codecs/wm9712.h"
++#include "pxa2xx-pcm.h"
++
++static struct snd_soc_machine tosa;
++
++#define TOSA_HP        0
++#define TOSA_MIC_INT   1
++#define TOSA_HEADSET   2
++#define TOSA_HP_OFF    3
++#define TOSA_SPK_ON    0
++#define TOSA_SPK_OFF   1
++
++static int tosa_jack_func;
++static int tosa_spk_func;
++
++static void tosa_ext_control(struct snd_soc_codec *codec)
++{
++	int spk = 0, mic_int = 0, hp = 0, hs = 0;
++
++	/* set up jack connection */
++	switch (tosa_jack_func) {
++	case TOSA_HP:
++		hp = 1;
++		break;
++	case TOSA_MIC_INT:
++		mic_int = 1;
++		break;
++	case TOSA_HEADSET:
++		hs = 1;
++		break;
++	}
++
++	if (tosa_spk_func == TOSA_SPK_ON)
++		spk = 1;
++
++	snd_soc_dapm_set_endpoint(codec, "Speaker", spk);
++	snd_soc_dapm_set_endpoint(codec, "Mic (Internal)", mic_int);
++	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
++	snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
++	snd_soc_dapm_sync_endpoints(codec);
++}
++
++static int tosa_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 */
++	tosa_ext_control(codec);
++	return 0;
++}
++
++static struct snd_soc_ops tosa_ops = {
++	.startup = tosa_startup,
++};
++
++static int tosa_get_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = tosa_jack_func;
++	return 0;
++}
++
++static int tosa_set_jack(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (tosa_jack_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	tosa_jack_func = ucontrol->value.integer.value[0];
++	tosa_ext_control(codec);
++	return 1;
++}
++
++static int tosa_get_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	ucontrol->value.integer.value[0] = tosa_spk_func;
++	return 0;
++}
++
++static int tosa_set_spk(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
++
++	if (tosa_spk_func == ucontrol->value.integer.value[0])
++		return 0;
++
++	tosa_spk_func = ucontrol->value.integer.value[0];
++	tosa_ext_control(codec);
++	return 1;
++}
++
++/* tosa dapm event handlers */
++static int tosa_hp_event(struct snd_soc_dapm_widget *w, int event)
++{
++	if (SND_SOC_DAPM_EVENT_ON(event))
++		set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
++	else
++		reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
++	return 0;
++}
++
++/* tosa machine dapm widgets */
++static const struct snd_soc_dapm_widget tosa_dapm_widgets[] = {
++SND_SOC_DAPM_HP("Headphone Jack", tosa_hp_event),
++SND_SOC_DAPM_HP("Headset Jack", NULL),
++SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
++SND_SOC_DAPM_SPK("Speaker", NULL),
++};
++
++/* tosa audio map */
++static const char *audio_map[][3] = {
++
++	/* headphone connected to HPOUTL, HPOUTR */
++	{"Headphone Jack", NULL, "HPOUTL"},
++	{"Headphone Jack", NULL, "HPOUTR"},
++
++	/* ext speaker connected to LOUT2, ROUT2 */
++	{"Speaker", NULL, "LOUT2"},
++	{"Speaker", NULL, "ROUT2"},
++
++	/* internal mic is connected to mic1, mic2 differential - with bias */
++	{"MIC1", NULL, "Mic Bias"},
++	{"MIC2", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Mic (Internal)"},
++
++	/* headset is connected to HPOUTR, and LINEINR with bias */
++	{"Headset Jack", NULL, "HPOUTR"},
++	{"LINEINR", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Headset Jack"},
++
++	{NULL, NULL, NULL},
++};
++
++static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
++	"Off"};
++static const char *spk_function[] = {"On", "Off"};
++static const struct soc_enum tosa_enum[] = {
++	SOC_ENUM_SINGLE_EXT(5, jack_function),
++	SOC_ENUM_SINGLE_EXT(2, spk_function),
++};
++
++static const struct snd_kcontrol_new tosa_controls[] = {
++	SOC_ENUM_EXT("Jack Function", tosa_enum[0], tosa_get_jack,
++		tosa_set_jack),
++	SOC_ENUM_EXT("Speaker Function", tosa_enum[1], tosa_get_spk,
++		tosa_set_spk),
++};
++
++static int tosa_ac97_init(struct snd_soc_codec *codec)
++{
++	int i, err;
++
++	snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
++	snd_soc_dapm_set_endpoint(codec, "MONOOUT", 0);
++
++	/* add tosa specific controls */
++	for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&tosa_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	/* add tosa specific widgets */
++	for (i = 0; i < ARRAY_SIZE(tosa_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &tosa_dapm_widgets[i]);
++	}
++
++	/* set up tosa specific audio path audio_map */
++	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_sync_endpoints(codec);
++	return 0;
++}
++
++static struct snd_soc_dai_link tosa_dai[] = {
++{
++	.name = "AC97",
++	.stream_name = "AC97 HiFi",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
++	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
++	.init = tosa_ac97_init,
++},
++{
++	.name = "AC97 Aux",
++	.stream_name = "AC97 Aux",
++	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
++	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
++},
++};
++
++static struct snd_soc_machine tosa = {
++	.name = "Tosa",
++	.dai_link = tosa_dai,
++	.num_links = ARRAY_SIZE(tosa_dai),
++	.ops = &tosa_ops,
++};
++
++static struct snd_soc_device tosa_snd_devdata = {
++	.machine = &tosa,
++	.platform = &pxa2xx_soc_platform,
++	.codec_dev = &soc_codec_dev_wm9712,
++};
++
++static struct platform_device *tosa_snd_device;
++
++static int __init tosa_init(void)
++{
++	int ret;
++
++	if (!machine_is_tosa())
++		return -ENODEV;
++
++	tosa_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!tosa_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
++	tosa_snd_devdata.dev = &tosa_snd_device->dev;
++	ret = platform_device_add(tosa_snd_device);
++
++	if (ret)
++		platform_device_put(tosa_snd_device);
++
++	return ret;
++}
++
++static void __exit tosa_exit(void)
++{
++	platform_device_unregister(tosa_snd_device);
++}
++
++module_init(tosa_init);
++module_exit(tosa_exit);
++
++/* Module information */
++MODULE_AUTHOR("Richard Purdie");
++MODULE_DESCRIPTION("ALSA SoC Tosa");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/soc-dapm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/soc-dapm.c
+@@ -0,0 +1,1327 @@
++/*
++ * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    12th Aug 2005   Initial version.
++ *    25th Oct 2005   Implemented path power domain.
++ *    18th Dec 2005   Implemented machine and stream level power domain.
++ *
++ *  Features:
++ *    o Changes power status of internal codec blocks depending on the
++ *      dynamic configuration of codec internal audio paths and active
++ *      DAC's/ADC's.
++ *    o Platform power domain - can support external components i.e. amps and
++ *      mic/meadphone insertion events.
++ *    o Automatic Mic Bias support
++ *    o Jack insertion power event initiation - e.g. hp insertion will enable
++ *      sinks, dacs, etc
++ *    o Delayed powerdown of audio susbsytem to reduce pops between a quick
++ *      device reopen.
++ *
++ *  Todo:
++ *    o DAPM power change sequencing - allow for configurable per
++ *      codec sequences.
++ *    o Support for analogue bias optimisation.
++ *    o Support for reduced codec oversampling rates.
++ *    o Support for reduced codec bias currents.
++ */
++
++#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/platform_device.h>
++#include <linux/jiffies.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc-dapm.h>
++#include <sound/initval.h>
++
++/* debug */
++#define DAPM_DEBUG 0
++#if DAPM_DEBUG
++#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
++#define dbg(format, arg...) printk(format, ## arg)
++#else
++#define dump_dapm(codec, action)
++#define dbg(format, arg...)
++#endif
++
++#define POP_DEBUG 0
++#if POP_DEBUG
++#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
++#define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time))
++#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
++#else
++#define pop_dbg(format, arg...)
++#define pop_wait(time)
++#endif
++
++/* dapm power sequences - make this per codec in the future */
++static int dapm_up_seq[] = {
++	snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
++	snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
++	snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
++};
++static int dapm_down_seq[] = {
++	snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
++	snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
++	snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
++};
++
++static int dapm_status = 1;
++module_param(dapm_status, int, 0);
++MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
++
++/* create a new dapm widget */
++static struct snd_soc_dapm_widget *dapm_cnew_widget(
++	const struct snd_soc_dapm_widget *_widget)
++{
++	struct snd_soc_dapm_widget* widget;
++	widget = kmalloc(sizeof(struct snd_soc_dapm_widget), GFP_KERNEL);
++	if (!widget)
++		return NULL;
++
++	memcpy(widget, _widget, sizeof(struct snd_soc_dapm_widget));
++	return widget;
++}
++
++/* set up initial codec paths */
++static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
++	struct snd_soc_dapm_path *p, int i)
++{
++	switch (w->id) {
++	case snd_soc_dapm_switch:
++	case snd_soc_dapm_mixer: {
++		int val;
++		int reg = w->kcontrols[i].private_value & 0xff;
++		int shift = (w->kcontrols[i].private_value >> 8) & 0x0f;
++		int mask = (w->kcontrols[i].private_value >> 16) & 0xff;
++		int invert = (w->kcontrols[i].private_value >> 24) & 0x01;
++
++		val = snd_soc_read(w->codec, reg);
++		val = (val >> shift) & mask;
++
++		if ((invert && !val) || (!invert && val))
++			p->connect = 1;
++		else
++			p->connect = 0;
++	}
++	break;
++	case snd_soc_dapm_mux: {
++		struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
++		int val, item, bitmask;
++
++		for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
++		;
++		val = snd_soc_read(w->codec, e->reg);
++		item = (val >> e->shift_l) & (bitmask - 1);
++
++		p->connect = 0;
++		for (i = 0; i < e->mask; i++) {
++			if (!(strcmp(p->name, e->texts[i])) && item == i)
++				p->connect = 1;
++		}
++	}
++	break;
++	/* does not effect routing - always connected */
++	case snd_soc_dapm_pga:
++	case snd_soc_dapm_output:
++	case snd_soc_dapm_adc:
++	case snd_soc_dapm_input:
++	case snd_soc_dapm_dac:
++	case snd_soc_dapm_micbias:
++	case snd_soc_dapm_vmid:
++		p->connect = 1;
++	break;
++	/* does effect routing - dynamically connected */
++	case snd_soc_dapm_hp:
++	case snd_soc_dapm_mic:
++	case snd_soc_dapm_spk:
++	case snd_soc_dapm_line:
++	case snd_soc_dapm_pre:
++	case snd_soc_dapm_post:
++		p->connect = 0;
++	break;
++	}
++}
++
++/* connect mux widget to it's interconnecting audio paths */
++static int dapm_connect_mux(struct snd_soc_codec *codec,
++	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
++	struct snd_soc_dapm_path *path, const char *control_name,
++	const struct snd_kcontrol_new *kcontrol)
++{
++	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
++	int i;
++
++	for (i = 0; i < e->mask; i++) {
++		if (!(strcmp(control_name, e->texts[i]))) {
++			list_add(&path->list, &codec->dapm_paths);
++			list_add(&path->list_sink, &dest->sources);
++			list_add(&path->list_source, &src->sinks);
++			path->name = (char*)e->texts[i];
++			dapm_set_path_status(dest, path, 0);
++			return 0;
++		}
++	}
++
++	return -ENODEV;
++}
++
++/* connect mixer widget to it's interconnecting audio paths */
++static int dapm_connect_mixer(struct snd_soc_codec *codec,
++	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
++	struct snd_soc_dapm_path *path, const char *control_name)
++{
++	int i;
++
++	/* search for mixer kcontrol */
++	for (i = 0; i < dest->num_kcontrols; i++) {
++		if (!strcmp(control_name, dest->kcontrols[i].name)) {
++			list_add(&path->list, &codec->dapm_paths);
++			list_add(&path->list_sink, &dest->sources);
++			list_add(&path->list_source, &src->sinks);
++			path->name = dest->kcontrols[i].name;
++			dapm_set_path_status(dest, path, i);
++			return 0;
++		}
++	}
++	return -ENODEV;
++}
++
++/* update dapm codec register bits */
++static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
++{
++	int change, power;
++	unsigned short old, new;
++	struct snd_soc_codec *codec = widget->codec;
++
++	/* check for valid widgets */
++	if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
++		widget->id == snd_soc_dapm_output ||
++		widget->id == snd_soc_dapm_hp ||
++		widget->id == snd_soc_dapm_mic ||
++		widget->id == snd_soc_dapm_line ||
++		widget->id == snd_soc_dapm_spk)
++		return 0;
++
++	power = widget->power;
++	if (widget->invert)
++		power = (power ? 0:1);
++
++	old = snd_soc_read(codec, widget->reg);
++	new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
++
++	change = old != new;
++	if (change) {
++		pop_dbg("pop test %s : %s in %d ms\n", widget->name,
++			widget->power ? "on" : "off", POP_TIME);
++		snd_soc_write(codec, widget->reg, new);
++		pop_wait(POP_TIME);
++	}
++	dbg("reg old %x new %x change %d\n", old, new, change);
++	return change;
++}
++
++/* ramps the volume up or down to minimise pops before or after a
++ * DAPM power event */
++static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
++{
++	const struct snd_kcontrol_new *k = widget->kcontrols;
++
++	if (widget->muted && !power)
++		return 0;
++	if (!widget->muted && power)
++		return 0;
++
++	if (widget->num_kcontrols && k) {
++		int reg = k->private_value & 0xff;
++		int shift = (k->private_value >> 8) & 0x0f;
++		int mask = (k->private_value >> 16) & 0xff;
++		int invert = (k->private_value >> 24) & 0x01;
++
++		if (power) {
++			int i;
++			/* power up has happended, increase volume to last level */
++			if (invert) {
++				for (i = mask; i > widget->saved_value; i--)
++					snd_soc_update_bits(widget->codec, reg, mask, i);
++			} else {
++				for (i = 0; i < widget->saved_value; i++)
++					snd_soc_update_bits(widget->codec, reg, mask, i);
++			}
++			widget->muted = 0;
++		} else {
++			/* power down is about to occur, decrease volume to mute */
++			int val = snd_soc_read(widget->codec, reg);
++			int i = widget->saved_value = (val >> shift) & mask;
++			if (invert) {
++				for (; i < mask; i++)
++					snd_soc_update_bits(widget->codec, reg, mask, i);
++			} else {
++				for (; i > 0; i--)
++					snd_soc_update_bits(widget->codec, reg, mask, i);
++			}
++			widget->muted = 1;
++		}
++	}
++	return 0;
++}
++
++/* create new dapm mixer control */
++static int dapm_new_mixer(struct snd_soc_codec *codec,
++	struct snd_soc_dapm_widget *w)
++{
++	int i, ret = 0;
++	char name[32];
++	struct snd_soc_dapm_path *path;
++
++	/* add kcontrol */
++	for (i = 0; i < w->num_kcontrols; i++) {
++
++		/* match name */
++		list_for_each_entry(path, &w->sources, list_sink) {
++
++			/* mixer/mux paths name must match control name */
++			if (path->name != (char*)w->kcontrols[i].name)
++				continue;
++
++			/* add dapm control with long name */
++			snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
++			path->long_name = kstrdup (name, GFP_KERNEL);
++			if (path->long_name == NULL)
++				return -ENOMEM;
++
++			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
++				path->long_name);
++			ret = snd_ctl_add(codec->card, path->kcontrol);
++			if (ret < 0) {
++				printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
++						path->long_name);
++				kfree(path->long_name);
++				path->long_name = NULL;
++				return ret;
++			}
++		}
++	}
++	return ret;
++}
++
++/* create new dapm mux control */
++static int dapm_new_mux(struct snd_soc_codec *codec,
++	struct snd_soc_dapm_widget *w)
++{
++	struct snd_soc_dapm_path *path = NULL;
++	struct snd_kcontrol *kcontrol;
++	int ret = 0;
++
++	if (!w->num_kcontrols) {
++		printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
++		return -EINVAL;
++	}
++
++	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
++	ret = snd_ctl_add(codec->card, kcontrol);
++	if (ret < 0)
++		goto err;
++
++	list_for_each_entry(path, &w->sources, list_sink)
++		path->kcontrol = kcontrol;
++
++	return ret;
++
++err:
++	printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
++	return ret;
++}
++
++/* create new dapm volume control */
++static int dapm_new_pga(struct snd_soc_codec *codec,
++	struct snd_soc_dapm_widget *w)
++{
++	struct snd_kcontrol *kcontrol;
++	int ret = 0;
++
++	if (!w->num_kcontrols)
++		return -EINVAL;
++
++	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
++	ret = snd_ctl_add(codec->card, kcontrol);
++	if (ret < 0) {
++		printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
++		return ret;
++	}
++
++	return ret;
++}
++
++/* reset 'walked' bit for each dapm path */
++static inline void dapm_clear_walk(struct snd_soc_codec *codec)
++{
++	struct snd_soc_dapm_path *p;
++
++	list_for_each_entry(p, &codec->dapm_paths, list)
++		p->walked = 0;
++}
++
++/*
++ * Recursively check for a completed path to an active or physically connected
++ * output widget. Returns number of complete paths.
++ */
++static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
++{
++	struct snd_soc_dapm_path *path;
++	int con = 0;
++
++	if (widget->id == snd_soc_dapm_adc && widget->active)
++		return 1;
++
++	if (widget->connected) {
++		/* connected pin ? */
++		if (widget->id == snd_soc_dapm_output && !widget->ext)
++			return 1;
++
++		/* connected jack or spk ? */
++		if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
++			widget->id == snd_soc_dapm_line)
++			return 1;
++	}
++
++	list_for_each_entry(path, &widget->sinks, list_source) {
++		if (path->walked)
++			continue;
++
++		if (path->sink && path->connect) {
++			path->walked = 1;
++			con += is_connected_output_ep(path->sink);
++		}
++	}
++
++	return con;
++}
++
++/*
++ * Recursively check for a completed path to an active or physically connected
++ * input widget. Returns number of complete paths.
++ */
++static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
++{
++	struct snd_soc_dapm_path *path;
++	int con = 0;
++
++	/* active stream ? */
++	if (widget->id == snd_soc_dapm_dac && widget->active)
++		return 1;
++
++	if (widget->connected) {
++		/* connected pin ? */
++		if (widget->id == snd_soc_dapm_input && !widget->ext)
++			return 1;
++
++		/* connected VMID/Bias for lower pops */
++		if (widget->id == snd_soc_dapm_vmid)
++			return 1;
++
++		/* connected jack ? */
++		if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
++			return 1;
++	}
++
++	list_for_each_entry(path, &widget->sources, list_sink) {
++		if (path->walked)
++			continue;
++
++		if (path->source && path->connect) {
++			path->walked = 1;
++			con += is_connected_input_ep(path->source);
++		}
++	}
++
++	return con;
++}
++
++/*
++ * Scan each dapm widget for complete audio path.
++ * A complete path is a route that has valid endpoints i.e.:-
++ *
++ *  o DAC to output pin.
++ *  o Input Pin to ADC.
++ *  o Input pin to Output pin (bypass, sidetone)
++ *  o DAC to ADC (loopback).
++ */
++int dapm_power_widgets(struct snd_soc_codec *codec, int event)
++{
++	struct snd_soc_dapm_widget *w;
++	int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
++
++	/* do we have a sequenced stream event */
++	if (event == SND_SOC_DAPM_STREAM_START) {
++		c = ARRAY_SIZE(dapm_up_seq);
++		seq = dapm_up_seq;
++	} else if (event == SND_SOC_DAPM_STREAM_STOP) {
++		c = ARRAY_SIZE(dapm_down_seq);
++		seq = dapm_down_seq;
++	}
++
++	for(i = 0; i < c; i++) {
++		list_for_each_entry(w, &codec->dapm_widgets, list) {
++
++			/* is widget in stream order */
++			if (seq && seq[i] && w->id != seq[i])
++				continue;
++
++			/* vmid - no action */
++			if (w->id == snd_soc_dapm_vmid)
++				continue;
++
++			/* active ADC */
++			if (w->id == snd_soc_dapm_adc && w->active) {
++				in = is_connected_input_ep(w);
++				dapm_clear_walk(w->codec);
++				w->power = (in != 0) ? 1 : 0;
++				dapm_update_bits(w);
++				continue;
++			}
++
++			/* active DAC */
++			if (w->id == snd_soc_dapm_dac && w->active) {
++				out = is_connected_output_ep(w);
++				dapm_clear_walk(w->codec);
++				w->power = (out != 0) ? 1 : 0;
++				dapm_update_bits(w);
++				continue;
++			}
++
++			/* programmable gain/attenuation */
++			if (w->id == snd_soc_dapm_pga) {
++				int on;
++				in = is_connected_input_ep(w);
++				dapm_clear_walk(w->codec);
++				out = is_connected_output_ep(w);
++				dapm_clear_walk(w->codec);
++				w->power = on = (out != 0 && in != 0) ? 1 : 0;
++
++				if (!on)
++					dapm_set_pga(w, on); /* lower volume to reduce pops */
++				dapm_update_bits(w);
++				if (on)
++					dapm_set_pga(w, on); /* restore volume from zero */
++
++				continue;
++			}
++
++			/* pre and post event widgets */
++			if (w->id == snd_soc_dapm_pre) {
++				if (!w->event)
++					continue;
++
++				if (event == SND_SOC_DAPM_STREAM_START) {
++					ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
++					if (ret < 0)
++						return ret;
++				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
++					ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
++					if (ret < 0)
++						return ret;
++				}
++				continue;
++			}
++			if (w->id == snd_soc_dapm_post) {
++				if (!w->event)
++					continue;
++
++				if (event == SND_SOC_DAPM_STREAM_START) {
++					ret = w->event(w, SND_SOC_DAPM_POST_PMU);
++					if (ret < 0)
++						return ret;
++				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
++					ret = w->event(w, SND_SOC_DAPM_POST_PMD);
++					if (ret < 0)
++						return ret;
++				}
++				continue;
++			}
++
++			/* all other widgets */
++			in = is_connected_input_ep(w);
++			dapm_clear_walk(w->codec);
++			out = is_connected_output_ep(w);
++			dapm_clear_walk(w->codec);
++			power = (out != 0 && in != 0) ? 1 : 0;
++			power_change = (w->power == power) ? 0: 1;
++			w->power = power;
++
++			/* call any power change event handlers */
++			if (power_change) {
++				if (w->event) {
++					dbg("power %s event for %s flags %x\n",
++						w->power ? "on" : "off", w->name, w->event_flags);
++					if (power) {
++						/* power up event */
++						if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
++							ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
++							if (ret < 0)
++								return ret;
++						}
++						dapm_update_bits(w);
++						if (w->event_flags & SND_SOC_DAPM_POST_PMU){
++							ret = w->event(w, SND_SOC_DAPM_POST_PMU);
++							if (ret < 0)
++								return ret;
++						}
++					} else {
++						/* power down event */
++						if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {
++							ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
++							if (ret < 0)
++								return ret;
++						}
++						dapm_update_bits(w);
++						if (w->event_flags & SND_SOC_DAPM_POST_PMD) {
++							ret = w->event(w, SND_SOC_DAPM_POST_PMD);
++							if (ret < 0)
++								return ret;
++						}
++					}
++				} else
++					/* no event handler */
++					dapm_update_bits(w);
++			}
++		}
++	}
++
++	return ret;
++}
++
++#if DAPM_DEBUG
++static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
++{
++	struct snd_soc_dapm_widget *w;
++	struct snd_soc_dapm_path *p = NULL;
++	int in, out;
++
++	printk("DAPM %s %s\n", codec->name, action);
++
++	list_for_each_entry(w, &codec->dapm_widgets, list) {
++
++		/* only display widgets that effect routing */
++		switch (w->id) {
++		case snd_soc_dapm_pre:
++		case snd_soc_dapm_post:
++		case snd_soc_dapm_vmid:
++			continue;
++		case snd_soc_dapm_mux:
++		case snd_soc_dapm_output:
++		case snd_soc_dapm_input:
++		case snd_soc_dapm_switch:
++		case snd_soc_dapm_hp:
++		case snd_soc_dapm_mic:
++		case snd_soc_dapm_spk:
++		case snd_soc_dapm_line:
++		case snd_soc_dapm_micbias:
++		case snd_soc_dapm_dac:
++		case snd_soc_dapm_adc:
++		case snd_soc_dapm_pga:
++		case snd_soc_dapm_mixer:
++			if (w->name) {
++				in = is_connected_input_ep(w);
++				dapm_clear_walk(w->codec);
++				out = is_connected_output_ep(w);
++				dapm_clear_walk(w->codec);
++				printk("%s: %s  in %d out %d\n", w->name,
++					w->power ? "On":"Off",in, out);
++
++				list_for_each_entry(p, &w->sources, list_sink) {
++					if (p->connect)
++						printk(" in  %s %s\n", p->name ? p->name : "static",
++							p->source->name);
++				}
++				list_for_each_entry(p, &w->sinks, list_source) {
++					p = list_entry(lp, struct snd_soc_dapm_path, list_source);
++					if (p->connect)
++						printk(" out %s %s\n", p->name ? p->name : "static",
++							p->sink->name);
++				}
++			}
++		break;
++		}
++	}
++}
++#endif
++
++/* test and update the power status of a mux widget */
++int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
++	struct snd_kcontrol *kcontrol, int mask, int val, struct soc_enum* e)
++{
++	struct snd_soc_dapm_path *path;
++	int found = 0;
++
++	if (widget->id != snd_soc_dapm_mux)
++		return -ENODEV;
++
++	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
++		return 0;
++
++	/* find dapm widget path assoc with kcontrol */
++	list_for_each_entry(path, &widget->codec->dapm_paths, list) {
++		if (path->kcontrol != kcontrol)
++			continue;
++
++		if (!path->name || ! e->texts[val])
++			continue;
++
++		found = 1;
++		/* we now need to match the string in the enum to the path */
++		if (!(strcmp(path->name, e->texts[val])))
++			path->connect = 1; /* new connection */
++		else
++			path->connect = 0; /* old connection must be powered down */
++	}
++
++	if (found)
++		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(dapm_mux_update_power);
++
++/* test and update the power status of a mixer widget */
++int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
++	struct snd_kcontrol *kcontrol, int reg, int val_mask, int val, int invert)
++{
++	struct snd_soc_dapm_path *path;
++	int found = 0;
++
++	if (widget->id != snd_soc_dapm_mixer)
++		return -ENODEV;
++
++	if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
++		return 0;
++
++	/* find dapm widget path assoc with kcontrol */
++	list_for_each_entry(path, &widget->codec->dapm_paths, list) {
++		if (path->kcontrol != kcontrol)
++			continue;
++
++		/* found, now check type */
++		found = 1;
++		if (val)
++			/* new connection */
++			path->connect = invert ? 0:1;
++		else
++			/* old connection must be powered down */
++			path->connect = invert ? 1:0;
++		break;
++	}
++
++	if (found)
++		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(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)
++{
++	struct snd_soc_device *devdata = dev_get_drvdata(dev);
++	struct snd_soc_codec *codec = devdata->codec;
++	struct snd_soc_dapm_widget *w;
++	int count = 0;
++	char *state = "not set";
++
++	list_for_each_entry(w, &codec->dapm_widgets, list) {
++
++		/* only display widgets that burnm power */
++		switch (w->id) {
++		case snd_soc_dapm_hp:
++		case snd_soc_dapm_mic:
++		case snd_soc_dapm_spk:
++		case snd_soc_dapm_line:
++		case snd_soc_dapm_micbias:
++		case snd_soc_dapm_dac:
++		case snd_soc_dapm_adc:
++		case snd_soc_dapm_pga:
++		case snd_soc_dapm_mixer:
++			if (w->name)
++				count += sprintf(buf + count, "%s: %s\n",
++					w->name, w->power ? "On":"Off");
++		break;
++		default:
++		break;
++		}
++	}
++
++	switch(codec->dapm_state){
++	case SNDRV_CTL_POWER_D0:
++		state = "D0";
++		break;
++	case SNDRV_CTL_POWER_D1:
++		state = "D1";
++		break;
++	case SNDRV_CTL_POWER_D2:
++		state = "D2";
++		break;
++	case SNDRV_CTL_POWER_D3hot:
++		state = "D3hot";
++		break;
++	case SNDRV_CTL_POWER_D3cold:
++		state = "D3cold";
++		break;
++	}
++	count += sprintf(buf + count, "PM State: %s\n", state);
++
++	return count;
++}
++
++static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
++
++int snd_soc_dapm_sys_add(struct device *dev)
++{
++	int ret = 0;
++
++	if (dapm_status)
++		ret = device_create_file(dev, &dev_attr_dapm_widget);
++
++	return ret;
++}
++
++static void snd_soc_dapm_sys_remove(struct device *dev)
++{
++	if (dapm_status)
++		device_remove_file(dev, &dev_attr_dapm_widget);
++}
++
++/* free all dapm widgets and resources */
++void dapm_free_widgets(struct snd_soc_codec *codec)
++{
++	struct snd_soc_dapm_widget *w, *next_w;
++	struct snd_soc_dapm_path *p, *next_p;
++
++	list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
++		list_del(&w->list);
++		kfree(w);
++	}
++
++	list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
++		list_del(&p->list);
++		kfree(p->long_name);
++		kfree(p);
++	}
++}
++
++/**
++ * snd_soc_dapm_sync_endpoints - scan and power dapm paths
++ * @codec: audio codec
++ *
++ * Walks all dapm audio paths and powers widgets according to their
++ * stream or path usage.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec)
++{
++	return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);
++
++/**
++ * snd_soc_dapm_connect_input - connect dapm widgets
++ * @codec: audio codec
++ * @sink: name of target widget
++ * @control: mixer control name
++ * @source: name of source name
++ *
++ * Connects 2 dapm widgets together via a named audio path. The sink is
++ * the widget receiving the audio signal, whilst the source is the sender
++ * of the audio signal.
++ *
++ * Returns 0 for success else error.
++ */
++int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
++	const char * control, const char *source)
++{
++	struct snd_soc_dapm_path *path;
++	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
++	int ret = 0;
++
++	/* find src and dest widgets */
++	list_for_each_entry(w, &codec->dapm_widgets, list) {
++
++		if (!wsink && !(strcmp(w->name, sink))) {
++			wsink = w;
++			continue;
++		}
++		if (!wsource && !(strcmp(w->name, source))) {
++			wsource = w;
++		}
++	}
++
++	if (wsource == NULL || wsink == NULL)
++		return -ENODEV;
++
++	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
++	if (!path)
++		return -ENOMEM;
++
++	path->source = wsource;
++	path->sink = wsink;
++	INIT_LIST_HEAD(&path->list);
++	INIT_LIST_HEAD(&path->list_source);
++	INIT_LIST_HEAD(&path->list_sink);
++
++	/* check for external widgets */
++	if (wsink->id == snd_soc_dapm_input) {
++		if (wsource->id == snd_soc_dapm_micbias ||
++			wsource->id == snd_soc_dapm_mic ||
++			wsink->id == snd_soc_dapm_line)
++			wsink->ext = 1;
++	}
++	if (wsource->id == snd_soc_dapm_output) {
++		if (wsink->id == snd_soc_dapm_spk ||
++			wsink->id == snd_soc_dapm_hp ||
++			wsink->id == snd_soc_dapm_line)
++			wsource->ext = 1;
++	}
++
++	/* connect static paths */
++	if (control == NULL) {
++		list_add(&path->list, &codec->dapm_paths);
++		list_add(&path->list_sink, &wsink->sources);
++		list_add(&path->list_source, &wsource->sinks);
++		path->connect = 1;
++		return 0;
++	}
++
++	/* connect dynamic paths */
++	switch(wsink->id) {
++	case snd_soc_dapm_adc:
++	case snd_soc_dapm_dac:
++	case snd_soc_dapm_pga:
++	case snd_soc_dapm_input:
++	case snd_soc_dapm_output:
++	case snd_soc_dapm_micbias:
++	case snd_soc_dapm_vmid:
++	case snd_soc_dapm_pre:
++	case snd_soc_dapm_post:
++		list_add(&path->list, &codec->dapm_paths);
++		list_add(&path->list_sink, &wsink->sources);
++		list_add(&path->list_source, &wsource->sinks);
++		path->connect = 1;
++		return 0;
++	case snd_soc_dapm_mux:
++		ret = dapm_connect_mux(codec, wsource, wsink, path, control,
++			&wsink->kcontrols[0]);
++		if (ret != 0)
++			goto err;
++		break;
++	case snd_soc_dapm_switch:
++	case snd_soc_dapm_mixer:
++		ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
++		if (ret != 0)
++			goto err;
++		break;
++	case snd_soc_dapm_hp:
++	case snd_soc_dapm_mic:
++	case snd_soc_dapm_line:
++	case snd_soc_dapm_spk:
++		list_add(&path->list, &codec->dapm_paths);
++		list_add(&path->list_sink, &wsink->sources);
++		list_add(&path->list_source, &wsource->sinks);
++		path->connect = 0;
++		return 0;
++	}
++	return 0;
++
++err:
++	printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
++		control, sink);
++	kfree(path);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
++
++/**
++ * snd_soc_dapm_new_widgets - add new dapm widgets
++ * @codec: audio codec
++ *
++ * Checks the codec for any new dapm widgets and creates them if found.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
++{
++	struct snd_soc_dapm_widget *w;
++
++	mutex_lock(&codec->mutex);
++	list_for_each_entry(w, &codec->dapm_widgets, list)
++	{
++		if (w->new)
++			continue;
++
++		switch(w->id) {
++		case snd_soc_dapm_switch:
++		case snd_soc_dapm_mixer:
++			dapm_new_mixer(codec, w);
++			break;
++		case snd_soc_dapm_mux:
++			dapm_new_mux(codec, w);
++			break;
++		case snd_soc_dapm_adc:
++		case snd_soc_dapm_dac:
++		case snd_soc_dapm_pga:
++			dapm_new_pga(codec, w);
++			break;
++		case snd_soc_dapm_input:
++		case snd_soc_dapm_output:
++		case snd_soc_dapm_micbias:
++		case snd_soc_dapm_spk:
++		case snd_soc_dapm_hp:
++		case snd_soc_dapm_mic:
++		case snd_soc_dapm_line:
++		case snd_soc_dapm_vmid:
++		case snd_soc_dapm_pre:
++		case snd_soc_dapm_post:
++			break;
++		}
++		w->new = 1;
++	}
++
++	dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
++	mutex_unlock(&codec->mutex);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
++
++/**
++ * snd_soc_dapm_get_volsw - dapm mixer get callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to get the value of a dapm mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int rshift = (kcontrol->private_value >> 12) & 0x0f;
++	int mask = (kcontrol->private_value >> 16) & 0xff;
++	int invert = (kcontrol->private_value >> 24) & 0x01;
++
++	/* return the saved value if we are powered down */
++	if (widget->id == snd_soc_dapm_pga && !widget->power) {
++		ucontrol->value.integer.value[0] = widget->saved_value;
++		return 0;
++	}
++
++	ucontrol->value.integer.value[0] =
++		(snd_soc_read(widget->codec, reg) >> shift) & mask;
++	if (shift != rshift)
++		ucontrol->value.integer.value[1] =
++			(snd_soc_read(widget->codec, reg) >> rshift) & mask;
++	if (invert) {
++		ucontrol->value.integer.value[0] =
++			mask - ucontrol->value.integer.value[0];
++		if (shift != rshift)
++			ucontrol->value.integer.value[1] =
++				mask - ucontrol->value.integer.value[1];
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
++
++/**
++ * snd_soc_dapm_put_volsw - dapm mixer set callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to set the value of a dapm mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int rshift = (kcontrol->private_value >> 12) & 0x0f;
++	int mask = (kcontrol->private_value >> 16) & 0xff;
++	int invert = (kcontrol->private_value >> 24) & 0x01;
++	unsigned short val, val2, val_mask;
++	int ret;
++
++	val = (ucontrol->value.integer.value[0] & mask);
++
++	if (invert)
++		val = mask - val;
++	val_mask = mask << shift;
++	val = val << shift;
++	if (shift != rshift) {
++		val2 = (ucontrol->value.integer.value[1] & mask);
++		if (invert)
++			val2 = mask - val2;
++		val_mask |= mask << rshift;
++		val |= val2 << rshift;
++	}
++
++	mutex_lock(&widget->codec->mutex);
++	widget->value = val;
++
++	/* save volume value if the widget is powered down */
++	if (widget->id == snd_soc_dapm_pga && !widget->power) {
++		widget->saved_value = val;
++		mutex_unlock(&widget->codec->mutex);
++		return 1;
++	}
++
++	dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
++	if (widget->event) {
++		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
++			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
++			if (ret < 0)
++				goto out;
++		}
++		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
++		if (widget->event_flags & SND_SOC_DAPM_POST_REG)
++			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
++	} else
++		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
++
++out:
++	mutex_unlock(&widget->codec->mutex);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
++
++/**
++ * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to get the value of a dapm enumerated double mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
++	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
++	unsigned short val, bitmask;
++
++	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
++		;
++	val = snd_soc_read(widget->codec, e->reg);
++	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
++	if (e->shift_l != e->shift_r)
++		ucontrol->value.enumerated.item[1] =
++			(val >> e->shift_r) & (bitmask - 1);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
++
++/**
++ * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to set the value of a dapm enumerated double mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
++	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
++	unsigned short val, mux;
++	unsigned short mask, bitmask;
++	int ret = 0;
++
++	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
++		;
++	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
++		return -EINVAL;
++	mux = ucontrol->value.enumerated.item[0];
++	val = mux << e->shift_l;
++	mask = (bitmask - 1) << e->shift_l;
++	if (e->shift_l != e->shift_r) {
++		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
++			return -EINVAL;
++		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
++		mask |= (bitmask - 1) << e->shift_r;
++	}
++
++	mutex_lock(&widget->codec->mutex);
++	widget->value = val;
++	dapm_mux_update_power(widget, kcontrol, mask, mux, e);
++	if (widget->event) {
++		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
++			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
++			if (ret < 0)
++				goto out;
++		}
++		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
++		if (widget->event_flags & SND_SOC_DAPM_POST_REG)
++			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
++	} else
++		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
++
++out:
++	mutex_unlock(&widget->codec->mutex);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
++
++/**
++ * snd_soc_dapm_new_control - create new dapm control
++ * @codec: audio codec
++ * @widget: widget template
++ *
++ * Creates a new dapm control based upon the template.
++ *
++ * Returns 0 for success else error.
++ */
++int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
++	const struct snd_soc_dapm_widget *widget)
++{
++	struct snd_soc_dapm_widget *w;
++
++	if ((w = dapm_cnew_widget(widget)) == NULL)
++		return -ENOMEM;
++
++	w->codec = codec;
++	INIT_LIST_HEAD(&w->sources);
++	INIT_LIST_HEAD(&w->sinks);
++	INIT_LIST_HEAD(&w->list);
++	list_add(&w->list, &codec->dapm_widgets);
++
++	/* machine layer set ups unconnected pins and insertions */
++	w->connected = 1;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
++
++/**
++ * snd_soc_dapm_stream_event - send a stream event to the dapm core
++ * @codec: audio codec
++ * @stream: stream name
++ * @event: stream event
++ *
++ * Sends a stream event to the dapm core. The core then makes any
++ * necessary widget power changes.
++ *
++ * Returns 0 for success else error.
++ */
++int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
++	char *stream, int event)
++{
++	struct snd_soc_dapm_widget *w;
++
++	mutex_lock(&codec->mutex);
++	list_for_each_entry(w, &codec->dapm_widgets, list)
++	{
++		if (!w->sname)
++			continue;
++		dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,
++			stream, event);
++		if (strstr(w->sname, stream)) {
++			switch(event) {
++			case SND_SOC_DAPM_STREAM_START:
++				w->active = 1;
++				break;
++			case SND_SOC_DAPM_STREAM_STOP:
++				w->active = 0;
++				break;
++			case SND_SOC_DAPM_STREAM_SUSPEND:
++				if (w->active)
++					w->suspend = 1;
++				w->active = 0;
++				break;
++			case SND_SOC_DAPM_STREAM_RESUME:
++				if (w->suspend) {
++					w->active = 1;
++					w->suspend = 0;
++				}
++				break;
++			case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
++				break;
++			case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
++				break;
++			}
++		}
++	}
++	mutex_unlock(&codec->mutex);
++
++	dapm_power_widgets(codec, event);
++	dump_dapm(codec, __FUNCTION__);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
++
++/**
++ * snd_soc_dapm_set_endpoint - set audio endpoint status
++ * @codec: audio codec
++ * @endpoint: audio signal endpoint (or start point)
++ * @status: point status
++ *
++ * Set audio endpoint status - connected or disconnected.
++ *
++ * Returns 0 for success else error.
++ */
++int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
++	char *endpoint, int status)
++{
++	struct snd_soc_dapm_widget *w;
++
++	list_for_each_entry(w, &codec->dapm_widgets, list) {
++		if (!strcmp(w->name, endpoint)) {
++			w->connected = status;
++		}
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
++
++/**
++ * snd_soc_dapm_free - free dapm resources
++ * @socdev: SoC device
++ *
++ * Free all dapm widgets and resources.
++ */
++void snd_soc_dapm_free(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++
++	snd_soc_dapm_sys_remove(socdev->dev);
++	dapm_free_widgets(codec);
++}
++EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/soc-core.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/soc-core.c
+@@ -0,0 +1,2063 @@
++/*
++ * soc-core.c  --  ALSA SoC Audio Layer
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    12th Aug 2005   Initial version.
++ *    25th Oct 2005   Working Codec, Interface and Platform registration.
++ *
++ *  TODO:
++ *   o Add hw rules to enforce rates, etc.
++ *   o More testing with other codecs/machines.
++ *   o Add more codecs and platforms to ensure good API coverage.
++ *   o Support TDM on PCM and I2S
++ */
++
++#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/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>
++
++/* debug */
++#define SOC_DEBUG 1
++#if SOC_DEBUG
++#define dbg(format, arg...) printk(format, ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++/* debug DAI capabilities matching */
++#define SOC_DEBUG_DAI 1
++#if SOC_DEBUG_DAI
++#define dbgc(format, arg...) printk(format, ## arg)
++#else
++#define dbgc(format, arg...)
++#endif
++
++#define CODEC_CPU(codec, cpu)	((codec << 4) | cpu)
++
++static DEFINE_MUTEX(pcm_mutex);
++static DEFINE_MUTEX(io_mutex);
++static struct workqueue_struct *soc_workq;
++static struct work_struct soc_stream_work;
++static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
++
++/* supported sample rates */
++/* ATTENTION: these values depend on the definition in pcm.h! */
++static const unsigned int rates[] = {
++	5512, 8000, 11025, 16000, 22050, 32000, 44100,
++	48000, 64000, 88200, 96000, 176400, 192000
++};
++
++/*
++ * This is a timeout to do a DAPM powerdown after a stream is closed().
++ * It can be used to eliminate pops between different playback streams, e.g.
++ * between two audio tracks.
++ */
++static int pmdown_time = 5000;
++module_param(pmdown_time, int, 0);
++MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
++
++#ifdef CONFIG_SND_SOC_AC97_BUS
++/* unregister ac97 codec */
++static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
++{
++	if (codec->ac97->dev.bus)
++		device_unregister(&codec->ac97->dev);
++	return 0;
++}
++
++/* stop no dev release warning */
++static void soc_ac97_device_release(struct device *dev){}
++
++/* register ac97 codec to bus */
++static int soc_ac97_dev_register(struct snd_soc_codec *codec)
++{
++	int err;
++
++	codec->ac97->dev.bus = &ac97_bus_type;
++	codec->ac97->dev.parent = NULL;
++	codec->ac97->dev.release = soc_ac97_device_release;
++
++	snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
++		 codec->card->number, 0, codec->name);
++	err = device_register(&codec->ac97->dev);
++	if (err < 0) {
++		snd_printk(KERN_ERR "Can't register ac97 bus\n");
++		codec->ac97->dev.bus = NULL;
++		return err;
++	}
++	return 0;
++}
++#endif
++
++static inline const char* get_dai_name(int type)
++{
++	switch(type) {
++	case SND_SOC_DAI_AC97:
++		return "AC97";
++	case SND_SOC_DAI_I2S:
++		return "I2S";
++	case SND_SOC_DAI_PCM:
++		return "PCM";
++	}
++	return NULL;
++}
++
++/* get rate format from rate */
++static inline int soc_get_rate_format(int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(rates); i++) {
++		if (rates[i] == rate)
++			return 1 << i;
++	}
++	return 0;
++}
++
++/* gets the audio system mclk/sysclk for the given parameters */
++static unsigned inline int soc_get_mclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_machine *machine = socdev->machine;
++	int i;
++
++	/* find the matching machine config and get it's mclk for the given
++	 * sample rate and hardware format */
++	for(i = 0; i < machine->num_links; i++) {
++		if (machine->dai_link[i].cpu_dai == rtd->cpu_dai &&
++			machine->dai_link[i].config_sysclk)
++			return machine->dai_link[i].config_sysclk(rtd, info);
++	}
++	return 0;
++}
++
++/* changes a bitclk multiplier mask to a divider mask */
++static u64 soc_bfs_rcw_to_div(u64 bfs, int rate, unsigned int mclk,
++	unsigned int pcmfmt, unsigned int chn)
++{
++	int i, j;
++	u64 bfs_ = 0;
++	int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
++
++	if (size <= 0)
++		return 0;
++
++	/* the minimum bit clock that has enough bandwidth */
++	min = size * rate * chn;
++	dbgc("rcw --> div min bclk %d with mclk %d\n", min, mclk);
++
++	for (i = 0; i < 64; i++) {
++		if ((bfs >> i) & 0x1) {
++			j = min * (i + 1);
++			bfs_ |= SND_SOC_FSBD(mclk/j);
++			dbgc("rcw --> div support mult %d\n",
++				SND_SOC_FSBD_REAL(1<<i));
++		}
++	}
++
++	return bfs_;
++}
++
++/* changes a bitclk divider mask to a multiplier mask */
++static u64 soc_bfs_div_to_rcw(u64 bfs, int rate, unsigned int mclk,
++	unsigned int pcmfmt, unsigned int chn)
++{
++	int i, j;
++	u64 bfs_ = 0;
++
++	int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
++
++	if (size <= 0)
++		return 0;
++
++	/* the minimum bit clock that has enough bandwidth */
++	min = size * rate * chn;
++	dbgc("div to rcw min bclk %d with mclk %d\n", min, mclk);
++
++	for (i = 0; i < 64; i++) {
++		if ((bfs >> i) & 0x1) {
++			j = mclk / (i + 1);
++			if (j >= min) {
++				bfs_ |= SND_SOC_FSBW(j/min);
++				dbgc("div --> rcw support div %d\n",
++					SND_SOC_FSBW_REAL(1<<i));
++			}
++		}
++	}
++
++	return bfs_;
++}
++
++/* changes a constant bitclk to a multiplier mask */
++static u64 soc_bfs_rate_to_rcw(u64 bfs, int rate, unsigned int mclk,
++	unsigned int pcmfmt, unsigned int chn)
++{
++	unsigned int bfs_ = rate * bfs;
++	int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
++
++	if (size <= 0)
++		return 0;
++
++	/* the minimum bit clock that has enough bandwidth */
++	min = size * rate * chn;
++	dbgc("rate --> rcw min bclk %d with mclk %d\n", min, mclk);
++
++	if (bfs_ < min)
++		return 0;
++	else {
++		bfs_ = SND_SOC_FSBW(bfs_/min);
++		dbgc("rate --> rcw support div %d\n", SND_SOC_FSBW_REAL(bfs_));
++		return bfs_;
++	}
++}
++
++/* changes a bitclk multiplier mask to a divider mask */
++static u64 soc_bfs_rate_to_div(u64 bfs, int rate, unsigned int mclk,
++	unsigned int pcmfmt, unsigned int chn)
++{
++	unsigned int bfs_ = rate * bfs;
++	int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
++
++	if (size <= 0)
++		return 0;
++
++	/* the minimum bit clock that has enough bandwidth */
++	min = size * rate * chn;
++	dbgc("rate --> div min bclk %d with mclk %d\n", min, mclk);
++
++	if (bfs_ < min)
++		return 0;
++	else {
++		bfs_ = SND_SOC_FSBW(mclk/bfs_);
++		dbgc("rate --> div support div %d\n", SND_SOC_FSBD_REAL(bfs_));
++		return bfs_;
++	}
++}
++
++/* Matches codec DAI and SoC CPU DAI hardware parameters */
++static int soc_hw_match_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_mode *codec_dai_mode = NULL;
++	struct snd_soc_dai_mode *cpu_dai_mode = NULL;
++	struct snd_soc_clock_info clk_info;
++	unsigned int fs, mclk, rate = params_rate(params),
++		chn, j, k, cpu_bclk, codec_bclk, pcmrate;
++	u16 fmt = 0;
++	u64 codec_bfs, cpu_bfs;
++
++	dbg("asoc: match version %s\n", SND_SOC_VERSION);
++	clk_info.rate = rate;
++	pcmrate = soc_get_rate_format(rate);
++
++	/* try and find a match from the codec and cpu DAI capabilities */
++	for (j = 0; j < rtd->codec_dai->caps.num_modes; j++) {
++		for (k = 0; k < rtd->cpu_dai->caps.num_modes; k++) {
++			codec_dai_mode = &rtd->codec_dai->caps.mode[j];
++			cpu_dai_mode = &rtd->cpu_dai->caps.mode[k];
++
++			if (!(codec_dai_mode->pcmrate & cpu_dai_mode->pcmrate &
++					pcmrate)) {
++				dbgc("asoc: DAI[%d:%d] failed to match rate\n", j, k);
++				continue;
++			}
++
++			fmt = codec_dai_mode->fmt & cpu_dai_mode->fmt;
++			if (!(fmt & SND_SOC_DAIFMT_FORMAT_MASK)) {
++				dbgc("asoc: DAI[%d:%d] failed to match format\n", j, k);
++				continue;
++			}
++
++			if (!(fmt & SND_SOC_DAIFMT_CLOCK_MASK)) {
++				dbgc("asoc: DAI[%d:%d] failed to match clock masters\n",
++					 j, k);
++				continue;
++			}
++
++			if (!(fmt & SND_SOC_DAIFMT_INV_MASK)) {
++				dbgc("asoc: DAI[%d:%d] failed to match invert\n", j, k);
++				continue;
++			}
++
++			if (!(codec_dai_mode->pcmfmt & cpu_dai_mode->pcmfmt)) {
++				dbgc("asoc: DAI[%d:%d] failed to match pcm format\n", j, k);
++				continue;
++			}
++
++			if (!(codec_dai_mode->pcmdir & cpu_dai_mode->pcmdir)) {
++				dbgc("asoc: DAI[%d:%d] failed to match direction\n", j, k);
++				continue;
++			}
++
++			/* todo - still need to add tdm selection */
++			rtd->cpu_dai->dai_runtime.fmt =
++			rtd->codec_dai->dai_runtime.fmt =
++				1 << (ffs(fmt & SND_SOC_DAIFMT_FORMAT_MASK) -1) |
++				1 << (ffs(fmt & SND_SOC_DAIFMT_CLOCK_MASK) - 1) |
++				1 << (ffs(fmt & SND_SOC_DAIFMT_INV_MASK) - 1);
++			clk_info.bclk_master =
++				rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK;
++
++			/* make sure the ratio between rate and master
++			 * clock is acceptable*/
++			fs = (cpu_dai_mode->fs & codec_dai_mode->fs);
++			if (fs == 0) {
++				dbgc("asoc: DAI[%d:%d] failed to match FS\n", j, k);
++				continue;
++			}
++			clk_info.fs = rtd->cpu_dai->dai_runtime.fs =
++				rtd->codec_dai->dai_runtime.fs = fs;
++
++			/* calculate audio system clocking using slowest clocks possible*/
++			mclk = soc_get_mclk(rtd, &clk_info);
++			if (mclk == 0) {
++				dbgc("asoc: DAI[%d:%d] configuration not clockable\n", j, k);
++				dbgc("asoc: rate %d fs %d master %x\n", rate, fs,
++					clk_info.bclk_master);
++				continue;
++			}
++
++			/* calculate word size (per channel) and frame size */
++			rtd->codec_dai->dai_runtime.pcmfmt =
++				rtd->cpu_dai->dai_runtime.pcmfmt =
++				1 << params_format(params);
++
++			chn = params_channels(params);
++			/* i2s always has left and right */
++			if (params_channels(params) == 1 &&
++				rtd->cpu_dai->dai_runtime.fmt & (SND_SOC_DAIFMT_I2S |
++					SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_LEFT_J))
++				chn <<= 1;
++
++			/* Calculate bfs - the ratio between bitclock and the sample rate
++			 * We must take into consideration the dividers and multipliers
++			 * used in the codec and cpu DAI modes. We always choose the
++			 * lowest possible clocks to reduce power.
++			 */
++			switch (CODEC_CPU(codec_dai_mode->flags, cpu_dai_mode->flags)) {
++			case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_DIV):
++				/* cpu & codec bfs dividers */
++				rtd->cpu_dai->dai_runtime.bfs =
++					rtd->codec_dai->dai_runtime.bfs =
++					1 << (fls(codec_dai_mode->bfs & cpu_dai_mode->bfs) - 1);
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_RCW):
++				/* normalise bfs codec divider & cpu rcw mult */
++				codec_bfs = soc_bfs_div_to_rcw(codec_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				rtd->cpu_dai->dai_runtime.bfs =
++					1 << (ffs(codec_bfs & cpu_dai_mode->bfs) - 1);
++				cpu_bfs = soc_bfs_rcw_to_div(cpu_dai_mode->bfs, rate, mclk,
++						rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				rtd->codec_dai->dai_runtime.bfs =
++					1 << (fls(codec_dai_mode->bfs & cpu_bfs) - 1);
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_DIV):
++				/* normalise bfs codec rcw mult & cpu divider */
++				codec_bfs = soc_bfs_rcw_to_div(codec_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				rtd->cpu_dai->dai_runtime.bfs =
++					1 << (fls(codec_bfs & cpu_dai_mode->bfs) -1);
++				cpu_bfs = soc_bfs_div_to_rcw(cpu_dai_mode->bfs, rate, mclk,
++						rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				rtd->codec_dai->dai_runtime.bfs =
++					1 << (ffs(codec_dai_mode->bfs & cpu_bfs) -1);
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_RCW):
++				/* codec & cpu bfs rate rcw multipliers */
++				rtd->cpu_dai->dai_runtime.bfs =
++					rtd->codec_dai->dai_runtime.bfs =
++					1 << (ffs(codec_dai_mode->bfs & cpu_dai_mode->bfs) -1);
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_RATE):
++				/* normalise cpu bfs rate const multiplier & codec div */
++				cpu_bfs = soc_bfs_rate_to_div(cpu_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				if(codec_dai_mode->bfs & cpu_bfs) {
++					rtd->codec_dai->dai_runtime.bfs = cpu_bfs;
++					rtd->cpu_dai->dai_runtime.bfs = cpu_dai_mode->bfs;
++				} else
++					rtd->cpu_dai->dai_runtime.bfs = 0;
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_RATE):
++				/* normalise cpu bfs rate const multiplier & codec rcw mult */
++				cpu_bfs = soc_bfs_rate_to_rcw(cpu_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				if(codec_dai_mode->bfs & cpu_bfs) {
++					rtd->codec_dai->dai_runtime.bfs = cpu_bfs;
++					rtd->cpu_dai->dai_runtime.bfs = cpu_dai_mode->bfs;
++				} else
++					rtd->cpu_dai->dai_runtime.bfs = 0;
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_RCW):
++				/* normalise cpu bfs rate rcw multiplier & codec const mult */
++				codec_bfs = soc_bfs_rate_to_rcw(codec_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				if(cpu_dai_mode->bfs & codec_bfs) {
++					rtd->cpu_dai->dai_runtime.bfs = codec_bfs;
++					rtd->codec_dai->dai_runtime.bfs = codec_dai_mode->bfs;
++				} else
++					rtd->cpu_dai->dai_runtime.bfs = 0;
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_DIV):
++				/* normalise cpu bfs div & codec const mult */
++				codec_bfs = soc_bfs_rate_to_div(codec_dai_mode->bfs, rate,
++					mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
++				if(codec_dai_mode->bfs & codec_bfs) {
++					rtd->cpu_dai->dai_runtime.bfs = codec_bfs;
++					rtd->codec_dai->dai_runtime.bfs = codec_dai_mode->bfs;
++				} else
++					rtd->cpu_dai->dai_runtime.bfs = 0;
++				break;
++			case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_RATE):
++				/* cpu & codec constant mult */
++				if(codec_dai_mode->bfs == cpu_dai_mode->bfs)
++					rtd->cpu_dai->dai_runtime.bfs =
++						rtd->codec_dai->dai_runtime.bfs =
++						codec_dai_mode->bfs;
++				else
++					rtd->cpu_dai->dai_runtime.bfs =
++						rtd->codec_dai->dai_runtime.bfs = 0;
++				break;
++			default:
++				if(codec_dai_mode->flags == 0)
++					printk(KERN_ERR "asoc: error missing codec DAI flags\n");
++				else
++					printk(KERN_ERR "asoc: error missing CPU DAI flags\n");
++				break;
++			}
++
++			/* make sure the bit clock speed is acceptable */
++			if (!rtd->cpu_dai->dai_runtime.bfs ||
++				!rtd->codec_dai->dai_runtime.bfs) {
++				dbgc("asoc: DAI[%d:%d] failed to match BFS\n", j, k);
++				dbgc("asoc: cpu_dai %llu codec %llu\n",
++					rtd->cpu_dai->dai_runtime.bfs,
++					rtd->codec_dai->dai_runtime.bfs);
++				dbgc("asoc: mclk %d hwfmt %x\n", mclk, fmt);
++				continue;
++			}
++
++			goto found;
++		}
++	}
++	printk(KERN_ERR "asoc: no matching DAI found between codec and CPU\n");
++	return -EINVAL;
++
++found:
++	/* we have matching DAI's, so complete the runtime info */
++	rtd->codec_dai->dai_runtime.pcmrate =
++		rtd->cpu_dai->dai_runtime.pcmrate =
++		soc_get_rate_format(rate);
++
++	rtd->codec_dai->dai_runtime.priv = codec_dai_mode->priv;
++	rtd->cpu_dai->dai_runtime.priv = cpu_dai_mode->priv;
++	rtd->codec_dai->dai_runtime.flags = codec_dai_mode->flags;
++	rtd->cpu_dai->dai_runtime.flags = cpu_dai_mode->flags;
++
++	/* for debug atm */
++	dbg("asoc: DAI[%d:%d] Match OK\n", j, k);
++	if (rtd->codec_dai->dai_runtime.flags == SND_SOC_DAI_BFS_DIV) {
++		codec_bclk = (rtd->codec_dai->dai_runtime.fs * params_rate(params)) /
++			SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++		dbg("asoc: codec fs %d mclk %d bfs div %d bclk %d\n",
++			rtd->codec_dai->dai_runtime.fs, mclk,
++			SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs),	codec_bclk);
++	} else if(rtd->codec_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RATE) {
++		codec_bclk = params_rate(params) * rtd->codec_dai->dai_runtime.bfs;
++		dbg("asoc: codec fs %d mclk %d bfs rate mult %llu bclk %d\n",
++			rtd->codec_dai->dai_runtime.fs, mclk,
++			rtd->codec_dai->dai_runtime.bfs, codec_bclk);
++	} else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RCW) {
++		codec_bclk = params_rate(params) * params_channels(params) *
++			snd_pcm_format_physical_width(rtd->codec_dai->dai_runtime.pcmfmt) *
++			SND_SOC_FSBW_REAL(rtd->codec_dai->dai_runtime.bfs);
++		dbg("asoc: codec fs %d mclk %d bfs rcw mult %d bclk %d\n",
++			rtd->codec_dai->dai_runtime.fs, mclk,
++			SND_SOC_FSBW_REAL(rtd->codec_dai->dai_runtime.bfs), codec_bclk);
++	} else
++		codec_bclk = 0;
++
++	if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_DIV) {
++		cpu_bclk = (rtd->cpu_dai->dai_runtime.fs * params_rate(params)) /
++			SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
++		dbg("asoc: cpu fs %d mclk %d bfs div %d bclk %d\n",
++			rtd->cpu_dai->dai_runtime.fs, mclk,
++			SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk);
++	} else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RATE) {
++		cpu_bclk = params_rate(params) * rtd->cpu_dai->dai_runtime.bfs;
++		dbg("asoc: cpu fs %d mclk %d bfs rate mult %llu bclk %d\n",
++			rtd->cpu_dai->dai_runtime.fs, mclk,
++			rtd->cpu_dai->dai_runtime.bfs, cpu_bclk);
++	} else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RCW) {
++		cpu_bclk = params_rate(params) * params_channels(params) *
++			snd_pcm_format_physical_width(rtd->cpu_dai->dai_runtime.pcmfmt) *
++			SND_SOC_FSBW_REAL(rtd->cpu_dai->dai_runtime.bfs);
++		dbg("asoc: cpu fs %d mclk %d bfs mult rcw %d bclk %d\n",
++			rtd->cpu_dai->dai_runtime.fs, mclk,
++			SND_SOC_FSBW_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk);
++	} else
++		cpu_bclk = 0;
++
++	/*
++	 * Check we have matching bitclocks. If we don't then it means the
++	 * sysclock returned by either the codec or cpu DAI (selected by the
++	 * machine sysclock function) is wrong compared with the supported DAI
++	 * modes for the codec or cpu DAI.
++	 */
++	if (cpu_bclk != codec_bclk && cpu_bclk){
++		printk(KERN_ERR
++			"asoc: codec and cpu bitclocks differ, audio may be wrong speed\n"
++			);
++		printk(KERN_ERR "asoc: codec %d != cpu %d\n", codec_bclk, cpu_bclk);
++	}
++
++	switch(rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		dbg("asoc: DAI codec BCLK master, LRC master\n");
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		dbg("asoc: DAI codec BCLK slave, LRC master\n");
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		dbg("asoc: DAI codec BCLK master, LRC slave\n");
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		dbg("asoc: DAI codec BCLK slave, LRC slave\n");
++		break;
++	}
++	dbg("asoc: mode %x, invert %x\n",
++		rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK,
++		rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK);
++	dbg("asoc: audio rate %d chn %d fmt %x\n", params_rate(params),
++		params_channels(params), params_format(params));
++
++	return 0;
++}
++
++static inline u32 get_rates(struct snd_soc_dai_mode *modes, int nmodes)
++{
++	int i;
++	u32 rates = 0;
++
++	for(i = 0; i < nmodes; i++)
++		rates |= modes[i].pcmrate;
++
++	return rates;
++}
++
++static inline u64 get_formats(struct snd_soc_dai_mode *modes, int nmodes)
++{
++	int i;
++	u64 formats = 0;
++
++	for(i = 0; i < nmodes; i++)
++		formats |= modes[i].pcmfmt;
++
++	return formats;
++}
++
++/*
++ * Called by ALSA when a PCM substream is opened, the runtime->hw record is
++ * 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)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec_dai *codec_dai = rtd->codec_dai;
++	struct snd_soc_cpu_dai *cpu_dai = rtd->cpu_dai;
++	int ret = 0;
++
++	mutex_lock(&pcm_mutex);
++
++	/* startup the audio subsystem */
++	if (rtd->cpu_dai->ops.startup) {
++		ret = rtd->cpu_dai->ops.startup(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't open interface %s\n",
++				rtd->cpu_dai->name);
++			goto out;
++		}
++	}
++
++	if (platform->pcm_ops->open) {
++		ret = platform->pcm_ops->open(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
++			goto platform_err;
++		}
++	}
++
++	if (machine->ops && machine->ops->startup) {
++		ret = machine->ops->startup(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: %s startup failed\n", machine->name);
++			goto machine_err;
++		}
++	}
++
++	if (rtd->codec_dai->ops.startup) {
++		ret = rtd->codec_dai->ops.startup(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't open codec %s\n",
++				rtd->codec_dai->name);
++			goto codec_dai_err;
++		}
++	}
++
++	/* create runtime params from DMA, codec and cpu DAI */
++	if (runtime->hw.rates)
++		runtime->hw.rates &=
++			get_rates(codec_dai->caps.mode, codec_dai->caps.num_modes) &
++			get_rates(cpu_dai->caps.mode, cpu_dai->caps.num_modes);
++	else
++		runtime->hw.rates =
++			get_rates(codec_dai->caps.mode, codec_dai->caps.num_modes) &
++			get_rates(cpu_dai->caps.mode, cpu_dai->caps.num_modes);
++	if (runtime->hw.formats)
++		runtime->hw.formats &=
++			get_formats(codec_dai->caps.mode, codec_dai->caps.num_modes) &
++			get_formats(cpu_dai->caps.mode, cpu_dai->caps.num_modes);
++	else
++		runtime->hw.formats =
++			get_formats(codec_dai->caps.mode, codec_dai->caps.num_modes) &
++			get_formats(cpu_dai->caps.mode, cpu_dai->caps.num_modes);
++
++	/* Check that the codec and cpu DAI's are compatible */
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		runtime->hw.rate_min =
++			max(rtd->codec_dai->playback.rate_min,
++				rtd->cpu_dai->playback.rate_min);
++		runtime->hw.rate_max =
++			min(rtd->codec_dai->playback.rate_max,
++				rtd->cpu_dai->playback.rate_max);
++		runtime->hw.channels_min =
++			max(rtd->codec_dai->playback.channels_min,
++				rtd->cpu_dai->playback.channels_min);
++		runtime->hw.channels_max =
++			min(rtd->codec_dai->playback.channels_max,
++				rtd->cpu_dai->playback.channels_max);
++	} else {
++		runtime->hw.rate_min =
++			max(rtd->codec_dai->capture.rate_min,
++				rtd->cpu_dai->capture.rate_min);
++		runtime->hw.rate_max =
++			min(rtd->codec_dai->capture.rate_max,
++				rtd->cpu_dai->capture.rate_max);
++		runtime->hw.channels_min =
++			max(rtd->codec_dai->capture.channels_min,
++				rtd->cpu_dai->capture.channels_min);
++		runtime->hw.channels_max =
++			min(rtd->codec_dai->capture.channels_max,
++				rtd->cpu_dai->capture.channels_max);
++	}
++
++	snd_pcm_limit_hw_rates(runtime);
++	if (!runtime->hw.rates) {
++		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
++			rtd->codec_dai->name, rtd->cpu_dai->name);
++		goto codec_dai_err;
++	}
++	if (!runtime->hw.formats) {
++		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
++			rtd->codec_dai->name, rtd->cpu_dai->name);
++		goto codec_dai_err;
++	}
++	if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
++		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
++			rtd->codec_dai->name, rtd->cpu_dai->name);
++		goto codec_dai_err;
++	}
++
++	dbg("asoc: %s <-> %s info:\n", rtd->codec_dai->name, rtd->cpu_dai->name);
++	dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
++	dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
++		runtime->hw.channels_max);
++	dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
++		runtime->hw.rate_max);
++
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		rtd->cpu_dai->playback.active = rtd->codec_dai->playback.active = 1;
++	else
++		rtd->cpu_dai->capture.active = rtd->codec_dai->capture.active = 1;
++	rtd->cpu_dai->active = rtd->codec_dai->active = 1;
++	rtd->cpu_dai->runtime = runtime;
++	socdev->codec->active++;
++	mutex_unlock(&pcm_mutex);
++	return 0;
++
++codec_dai_err:
++	if (machine->ops && machine->ops->shutdown)
++		machine->ops->shutdown(substream);
++
++machine_err:
++	if (platform->pcm_ops->close)
++		platform->pcm_ops->close(substream);
++
++platform_err:
++	if (rtd->cpu_dai->ops.shutdown)
++		rtd->cpu_dai->ops.shutdown(substream);
++out:
++	mutex_unlock(&pcm_mutex);
++	return ret;
++}
++
++/*
++ * Power down the audio subsytem pmdown_time msecs after close is called.
++ * This is to ensure there are no pops or clicks in between any music tracks
++ * due to DAPM power cycling.
++ */
++static void close_delayed_work(void *data)
++{
++	struct snd_soc_device *socdev = data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *codec_dai;
++	int i;
++
++	mutex_lock(&pcm_mutex);
++	for(i = 0; i < codec->num_dai; i++) {
++		codec_dai = &codec->dai[i];
++
++		dbg("pop wq checking: %s status: %s waiting: %s\n",
++			codec_dai->playback.stream_name,
++			codec_dai->playback.active ? "active" : "inactive",
++			codec_dai->pop_wait ? "yes" : "no");
++
++		/* are we waiting on this codec DAI stream */
++		if (codec_dai->pop_wait == 1) {
++
++			codec_dai->pop_wait = 0;
++			snd_soc_dapm_stream_event(codec, codec_dai->playback.stream_name,
++				SND_SOC_DAPM_STREAM_STOP);
++
++			/* power down the codec power domain if no longer active */
++			if (codec->active == 0) {
++				dbg("pop wq D3 %s %s\n", codec->name,
++					codec_dai->playback.stream_name);
++		 		if (codec->dapm_event)
++					codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++			}
++		}
++	}
++	mutex_unlock(&pcm_mutex);
++}
++
++/*
++ * Called by ALSA when a PCM substream is closed. Private data can be
++ * freed here. The cpu DAI, codec DAI, machine and platform are also
++ * shutdown.
++ */
++static int soc_codec_close(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec *codec = socdev->codec;
++
++	mutex_lock(&pcm_mutex);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		rtd->cpu_dai->playback.active = rtd->codec_dai->playback.active = 0;
++	else
++		rtd->cpu_dai->capture.active = rtd->codec_dai->capture.active = 0;
++
++	if (rtd->codec_dai->playback.active == 0 &&
++		rtd->codec_dai->capture.active == 0) {
++		rtd->cpu_dai->active = rtd->codec_dai->active = 0;
++	}
++	codec->active--;
++
++	if (rtd->cpu_dai->ops.shutdown)
++		rtd->cpu_dai->ops.shutdown(substream);
++
++	if (rtd->codec_dai->ops.shutdown)
++		rtd->codec_dai->ops.shutdown(substream);
++
++	if (machine->ops && machine->ops->shutdown)
++		machine->ops->shutdown(substream);
++
++	if (platform->pcm_ops->close)
++		platform->pcm_ops->close(substream);
++	rtd->cpu_dai->runtime = NULL;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		/* start delayed pop wq here for playback streams */
++		rtd->codec_dai->pop_wait = 1;
++		queue_delayed_work(soc_workq, &soc_stream_work,
++			msecs_to_jiffies(pmdown_time));
++	} else {
++		/* capture streams can be powered down now */
++		snd_soc_dapm_stream_event(codec, rtd->codec_dai->capture.stream_name,
++			SND_SOC_DAPM_STREAM_STOP);
++
++		if (codec->active == 0 && rtd->codec_dai->pop_wait == 0){
++			if (codec->dapm_event)
++				codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++		}
++	}
++
++	mutex_unlock(&pcm_mutex);
++	return 0;
++}
++
++/*
++ * Called by ALSA when the PCM substream is prepared, can set format, sample
++ * 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)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	mutex_lock(&pcm_mutex);
++	if (platform->pcm_ops->prepare) {
++		ret = platform->pcm_ops->prepare(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: platform prepare error\n");
++			goto out;
++		}
++	}
++
++	if (rtd->codec_dai->ops.prepare) {
++		ret = rtd->codec_dai->ops.prepare(substream);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: codec DAI prepare error\n");
++			goto out;
++		}
++	}
++
++	if (rtd->cpu_dai->ops.prepare)
++		ret = rtd->cpu_dai->ops.prepare(substream);
++
++	/* we only want to start a DAPM playback stream if we are not waiting
++	 * on an existing one stopping */
++	if (rtd->codec_dai->pop_wait) {
++		/* we are waiting for the delayed work to start */
++		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
++				snd_soc_dapm_stream_event(codec,
++					rtd->codec_dai->capture.stream_name,
++					SND_SOC_DAPM_STREAM_START);
++		else {
++			rtd->codec_dai->pop_wait = 0;
++			cancel_delayed_work(&soc_stream_work);
++			if (rtd->codec_dai->digital_mute)
++				rtd->codec_dai->digital_mute(codec, rtd->codec_dai, 0);
++		}
++	} else {
++		/* no delayed work - do we need to power up codec */
++		if (codec->dapm_state != SNDRV_CTL_POWER_D0) {
++
++			if (codec->dapm_event)
++				codec->dapm_event(codec, SNDRV_CTL_POWER_D1);
++
++			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++				snd_soc_dapm_stream_event(codec,
++					rtd->codec_dai->playback.stream_name,
++					SND_SOC_DAPM_STREAM_START);
++			else
++				snd_soc_dapm_stream_event(codec,
++					rtd->codec_dai->capture.stream_name,
++					SND_SOC_DAPM_STREAM_START);
++
++			if (codec->dapm_event)
++				codec->dapm_event(codec, SNDRV_CTL_POWER_D0);
++			if (rtd->codec_dai->digital_mute)
++				rtd->codec_dai->digital_mute(codec, rtd->codec_dai, 0);
++
++		} else {
++			/* codec already powered - power on widgets */
++			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++				snd_soc_dapm_stream_event(codec,
++					rtd->codec_dai->playback.stream_name,
++					SND_SOC_DAPM_STREAM_START);
++			else
++				snd_soc_dapm_stream_event(codec,
++					rtd->codec_dai->capture.stream_name,
++					SND_SOC_DAPM_STREAM_START);
++			if (rtd->codec_dai->digital_mute)
++				rtd->codec_dai->digital_mute(codec, rtd->codec_dai, 0);
++		}
++	}
++
++out:
++	mutex_unlock(&pcm_mutex);
++	return ret;
++}
++
++/*
++ * 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 soc_pcm_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_device *socdev = rtd->socdev;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_machine *machine = socdev->machine;
++	int ret = 0;
++
++	mutex_lock(&pcm_mutex);
++
++	/* we don't need to match any AC97 params */
++	if (rtd->cpu_dai->type != SND_SOC_DAI_AC97) {
++		ret = soc_hw_match_params(substream, params);
++		if (ret < 0)
++			goto out;
++	} else {
++		struct snd_soc_clock_info clk_info;
++		clk_info.rate = params_rate(params);
++		ret = soc_get_mclk(rtd, &clk_info);
++		if (ret < 0)
++			goto out;
++	}
++
++	if (rtd->codec_dai->ops.hw_params) {
++		ret = rtd->codec_dai->ops.hw_params(substream, params);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
++				rtd->codec_dai->name);
++			goto out;
++		}
++	}
++
++	if (rtd->cpu_dai->ops.hw_params) {
++		ret = rtd->cpu_dai->ops.hw_params(substream, params);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't set interface %s hw params\n",
++				rtd->cpu_dai->name);
++			goto interface_err;
++		}
++	}
++
++	if (platform->pcm_ops->hw_params) {
++		ret = platform->pcm_ops->hw_params(substream, params);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't set platform %s hw params\n",
++				platform->name);
++			goto platform_err;
++		}
++	}
++
++	if (machine->ops && machine->ops->hw_params) {
++		ret = machine->ops->hw_params(substream, params);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: machine hw_params failed\n");
++			goto machine_err;
++		}
++	}
++
++out:
++	mutex_unlock(&pcm_mutex);
++	return ret;
++
++machine_err:
++	if (platform->pcm_ops->hw_free)
++		platform->pcm_ops->hw_free(substream);
++
++platform_err:
++	if (rtd->cpu_dai->ops.hw_free)
++		rtd->cpu_dai->ops.hw_free(substream);
++
++interface_err:
++	if (rtd->codec_dai->ops.hw_free)
++		rtd->codec_dai->ops.hw_free(substream);
++
++	mutex_unlock(&pcm_mutex);
++	return ret;
++}
++
++/*
++ * Free's resources allocated by hw_params, can be called multiple times
++ */
++static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_machine *machine = socdev->machine;
++
++	mutex_lock(&pcm_mutex);
++
++	/* apply codec digital mute */
++	if (!codec->active && rtd->codec_dai->digital_mute)
++		rtd->codec_dai->digital_mute(codec, rtd->codec_dai, 1);
++
++	/* free any machine hw params */
++	if (machine->ops && machine->ops->hw_free)
++		machine->ops->hw_free(substream);
++
++	/* free any DMA resources */
++	if (platform->pcm_ops->hw_free)
++		platform->pcm_ops->hw_free(substream);
++
++	/* now free hw params for the DAI's  */
++	if (rtd->codec_dai->ops.hw_free)
++		rtd->codec_dai->ops.hw_free(substream);
++
++	if (rtd->cpu_dai->ops.hw_free)
++		rtd->cpu_dai->ops.hw_free(substream);
++
++	mutex_unlock(&pcm_mutex);
++	return 0;
++}
++
++static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_platform *platform = socdev->platform;
++	int ret;
++
++	if (rtd->codec_dai->ops.trigger) {
++		ret = rtd->codec_dai->ops.trigger(substream, cmd);
++		if (ret < 0)
++			return ret;
++	}
++
++	if (platform->pcm_ops->trigger) {
++		ret = platform->pcm_ops->trigger(substream, cmd);
++		if (ret < 0)
++			return ret;
++	}
++
++	if (rtd->cpu_dai->ops.trigger) {
++		ret = rtd->cpu_dai->ops.trigger(substream, cmd);
++		if (ret < 0)
++			return ret;
++	}
++	return 0;
++}
++
++/* 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,
++};
++
++#ifdef CONFIG_PM
++/* powers down audio subsystem for suspend */
++static int soc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ 	struct snd_soc_machine *machine = socdev->machine;
++ 	struct snd_soc_platform *platform = socdev->platform;
++ 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++
++	/* mute any active DAC's */
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
++		if (dai->digital_mute && dai->playback.active)
++			dai->digital_mute(codec, dai, 1);
++	}
++
++	if (machine->suspend_pre)
++		machine->suspend_pre(pdev, state);
++
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai  *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
++			cpu_dai->suspend(pdev, cpu_dai);
++		if (platform->suspend)
++			platform->suspend(pdev, cpu_dai);
++	}
++
++	/* close any waiting streams and save state */
++	flush_workqueue(soc_workq);
++	codec->suspend_dapm_state = codec->dapm_state;
++
++	for(i = 0; i < codec->num_dai; i++) {
++		char *stream = codec->dai[i].playback.stream_name;
++		if (stream != NULL)
++			snd_soc_dapm_stream_event(codec, stream,
++				SND_SOC_DAPM_STREAM_SUSPEND);
++		stream = codec->dai[i].capture.stream_name;
++		if (stream != NULL)
++			snd_soc_dapm_stream_event(codec, stream,
++				SND_SOC_DAPM_STREAM_SUSPEND);
++	}
++
++	if (codec_dev->suspend)
++		codec_dev->suspend(pdev, state);
++
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
++			cpu_dai->suspend(pdev, cpu_dai);
++	}
++
++	if (machine->suspend_post)
++		machine->suspend_post(pdev, state);
++
++	return 0;
++}
++
++/* powers up audio subsystem after a suspend */
++static int soc_resume(struct platform_device *pdev)
++{
++ 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ 	struct snd_soc_machine *machine = socdev->machine;
++ 	struct snd_soc_platform *platform = socdev->platform;
++ 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++
++	if (machine->resume_pre)
++		machine->resume_pre(pdev);
++
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
++			cpu_dai->resume(pdev, cpu_dai);
++	}
++
++	if (codec_dev->resume)
++		codec_dev->resume(pdev);
++
++	for(i = 0; i < codec->num_dai; i++) {
++		char* stream = codec->dai[i].playback.stream_name;
++		if (stream != NULL)
++			snd_soc_dapm_stream_event(codec, stream,
++				SND_SOC_DAPM_STREAM_RESUME);
++		stream = codec->dai[i].capture.stream_name;
++		if (stream != NULL)
++			snd_soc_dapm_stream_event(codec, stream,
++				SND_SOC_DAPM_STREAM_RESUME);
++	}
++
++	/* unmute any active DAC's */
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
++		if (dai->digital_mute && dai->playback.active)
++			dai->digital_mute(codec, dai, 0);
++	}
++
++	for(i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
++			cpu_dai->resume(pdev, cpu_dai);
++		if (platform->resume)
++			platform->resume(pdev, cpu_dai);
++	}
++
++	if (machine->resume_post)
++		machine->resume_post(pdev);
++
++	return 0;
++}
++
++#else
++#define soc_suspend	NULL
++#define soc_resume	NULL
++#endif
++
++/* probes a new socdev */
++static int soc_probe(struct platform_device *pdev)
++{
++	int ret = 0, i;
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
++
++	if (machine->probe) {
++		ret = machine->probe(pdev);
++		if(ret < 0)
++			return ret;
++	}
++
++	for (i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->probe) {
++			ret = cpu_dai->probe(pdev);
++			if(ret < 0)
++				goto cpu_dai_err;
++		}
++	}
++
++	if (codec_dev->probe) {
++		ret = codec_dev->probe(pdev);
++		if(ret < 0)
++			goto cpu_dai_err;
++	}
++
++	if (platform->probe) {
++		ret = platform->probe(pdev);
++		if(ret < 0)
++			goto platform_err;
++	}
++
++	/* DAPM stream work */
++	soc_workq = create_workqueue("kdapm");
++	if (soc_workq == NULL)
++		goto work_err;
++	INIT_WORK(&soc_stream_work, close_delayed_work, socdev);
++	return 0;
++
++work_err:
++	if (platform->remove)
++		platform->remove(pdev);
++
++platform_err:
++	if (codec_dev->remove)
++		codec_dev->remove(pdev);
++
++cpu_dai_err:
++	for (i--; i > 0; i--) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->remove)
++			cpu_dai->remove(pdev);
++	}
++
++	if (machine->remove)
++		machine->remove(pdev);
++
++	return ret;
++}
++
++/* removes a socdev */
++static int soc_remove(struct platform_device *pdev)
++{
++	int i;
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_platform *platform = socdev->platform;
++	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
++
++	if (soc_workq)
++		destroy_workqueue(soc_workq);
++
++	if (platform->remove)
++		platform->remove(pdev);
++
++	if (codec_dev->remove)
++		codec_dev->remove(pdev);
++
++	for (i = 0; i < machine->num_links; i++) {
++		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
++		if (cpu_dai->remove)
++			cpu_dai->remove(pdev);
++	}
++
++	if (machine->remove)
++		machine->remove(pdev);
++
++	return 0;
++}
++
++/* ASoC platform driver */
++static struct platform_driver soc_driver = {
++	.driver		= {
++		.name		= "soc-audio",
++	},
++	.probe		= soc_probe,
++	.remove		= soc_remove,
++	.suspend	= soc_suspend,
++	.resume		= soc_resume,
++};
++
++/* create a new pcm */
++static int soc_new_pcm(struct snd_soc_device *socdev,
++	struct snd_soc_dai_link *dai_link, int num)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai;
++	struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai;
++	struct snd_soc_pcm_runtime *rtd;
++	struct snd_pcm *pcm;
++	char new_name[64];
++	int ret = 0, playback = 0, capture = 0;
++
++	rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
++	if (rtd == NULL)
++		return -ENOMEM;
++	rtd->cpu_dai = cpu_dai;
++	rtd->codec_dai = codec_dai;
++	rtd->socdev = socdev;
++
++	/* check client and interface hw capabilities */
++	sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name,
++		get_dai_name(cpu_dai->type), num);
++
++	if (codec_dai->playback.channels_min)
++		playback = 1;
++	if (codec_dai->capture.channels_min)
++		capture = 1;
++
++	ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
++		capture, &pcm);
++	if (ret < 0) {
++		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
++		kfree(rtd);
++		return ret;
++	}
++
++	pcm->private_data = rtd;
++	soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
++	soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
++	soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
++	soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
++	soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
++	soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
++	soc_pcm_ops.page = socdev->platform->pcm_ops->page;
++
++	if (playback)
++		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
++
++	if (capture)
++		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
++
++	ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
++	if (ret < 0) {
++		printk(KERN_ERR "asoc: platform pcm constructor failed\n");
++		kfree(rtd);
++		return ret;
++	}
++
++	pcm->private_free = socdev->platform->pcm_free;
++	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
++		cpu_dai->name);
++	return ret;
++}
++
++/* codec register dump */
++static ssize_t codec_reg_show(struct device *dev,
++	struct device_attribute *attr, char *buf)
++{
++	struct snd_soc_device *devdata = dev_get_drvdata(dev);
++	struct snd_soc_codec *codec = devdata->codec;
++	int i, step = 1, count = 0;
++
++	if (!codec->reg_cache_size)
++		return 0;
++
++	if (codec->reg_cache_step)
++		step = codec->reg_cache_step;
++
++	count += sprintf(buf, "%s registers\n", codec->name);
++	for(i = 0; i < codec->reg_cache_size; i += step)
++		count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i));
++
++	return count;
++}
++static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
++
++/**
++ * snd_soc_new_ac97_codec - initailise AC97 device
++ * @codec: audio codec
++ * @ops: AC97 bus operations
++ * @num: AC97 codec number
++ *
++ * Initialises AC97 codec resources for use by ad-hoc devices only.
++ */
++int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
++	struct snd_ac97_bus_ops *ops, int num)
++{
++	mutex_lock(&codec->mutex);
++
++	codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
++	if (codec->ac97 == NULL) {
++		mutex_unlock(&codec->mutex);
++		return -ENOMEM;
++	}
++
++	codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL);
++	if (codec->ac97->bus == NULL) {
++		kfree(codec->ac97);
++		codec->ac97 = NULL;
++		mutex_unlock(&codec->mutex);
++		return -ENOMEM;
++	}
++
++	codec->ac97->bus->ops = ops;
++	codec->ac97->num = num;
++	mutex_unlock(&codec->mutex);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
++
++/**
++ * snd_soc_free_ac97_codec - free AC97 codec device
++ * @codec: audio codec
++ *
++ * Frees AC97 codec device resources.
++ */
++void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
++{
++	mutex_lock(&codec->mutex);
++	kfree(codec->ac97->bus);
++	kfree(codec->ac97);
++	codec->ac97 = NULL;
++	mutex_unlock(&codec->mutex);
++}
++EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
++
++/**
++ * snd_soc_update_bits - update codec register bits
++ * @codec: audio codec
++ * @reg: codec register
++ * @mask: register mask
++ * @value: new value
++ *
++ * Writes new register value.
++ *
++ * Returns 1 for change else 0.
++ */
++int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
++				unsigned short mask, unsigned short value)
++{
++	int change;
++	unsigned short old, new;
++
++	mutex_lock(&io_mutex);
++	old = snd_soc_read(codec, reg);
++	new = (old & ~mask) | value;
++	change = old != new;
++	if (change)
++		snd_soc_write(codec, reg, new);
++
++	mutex_unlock(&io_mutex);
++	return change;
++}
++EXPORT_SYMBOL_GPL(snd_soc_update_bits);
++
++/**
++ * snd_soc_test_bits - test register for change
++ * @codec: audio codec
++ * @reg: codec register
++ * @mask: register mask
++ * @value: new value
++ *
++ * Tests a register with a new value and checks if the new value is
++ * different from the old value.
++ *
++ * Returns 1 for change else 0.
++ */
++int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
++				unsigned short mask, unsigned short value)
++{
++	int change;
++	unsigned short old, new;
++
++	mutex_lock(&io_mutex);
++	old = snd_soc_read(codec, reg);
++	new = (old & ~mask) | value;
++	change = old != new;
++	mutex_unlock(&io_mutex);
++
++	return change;
++}
++EXPORT_SYMBOL_GPL(snd_soc_test_bits);
++
++/**
++ * snd_soc_get_rate - get int sample rate
++ * @hwpcmrate: the hardware pcm rate
++ *
++ * Returns the audio rate integaer value, else 0.
++ */
++int snd_soc_get_rate(int hwpcmrate)
++{
++	int rate = ffs(hwpcmrate) - 1;
++
++	if (rate > ARRAY_SIZE(rates))
++		return 0;
++	return rates[rate];
++}
++EXPORT_SYMBOL_GPL(snd_soc_get_rate);
++
++/**
++ * snd_soc_new_pcms - create new sound card and pcms
++ * @socdev: the SoC audio device
++ *
++ * Create a new sound card based upon the codec and interface pcms.
++ *
++ * Returns 0 for success, else error.
++ */
++int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char * xid)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_machine *machine = socdev->machine;
++	int ret = 0, i;
++
++	mutex_lock(&codec->mutex);
++
++	/* register a sound card */
++	codec->card = snd_card_new(idx, xid, codec->owner, 0);
++	if (!codec->card) {
++		printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
++			codec->name);
++		mutex_unlock(&codec->mutex);
++		return -ENODEV;
++	}
++
++	codec->card->dev = socdev->dev;
++	codec->card->private_data = codec;
++	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
++
++	/* create the pcms */
++	for(i = 0; i < machine->num_links; i++) {
++		ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: can't create pcm %s\n",
++				machine->dai_link[i].stream_name);
++			mutex_unlock(&codec->mutex);
++			return ret;
++		}
++	}
++
++	mutex_unlock(&codec->mutex);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
++
++/**
++ * snd_soc_register_card - register sound card
++ * @socdev: the SoC audio device
++ *
++ * Register a SoC sound card. Also registers an AC97 device if the
++ * codec is AC97 for ad hoc devices.
++ *
++ * Returns 0 for success, else error.
++ */
++int snd_soc_register_card(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_machine *machine = socdev->machine;
++	int ret = 0, i, ac97 = 0, err = 0;
++
++	mutex_lock(&codec->mutex);
++	for(i = 0; i < machine->num_links; i++) {
++		if (socdev->machine->dai_link[i].init) {
++			err = socdev->machine->dai_link[i].init(codec);
++			if (err < 0) {
++				printk(KERN_ERR "asoc: failed to init %s\n",
++					socdev->machine->dai_link[i].stream_name);
++				continue;
++			}
++		}
++		if (socdev->machine->dai_link[i].cpu_dai->type == SND_SOC_DAI_AC97)
++			ac97 = 1;
++	}
++	snprintf(codec->card->shortname, sizeof(codec->card->shortname),
++		 "%s", machine->name);
++	snprintf(codec->card->longname, sizeof(codec->card->longname),
++		 "%s (%s)", machine->name, codec->name);
++
++	ret = snd_card_register(codec->card);
++	if (ret < 0) {
++		printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",
++				codec->name);
++		goto out;
++	}
++
++#ifdef CONFIG_SND_SOC_AC97_BUS
++	if (ac97) {
++		ret = soc_ac97_dev_register(codec);
++		if (ret < 0) {
++			printk(KERN_ERR "asoc: AC97 device register failed\n");
++			snd_card_free(codec->card);
++			goto out;
++		}
++	}
++#endif
++
++	err = snd_soc_dapm_sys_add(socdev->dev);
++	if (err < 0)
++		printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
++
++	err = device_create_file(socdev->dev, &dev_attr_codec_reg);
++	if (err < 0)
++		printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");
++out:
++	mutex_unlock(&codec->mutex);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(snd_soc_register_card);
++
++/**
++ * snd_soc_free_pcms - free sound card and pcms
++ * @socdev: the SoC audio device
++ *
++ * Frees sound card and pcms associated with the socdev.
++ * Also unregister the codec if it is an AC97 device.
++ */
++void snd_soc_free_pcms(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++
++	mutex_lock(&codec->mutex);
++#ifdef CONFIG_SND_SOC_AC97_BUS
++	if (codec->ac97)
++		soc_ac97_dev_unregister(codec);
++#endif
++
++	if (codec->card)
++		snd_card_free(codec->card);
++	device_remove_file(socdev->dev, &dev_attr_codec_reg);
++	mutex_unlock(&codec->mutex);
++}
++EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
++
++/**
++ * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
++ * @substream: the pcm substream
++ * @hw: the hardware parameters
++ *
++ * Sets the substream runtime hardware parameters.
++ */
++int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
++	const struct snd_pcm_hardware *hw)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	runtime->hw.info = hw->info;
++	runtime->hw.formats = hw->formats;
++	runtime->hw.period_bytes_min = hw->period_bytes_min;
++	runtime->hw.period_bytes_max = hw->period_bytes_max;
++	runtime->hw.periods_min = hw->periods_min;
++	runtime->hw.periods_max = hw->periods_max;
++	runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
++	runtime->hw.fifo_size = hw->fifo_size;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
++
++/**
++ * snd_soc_cnew - create new control
++ * @_template: control template
++ * @data: control private data
++ * @lnng_name: control long name
++ *
++ * Create a new mixer control from a template control.
++ *
++ * Returns 0 for success, else error.
++ */
++struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
++	void *data, char *long_name)
++{
++	struct snd_kcontrol_new template;
++
++	memcpy(&template, _template, sizeof(template));
++	if (long_name)
++		template.name = long_name;
++	template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
++	template.index = 0;
++
++	return snd_ctl_new1(&template, data);
++}
++EXPORT_SYMBOL_GPL(snd_soc_cnew);
++
++/**
++ * snd_soc_info_enum_double - enumerated double mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about a double enumerated
++ * mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_enum_double(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 = e->shift_l == e->shift_r ? 1 : 2;
++	uinfo->value.enumerated.items = e->mask;
++
++	if (uinfo->value.enumerated.item > e->mask - 1)
++		uinfo->value.enumerated.item = e->mask - 1;
++	strcpy(uinfo->value.enumerated.name,
++		e->texts[uinfo->value.enumerated.item]);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
++
++/**
++ * snd_soc_get_enum_double - enumerated double mixer get callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to get the value of a double enumerated mixer.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
++	unsigned short val, bitmask;
++
++	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
++		;
++	val = snd_soc_read(codec, e->reg);
++	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
++	if (e->shift_l != e->shift_r)
++		ucontrol->value.enumerated.item[1] =
++			(val >> e->shift_r) & (bitmask - 1);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
++
++/**
++ * snd_soc_put_enum_double - enumerated double mixer put callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to set the value of a double enumerated mixer.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
++	unsigned short val;
++	unsigned short mask, bitmask;
++
++	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
++		;
++	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
++		return -EINVAL;
++	val = ucontrol->value.enumerated.item[0] << e->shift_l;
++	mask = (bitmask - 1) << e->shift_l;
++	if (e->shift_l != e->shift_r) {
++		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
++			return -EINVAL;
++		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
++		mask |= (bitmask - 1) << e->shift_r;
++	}
++
++	return snd_soc_update_bits(codec, e->reg, mask, val);
++}
++EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
++
++/**
++ * snd_soc_info_enum_ext - external enumerated single mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about an external enumerated
++ * single mixer.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_enum_ext(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->mask;
++
++	if (uinfo->value.enumerated.item > e->mask - 1)
++		uinfo->value.enumerated.item = e->mask - 1;
++	strcpy(uinfo->value.enumerated.name,
++		e->texts[uinfo->value.enumerated.item]);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
++
++/**
++ * snd_soc_info_volsw_ext - external single mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about a single external mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo)
++{
++	int mask = kcontrol->private_value;
++
++	uinfo->type =
++		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = mask;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
++
++/**
++ * snd_soc_info_bool_ext - external single boolean mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about a single boolean external mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_bool_ext);
++
++/**
++ * snd_soc_info_volsw - single mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about a single mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo)
++{
++	int mask = (kcontrol->private_value >> 16) & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int rshift = (kcontrol->private_value >> 12) & 0x0f;
++
++	uinfo->type =
++		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->count = shift == rshift ? 1 : 2;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = mask;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
++
++/**
++ * snd_soc_get_volsw - single mixer get callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to get the value of a single mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int rshift = (kcontrol->private_value >> 12) & 0x0f;
++	int mask = (kcontrol->private_value >> 16) & 0xff;
++	int invert = (kcontrol->private_value >> 24) & 0x01;
++
++	ucontrol->value.integer.value[0] =
++		(snd_soc_read(codec, reg) >> shift) & mask;
++	if (shift != rshift)
++		ucontrol->value.integer.value[1] =
++			(snd_soc_read(codec, reg) >> rshift) & mask;
++	if (invert) {
++		ucontrol->value.integer.value[0] =
++			mask - ucontrol->value.integer.value[0];
++		if (shift != rshift)
++			ucontrol->value.integer.value[1] =
++				mask - ucontrol->value.integer.value[1];
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
++
++/**
++ * snd_soc_put_volsw - single mixer put callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to set the value of a single mixer control.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int rshift = (kcontrol->private_value >> 12) & 0x0f;
++	int mask = (kcontrol->private_value >> 16) & 0xff;
++	int invert = (kcontrol->private_value >> 24) & 0x01;
++	int err;
++	unsigned short val, val2, val_mask;
++
++	val = (ucontrol->value.integer.value[0] & mask);
++	if (invert)
++		val = mask - val;
++	val_mask = mask << shift;
++	val = val << shift;
++	if (shift != rshift) {
++		val2 = (ucontrol->value.integer.value[1] & mask);
++		if (invert)
++			val2 = mask - val2;
++		val_mask |= mask << rshift;
++		val |= val2 << rshift;
++	}
++	err = snd_soc_update_bits(codec, reg, val_mask, val);
++	return err;
++}
++EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
++
++/**
++ * snd_soc_info_volsw_2r - double mixer info callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to provide information about a double mixer control that
++ * spans 2 codec registers.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_info *uinfo)
++{
++	int mask = (kcontrol->private_value >> 12) & 0xff;
++
++	uinfo->type =
++		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->count = 2;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = mask;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
++
++/**
++ * snd_soc_get_volsw_2r - double mixer get callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to get the value of a double mixer control that spans 2 registers.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int reg2 = (kcontrol->private_value >> 24) & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int mask = (kcontrol->private_value >> 12) & 0xff;
++	int invert = (kcontrol->private_value >> 20) & 0x01;
++
++	ucontrol->value.integer.value[0] =
++		(snd_soc_read(codec, reg) >> shift) & mask;
++	ucontrol->value.integer.value[1] =
++		(snd_soc_read(codec, reg2) >> shift) & mask;
++	if (invert) {
++		ucontrol->value.integer.value[0] =
++			mask - ucontrol->value.integer.value[0];
++		ucontrol->value.integer.value[1] =
++			mask - ucontrol->value.integer.value[1];
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
++
++/**
++ * snd_soc_put_volsw_2r - double mixer set callback
++ * @kcontrol: mixer control
++ * @uinfo: control element information
++ *
++ * Callback to set the value of a double mixer control that spans 2 registers.
++ *
++ * Returns 0 for success.
++ */
++int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
++	struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++	int reg = kcontrol->private_value & 0xff;
++	int reg2 = (kcontrol->private_value >> 24) & 0xff;
++	int shift = (kcontrol->private_value >> 8) & 0x0f;
++	int mask = (kcontrol->private_value >> 12) & 0xff;
++	int invert = (kcontrol->private_value >> 20) & 0x01;
++	int err;
++	unsigned short val, val2, val_mask;
++
++	val_mask = mask << shift;
++	val = (ucontrol->value.integer.value[0] & mask);
++	val2 = (ucontrol->value.integer.value[1] & mask);
++
++	if (invert) {
++		val = mask - val;
++		val2 = mask - val2;
++	}
++
++	val = val << shift;
++	val2 = val2 << shift;
++
++	if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)
++		return err;
++
++	err = snd_soc_update_bits(codec, reg2, val_mask, val2);
++	return err;
++}
++EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
++
++static int __devinit snd_soc_init(void)
++{
++	printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
++	return platform_driver_register(&soc_driver);
++}
++
++static void snd_soc_exit(void)
++{
++ 	platform_driver_unregister(&soc_driver);
++}
++
++module_init(snd_soc_init);
++module_exit(snd_soc_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("ALSA SoC Core");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/at91/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/Kconfig
+@@ -0,0 +1,24 @@
++menu "SoC Audio for the Atmel AT91"
++
++config SND_AT91_SOC
++	tristate "SoC Audio for the Atmel AT91 System-on-Chip"
++	depends on ARCH_AT91 && SND
++	select SND_PCM
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the AT91 SSC interface. You will also need
++	  to select the audio interfaces to support below.
++
++config SND_AT91_SOC_I2S
++	tristate
++
++config SND_AT91_SOC_ETI_B1_WM8731
++	tristate "SoC I2S Audio support for Endrelia ETI-B1 board"
++	depends on SND_AT91_SOC && MACH_ETI_B1
++	select SND_AT91_SOC_I2S
++	select SND_SOC_WM8731
++	help
++	  Say Y if you want to add support for SoC audio on Endrelia
++          ETI-B1 board.
++
++endmenu
+Index: linux-2.6-pxa-new/sound/soc/at91/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/Makefile
+@@ -0,0 +1,11 @@
++# AT91 Platform Support
++snd-soc-at91-objs := at91rm9200-pcm.o
++snd-soc-at91-i2s-objs := at91rm9200-i2s.o
++
++obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
++obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o
++
++# AT91 Machine Support
++snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
++
++obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
+Index: linux-2.6-pxa-new/sound/soc/at91/at91rm9200-i2s.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/at91rm9200-i2s.c
+@@ -0,0 +1,715 @@
++/*
++ * at91rm9200-i2s.c  --  ALSA Soc Audio Layer Platform driver and DMA engine
++ *
++ * Author: Frank Mandarino <fmandarino at endrelia.com>
++ *         Endrelia Technologies Inc.
++ *
++ * Based on pxa2xx Platform drivers by
++ * Liam Girdwood <liam.girdwood at wolfsonmicro.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.
++ *
++ *  Revision history
++ *     3rd Mar 2006   Initial version.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/arch/at91rm9200.h>
++#include <asm/arch/at91rm9200_ssc.h>
++#include <asm/arch/at91rm9200_pdc.h>
++#include <asm/arch/hardware.h>
++
++#include "at91rm9200-pcm.h"
++
++#if 0
++#define	DBG(x...)	printk(KERN_DEBUG "at91rm9200-i2s:" x)
++#else
++#define	DBG(x...)
++#endif
++
++#define AT91RM9200_I2S_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF)
++
++#define AT91RM9200_I2S_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++/* priv is (SSC_CMR.DIV << 16 | SSC_TCMR.PERIOD ) */
++static struct snd_soc_dai_mode at91rm9200_i2s[] = {
++
++	/* 8k: BCLK = (MCLK/10) = (60MHz/50) = 1.2MHz */
++	{
++		.fmt = AT91RM9200_I2S_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = AT91RM9200_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = SND_SOC_FSBD(10),
++		.priv = (25 << 16 | 74),
++	},
++
++	/* 16k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */
++	{
++		.fmt = AT91RM9200_I2S_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_16000,
++		.pcmdir = AT91RM9200_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 750,
++		.bfs = SND_SOC_FSBD(3),
++		.priv = (7 << 16 | 133),
++	},
++
++	/* 32k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */
++	{
++		.fmt = AT91RM9200_I2S_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = AT91RM9200_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 375,
++		.bfs = SND_SOC_FSBD(3),
++		.priv = (7 << 16 | 66),
++	},
++
++	/* 48k: BCLK = (MCLK/5) ~= (60MHz/26) = 2.3076923MHz */
++	{
++		.fmt = AT91RM9200_I2S_DAIFMT,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = AT91RM9200_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs SND_SOC_FSBD(5),
++		.priv = (13 << 16 | 23),
++	},
++};
++
++
++/*
++ * SSC registers required by the PCM DMA engine.
++ */
++static struct at91rm9200_ssc_regs ssc_reg[3] = {
++	{
++	.cr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_CR),
++	.ier	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_IER),
++	.idr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_IDR),
++	},
++	{
++	.cr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_CR),
++	.ier	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_IER),
++	.idr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_IDR),
++	},
++	{
++	.cr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_CR),
++	.ier	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_IER),
++	.idr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_IDR),
++	},
++};
++
++static struct at91rm9200_pdc_regs pdc_tx_reg[3] = {
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_PTCR),
++	},
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_PTCR),
++	},
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_PTCR),
++	},
++};
++
++static struct at91rm9200_pdc_regs pdc_rx_reg[3] = {
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_PTCR),
++	},
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_PTCR),
++	},
++	{
++	.xpr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RPR),
++	.xcr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RCR),
++	.xnpr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RNPR),
++	.xncr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RNCR),
++	.ptcr	= (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_PTCR),
++	},
++};
++
++/*
++ * SSC & PDC status bits for transmit and receive.
++ */
++static struct at91rm9200_ssc_mask ssc_tx_mask = {
++	.ssc_enable	= AT91_SSC_TXEN,
++	.ssc_disable	= AT91_SSC_TXDIS,
++	.ssc_endx	= AT91_SSC_ENDTX,
++	.ssc_endbuf	= AT91_SSC_TXBUFE,
++	.pdc_enable	= AT91_PDC_TXTEN,
++	.pdc_disable	= AT91_PDC_TXTDIS,
++};
++
++static struct at91rm9200_ssc_mask ssc_rx_mask = {
++	.ssc_enable	= AT91_SSC_RXEN,
++	.ssc_disable	= AT91_SSC_RXDIS,
++	.ssc_endx	= AT91_SSC_ENDRX,
++	.ssc_endbuf	= AT91_SSC_RXBUFF,
++	.pdc_enable	= AT91_PDC_RXTEN,
++	.pdc_disable	= AT91_PDC_RXTDIS,
++};
++
++/*
++ * A MUTEX is used to protect an SSC initialzed flag which allows
++ * the substream hw_params() call to initialize the SSC only if
++ * there are no other substreams open.  If there are other
++ * substreams open, the hw_param() call can only check that
++ * it is using the same format and rate.
++ */
++static DECLARE_MUTEX(ssc0_mutex);
++static DECLARE_MUTEX(ssc1_mutex);
++static DECLARE_MUTEX(ssc2_mutex);
++
++/*
++ * DMA parameters.
++ */
++static at91rm9200_pcm_dma_params_t ssc_dma_params[3][2] = {
++	{{
++	.name		= "SSC0/I2S PCM Stereo out",
++	.ssc		= &ssc_reg[0],
++	.pdc		= &pdc_tx_reg[0],
++	.mask		= &ssc_tx_mask,
++	},
++	{
++	.name		= "SSC0/I2S PCM Stereo in",
++	.ssc		= &ssc_reg[0],
++	.pdc		= &pdc_rx_reg[0],
++	.mask		= &ssc_rx_mask,
++	}},
++	{{
++	.name		= "SSC1/I2S PCM Stereo out",
++	.ssc		= &ssc_reg[1],
++	.pdc		= &pdc_tx_reg[1],
++	.mask		= &ssc_tx_mask,
++	},
++	{
++	.name		= "SSC1/I2S PCM Stereo in",
++	.ssc		= &ssc_reg[1],
++	.pdc		= &pdc_rx_reg[1],
++	.mask		= &ssc_rx_mask,
++	}},
++	{{
++	.name		= "SSC2/I2S PCM Stereo out",
++	.ssc		= &ssc_reg[2],
++	.pdc		= &pdc_tx_reg[2],
++	.mask		= &ssc_tx_mask,
++	},
++	{
++	.name		= "SSC1/I2S PCM Stereo in",
++	.ssc		= &ssc_reg[2],
++	.pdc		= &pdc_rx_reg[2],
++	.mask		= &ssc_rx_mask,
++	}},
++};
++
++
++struct at91rm9200_ssc_state {
++	u32	ssc_cmr;
++	u32	ssc_rcmr;
++	u32	ssc_rfmr;
++	u32	ssc_tcmr;
++	u32	ssc_tfmr;
++	u32	ssc_sr;
++	u32	ssc_imr;
++};
++
++static struct at91rm9200_ssc_info {
++	char		*name;
++	void __iomem    *ssc_base;
++	u32		pid;
++	spinlock_t 	lock;		/* lock for dir_mask */
++	int		dir_mask;	/* 0=unused, 1=playback, 2=capture */
++	struct semaphore *mutex;
++	int		initialized;
++	int		pcmfmt;
++	int		rate;
++	at91rm9200_pcm_dma_params_t *dma_params[2];
++	struct at91rm9200_ssc_state ssc_state;
++
++} ssc_info[3] = {
++	{
++	.name		= "ssc0",
++	.ssc_base	= (void __iomem *) AT91_VA_BASE_SSC0,
++	.pid		= AT91_ID_SSC0,
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.dir_mask	= 0,
++	.mutex		= &ssc0_mutex,
++	.initialized	= 0,
++	},
++	{
++	.name		= "ssc1",
++	.ssc_base	= (void __iomem *) AT91_VA_BASE_SSC1,
++	.pid		= AT91_ID_SSC1,
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.dir_mask	= 0,
++	.mutex		= &ssc1_mutex,
++	.initialized	= 0,
++	},
++	{
++	.name		= "ssc2",
++	.ssc_base	= (void __iomem *) AT91_VA_BASE_SSC2,
++	.pid		= AT91_ID_SSC2,
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.dir_mask	= 0,
++	.mutex		= &ssc2_mutex,
++	.initialized	= 0,
++	},
++};
++
++
++static irqreturn_t at91rm9200_i2s_interrupt(int irq, void *dev_id)
++{
++	struct at91rm9200_ssc_info *ssc_p = dev_id;
++	at91rm9200_pcm_dma_params_t *dma_params;
++	u32 ssc_sr;
++	int i;
++
++	ssc_sr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR)
++			& at91_ssc_read(ssc_p->ssc_base + AT91_SSC_IMR);
++
++	/*
++	 * Loop through the substreams attached to this SSC.  If
++	 * a DMA-related interrupt occurred on that substream, call
++	 * the DMA interrupt handler function, if one has been
++	 * registered in the dma_params structure by the PCM driver.
++	 */
++	for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
++		dma_params = ssc_p->dma_params[i];
++
++		if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
++			(ssc_sr &
++			(dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
++
++			dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
++	}
++
++	return IRQ_HANDLED;
++}
++
++static int at91rm9200_i2s_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct at91rm9200_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id];
++	int dir_mask;
++
++	DBG("i2s_startup: SSC_SR=0x%08lx\n",
++			at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR));
++	dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
++
++	spin_lock_irq(&ssc_p->lock);
++	if (ssc_p->dir_mask & dir_mask) {
++		spin_unlock_irq(&ssc_p->lock);
++		return -EBUSY;
++	}
++	ssc_p->dir_mask |= dir_mask;
++	spin_unlock_irq(&ssc_p->lock);
++
++	return 0;
++}
++
++static void at91rm9200_i2s_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct at91rm9200_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id];
++	at91rm9200_pcm_dma_params_t *dma_params = rtd->cpu_dai->dma_data;
++	int dir, dir_mask;
++
++	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
++
++	if (dma_params != NULL) {
++		at91_ssc_write(dma_params->ssc->cr, dma_params->mask->ssc_disable);
++		DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
++			at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR));
++
++		dma_params->substream = NULL;
++		ssc_p->dma_params[dir] = NULL;
++	}
++
++	dir_mask = 1 << dir;
++
++	spin_lock_irq(&ssc_p->lock);
++	ssc_p->dir_mask &= ~dir_mask;
++	if (!ssc_p->dir_mask) {
++		/* Shutdown the SSC clock. */
++		DBG("Stopping pid %d clock\n", ssc_p->pid);
++		at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->pid);
++
++		if (ssc_p->initialized)
++			free_irq(ssc_p->pid, ssc_p);
++
++		/* Reset the SSC */
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR, AT91_SSC_SWRST);
++
++		/* Force a re-init on the next hw_params() call. */
++		ssc_p->initialized = 0;
++	}
++	spin_unlock_irq(&ssc_p->lock);
++}
++
++#ifdef CONFIG_PM
++static int at91rm9200_i2s_suspend(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	struct at91rm9200_ssc_info *ssc_p;
++
++	if(!dai->active)
++		return 0;
++
++	ssc_p = &ssc_info[dai->id];
++
++	/* Save the status register before disabling transmit and receive. */
++	ssc_p->state->ssc_sr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR);
++	at91_ssc_write(ssc_p->ssc_base +
++		AT91_SSC_CR, AT91_SSC_TXDIS | AT91_SSC_RXDIS);
++
++	/* Save the current interrupt mask, then disable unmasked interrupts. */
++	ssc_p->state->ssc_imr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_IMR);
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_IDR, ssc_p->state->ssc_imr);
++
++	ssc_p->state->ssc_cmr  = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_CMR);
++	ssc_p->state->ssc_rcmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR);
++	ssc_p->state->ssc_rfmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR);
++	ssc_p->state->ssc_tcmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR);
++	ssc_p->state->ssc_tfmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR);
++
++	return 0;
++}
++
++static int at91rm9200_i2s_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	struct at91rm9200_ssc_info *ssc_p;
++	u32 cr_mask;
++
++	if(!dai->active)
++		return 0;
++
++	ssc_p = &ssc_info[dai->id];
++
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_tfmr);
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_tcmr);
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_rfmr);
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_rcmr);
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CMR,  ssc_p->state->ssc_cmr);
++
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_IER,  ssc_p->state->ssc_imr);
++
++	at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR,
++		((ssc_p->state->ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
++		((ssc_p->state->ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
++
++	return 0;
++}
++
++#else
++#define at91rm9200_i2s_suspend	NULL
++#define at91rm9200_i2s_resume	NULL
++#endif
++
++static unsigned int at91rm9200_i2s_config_sysclk(
++	struct snd_soc_cpu_dai *iface, struct snd_soc_clock_info *info,
++	unsigned int clk)
++{
++	/* Currently, there is only support for USB (12Mhz) mode */
++	if (clk != 12000000)
++		return 0;
++	return 12000000;
++}
++
++static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int id = rtd->cpu_dai->id;
++	struct at91rm9200_ssc_info *ssc_p = &ssc_info[id];
++	at91rm9200_pcm_dma_params_t *dma_params;
++	unsigned int pcmfmt, rate;
++	int dir, channels, bits;
++	struct clk *mck_clk;
++	unsigned long bclk;
++	u32 div, period, tfmr, rfmr, tcmr, rcmr;
++	int ret;
++
++	/*
++	 * Currently, there is only one set of dma params for
++	 * each direction.  If more are added, this code will
++	 * have to be changed to select the proper set.
++	 */
++	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
++
++	dma_params = &ssc_dma_params[id][dir];
++	dma_params->substream = substream;
++
++	ssc_p->dma_params[dir] = dma_params;
++	rtd->cpu_dai->dma_data = dma_params;
++
++	rate = params_rate(params);
++	channels = params_channels(params);
++
++	pcmfmt = rtd->cpu_dai->dai_runtime.pcmfmt;
++	switch (pcmfmt) {
++		case SNDRV_PCM_FMTBIT_S16_LE:
++			/* likely this is all we'll ever support, but ... */
++			bits = 16;
++			dma_params->pdc_xfer_size = 2;
++			break;
++		default:
++			printk(KERN_WARNING "at91rm9200-i2s: unsupported format %x\n",
++				pcmfmt);
++			return -EINVAL;
++	}
++
++	/* Don't allow both SSC substreams to initialize at the same time. */
++	down(ssc_p->mutex);
++
++	/*
++	 * If this SSC is alreadly initialized, then this substream must use
++	 * the same format and rate.
++	 */
++	if (ssc_p->initialized) {
++		if (pcmfmt != ssc_p->pcmfmt || rate != ssc_p->rate) {
++			printk(KERN_WARNING "at91rm9200-i2s: "
++				"incompatible substream in other direction\n");
++			up(ssc_p->mutex);
++			return -EINVAL;
++		}
++	} else {
++		/* Enable PMC peripheral clock for this SSC */
++		DBG("Starting pid %d clock\n", ssc_p->pid);
++		at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->pid);
++
++		/* Reset the SSC */
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR, AT91_SSC_SWRST);
++
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RPR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RCR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RNPR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RNCR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TPR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TCR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TNPR, 0);
++		at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TNCR, 0);
++
++		mck_clk = clk_get(NULL, "mck");
++
++		div = rtd->cpu_dai->dai_runtime.priv >> 16;
++		period = rtd->cpu_dai->dai_runtime.priv & 0xffff;
++		bclk = 60000000 / (2 * div);
++
++		DBG("mck %ld fsbd %d bfs %d bfs_real %d bclk %ld div %d period %d\n",
++			clk_get_rate(mck_clk),
++			SND_SOC_FSBD(6),
++			rtd->cpu_dai->dai_runtime.bfs,
++			SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs),
++			bclk,
++			div,
++			period);
++
++		clk_put(mck_clk);
++
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CMR, div);
++
++		/*
++		 * Setup the TFMR and RFMR for the proper data format.
++		 */
++		tfmr =
++		  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
++		| (( 0				<< 23) & AT91_SSC_FSDEN)
++		| (( AT91_SSC_FSOS_NEGATIVE	     ) & AT91_SSC_FSOS)
++		| (((bits - 1)			<< 16) & AT91_SSC_FSLEN)
++		| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
++		| (( 1				<<  7) & AT91_SSC_MSBF)
++		| (( 0				<<  5) & AT91_SSC_DATDEF)
++		| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
++		DBG("SSC_TFMR=0x%08x\n", tfmr);
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_TFMR, tfmr);
++
++		rfmr =
++		  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
++		| (( AT91_SSC_FSOS_NONE		     ) & AT91_SSC_FSOS)
++		| (( 0				<< 16) & AT91_SSC_FSLEN)
++		| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
++		| (( 1				<<  7) & AT91_SSC_MSBF)
++		| (( 0				<<  5) & AT91_SSC_LOOP)
++		| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
++
++		DBG("SSC_RFMR=0x%08x\n", rfmr);
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RFMR, rfmr);
++
++		/*
++		 * Setup the TCMR and RCMR to generate the proper BCLK
++		 * and LRC signals.
++		 */
++		tcmr =
++		  (( period			<< 24) & AT91_SSC_PERIOD)
++		| (( 1				<< 16) & AT91_SSC_STTDLY)
++		| (( AT91_SSC_START_FALLING_RF       ) & AT91_SSC_START)
++		| (( AT91_SSC_CKI_FALLING	     ) & AT91_SSC_CKI)
++		| (( AT91_SSC_CKO_CONTINUOUS	     ) & AT91_SSC_CKO)
++		| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
++
++		DBG("SSC_TCMR=0x%08x\n", tcmr);
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_TCMR, tcmr);
++
++		rcmr =
++		  (( 0				<< 24) & AT91_SSC_PERIOD)
++		| (( 1				<< 16) & AT91_SSC_STTDLY)
++		| (( AT91_SSC_START_TX_RX	     ) & AT91_SSC_START)
++		| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
++		| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
++		| (( AT91_SSC_CKS_CLOCK		     ) & AT91_SSC_CKS);
++
++		DBG("SSC_RCMR=0x%08x\n", rcmr);
++		at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, rcmr);
++
++		if ((ret = request_irq(ssc_p->pid, at91rm9200_i2s_interrupt,
++					0, ssc_p->name, ssc_p)) < 0) {
++			printk(KERN_WARNING "at91rm9200-i2s: request_irq failure\n");
++			return ret;
++		}
++
++		/*
++		 * Save the current substream parameters in order to check
++		 * that the substream in the opposite direction uses the
++		 * same parameters.
++		 */
++		ssc_p->pcmfmt = pcmfmt;
++		ssc_p->rate = rate;
++		ssc_p->initialized = 1;
++
++		DBG("hw_params: SSC initialized\n");
++	}
++
++	up(ssc_p->mutex);
++
++	return 0;
++}
++
++
++static int at91rm9200_i2s_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	at91rm9200_pcm_dma_params_t *dma_params = rtd->cpu_dai->dma_data;
++
++	at91_ssc_write(dma_params->ssc->cr, dma_params->mask->ssc_enable);
++
++	DBG("%s enabled SSC_SR=0x%08lx\n",
++	substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "transmit" : "receive",
++	at91_ssc_read(ssc_info[rtd->cpu_dai->id].ssc_base + AT91_SSC_SR));
++	return 0;
++}
++
++
++struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = {
++	{	.name = "at91rm9200-ssc0/i2s",
++		.id = 0,
++		.type = SND_SOC_DAI_I2S,
++		.suspend = at91rm9200_i2s_suspend,
++		.resume = at91rm9200_i2s_resume,
++		.config_sysclk = at91rm9200_i2s_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = at91rm9200_i2s_startup,
++			.shutdown = at91rm9200_i2s_shutdown,
++			.prepare = at91rm9200_i2s_prepare,
++			.hw_params = at91rm9200_i2s_hw_params,},
++		.caps = {
++			.mode = &at91rm9200_i2s[0],
++			.num_modes = ARRAY_SIZE(at91rm9200_i2s),},
++	},
++	{	.name = "at91rm9200-ssc1/i2s",
++		.id = 1,
++		.type = SND_SOC_DAI_I2S,
++		.suspend = at91rm9200_i2s_suspend,
++		.resume = at91rm9200_i2s_resume,
++		.config_sysclk = at91rm9200_i2s_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = at91rm9200_i2s_startup,
++			.shutdown = at91rm9200_i2s_shutdown,
++			.prepare = at91rm9200_i2s_prepare,
++			.hw_params = at91rm9200_i2s_hw_params,},
++		.caps = {
++			.mode = &at91rm9200_i2s[0],
++			.num_modes = ARRAY_SIZE(at91rm9200_i2s),},
++	},
++	{	.name = "at91rm9200-ssc2/i2s",
++		.id = 2,
++		.type = SND_SOC_DAI_I2S,
++		.suspend = at91rm9200_i2s_suspend,
++		.resume = at91rm9200_i2s_resume,
++		.config_sysclk = at91rm9200_i2s_config_sysclk,
++		.playback = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.capture = {
++			.channels_min = 1,
++			.channels_max = 2,},
++		.ops = {
++			.startup = at91rm9200_i2s_startup,
++			.shutdown = at91rm9200_i2s_shutdown,
++			.prepare = at91rm9200_i2s_prepare,
++			.hw_params = at91rm9200_i2s_hw_params,},
++		.caps = {
++			.mode = &at91rm9200_i2s[0],
++			.num_modes = ARRAY_SIZE(at91rm9200_i2s),},
++	},
++};
++
++EXPORT_SYMBOL_GPL(at91rm9200_i2s_dai);
++
++/* Module information */
++MODULE_AUTHOR("Frank Mandarino, fmandarino at endrelia.com, www.endrelia.com");
++MODULE_DESCRIPTION("AT91RM9200 I2S ASoC Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/at91/at91rm9200-pcm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/at91rm9200-pcm.c
+@@ -0,0 +1,428 @@
++/*
++ * at91rm9200-pcm.c -- ALSA PCM interface for the Atmel AT91RM9200 chip.
++ *
++ * Author:	Frank Mandarino <fmandarino at endrelia.com>
++ *		Endrelia Technologies Inc.
++ * Created:	Mar 3, 2006
++ *
++ * Based on pxa2xx-pcm.c by:
++ *
++ * Author:	Nicolas Pitre
++ * Created:	Nov 30, 2004
++ * Copyright:	(C) 2004 MontaVista Software, 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/arch/at91rm9200.h>
++#include <asm/arch/at91rm9200_ssc.h>
++#include <asm/arch/at91rm9200_pdc.h>
++#include <asm/arch/hardware.h>
++
++#include "at91rm9200-pcm.h"
++
++#if 0
++#define	DBG(x...)	printk(KERN_INFO "at91rm9200-pcm: " x)
++#else
++#define	DBG(x...)
++#endif
++
++static const snd_pcm_hardware_t at91rm9200_pcm_hardware = {
++	.info			= SNDRV_PCM_INFO_MMAP |
++				  SNDRV_PCM_INFO_MMAP_VALID |
++				  SNDRV_PCM_INFO_INTERLEAVED |
++				  SNDRV_PCM_INFO_PAUSE,
++	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
++	.period_bytes_min	= 32,
++	.period_bytes_max	= 8192,
++	.periods_min		= 2,
++	.periods_max		= 1024,
++	.buffer_bytes_max	= 32 * 1024,
++};
++
++struct at91rm9200_runtime_data {
++	at91rm9200_pcm_dma_params_t *params;
++	dma_addr_t dma_buffer;			/* physical address of dma buffer */
++	dma_addr_t dma_buffer_end;		/* first address beyond DMA buffer */
++	size_t period_size;
++	dma_addr_t period_ptr;			/* physical address of next period */
++	u32 pdc_xpr_save;			/* PDC register save */
++	u32 pdc_xcr_save;
++	u32 pdc_xnpr_save;
++	u32 pdc_xncr_save;
++};
++
++static void at91rm9200_pcm_dma_irq(u32 ssc_sr,
++	struct snd_pcm_substream *substream)
++{
++	struct at91rm9200_runtime_data *prtd = substream->runtime->private_data;
++	at91rm9200_pcm_dma_params_t *params = prtd->params;
++	static int count = 0;
++
++	count++;
++
++	if (ssc_sr & params->mask->ssc_endbuf) {
++
++		printk(KERN_WARNING
++			"at91rm9200-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
++			substream->stream == SNDRV_PCM_STREAM_PLAYBACK
++				? "underrun" : "overrun",
++			params->name, ssc_sr, count);
++
++		/* re-start the PDC */
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable);
++
++		prtd->period_ptr += prtd->period_size;
++		if (prtd->period_ptr >= prtd->dma_buffer_end) {
++			prtd->period_ptr = prtd->dma_buffer;
++		}
++
++		at91_ssc_write(params->pdc->xpr, prtd->period_ptr);
++		at91_ssc_write(params->pdc->xcr,
++				prtd->period_size / params->pdc_xfer_size);
++
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable);
++	}
++
++	if (ssc_sr & params->mask->ssc_endx) {
++
++		/* Load the PDC next pointer and counter registers */
++		prtd->period_ptr += prtd->period_size;
++		if (prtd->period_ptr >= prtd->dma_buffer_end) {
++			prtd->period_ptr = prtd->dma_buffer;
++		}
++		at91_ssc_write(params->pdc->xnpr, prtd->period_ptr);
++		at91_ssc_write(params->pdc->xncr,
++				prtd->period_size / params->pdc_xfer_size);
++	}
++
++	snd_pcm_period_elapsed(substream);
++}
++
++static int at91rm9200_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	snd_pcm_runtime_t *runtime = substream->runtime;
++	struct at91rm9200_runtime_data *prtd = runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	/* this may get called several times by oss emulation
++	 * with different params */
++
++	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
++	runtime->dma_bytes = params_buffer_bytes(params);
++
++	prtd->params = rtd->cpu_dai->dma_data;
++	prtd->params->dma_intr_handler = at91rm9200_pcm_dma_irq;
++
++	prtd->dma_buffer = runtime->dma_addr;
++	prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
++	prtd->period_size = params_period_bytes(params);
++
++	DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
++		prtd->params->name, runtime->dma_bytes, prtd->period_size);
++	return 0;
++}
++
++static int at91rm9200_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	struct at91rm9200_runtime_data *prtd = substream->runtime->private_data;
++	at91rm9200_pcm_dma_params_t *params = prtd->params;
++
++	if (params != NULL) {
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable);
++		prtd->params->dma_intr_handler = NULL;
++	}
++
++	return 0;
++}
++
++static int at91rm9200_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct at91rm9200_runtime_data *prtd = substream->runtime->private_data;
++	at91rm9200_pcm_dma_params_t *params = prtd->params;
++
++	at91_ssc_write(params->ssc->idr,
++			params->mask->ssc_endx | params->mask->ssc_endbuf);
++
++	at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable);
++	return 0;
++}
++
++static int at91rm9200_pcm_trigger(struct snd_pcm_substream *substream,
++	int cmd)
++{
++	struct at91rm9200_runtime_data *prtd = substream->runtime->private_data;
++	at91rm9200_pcm_dma_params_t *params = prtd->params;
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		prtd->period_ptr = prtd->dma_buffer;
++
++		at91_ssc_write(params->pdc->xpr, prtd->period_ptr);
++		at91_ssc_write(params->pdc->xcr,
++				prtd->period_size / params->pdc_xfer_size);
++
++		prtd->period_ptr += prtd->period_size;
++		at91_ssc_write(params->pdc->xnpr, prtd->period_ptr);
++		at91_ssc_write(params->pdc->xncr,
++				prtd->period_size / params->pdc_xfer_size);
++
++		DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
++			(unsigned long) prtd->period_ptr,
++			at91_ssc_read(params->pdc->xpr),
++			at91_ssc_read(params->pdc->xcr),
++			at91_ssc_read(params->pdc->xnpr),
++			at91_ssc_read(params->pdc->xncr));
++
++		at91_ssc_write(params->ssc->ier,
++			params->mask->ssc_endx | params->mask->ssc_endbuf);
++
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable);
++
++		DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc->ier - 4),
++					at91_ssc_read(params->ssc->ier + 8));
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable);
++		break;
++
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable);
++		break;
++
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t at91rm9200_pcm_pointer(
++	struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct at91rm9200_runtime_data *prtd = runtime->private_data;
++	at91rm9200_pcm_dma_params_t *params = prtd->params;
++	dma_addr_t ptr;
++	snd_pcm_uframes_t x;
++
++	ptr = (dma_addr_t) at91_ssc_read(params->pdc->xpr);
++	x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
++
++	if (x == runtime->buffer_size)
++		x = 0;
++	return x;
++}
++
++static int at91rm9200_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct at91rm9200_runtime_data *prtd;
++	int ret = 0;
++
++	snd_soc_set_runtime_hwparams(substream, &at91rm9200_pcm_hardware);
++
++	/* ensure that buffer size is a multiple of period size */
++	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
++	if (ret < 0)
++		goto out;
++
++	prtd = kzalloc(sizeof(struct at91rm9200_runtime_data), GFP_KERNEL);
++	if (prtd == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	runtime->private_data = prtd;
++
++ out:
++	return ret;
++}
++
++static int at91rm9200_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct at91rm9200_runtime_data *prtd = substream->runtime->private_data;
++
++	kfree(prtd);
++	return 0;
++}
++
++static int at91rm9200_pcm_mmap(struct snd_pcm_substream *substream,
++	struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++				     runtime->dma_area,
++				     runtime->dma_addr,
++				     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops at91rm9200_pcm_ops = {
++	.open		= at91rm9200_pcm_open,
++	.close		= at91rm9200_pcm_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= at91rm9200_pcm_hw_params,
++	.hw_free	= at91rm9200_pcm_hw_free,
++	.prepare	= at91rm9200_pcm_prepare,
++	.trigger	= at91rm9200_pcm_trigger,
++	.pointer	= at91rm9200_pcm_pointer,
++	.mmap		= at91rm9200_pcm_mmap,
++};
++
++static int at91rm9200_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
++	int stream)
++{
++	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
++	struct snd_dma_buffer *buf = &substream->dma_buffer;
++	size_t size = at91rm9200_pcm_hardware.buffer_bytes_max;
++
++	buf->dev.type = SNDRV_DMA_TYPE_DEV;
++	buf->dev.dev = pcm->card->dev;
++	buf->private_data = NULL;
++	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
++					   &buf->addr, GFP_KERNEL);
++
++	DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
++		(void *) buf->area,
++		(void *) buf->addr,
++		size);
++
++	if (!buf->area)
++		return -ENOMEM;
++
++	buf->bytes = size;
++	return 0;
++}
++
++static u64 at91rm9200_pcm_dmamask = 0xffffffff;
++
++static int at91rm9200_pcm_new(struct snd_card *card,
++	struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
++{
++	int ret = 0;
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &at91rm9200_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = 0xffffffff;
++
++	if (dai->playback.channels_min) {
++		ret = at91rm9200_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			goto out;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = at91rm9200_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			goto out;
++	}
++ out:
++	return ret;
++}
++
++static void at91rm9200_pcm_free_dma_buffers(struct snd_pcm *pcm)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_dma_buffer *buf;
++	int stream;
++
++	for (stream = 0; stream < 2; stream++) {
++		substream = pcm->streams[stream].substream;
++		if (!substream)
++			continue;
++
++		buf = &substream->dma_buffer;
++		if (!buf->area)
++			continue;
++
++		dma_free_writecombine(pcm->card->dev, buf->bytes,
++				      buf->area, buf->addr);
++		buf->area = NULL;
++	}
++}
++
++static int at91rm9200_pcm_suspend(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	struct snd_pcm_runtime *runtime = dai->runtime;
++	struct at91rm9200_runtime_data *prtd;
++	at91rm9200_pcm_dma_params_t *params;
++
++	if (!runtime)
++		return 0;
++
++	prtd = runtime->private_data;
++	params = prtd->params;
++
++	/* disable the PDC and save the PDC registers */
++
++	at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable);
++
++	prtd->pdc_xpr_save  = at91_ssc_read(params->pdc->xpr);
++	prtd->pdc_xcr_save  = at91_ssc_read(params->pdc->xcr);
++	prtd->pdc_xnpr_save = at91_ssc_read(params->pdc->xnpr);
++	prtd->pdc_xncr_save = at91_ssc_read(params->pdc->xncr);
++
++	return 0;
++}
++
++static int at91rm9200_pcm_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	struct snd_pcm_runtime *runtime = dai->runtime;
++	struct at91rm9200_runtime_data *prtd;
++	at91rm9200_pcm_dma_params_t *params;
++
++	if (!runtime)
++		return 0;
++
++	prtd = runtime->private_data;
++	params = prtd->params;
++
++	/* restore the PDC registers and enable the PDC */
++	at91_ssc_write(params->pdc->xpr,  prtd->pdc_xpr_save);
++	at91_ssc_write(params->pdc->xcr,  prtd->pdc_xcr_save);
++	at91_ssc_write(params->pdc->xnpr, prtd->pdc_xnpr_save);
++	at91_ssc_write(params->pdc->xncr, prtd->pdc_xncr_save);
++
++	at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable);
++	return 0;
++}
++
++struct snd_soc_platform at91rm9200_soc_platform = {
++	.name		= "at91rm9200-audio",
++	.pcm_ops 	= &at91rm9200_pcm_ops,
++	.pcm_new	= at91rm9200_pcm_new,
++	.pcm_free	= at91rm9200_pcm_free_dma_buffers,
++	.suspend	= at91rm9200_pcm_suspend,
++	.resume		= at91rm9200_pcm_resume,
++};
++
++EXPORT_SYMBOL_GPL(at91rm9200_soc_platform);
++
++MODULE_AUTHOR("Frank Mandarino <fmandarino at endrelia.com>");
++MODULE_DESCRIPTION("Atmel AT91RM9200 PCM module");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/at91/at91rm9200-pcm.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/at91rm9200-pcm.h
+@@ -0,0 +1,75 @@
++/*
++ * at91rm9200-pcm.h - ALSA PCM interface for the Atmel AT91RM9200 chip
++ *
++ * Author:	Frank Mandarino <fmandarino at endrelia.com>
++ *		Endrelia Technologies Inc.
++ * Created:	Mar 3, 2006
++ *
++ * Based on pxa2xx-pcm.h by:
++ *
++ * Author:	Nicolas Pitre
++ * Created:	Nov 30, 2004
++ * Copyright:	MontaVista Software, 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.
++ */
++
++/*
++ * Registers and status bits that are required by the PCM driver.
++ */
++struct at91rm9200_ssc_regs {
++	void __iomem 	*cr;		/* SSC control */
++	void __iomem	*ier;		/* SSC interrupt enable */
++	void __iomem	*idr;		/* SSC interrupt disable */
++};
++
++struct at91rm9200_pdc_regs {
++	void __iomem	*xpr;		/* PDC recv/trans pointer */
++	void __iomem	*xcr;		/* PDC recv/trans counter */
++	void __iomem	*xnpr;		/* PDC next recv/trans pointer */
++	void __iomem	*xncr;		/* PDC next recv/trans counter */
++	void __iomem	*ptcr;		/* PDC transfer control */
++};
++
++struct at91rm9200_ssc_mask {
++	u32	ssc_enable;		/* SSC recv/trans enable */
++	u32	ssc_disable;		/* SSC recv/trans disable */
++	u32	ssc_endx;		/* SSC ENDTX or ENDRX */
++	u32	ssc_endbuf;		/* SSC TXBUFE or RXBUFF */
++	u32	pdc_enable;		/* PDC recv/trans enable */
++	u32	pdc_disable;		/* PDC recv/trans disable */
++};
++
++
++/*
++ * This structure, shared between the PCM driver and the interface,
++ * contains all information required by the PCM driver to perform the
++ * PDC DMA operation.  All fields except dma_intr_handler() are initialized
++ * by the interface.  The dms_intr_handler() pointer is set by the PCM
++ * driver and called by the interface SSC interrupt handler if it is
++ * non-NULL.
++ */
++typedef struct {
++	char *name;			/* stream identifier */
++	int pdc_xfer_size;		/* PDC counter increment in bytes */
++	struct at91rm9200_ssc_regs *ssc; /* SSC register addresses */
++	struct at91rm9200_pdc_regs *pdc; /* PDC receive/transmit registers */
++	struct at91rm9200_ssc_mask *mask;/* SSC & PDC status bits */
++	snd_pcm_substream_t *substream;
++	void (*dma_intr_handler)(u32, snd_pcm_substream_t *);
++} at91rm9200_pcm_dma_params_t;
++
++extern struct snd_soc_cpu_dai at91rm9200_i2s_dai[3];
++extern struct snd_soc_platform at91rm9200_soc_platform;
++
++
++/*
++ * SSC I/O helpers.
++ * E.g., at91_ssc_write(AT91_SSC(1) + AT91_SSC_CR, AT91_SSC_RXEN);
++ */
++#define AT91_SSC(x) (((x)==0) ? AT91_VA_BASE_SSC0 :\
++	 ((x)==1) ? AT91_VA_BASE_SSC1 : ((x)==2) ? AT91_VA_BASE_SSC2 : NULL)
++#define at91_ssc_read(a)	((unsigned long) __raw_readl(a))
++#define at91_ssc_write(a,v)	__raw_writel((v),(a))
+Index: linux-2.6-pxa-new/sound/soc/imx/imx-ssi.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx-ssi.c
+@@ -0,0 +1,452 @@
++/*
++ * imx-ssi.c  --  SSI driver for Freescale IMX
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Based on mxc-alsa-mc13783 (C) 2006 Freescale.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    29th Aug 2006   Initial version.
++ *
++ */
++
++#define IMX_DSP_DAIFMT \
++	( SND_SOC_DAIFMT_DSP__A |SND_SOC_DAIFMT_DSP_B  | \
++	SND_SOC_DAIFMT_CBS_CFS |SND_SOC_DAIFMT_CBM_CFS | \
++	SND_SOC_DAIFMT_CBS_CFM |SND_SOC_DAIFMT_NB_NF |\
++	SND_SOC_DAIFMT_NB_IF)
++
++#define IMX_DSP_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define IMX_DSP_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 | SNDRV_PCM_RATE_88200 | \
++	SNDRV_PCM_RATE_96000)
++
++#define IMX_DSP_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE)
++
++static struct snd_soc_dai_mode imx_dsp_pcm_modes[] = {
++
++	/* frame master and clock slave mode */
++	{IMX_DSP_DAIFMT | SND_SOC_DAIFMT_CBM_CFS,
++		SND_SOC_DAITDM_LRDW(0,0), IMX_DSP_BITS, IMX_DSP_RATES,
++		 IMX_DSP_DIR, 0, SND_SOC_FS_ALL,
++		 SND_SOC_FSB(32) | SND_SOC_FSB(32) | SND_SOC_FSB(16)},
++
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_out = {
++	.name			= "SSI1 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = emi_2_per,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_STX0,
++		.event_id = DMA_REQ_SSI1_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_in = {
++	.name			= "SSI1 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_SRX0,
++		.event_id = DMA_REQ_SSI1_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_out = {
++	.name			= "SSI2 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_STX0,
++		.event_id = DMA_REQ_SSI2_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_in = {
++	.name			= "SSI2 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_SRX0,
++		.event_id = DMA_REQ_SSI2_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static int imx_dsp_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (!rtd->cpu_dai->active) {
++
++	}
++
++	return 0;
++}
++
++static int imx_ssi1_hw_tx_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 bfs, div;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
++
++	SSI1_STCR = 0;
++	SSI1_STCCR = 0;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_DSP_B:
++		SSI1_STCR |= SSI_STCR_TEFS; // data 1 bit after sync
++	case SND_SOC_DAIFMT_DSP_A:
++		SSI1_STCR |= SSI_STCR_TFSL; // frame is 1 bclk long
++		break;
++	}
++
++	/* DAI clock inversion */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		SSI1_STCR |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		SSI1_STCR |= SSI_STCR_TSCKP;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		SSI1_STCR |= SSI_STCR_TFSI;
++		break;
++	}
++
++	/* DAI data (word) size */
++	switch(rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		SSI1_STCCR |= SSI_STCCR_WL(16);
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		SSI1_STCCR |= SSI_STCCR_WL(20);
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		SSI1_STCCR |= SSI_STCCR_WL(24);
++		break;
++	}
++
++	/* DAI clock master masks */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK){
++	case SND_SOC_DAIFMT_CBM_CFM:
++		SSI1_STCR |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		SSI1_STCR |= SSI_STCR_TFDIR;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		SSI1_STCR |= SSI_STCR_TXDIR;
++		break;
++	}
++
++	/* DAI BCLK ratio to SYSCLK / MCLK */
++	/* prescaler modulus - todo */
++	switch (bfs) {
++	case 2:
++		break;
++	case 4:
++		break;
++	case 8:
++		break;
++	case 16:
++		break;
++	}
++
++	/* TDM - todo, only fifo 0 atm */
++	SSI1_STCR |= SSI_STCR_TFEN0;
++	SSI1_STCCR |= SSI_STCCR_DC(params_channels(params));
++
++	return 0;
++}
++
++static int imx_ssi1_hw_rx_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 bfs, div;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
++
++	SSI1_SRCR = 0;
++	SSI1_SRCCR = 0;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_DSP_B:
++		SSI1_SRCR |= SSI_SRCR_REFS; // data 1 bit after sync
++	case SND_SOC_DAIFMT_DSP_A:
++		SSI1_SRCR |= SSI_SRCR_RFSL; // frame is 1 bclk long
++		break;
++	}
++
++	/* DAI clock inversion */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		SSI1_SRCR |= SSI_SRCR_TFSI | SSI_SRCR_TSCKP;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		SSI1_SRCR |= SSI_SRCR_RSCKP;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		SSI1_SRCR |= SSI_SRCR_RFSI;
++		break;
++	}
++
++	/* DAI data (word) size */
++	switch(rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(16);
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(20);
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(24);
++		break;
++	}
++
++	/* DAI clock master masks */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK){
++	case SND_SOC_DAIFMT_CBM_CFM:
++		SSI1_SRCR |= SSI_SRCR_RFDIR | SSI_SRCR_RXDIR;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		SSI1_SRCR |= SSI_SRCR_RFDIR;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		SSI1_SRCR |= SSI_SRCR_RXDIR;
++		break;
++	}
++
++	/* DAI BCLK ratio to SYSCLK / MCLK */
++	/* prescaler modulus - todo */
++	switch (bfs) {
++	case 2:
++		break;
++	case 4:
++		break;
++	case 8:
++		break;
++	case 16:
++		break;
++	}
++
++	/* TDM - todo, only fifo 0 atm */
++	SSI1_SRCR |= SSI_SRCR_RFEN0;
++	SSI1_SRCCR |= SSI_SRCCR_DC(params_channels(params));
++
++	return 0;
++}
++
++static int imx_ssi_dsp_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	/* clear register if not enabled */
++	if(!(SSI1_SCR & SSI_SCR_SSIEN))
++		SSI1_SCR = 0;
++
++	/* async */
++	if (rtd->cpu_dai->flags & SND_SOC_DAI_ASYNC)
++		SSI1_SCR |= SSI_SCR_SYN;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++	case SND_SOC_DAIFMT_LEFT_J:
++		SSI1_SCR |= SSI_SCR_NET;
++		break;
++	}
++
++	/* TDM  - to complete */
++
++	/* Tx/Rx config */
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		return imx_ssi1_dsp_hw_tx_params(substream, params);
++	} else {
++		return imx_ssi1_dsp_hw_rx_params(substream, params);
++	}
++}
++
++
++
++static int imx_ssi_dsp_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++			SSI1_SCR |= SSI_SCR_TE;
++			SSI1_SIER |= SSI_SIER_TDMAE;
++		} else {
++			SSI1_SCR |= SSI_SCR_RE;
++			SSI1_SIER |= SSI_SIER_RDMAE;
++		}
++		SSI1_SCR |= SSI_SCR_SSIEN;
++
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR |= SSI_SCR_TE;
++		else
++			SSI1_SCR |= SSI_SCR_RE;
++	break
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR &= ~SSI_SCR_TE;
++		else
++			SSI1_SCR &= ~SSI_SCR_RE;
++	break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void imx_ssi_dsp_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	/* shutdown SSI */
++	if (!rtd->cpu_dai->active) {
++		if(rtd->cpu_dai->id == 0)
++			SSI1_SCR &= ~SSI_SCR_SSIEN;
++		else
++			SSI2_SCR &= ~SSI_SCR_SSIEN;
++	}
++}
++
++#ifdef CONFIG_PM
++static int imx_ssi_dsp_suspend(struct platform_device *dev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR &= ~SSI_SCR_SSIEN;
++	else
++		SSI2_SCR &= ~SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++static int imx_ssi_dsp_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR |= SSI_SCR_SSIEN;
++	else
++		SSI2_SCR |= SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++#else
++#define imx_ssi_dsp_suspend	NULL
++#define imx_ssi_dsp_resume	NULL
++#endif
++
++static unsigned int imx_ssi_config_dsp_sysclk(struct snd_soc_cpu_dai *iface,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	return clk;
++}
++
++struct snd_soc_cpu_dai imx_ssi_dsp_dai = {
++	.name = "imx-dsp-1",
++	.id = 0,
++	.type = SND_SOC_DAI_PCM,
++	.suspend = imx_ssi_dsp_suspend,
++	.resume = imx_ssi_dsp_resume,
++	.config_sysclk = imx_ssi_config_dsp_sysclk,
++	.playback = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.startup = imx_ssi_dsp_startup,
++		.shutdown = imx_ssi_dsp_shutdown,
++		.trigger = imx_ssi_trigger,
++		.hw_params = imx_ssi_dsp_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_dsp_modes),
++		.mode = imx_dsp_modes,},
++},
++{
++	.name = "imx-dsp-2",
++	.id = 1,
++	.type = SND_SOC_DAI_PCM,
++	.suspend = imx_ssi_dsp_suspend,
++	.resume = imx_ssi_dsp_resume,
++	.config_sysclk = imx_ssi_config_dsp_sysclk,
++	.playback = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.startup = imx_dsp_startup,
++		.shutdown = imx_dsp_shutdown,
++		.trigger = imx_ssi1_trigger,
++		.hw_params = imx_ssi1_pcm_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_dsp_modes),
++		.mode = imx_dsp_modes,},
++};
++
++
++EXPORT_SYMBOL_GPL(imx_ssi_dsp_dai);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("i.MX ASoC SSI driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/imx/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/Kconfig
+@@ -0,0 +1,31 @@
++menu "SoC Audio for the Freescale i.MX"
++
++config SND_MXC_SOC
++	tristate "SoC Audio for the Freescale i.MX CPU"
++	depends on ARCH_MXC && SND
++	select SND_PCM
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the MXC AC97, I2S or SSP interface. You will also need
++	  to select the audio interfaces to support below.
++
++config SND_MXC_AC97
++	tristate
++	select SND_AC97_CODEC
++
++config SND_MXC_SOC_AC97
++	tristate
++	select SND_AC97_BUS
++
++config SND_MXC_SOC_SSI
++	tristate
++
++config SND_MXC_SOC_MX3_WM8753
++	tristate "SoC Audio support for MX31 - WM8753"
++	depends on SND_MXC_SOC && ARCH_MX3
++	select SND_MXC_SOC_SSI
++	help
++	  Say Y if you want to add support for SoC audio on MX31ADS
++	  with the WM8753.
++
++endmenu
+Index: linux-2.6-pxa-new/sound/soc/imx/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/Makefile
+@@ -0,0 +1,18 @@
++# i.MX Platform Support
++snd-soc-imx21-objs := imx21-pcm.o
++snd-soc-imx31-objs := imx31-pcm.o
++snd-soc-imx-ac97-objs := imx-ac97.o
++snd-soc-imx-i2s-objs := imx-i2s.o
++
++obj-$(CONFIG_SND_MXC_SOC) += snd-soc-imx.o
++obj-$(CONFIG_SND_MXC_SOC_AC97) += snd-soc-imx-ac97.o
++obj-$(CONFIG_SND_MXC_SOC_I2S) += snd-soc-imx-i2s.o
++
++# i.MX Machine Support
++snd-soc-mx31ads-wm8753-objs := mx31ads_wm8753.o
++obj-$(CONFIG_SND_SOC_MX31ADS_WM8753) += snd-soc-mx31ads-wm8753.o
++snd-soc-mx21ads-wm8753-objs := mx21ads_wm8753.o
++obj-$(CONFIG_SND_SOC_MX21ADS_WM8753) += snd-soc-mx21ads-wm8753.o
++snd-soc-mx21ads-wm8731-objs := mx21ads_wm8731.o
++obj-$(CONFIG_SND_SOC_MX21ADS_WM8731) += snd-soc-mx21ads-wm8731.o
++
+Index: linux-2.6.17/sound/Makefile
+===================================================================
+--- linux-2.6.17.orig/sound/Makefile	2006-06-18 02:49:35.000000000 +0100
++++ linux-2.6.17/sound/Makefile	2006-07-04 14:04:41.000000000 +0100
+@@ -4,7 +4,7 @@
+ obj-$(CONFIG_SOUND) += soundcore.o
+ obj-$(CONFIG_SOUND_PRIME) += oss/
+ obj-$(CONFIG_DMASOUND) += oss/
+-obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
++obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
+ 
+ ifeq ($(CONFIG_SND),y)
+   obj-y += last.o
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8711.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8711.c
+@@ -0,0 +1,843 @@
++/*
++ * wm8711.c  --  WM8711 ALSA SoC Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics
++ *
++ * Author: Mike Arthur <linux at wolfsonmicro.com>
++ *
++ * Based on wm8711.c by Richard Purdie
++ *
++ * 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/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8711.h"
++
++#define AUDIO_NAME "wm8711"
++#define WM8711_VERSION "0.2"
++
++/*
++ * Debug
++ */
++
++#define WM8711_DEBUG 0
++
++#ifdef WM8711_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8711;
++
++/*
++ * wm8711 register cache
++ * We can't read the WM8711 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ * There is no point in caching the reset register
++ */
++static const u16 wm8711_reg[WM8711_CACHEREGNUM] = {
++    0x0079, 0x0079, 0x000a, 0x0008,
++    0x009f, 0x000a, 0x0000, 0x0000
++};
++
++#define WM8711_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8711_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK)
++
++#define WM8711_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++#define WM8711_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
++	SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8711_modes[] = {
++	/* codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 1536,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 2304,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 1408,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 2112,
++		.bfs = 64,
++	},
++
++	/* 32k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_32000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 576,
++		.bfs = 64,
++	},
++
++	/* 44.1k & 48k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 256,
++		.bfs = 64,
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 64,
++	},
++
++	/* 88.2 & 96k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 128,
++		.bfs = 64,
++
++	},
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 192,
++		.bfs = 64,
++	},
++
++	/* USB codec frame and clock master modes */
++	/* 8k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_8000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 1500,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 44.1k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 272,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 48k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_48000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 250,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 88.2k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_88200,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 136,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* 96k */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = SNDRV_PCM_RATE_96000,
++		.pcmdir = WM8711_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 125,
++		.bfs = SND_SOC_FSBD(1),
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8711_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8711_HIFI_BITS,
++		.pcmrate = WM8711_RATES,
++		.pcmdir = WM8711_DIR,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8711 register cache
++ */
++static inline unsigned int wm8711_read_reg_cache(struct snd_soc_codec * codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8711_RESET)
++		return 0;
++	if (reg >= WM8711_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8711 register cache
++ */
++static inline void wm8711_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8711_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8711 register space
++ */
++static int wm8711_write(struct snd_soc_codec * codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8753 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8711_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8711_reset(c)	wm8711_write(c, WM8711_RESET, 0)
++
++static const struct snd_kcontrol_new wm8711_snd_controls[] = {
++
++SOC_DOUBLE_R("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V,
++	0, 127, 0),
++SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V,
++	7, 1, 0),
++
++};
++
++/* add non dapm controls */
++static int wm8711_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8711_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8711_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Output Mixer */
++static const snd_kcontrol_new_t wm8711_output_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0),
++SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0),
++};
++
++static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = {
++SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1,
++	&wm8711_output_mixer_controls[0],
++	ARRAY_SIZE(wm8711_output_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1),
++SND_SOC_DAPM_OUTPUT("LOUT"),
++SND_SOC_DAPM_OUTPUT("LHPOUT"),
++SND_SOC_DAPM_OUTPUT("ROUT"),
++SND_SOC_DAPM_OUTPUT("RHPOUT"),
++};
++
++static const char *intercon[][3] = {
++	/* output mixer */
++	{"Output Mixer", "Line Bypass Switch", "Line Input"},
++	{"Output Mixer", "HiFi Playback Switch", "DAC"},
++
++	/* outputs */
++	{"RHPOUT", NULL, "Output Mixer"},
++	{"ROUT", NULL, "Output Mixer"},
++	{"LHPOUT", NULL, "Output Mixer"},
++	{"LOUT", NULL, "Output Mixer"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8711_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8711_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8711_dapm_widgets[i]);
++	}
++
++	/* set up audio path interconnects */
++	for(i = 0; intercon[i][0] != NULL; i++) {
++		snd_soc_dapm_connect_input(codec, intercon[i][0], intercon[i][1],
++			intercon[i][2]);
++	}
++
++	snd_soc_dapm_new_widgets(codec);
++	return 0;
++}
++
++struct _coeff_div {
++	u32 mclk;
++	u32 rate;
++	u16 fs;
++	u8 sr:4;
++	u8 bosr:1;
++	u8 usb:1;
++};
++
++/* codec mclk clock divider coefficients */
++static const struct _coeff_div coeff_div[] = {
++	/* 48k */
++	{12288000, 48000, 256, 0x0, 0x0, 0x0},
++	{18432000, 48000, 384, 0x0, 0x1, 0x0},
++	{12000000, 48000, 250, 0x0, 0x0, 0x1},
++
++	/* 32k */
++	{12288000, 32000, 384, 0x6, 0x0, 0x0},
++	{18432000, 32000, 576, 0x6, 0x1, 0x0},
++
++	/* 8k */
++	{12288000, 8000, 1536, 0x3, 0x0, 0x0},
++	{18432000, 8000, 2304, 0x3, 0x1, 0x0},
++	{11289600, 8000, 1408, 0xb, 0x0, 0x0},
++	{16934400, 8000, 2112, 0xb, 0x1, 0x0},
++	{12000000, 8000, 1500, 0x3, 0x0, 0x1},
++
++	/* 96k */
++	{12288000, 96000, 128, 0x7, 0x0, 0x0},
++	{18432000, 96000, 192, 0x7, 0x1, 0x0},
++	{12000000, 96000, 125, 0x7, 0x0, 0x1},
++
++	/* 44.1k */
++	{11289600, 44100, 256, 0x8, 0x0, 0x0},
++	{16934400, 44100, 384, 0x8, 0x1, 0x0},
++	{12000000, 44100, 272, 0x8, 0x1, 0x1},
++
++	/* 88.2k */
++	{11289600, 88200, 128, 0xf, 0x0, 0x0},
++	{16934400, 88200, 192, 0xf, 0x1, 0x0},
++	{12000000, 88200, 136, 0xf, 0x1, 0x1},
++};
++
++static inline int get_coeff(int mclk, int rate)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
++		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
++			return i;
++	}
++	return 0;
++}
++
++/* WM8711 supports numerous clocks per sample rate */
++static unsigned int wm8711_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	dai->mclk = 0;
++
++	/* check that the calculated FS and rate actually match a clock from
++	 * the machine driver */
++	if (info->fs * info->rate == clk)
++		dai->mclk = clk;
++
++	return dai->mclk;
++}
++
++static int wm8711_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 iface = 0, srate;
++	int i = get_coeff(rtd->codec_dai->mclk,
++		snd_soc_get_rate(rtd->codec_dai->dai_runtime.pcmrate));
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		iface |= 0x0040;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++	srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) |
++		coeff_div[i].usb;
++	wm8711_write(codec, WM8711_SRATE, srate);
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		iface |= 0x0013;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FORMAT_S16_LE:
++		break;
++	case SNDRV_PCM_FORMAT_S20_3LE:
++		iface |= 0x0004;
++		break;
++	case SNDRV_PCM_FORMAT_S24_LE:
++		iface |= 0x0008;
++		break;
++	case SNDRV_PCM_FORMAT_S32_LE:
++		iface |= 0x000c;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0090;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0010;
++		break;
++	}
++
++	/* set iface */
++	wm8711_write(codec, WM8711_IFACE, iface);
++
++    /* set active */
++    wm8711_write(codec, WM8711_ACTIVE, 0x0001);
++    return 0;
++}
++
++static void wm8711_shutdown(struct snd_pcm_substream *substream)
++{
++    struct snd_soc_pcm_runtime *rtd = substream->private_data;
++    struct snd_soc_device *socdev = rtd->socdev;
++    struct snd_soc_codec *codec = socdev->codec;
++
++    /* deactivate */
++    if (!codec->active) {
++        udelay(50);
++        wm8711_write(codec, WM8711_ACTIVE, 0x0);
++    }
++}
++
++static int wm8711_mute(struct snd_soc_codec *codec,
++    struct snd_soc_codec_dai *dai, int mute)
++{
++    u16 mute_reg = wm8711_read_reg_cache(codec, WM8711_APDIGI) & 0xfff7;
++    if (mute)
++        wm8711_write(codec, WM8711_APDIGI, mute_reg | 0x8);
++    else
++        wm8711_write(codec, WM8711_APDIGI, mute_reg);
++
++	return 0;
++}
++
++static int wm8711_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 reg = wm8711_read_reg_cache(codec, WM8711_PWR) & 0xff7f;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, osc on, dac unmute */
++		wm8711_write(codec, WM8711_PWR, reg);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, */
++		wm8711_write(codec, WM8711_PWR, reg | 0x0040);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8711_write(codec, WM8711_ACTIVE, 0x0);
++		wm8711_write(codec, WM8711_PWR, 0xffff);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8711_dai = {
++	.name = "WM8711",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8711_config_sysclk,
++	.digital_mute = wm8711_mute,
++	.ops = {
++		.prepare = wm8711_pcm_prepare,
++        .shutdown = wm8711_shutdown,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8711_modes),
++		.mode = wm8711_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8711_dai);
++
++static int wm8711_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;
++
++	wm8711_write(codec, WM8711_ACTIVE, 0x0);
++	wm8711_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8711_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8711_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8711_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8711 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8711_init(struct snd_soc_device* socdev)
++{
++	struct snd_soc_codec* codec = socdev->codec;
++	int reg, ret = 0;
++
++	codec->name = "WM8711";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8711_read_reg_cache;
++	codec->write = wm8711_write;
++	codec->dapm_event = wm8711_dapm_event;
++	codec->dai = &wm8711_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8711_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8711_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8711_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8711_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8711_reg);
++
++	wm8711_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8711_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* set the update bits */
++	reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V);
++	wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100);
++	reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V);
++	wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100);
++
++	wm8711_add_controls(codec);
++	wm8711_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 struct snd_soc_device *wm8711_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8711 2 wire address is determined by GPIO5
++ * state during powerup.
++ *    low  = 0x1a
++ *    high = 0x1b
++ */
++#define I2C_DRIVERID_WM8711 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8711_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8711_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8711_socdev;
++	struct wm8711_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++
++	i2c_set_clientdata(i2c, codec);
++
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if (ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++        goto err;
++    }
++
++	ret = wm8711_init(socdev);
++    if (ret < 0) {
++        err("failed to initialise WM8711\n");
++        goto err;
++    }
++    return ret;
++
++err:
++    kfree(codec);
++    kfree(i2c);
++    return ret;
++
++}
++
++static int wm8711_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++
++	i2c_detach_client(client);
++
++	kfree(codec->reg_cache);
++	kfree(client);
++
++	return 0;
++}
++
++static int wm8711_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8711_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8711_i2c_driver = {
++	.driver = {
++		.name = "WM8711 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8711,
++	.attach_adapter = wm8711_i2c_attach,
++	.detach_client =  wm8711_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8711",
++	.driver = &wm8711_i2c_driver,
++};
++#endif
++
++static int wm8711_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8711_setup_data *setup;
++	struct snd_soc_codec* codec;
++	int ret = 0;
++
++	info("WM8711 Audio Codec %s", WM8711_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);
++
++	wm8711_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8711_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8711_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)
++		wm8711_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8711_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8711 = {
++	.probe = 	wm8711_probe,
++	.remove = 	wm8711_remove,
++	.suspend = 	wm8711_suspend,
++	.resume =	wm8711_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
++
++MODULE_DESCRIPTION("ASoC WM8711 driver");
++MODULE_AUTHOR("Mike Arthur");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8711.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8711.h
+@@ -0,0 +1,39 @@
++/*
++ * wm8711.h  --  WM8711 Soc Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics
++ *
++ * Author: Mike Arthur <linux at wolfsonmicro.com>
++ *
++ * Based on wm8731.h
++ *
++ * 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 _WM8711_H
++#define _WM8711_H
++
++/* WM8711 register space */
++
++#define WM8711_LOUT1V   0x02
++#define WM8711_ROUT1V   0x03
++#define WM8711_APANA    0x04
++#define WM8711_APDIGI   0x05
++#define WM8711_PWR      0x06
++#define WM8711_IFACE    0x07
++#define WM8711_SRATE    0x08
++#define WM8711_ACTIVE   0x09
++#define WM8711_RESET	0x0f
++
++#define WM8711_CACHEREGNUM 	8
++
++struct wm8711_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8711_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8711;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8980.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8980.c
+@@ -0,0 +1,991 @@
++/*
++ * wm8980.c  --  WM8980 ALSA Soc Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ *
++ * Authors:
++ * Mike Arthur      <linux at wolfsonmicro.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/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8980.h"
++
++#define AUDIO_NAME "wm8980"
++#define WM8980_VERSION "0.2"
++
++/*
++ * Debug
++ */
++
++#define WM8980_DEBUG 0
++
++#ifdef WM8980_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8980;
++
++/*
++ * wm8980 register cache
++ * We can't read the WM8980 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8980_reg[WM8980_CACHEREGNUM] = {
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0050, 0x0000, 0x0140, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x00ff,
++    0x00ff, 0x0000, 0x0100, 0x00ff,
++    0x00ff, 0x0000, 0x012c, 0x002c,
++    0x002c, 0x002c, 0x002c, 0x0000,
++    0x0032, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0038, 0x000b, 0x0032, 0x0000,
++    0x0008, 0x000c, 0x0093, 0x00e9,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0033, 0x0010, 0x0010, 0x0100,
++    0x0100, 0x0002, 0x0001, 0x0001,
++    0x0039, 0x0039, 0x0039, 0x0039,
++    0x0001, 0x0001,
++};
++
++#define WM8980_DAIFMT \
++	(SND_SOC_DAIFMT_I2S  | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++    SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_DSP_B  | SND_SOC_DAIFMT_NB_NF   | \
++    SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF  | SND_SOC_DAIFMT_IB_IF)
++
++#define WM8980_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8980_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)
++
++#define WM8980_PCM_FORMATS \
++	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++	SNDRV_PCM_FORMAT_S24_3LE | SNDRV_PCM_FORMAT_S24_LE  | \
++    SNDRV_PCM_FORMAT_S32_LE)
++
++#define WM8980_BCLK \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | SND_SOC_FSBD(8) |\
++    SND_SOC_FSBD(16) | SND_SOC_FSBD(32))
++
++static struct snd_soc_dai_mode wm8980_modes[] = {
++	/* codec frame and clock master modes */
++	{
++		.fmt = WM8980_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8980_PCM_FORMATS,
++		.pcmrate = WM8980_RATES,
++		.pcmdir = WM8980_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8980_BCLK,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8980_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++        .pcmfmt = WM8980_PCM_FORMATS,
++        .pcmrate = WM8980_RATES,
++        .pcmdir = WM8980_DIR,
++        .fs = SND_SOC_FS_ALL,
++        .bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8980 register cache
++ */
++static inline unsigned int wm8980_read_reg_cache(struct snd_soc_codec  *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8980_RESET)
++		return 0;
++	if (reg >= WM8980_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8980 register cache
++ */
++static inline void wm8980_write_reg_cache(struct snd_soc_codec  *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8980_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8980 register space
++ */
++static int wm8980_write(struct snd_soc_codec  *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8980 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8980_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -1;
++}
++
++#define wm8980_reset(c)	wm8980_write(c, WM8980_RESET, 0)
++
++static const char *wm8980_companding[] = {"Off", "NC", "u-law", "A-law" };
++static const char *wm8980_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
++static const char *wm8980_eqmode[] = {"Capture", "Playback" };
++static const char *wm8980_bw[] = {"Narrow", "Wide" };
++static const char *wm8980_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" };
++static const char *wm8980_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" };
++static const char *wm8980_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" };
++static const char *wm8980_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" };
++static const char *wm8980_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" };
++static const char *wm8980_alc[] =
++    {"ALC both on", "ALC left only", "ALC right only", "Limiter" };
++
++static const struct soc_enum wm8980_enum[] = {
++	SOC_ENUM_SINGLE(WM8980_COMP, 1, 4, wm8980_companding), /* adc */
++	SOC_ENUM_SINGLE(WM8980_COMP, 3, 4, wm8980_companding), /* dac */
++	SOC_ENUM_SINGLE(WM8980_DAC,  4, 4, wm8980_deemp),
++	SOC_ENUM_SINGLE(WM8980_EQ1,  8, 2, wm8980_eqmode),
++
++	SOC_ENUM_SINGLE(WM8980_EQ1,  5, 4, wm8980_eq1),
++	SOC_ENUM_SINGLE(WM8980_EQ2,  8, 2, wm8980_bw),
++	SOC_ENUM_SINGLE(WM8980_EQ2,  5, 4, wm8980_eq2),
++	SOC_ENUM_SINGLE(WM8980_EQ3,  8, 2, wm8980_bw),
++
++	SOC_ENUM_SINGLE(WM8980_EQ3,  5, 4, wm8980_eq3),
++	SOC_ENUM_SINGLE(WM8980_EQ4,  8, 2, wm8980_bw),
++	SOC_ENUM_SINGLE(WM8980_EQ4,  5, 4, wm8980_eq4),
++	SOC_ENUM_SINGLE(WM8980_EQ5,  8, 2, wm8980_bw),
++
++	SOC_ENUM_SINGLE(WM8980_EQ5,  5, 4, wm8980_eq5),
++	SOC_ENUM_SINGLE(WM8980_ALC3,  8, 2, wm8980_alc),
++};
++
++static const struct snd_kcontrol_new wm8980_snd_controls[] = {
++SOC_SINGLE("Digital Loopback Switch", WM8980_COMP, 0, 1, 0),
++
++SOC_ENUM("ADC Companding", wm8980_enum[0]),
++SOC_ENUM("DAC Companding", wm8980_enum[1]),
++
++SOC_SINGLE("Jack Detection Enable", WM8980_JACK1, 6, 1, 0),
++
++SOC_SINGLE("DAC Right Inversion Switch", WM8980_DAC, 1, 1, 0),
++SOC_SINGLE("DAC Left Inversion Switch", WM8980_DAC, 0, 1, 0),
++
++SOC_SINGLE("Left Playback Volume", WM8980_DACVOLL, 0, 127, 0),
++SOC_SINGLE("Right Playback Volume", WM8980_DACVOLR, 0, 127, 0),
++
++SOC_SINGLE("High Pass Filter Switch", WM8980_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Filter Switch", WM8980_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Cut Off", WM8980_ADC, 4, 7, 0),
++SOC_SINGLE("Right ADC Inversion Switch", WM8980_ADC, 1, 1, 0),
++SOC_SINGLE("Left ADC Inversion Switch", WM8980_ADC, 0, 1, 0),
++
++SOC_SINGLE("Left Capture Volume", WM8980_ADCVOLL,  0, 127, 0),
++SOC_SINGLE("Right Capture Volume", WM8980_ADCVOLR,  0, 127, 0),
++
++SOC_ENUM("Equaliser Function", wm8980_enum[3]),
++SOC_ENUM("EQ1 Cut Off", wm8980_enum[4]),
++SOC_SINGLE("EQ1 Volume", WM8980_EQ1,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ2 Bandwith", wm8980_enum[5]),
++SOC_ENUM("EQ2 Cut Off", wm8980_enum[6]),
++SOC_SINGLE("EQ2 Volume", WM8980_EQ2,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ3 Bandwith", wm8980_enum[7]),
++SOC_ENUM("EQ3 Cut Off", wm8980_enum[8]),
++SOC_SINGLE("EQ3 Volume", WM8980_EQ3,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ4 Bandwith", wm8980_enum[9]),
++SOC_ENUM("EQ4 Cut Off", wm8980_enum[10]),
++SOC_SINGLE("EQ4 Volume", WM8980_EQ4,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ5 Bandwith", wm8980_enum[11]),
++SOC_ENUM("EQ5 Cut Off", wm8980_enum[12]),
++SOC_SINGLE("EQ5 Volume", WM8980_EQ5,  0, 31, 1),
++
++SOC_SINGLE("DAC Playback Limiter Switch", WM8980_DACLIM1,  8, 1, 0),
++SOC_SINGLE("DAC Playback Limiter Decay", WM8980_DACLIM1,  4, 15, 0),
++SOC_SINGLE("DAC Playback Limiter Attack", WM8980_DACLIM1,  0, 15, 0),
++
++SOC_SINGLE("DAC Playback Limiter Threshold", WM8980_DACLIM2,  4, 7, 0),
++SOC_SINGLE("DAC Playback Limiter Boost", WM8980_DACLIM2,  0, 15, 0),
++
++SOC_SINGLE("ALC Enable Switch", WM8980_ALC1,  8, 1, 0),
++SOC_SINGLE("ALC Capture Max Gain", WM8980_ALC1,  3, 7, 0),
++SOC_SINGLE("ALC Capture Min Gain", WM8980_ALC1,  0, 7, 0),
++
++SOC_SINGLE("ALC Capture ZC Switch", WM8980_ALC2,  8, 1, 0),
++SOC_SINGLE("ALC Capture Hold", WM8980_ALC2,  4, 7, 0),
++SOC_SINGLE("ALC Capture Target", WM8980_ALC2,  0, 15, 0),
++
++SOC_ENUM("ALC Capture Mode", wm8980_enum[13]),
++SOC_SINGLE("ALC Capture Decay", WM8980_ALC3,  4, 15, 0),
++SOC_SINGLE("ALC Capture Attack", WM8980_ALC3,  0, 15, 0),
++
++SOC_SINGLE("ALC Capture Noise Gate Switch", WM8980_NGATE,  3, 1, 0),
++SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8980_NGATE,  0, 7, 0),
++
++SOC_SINGLE("Left Capture PGA ZC Switch", WM8980_INPPGAL,  7, 1, 0),
++SOC_SINGLE("Left Capture PGA Volume", WM8980_INPPGAL,  0, 63, 0),
++
++SOC_SINGLE("Right Capture PGA ZC Switch", WM8980_INPPGAR,  7, 1, 0),
++SOC_SINGLE("Right Capture PGA Volume", WM8980_INPPGAR,  0, 63, 0),
++
++SOC_SINGLE("Left Headphone Playback ZC Switch", WM8980_HPVOLL,  7, 1, 0),
++SOC_SINGLE("Left Headphone Playback Switch", WM8980_HPVOLL,  6, 1, 1),
++SOC_SINGLE("Left Headphone Playback Volume", WM8980_HPVOLL,  0, 63, 0),
++
++SOC_SINGLE("Right Headphone Playback ZC Switch", WM8980_HPVOLR,  7, 1, 0),
++SOC_SINGLE("Right Headphone Playback Switch", WM8980_HPVOLR,  6, 1, 1),
++SOC_SINGLE("Right Headphone Playback Volume", WM8980_HPVOLR,  0, 63, 0),
++
++SOC_SINGLE("Left Speaker Playback ZC Switch", WM8980_SPKVOLL,  7, 1, 0),
++SOC_SINGLE("Left Speaker Playback Switch", WM8980_SPKVOLL,  6, 1, 1),
++SOC_SINGLE("Left Speaker Playback Volume", WM8980_SPKVOLL,  0, 63, 0),
++
++SOC_SINGLE("Right Speaker Playback ZC Switch", WM8980_SPKVOLR,  7, 1, 0),
++SOC_SINGLE("Right Speaker Playback Switch", WM8980_SPKVOLR,  6, 1, 1),
++SOC_SINGLE("Right Speaker Playback Volume", WM8980_SPKVOLR,  0, 63, 0),
++
++SOC_DOUBLE_R("Capture Boost(+20dB)", WM8980_ADCBOOSTL, WM8980_ADCBOOSTR,
++	8, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm8980_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8980_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8980_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Left Output Mixer */
++static const snd_kcontrol_new_t wm8980_left_mixer_controls[] = {
++SOC_DAPM_SINGLE("Right PCM Playback Switch", WM8980_OUTPUT, 6, 1, 1),
++SOC_DAPM_SINGLE("Left PCM Playback Switch", WM8980_MIXL, 0, 1, 1),
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8980_MIXL, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8980_MIXL, 5, 1, 0),
++};
++
++/* Right Output Mixer */
++static const snd_kcontrol_new_t wm8980_right_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left PCM Playback Switch", WM8980_OUTPUT, 5, 1, 1),
++SOC_DAPM_SINGLE("Right PCM Playback Switch", WM8980_MIXR, 0, 1, 1),
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8980_MIXR, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8980_MIXR, 5, 1, 0),
++};
++
++/* Left AUX Input boost vol */
++static const snd_kcontrol_new_t wm8980_laux_boost_controls =
++SOC_DAPM_SINGLE("Left Aux Volume", WM8980_ADCBOOSTL, 0, 3, 0);
++
++/* Right AUX Input boost vol */
++static const snd_kcontrol_new_t wm8980_raux_boost_controls =
++SOC_DAPM_SINGLE("Right Aux Volume", WM8980_ADCBOOSTR, 0, 3, 0);
++
++/* Left Input boost vol */
++static const snd_kcontrol_new_t wm8980_lmic_boost_controls =
++SOC_DAPM_SINGLE("Left Input Volume", WM8980_ADCBOOSTL, 4, 3, 0);
++
++/* Right Input boost vol */
++static const snd_kcontrol_new_t wm8980_rmic_boost_controls =
++SOC_DAPM_SINGLE("Right Input Volume", WM8980_ADCBOOSTR, 4, 3, 0);
++
++/* Left Aux In to PGA */
++static const snd_kcontrol_new_t wm8980_laux_capture_boost_controls =
++SOC_DAPM_SINGLE("Left Capture Switch", WM8980_ADCBOOSTL,  8, 1, 0);
++
++/* Right  Aux In to PGA */
++static const snd_kcontrol_new_t wm8980_raux_capture_boost_controls =
++SOC_DAPM_SINGLE("Right Capture Switch", WM8980_ADCBOOSTR,  8, 1, 0);
++
++/* Left Input P In to PGA */
++static const snd_kcontrol_new_t wm8980_lmicp_capture_boost_controls =
++SOC_DAPM_SINGLE("Left Input P Capture Boost Switch", WM8980_INPUT,  0, 1, 0);
++
++/* Right Input P In to PGA */
++static const snd_kcontrol_new_t wm8980_rmicp_capture_boost_controls =
++SOC_DAPM_SINGLE("Right Input P Capture Boost Switch", WM8980_INPUT,  4, 1, 0);
++
++/* Left Input N In to PGA */
++static const snd_kcontrol_new_t wm8980_lmicn_capture_boost_controls =
++SOC_DAPM_SINGLE("Left Input N Capture Boost Switch", WM8980_INPUT,  1, 1, 0);
++
++/* Right Input N In to PGA */
++static const snd_kcontrol_new_t wm8980_rmicn_capture_boost_controls =
++SOC_DAPM_SINGLE("Right Input N Capture Boost Switch", WM8980_INPUT,  5, 1, 0);
++
++// TODO Widgets
++static const struct snd_soc_dapm_widget wm8980_dapm_widgets[] = {
++#if 0
++//SND_SOC_DAPM_MUTE("Mono Mute", WM8980_MONOMIX, 6, 0),
++//SND_SOC_DAPM_MUTE("Speaker Mute", WM8980_SPKMIX, 6, 0),
++
++SND_SOC_DAPM_MIXER("Speaker Mixer", WM8980_POWER3, 2, 0,
++	&wm8980_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm8980_speaker_mixer_controls)),
++SND_SOC_DAPM_MIXER("Mono Mixer", WM8980_POWER3, 3, 0,
++	&wm8980_mono_mixer_controls[0],
++	ARRAY_SIZE(wm8980_mono_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8980_POWER3, 0, 0),
++SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8980_POWER3, 0, 0),
++SND_SOC_DAPM_PGA("Aux Input", WM8980_POWER1, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkN Out", WM8980_POWER3, 5, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkP Out", WM8980_POWER3, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", WM8980_POWER3, 7, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mic PGA", WM8980_POWER2, 2, 0, NULL, 0),
++
++SND_SOC_DAPM_PGA("Aux Boost", SND_SOC_NOPM, 0, 0,
++	&wm8980_aux_boost_controls, 1),
++SND_SOC_DAPM_PGA("Mic Boost", SND_SOC_NOPM, 0, 0,
++	&wm8980_mic_boost_controls, 1),
++SND_SOC_DAPM_SWITCH("Capture Boost", SND_SOC_NOPM, 0, 0,
++	&wm8980_capture_boost_controls),
++
++SND_SOC_DAPM_MIXER("Boost Mixer", WM8980_POWER2, 4, 0, NULL, 0),
++
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8980_POWER1, 4, 0),
++
++SND_SOC_DAPM_INPUT("MICN"),
++SND_SOC_DAPM_INPUT("MICP"),
++SND_SOC_DAPM_INPUT("AUX"),
++SND_SOC_DAPM_OUTPUT("MONOOUT"),
++SND_SOC_DAPM_OUTPUT("SPKOUTP"),
++SND_SOC_DAPM_OUTPUT("SPKOUTN"),
++#endif
++};
++
++static const char *audio_map[][3] = {
++	/* Mono output mixer */
++	{"Mono Mixer", "PCM Playback Switch", "DAC"},
++	{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Speaker output mixer */
++	{"Speaker Mixer", "PCM Playback Switch", "DAC"},
++	{"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Outputs */
++	{"Mono Out", NULL, "Mono Mixer"},
++	{"MONOOUT", NULL, "Mono Out"},
++	{"SpkN Out", NULL, "Speaker Mixer"},
++	{"SpkP Out", NULL, "Speaker Mixer"},
++	{"SPKOUTN", NULL, "SpkN Out"},
++	{"SPKOUTP", NULL, "SpkP Out"},
++
++	/* Boost Mixer */
++	{"Boost Mixer", NULL, "ADC"},
++	{"Capture Boost Switch", "Aux Capture Boost Switch", "AUX"},
++	{"Aux Boost", "Aux Volume", "Boost Mixer"},
++	{"Capture Boost", "Capture Switch", "Boost Mixer"},
++	{"Mic Boost", "Mic Volume", "Boost Mixer"},
++
++	/* Inputs */
++	{"MICP", NULL, "Mic Boost"},
++	{"MICN", NULL, "Mic PGA"},
++	{"Mic PGA", NULL, "Capture Boost"},
++	{"AUX", NULL, "Aux Input"},
++
++    /*  */
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8980_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8980_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8980_dapm_widgets[i]);
++	}
++
++	/* set up audio path map */
++	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;
++}
++
++struct pll_ {
++	unsigned int in_hz, out_hz;
++	unsigned int pre:4; /* prescale - 1 */
++	unsigned int n:4;
++	unsigned int k;
++};
++
++struct pll_ pll[] = {
++	{12000000, 11289600, 0, 7, 0x86c220},
++	{12000000, 12288000, 0, 8, 0x3126e8},
++	{13000000, 11289600, 0, 6, 0xf28bd4},
++	{13000000, 12288000, 0, 7, 0x8fd525},
++	{12288000, 11289600, 0, 7, 0x59999a},
++	{11289600, 12288000, 0, 8, 0x80dee9},
++	/* TODO: liam - add more entries */
++};
++
++static int set_pll(struct snd_soc_codec *codec, unsigned int in,
++	unsigned int out)
++{
++	int i;
++	u16 reg;
++
++	if(out == 0) {
++		reg = wm8980_read_reg_cache(codec, WM8980_POWER1);
++		wm8980_write(codec, WM8980_POWER1, reg & 0x1df);
++		return 0;
++	}
++
++	for(i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (in == pll[i].in_hz && out == pll[i].out_hz) {
++			wm8980_write(codec, WM8980_PLLN, (pll[i].pre << 4) | pll[i].n);
++			wm8980_write(codec, WM8980_PLLK1, pll[i].k >> 18);
++			wm8980_write(codec, WM8980_PLLK1, (pll[i].k >> 9) && 0x1ff);
++			wm8980_write(codec, WM8980_PLLK1, pll[i].k && 0x1ff);
++			reg = wm8980_read_reg_cache(codec, WM8980_POWER1);
++			wm8980_write(codec, WM8980_POWER1, reg | 0x020);
++			return 0;
++		}
++	}
++	return -EINVAL;
++}
++
++/* mclk dividers * 2 */
++static unsigned char mclk_div[] = {2, 3, 4, 6, 8, 12, 16, 24};
++
++/* we need 256FS to drive the DAC's and ADC's */
++static unsigned int wm8980_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if ((best_clk >> 1) * mclk_div[i] == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = mclk_div[i];
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == clk) {
++			for (j = 0; j < ARRAY_SIZE(mclk_div); j++) {
++				if (pll[i].out_hz == mclk_div[j] * (best_clk >> 1)) {
++					dai->pll_in = clk;
++					dai->pll_out = pll[i].out_hz;
++					dai->clk_div = mclk_div[j];
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++static int wm8980_pcm_prepare(snd_pcm_substream_t *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *dai = rtd->codec_dai;
++	u16 iface = 0, bfs, clk = 0, adn;
++	int fs = 48000 << 7, i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	switch (bfs) {
++	case 2:
++		clk |= 0x1 << 2;
++		break;
++	case 4:
++		clk |= 0x2 << 2;
++		break;
++	case 8:
++		clk |= 0x3 << 2;
++		break;
++	case 16:
++		clk |= 0x4 << 2;
++		break;
++	case 32:
++		clk |= 0x5 << 2;
++		break;
++	}
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		clk |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0010;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0008;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x00018;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0020;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0040;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x0060;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0180;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0100;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0080;
++		break;
++	}
++
++	/* filter coefficient */
++	adn = wm8980_read_reg_cache(codec, WM8980_ADD) & 0x1f1;
++	switch (rtd->codec_dai->dai_runtime.pcmrate) {
++	case SNDRV_PCM_RATE_8000:
++		adn |= 0x5 << 1;
++		fs = 8000 << 7;
++		break;
++	case SNDRV_PCM_RATE_11025:
++		adn |= 0x4 << 1;
++		fs = 11025 << 7;
++		break;
++	case SNDRV_PCM_RATE_16000:
++		adn |= 0x3 << 1;
++		fs = 16000 << 7;
++		break;
++	case SNDRV_PCM_RATE_22050:
++		adn |= 0x2 << 1;
++		fs = 22050 << 7;
++		break;
++	case SNDRV_PCM_RATE_32000:
++		adn |= 0x1 << 1;
++		fs = 32000 << 7;
++		break;
++	case SNDRV_PCM_RATE_44100:
++		fs = 44100 << 7;
++		break;
++	}
++
++	/* do we need to enable the PLL */
++	if(dai->pll_in)
++		set_pll(codec, dai->pll_in, dai->pll_out);
++
++	/* divide the clock to 256 fs */
++	for(i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if (dai->clk_div == mclk_div[i]) {
++			clk |= i << 5;
++			clk &= 0xff;
++			goto set;
++		}
++	}
++
++set:
++	/* set iface */
++	wm8980_write(codec, WM8980_IFACE, iface);
++	wm8980_write(codec, WM8980_CLOCK, clk);
++
++	return 0;
++}
++
++static int wm8980_hw_free(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	set_pll(codec, 0, 0);
++	return 0;
++}
++
++static int wm8980_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8980_read_reg_cache(codec, WM8980_DAC) & 0xffbf;
++	if(mute)
++		wm8980_write(codec, WM8980_DAC, mute_reg | 0x40);
++	else
++		wm8980_write(codec, WM8980_DAC, mute_reg);
++
++	return 0;
++}
++
++/* TODO: liam need to make this lower power with dapm */
++static int wm8980_dapm_event(struct snd_soc_codec *codec, int event)
++{
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, clk and osc on, dac unmute, active */
++		wm8980_write(codec, WM8980_POWER1, 0x1ff);
++		wm8980_write(codec, WM8980_POWER2, 0x1ff);
++		wm8980_write(codec, WM8980_POWER3, 0x1ff);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, dac mute, inactive */
++
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8980_write(codec, WM8980_POWER1, 0x0);
++		wm8980_write(codec, WM8980_POWER2, 0x0);
++		wm8980_write(codec, WM8980_POWER3, 0x0);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8980_dai = {
++	.name = "WM8980 HiFi",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.config_sysclk = wm8980_config_sysclk,
++	.digital_mute = wm8980_mute,
++	.ops = {
++		.prepare = wm8980_pcm_prepare,
++		.hw_free = wm8980_hw_free,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8980_modes),
++		.mode = wm8980_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8980_dai);
++
++static int wm8980_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;
++
++	wm8980_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8980_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8980_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8980_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8980_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8980 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8980_init(struct snd_soc_device* socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "WM8980";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8980_read_reg_cache;
++	codec->write = wm8980_write;
++	codec->dapm_event = wm8980_dapm_event;
++	codec->dai = &wm8980_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8980_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8980_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8980_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8980_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8980_reg);
++
++	wm8980_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8980_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8980_add_controls(codec);
++	wm8980_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 struct snd_soc_device *wm8980_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8980 2 wire address is 0x1a
++ */
++#define I2C_DRIVERID_WM8980 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8980_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8980_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8980_socdev;
++	struct wm8980_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++
++	i2c_set_clientdata(i2c, codec);
++
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if(ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8980_init(socdev);
++	if(ret < 0) {
++		err("failed to initialise WM8980\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++
++}
++
++static int wm8980_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++
++	i2c_detach_client(client);
++
++	kfree(codec->reg_cache);
++	kfree(client);
++
++	return 0;
++}
++
++static int wm8980_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8980_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8980_i2c_driver = {
++	.driver = {
++		.name = "WM8980 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8980,
++	.attach_adapter = wm8980_i2c_attach,
++	.detach_client =  wm8980_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8980",
++	.driver = &wm8980_i2c_driver,
++};
++#endif
++
++static int wm8980_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8980_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8980 Audio Codec %s", WM8980_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);
++
++	wm8980_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8980_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8980_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)
++		wm8980_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8980_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8980 = {
++	.probe = 	wm8980_probe,
++	.remove = 	wm8980_remove,
++	.suspend = 	wm8980_suspend,
++	.resume =	wm8980_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8980);
++
++MODULE_DESCRIPTION("ASoC WM8980 driver");
++MODULE_AUTHOR("Mike Arthur");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8980.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8980.h
+@@ -0,0 +1,77 @@
++/*
++ * wm8980.h  --  WM8980 Soc Audio driver
++ *
++ * 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 _WM8980_H
++#define _WM8980_H
++
++/* WM8980 register space */
++
++#define WM8980_RESET		0x0
++#define WM8980_POWER1		0x1
++#define WM8980_POWER2		0x2
++#define WM8980_POWER3		0x3
++#define WM8980_IFACE		0x4
++#define WM8980_COMP			0x5
++#define WM8980_CLOCK		0x6
++#define WM8980_ADD			0x7
++#define WM8980_GPIO			0x8
++#define WM8980_JACK1        0x9
++#define WM8980_DAC			0xa
++#define WM8980_DACVOLL	    0xb
++#define WM8980_DACVOLR      0xc
++#define WM8980_JACK2        0xd
++#define WM8980_ADC			0xe
++#define WM8980_ADCVOLL		0xf
++#define WM8980_ADCVOLR      0x10
++#define WM8980_EQ1			0x12
++#define WM8980_EQ2			0x13
++#define WM8980_EQ3			0x14
++#define WM8980_EQ4			0x15
++#define WM8980_EQ5			0x16
++#define WM8980_DACLIM1		0x18
++#define WM8980_DACLIM2		0x19
++#define WM8980_NOTCH1		0x1b
++#define WM8980_NOTCH2		0x1c
++#define WM8980_NOTCH3		0x1d
++#define WM8980_NOTCH4		0x1e
++#define WM8980_ALC1			0x20
++#define WM8980_ALC2			0x21
++#define WM8980_ALC3			0x22
++#define WM8980_NGATE		0x23
++#define WM8980_PLLN			0x24
++#define WM8980_PLLK1		0x25
++#define WM8980_PLLK2		0x26
++#define WM8980_PLLK3		0x27
++#define WM8980_VIDEO		0x28
++#define WM8980_3D           0x29
++#define WM8980_BEEP         0x2b
++#define WM8980_INPUT		0x2c
++#define WM8980_INPPGAL  	0x2d
++#define WM8980_INPPGAR      0x2e
++#define WM8980_ADCBOOSTL	0x2f
++#define WM8980_ADCBOOSTR    0x30
++#define WM8980_OUTPUT		0x31
++#define WM8980_MIXL	        0x32
++#define WM8980_MIXR         0x33
++#define WM8980_HPVOLL		0x34
++#define WM8980_HPVOLR       0x35
++#define WM8980_SPKVOLL      0x36
++#define WM8980_SPKVOLR      0x37
++#define WM8980_OUT3MIX		0x38
++#define WM8980_MONOMIX      0x39
++
++#define WM8980_CACHEREGNUM 	58
++
++struct wm8980_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8980_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8980;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/at91/eti_b1_wm8731.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/at91/eti_b1_wm8731.c
+@@ -0,0 +1,230 @@
++/*
++ * eti_b1_wm8731  --  SoC audio for Endrelia ETI_B1.
++ *
++ * Author:	Frank Mandarino <fmandarino at endrelia.com>
++ *		Endrelia Technologies Inc.
++ * Created:	Mar 29, 2006
++ *
++ * Based on corgi.c by:
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Copyright 2005 Openedhand Ltd.
++ *
++ * Authors: Liam Girdwood <liam.girdwood at wolfsonmicro.com>
++ *          Richard Purdie <richard at openedhand.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.
++ *
++ *  Revision history
++ *    30th Nov 2005   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/clk.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/arch/at91rm9200.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/hardware.h>
++
++#include "../codecs/wm8731.h"
++#include "at91rm9200-pcm.h"
++
++#if 0
++#define	DBG(x...)	printk(KERN_INFO "eti_b1_wm8731:" x)
++#else
++#define	DBG(x...)
++#endif
++
++static struct clk *pck1_clk;
++static struct clk *pllb_clk;
++
++static int eti_b1_startup(snd_pcm_substream_t *substream)
++{
++	/* Start PCK1 clock. */
++	clk_enable(pck1_clk);
++	DBG("pck1 started\n");
++
++	return 0;
++}
++
++static void eti_b1_shutdown(snd_pcm_substream_t *substream)
++{
++	/* Stop PCK1 clock. */
++	clk_disable(pck1_clk);
++	DBG("pck1 stopped\n");
++}
++
++static struct snd_soc_ops eti_b1_ops = {
++	.startup = eti_b1_startup,
++	.shutdown = eti_b1_shutdown,
++};
++
++
++static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
++	SND_SOC_DAPM_MIC("Int Mic", NULL),
++	SND_SOC_DAPM_SPK("Ext Spk", NULL),
++};
++
++static const char *intercon[][3] = {
++
++	/* speaker connected to LHPOUT */
++	{"Ext Spk", NULL, "LHPOUT"},
++
++	/* mic is connected to Mic Jack, with WM8731 Mic Bias */
++	{"MICIN", NULL, "Mic Bias"},
++	{"Mic Bias", NULL, "Int Mic"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++/*
++ * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
++ */
++static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
++{
++	int i;
++
++	DBG("eti_b1_wm8731_init() called\n");
++
++	/* Add specific widgets */
++	for(i = 0; i < ARRAY_SIZE(eti_b1_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &eti_b1_dapm_widgets[i]);
++	}
++
++	/* Set up specific audio path interconnects */
++	for(i = 0; intercon[i][0] != NULL; i++) {
++		snd_soc_dapm_connect_input(codec, intercon[i][0],
++			intercon[i][1], intercon[i][2]);
++	}
++
++	/* not connected */
++	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
++	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
++
++	/* always connected */
++	snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
++	snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
++
++	snd_soc_dapm_sync_endpoints(codec);
++
++	return 0;
++}
++
++unsigned int eti_b1_config_sysclk(struct snd_soc_pcm_runtime *rtd,
++	struct snd_soc_clock_info *info)
++{
++	if(info->bclk_master & SND_SOC_DAIFMT_CBS_CFS) {
++		return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 12000000);
++	}
++	return 0;
++}
++
++static struct snd_soc_dai_link eti_b1_dai = {
++	.name = "WM8731",
++	.stream_name = "WM8731",
++	.cpu_dai = &at91rm9200_i2s_dai[1],
++	.codec_dai = &wm8731_dai,
++	.init = eti_b1_wm8731_init,
++	.config_sysclk = eti_b1_config_sysclk,
++};
++
++static struct snd_soc_machine snd_soc_machine_eti_b1 = {
++	.name = "ETI_B1",
++	.dai_link = &eti_b1_dai,
++	.num_links = 1,
++	.ops = &eti_b1_ops,
++};
++
++static struct wm8731_setup_data eti_b1_wm8731_setup = {
++	.i2c_address = 0x1a,
++};
++
++static struct snd_soc_device eti_b1_snd_devdata = {
++	.machine = &snd_soc_machine_eti_b1,
++	.platform = &at91rm9200_soc_platform,
++	.codec_dev = &soc_codec_dev_wm8731,
++	.codec_data = &eti_b1_wm8731_setup,
++};
++
++static struct platform_device *eti_b1_snd_device;
++
++static int __init eti_b1_init(void)
++{
++	int ret;
++	u32 ssc_pio_lines;
++
++	eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
++	if (!eti_b1_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
++	eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
++
++	ret = platform_device_add(eti_b1_snd_device);
++	if (ret) {
++		platform_device_put(eti_b1_snd_device);
++		return ret;
++	}
++
++ 	ssc_pio_lines = AT91_PB6_TF1 | AT91_PB7_TK1 | AT91_PB8_TD1
++			| AT91_PB9_RD1 /* | AT91_PB10_RK1 | AT91_PB11_RF1 */;
++
++	/* Reset all PIO registers and assign lines to peripheral A */
++ 	at91_sys_write(AT91_PIOB + PIO_PDR,  ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_ODR,  ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_IDR,  ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_ASR,  ssc_pio_lines);
++ 	at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
++
++	/*
++	 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
++	 */
++	pllb_clk = clk_get(NULL, "pllb");
++	pck1_clk = clk_get(NULL, "pck1");
++
++	clk_set_parent(pck1_clk, pllb_clk);
++	clk_set_rate(pck1_clk, 12000000);
++
++	DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
++
++	/* assign the GPIO pin to PCK1 */
++	at91_set_B_periph(AT91_PIN_PA24, 0);
++
++	return ret;
++}
++
++static void __exit eti_b1_exit(void)
++{
++	clk_put(pck1_clk);
++	clk_put(pllb_clk);
++
++	platform_device_unregister(eti_b1_snd_device);
++}
++
++module_init(eti_b1_init);
++module_exit(eti_b1_exit);
++
++/* Module information */
++MODULE_AUTHOR("Frank Mandarino <fmandarino at endrelia.com>");
++MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8510.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8510.c
+@@ -0,0 +1,895 @@
++/*
++ * wm8510.c  --  WM8510 ALSA Soc Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ *
++ * Author: Liam Girdwood <liam.girdwood at wolfsonmicro.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/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8510.h"
++
++#define AUDIO_NAME "wm8510"
++#define WM8510_VERSION "0.5"
++
++/*
++ * Debug
++ */
++
++#define WM8510_DEBUG 0
++
++#ifdef WM8510_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8510;
++
++/*
++ * wm8510 register cache
++ * We can't read the WM8510 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0050, 0x0000, 0x0140, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x00ff,
++    0x0000, 0x0000, 0x0100, 0x00ff,
++    0x0000, 0x0000, 0x012c, 0x002c,
++    0x002c, 0x002c, 0x002c, 0x0000,
++    0x0032, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0038, 0x000b, 0x0032, 0x0000,
++    0x0008, 0x000c, 0x0093, 0x00e9,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0003, 0x0010, 0x0000, 0x0000,
++    0x0000, 0x0002, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0039, 0x0000,
++    0x0000,
++};
++
++#define WM8510_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
++	SND_SOC_DAIFMT_IB_IF)
++
++#define WM8510_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8510_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)
++
++#define WM8794_BCLK \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | SND_SOC_FSBD(8) |\
++	 SND_SOC_FSBD(16) | SND_SOC_FSBD(32))
++
++#define WM8794_HIFI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_mode wm8510_modes[] = {
++	/* codec frame and clock master modes */
++	{
++		.fmt = WM8510_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8794_HIFI_BITS,
++		.pcmrate = WM8510_RATES,
++		.pcmdir = WM8510_DIR,
++		.fs = 256,
++		.bfs = WM8794_BCLK,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8510_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = WM8794_HIFI_BITS,
++		.pcmrate = WM8510_RATES,
++		.pcmdir = WM8510_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8510 register cache
++ */
++static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec * codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8510_RESET)
++		return 0;
++	if (reg >= WM8510_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8510 register cache
++ */
++static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8510_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8510 register space
++ */
++static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8510 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8510_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -EIO;
++}
++
++#define wm8510_reset(c)	wm8510_write(c, WM8510_RESET, 0)
++
++static const char *wm8510_companding[] = {"Off", "NC", "u-law", "A-law" };
++static const char *wm8510_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
++static const char *wm8510_alc[] = {"ALC", "Limiter" };
++
++static const struct soc_enum wm8510_enum[] = {
++	SOC_ENUM_SINGLE(WM8510_COMP, 1, 4, wm8510_companding), /* adc */
++	SOC_ENUM_SINGLE(WM8510_COMP, 3, 4, wm8510_companding), /* dac */
++	SOC_ENUM_SINGLE(WM8510_DAC,  4, 4, wm8510_deemp),
++	SOC_ENUM_SINGLE(WM8510_ALC3,  8, 2, wm8510_alc),
++};
++
++static const struct snd_kcontrol_new wm8510_snd_controls[] = {
++
++SOC_SINGLE("Digital Loopback Switch", WM8510_COMP, 0, 1, 0),
++
++SOC_ENUM("DAC Companding", wm8510_enum[1]),
++SOC_ENUM("ADC Companding", wm8510_enum[0]),
++
++SOC_ENUM("Playback De-emphasis", wm8510_enum[2]),
++SOC_SINGLE("DAC Inversion Switch", WM8510_DAC, 0, 1, 0),
++
++SOC_SINGLE("Master Playback Volume", WM8510_DACVOL, 0, 127, 0),
++
++SOC_SINGLE("High Pass Filter Switch", WM8510_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Cut Off", WM8510_ADC, 4, 7, 0),
++SOC_SINGLE("ADC Inversion Switch", WM8510_COMP, 0, 1, 0),
++
++SOC_SINGLE("Capture Volume", WM8510_ADCVOL,  0, 127, 0),
++
++SOC_SINGLE("DAC Playback Limiter Switch", WM8510_DACLIM1,  8, 1, 0),
++SOC_SINGLE("DAC Playback Limiter Decay", WM8510_DACLIM1,  4, 15, 0),
++SOC_SINGLE("DAC Playback Limiter Attack", WM8510_DACLIM1,  0, 15, 0),
++
++SOC_SINGLE("DAC Playback Limiter Threshold", WM8510_DACLIM2,  4, 7, 0),
++SOC_SINGLE("DAC Playback Limiter Boost", WM8510_DACLIM2,  0, 15, 0),
++
++SOC_SINGLE("ALC Enable Switch", WM8510_ALC1,  8, 1, 0),
++SOC_SINGLE("ALC Capture Max Gain", WM8510_ALC1,  3, 7, 0),
++SOC_SINGLE("ALC Capture Min Gain", WM8510_ALC1,  0, 7, 0),
++
++SOC_SINGLE("ALC Capture ZC Switch", WM8510_ALC2,  8, 1, 0),
++SOC_SINGLE("ALC Capture Hold", WM8510_ALC2,  4, 7, 0),
++SOC_SINGLE("ALC Capture Target", WM8510_ALC2,  0, 15, 0),
++
++SOC_ENUM("ALC Capture Mode", wm8510_enum[3]),
++SOC_SINGLE("ALC Capture Decay", WM8510_ALC3,  4, 15, 0),
++SOC_SINGLE("ALC Capture Attack", WM8510_ALC3,  0, 15, 0),
++
++SOC_SINGLE("ALC Capture Noise Gate Switch", WM8510_NGATE,  3, 1, 0),
++SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8510_NGATE,  0, 7, 0),
++
++SOC_SINGLE("Capture PGA ZC Switch", WM8510_INPPGA,  7, 1, 0),
++SOC_SINGLE("Capture PGA Volume", WM8510_INPPGA,  0, 63, 0),
++
++SOC_SINGLE("Speaker Playback ZC Switch", WM8510_SPKVOL,  7, 1, 0),
++SOC_SINGLE("Speaker Playback Switch", WM8510_SPKVOL,  6, 1, 1),
++SOC_SINGLE("Speaker Playback Volume", WM8510_SPKVOL,  0, 63, 0),
++
++SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST,  8, 1, 0),
++SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm8510_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8510_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Speaker Output Mixer */
++static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_SPKMIX, 5, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_SPKMIX, 0, 1, 1),
++};
++
++/* Mono Output Mixer */
++static const struct snd_kcontrol_new wm8510_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_MONOMIX, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_MONOMIX, 2, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 1),
++};
++
++/* AUX Input boost vol */
++static const struct snd_kcontrol_new wm8510_aux_boost_controls =
++SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0);
++
++/* Mic Input boost vol */
++static const struct snd_kcontrol_new wm8510_mic_boost_controls =
++SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0);
++
++/* Capture boost switch */
++static const struct snd_kcontrol_new wm8510_capture_boost_controls =
++SOC_DAPM_SINGLE("Capture Boost Switch", WM8510_INPPGA,  6, 1, 0);
++
++/* Aux In to PGA */
++static const struct snd_kcontrol_new wm8510_aux_capture_boost_controls =
++SOC_DAPM_SINGLE("Aux Capture Boost Switch", WM8510_INPPGA,  2, 1, 0);
++
++/* Mic P In to PGA */
++static const struct snd_kcontrol_new wm8510_micp_capture_boost_controls =
++SOC_DAPM_SINGLE("Mic P Capture Boost Switch", WM8510_INPPGA,  0, 1, 0);
++
++/* Mic N In to PGA */
++static const struct snd_kcontrol_new wm8510_micn_capture_boost_controls =
++SOC_DAPM_SINGLE("Mic N Capture Boost Switch", WM8510_INPPGA,  1, 1, 0);
++
++static const struct snd_soc_dapm_widget wm8510_dapm_widgets[] = {
++SND_SOC_DAPM_MIXER("Speaker Mixer", WM8510_POWER3, 2, 0,
++	&wm8510_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm8510_speaker_mixer_controls)),
++SND_SOC_DAPM_MIXER("Mono Mixer", WM8510_POWER3, 3, 0,
++	&wm8510_mono_mixer_controls[0],
++	ARRAY_SIZE(wm8510_mono_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8510_POWER3, 0, 0),
++SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8510_POWER3, 0, 0),
++SND_SOC_DAPM_PGA("Aux Input", WM8510_POWER1, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0, NULL, 0),
++
++SND_SOC_DAPM_PGA("Aux Boost", SND_SOC_NOPM, 0, 0,
++	&wm8510_aux_boost_controls, 1),
++SND_SOC_DAPM_PGA("Mic Boost", SND_SOC_NOPM, 0, 0,
++	&wm8510_mic_boost_controls, 1),
++SND_SOC_DAPM_SWITCH("Capture Boost", SND_SOC_NOPM, 0, 0,
++	&wm8510_capture_boost_controls),
++
++SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, NULL, 0),
++
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8510_POWER1, 4, 0),
++
++SND_SOC_DAPM_INPUT("MICN"),
++SND_SOC_DAPM_INPUT("MICP"),
++SND_SOC_DAPM_INPUT("AUX"),
++SND_SOC_DAPM_OUTPUT("MONOOUT"),
++SND_SOC_DAPM_OUTPUT("SPKOUTP"),
++SND_SOC_DAPM_OUTPUT("SPKOUTN"),
++};
++
++static const char *audio_map[][3] = {
++	/* Mono output mixer */
++	{"Mono Mixer", "PCM Playback Switch", "DAC"},
++	{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Speaker output mixer */
++	{"Speaker Mixer", "PCM Playback Switch", "DAC"},
++	{"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Outputs */
++	{"Mono Out", NULL, "Mono Mixer"},
++	{"MONOOUT", NULL, "Mono Out"},
++	{"SpkN Out", NULL, "Speaker Mixer"},
++	{"SpkP Out", NULL, "Speaker Mixer"},
++	{"SPKOUTN", NULL, "SpkN Out"},
++	{"SPKOUTP", NULL, "SpkP Out"},
++
++	/* Boost Mixer */
++	{"Boost Mixer", NULL, "ADC"},
++    {"Capture Boost Switch", "Aux Capture Boost Switch", "AUX"},
++	{"Aux Boost", "Aux Volume", "Boost Mixer"},
++    {"Capture Boost", "Capture Switch", "Boost Mixer"},
++	{"Mic Boost", "Mic Volume", "Boost Mixer"},
++
++	/* Inputs */
++	{"MICP", NULL, "Mic Boost"},
++	{"MICN", NULL, "Mic PGA"},
++	{"Mic PGA", NULL, "Capture Boost"},
++	{"AUX", NULL, "Aux Input"},
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8510_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8510_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8510_dapm_widgets[i]);
++	}
++
++	/* set up audio path audio_mapnects */
++	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;
++}
++
++struct pll_ {
++	unsigned int in_hz, out_hz;
++	unsigned int pre:4; /* prescale - 1 */
++	unsigned int n:4;
++	unsigned int k;
++};
++
++struct pll_ pll[] = {
++	{12000000, 11289600, 0, 7, 0x86c220},
++	{12000000, 12288000, 0, 8, 0x3126e8},
++	{13000000, 11289600, 0, 6, 0xf28bd4},
++	{13000000, 12288000, 0, 7, 0x8fd525},
++	{12288000, 11289600, 0, 7, 0x59999a},
++	{11289600, 12288000, 0, 8, 0x80dee9},
++	/* liam - add more entries */
++};
++
++static int set_pll(struct snd_soc_codec *codec, unsigned int in,
++	unsigned int out)
++{
++	int i;
++	u16 reg;
++
++	if(out == 0) {
++		reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
++		wm8510_write(codec, WM8510_POWER1, reg & 0x1df);
++		return 0;
++	}
++
++	for(i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (in == pll[i].in_hz && out == pll[i].out_hz) {
++			wm8510_write(codec, WM8510_PLLN, (pll[i].pre << 4) | pll[i].n);
++			wm8510_write(codec, WM8510_PLLK1, pll[i].k >> 18);
++			wm8510_write(codec, WM8510_PLLK1, (pll[i].k >> 9) && 0x1ff);
++			wm8510_write(codec, WM8510_PLLK1, pll[i].k && 0x1ff);
++			reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
++			wm8510_write(codec, WM8510_POWER1, reg | 0x020);
++			return 0;
++		}
++	}
++	return -EINVAL;
++}
++
++/* mclk dividers * 2 */
++static unsigned char mclk_div[] = {2, 3, 4, 6, 8, 12, 16, 24};
++
++/* we need 256FS to drive the DAC's and ADC's */
++static unsigned int wm8510_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if ((best_clk >> 1) * mclk_div[i] == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = mclk_div[i];
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == clk) {
++			for (j = 0; j < ARRAY_SIZE(mclk_div); j++) {
++				if (pll[i].out_hz == mclk_div[j] * (best_clk >> 1)) {
++					dai->pll_in = clk;
++					dai->pll_out = pll[i].out_hz;
++					dai->clk_div = mclk_div[j];
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++static int wm8510_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *dai = rtd->codec_dai;
++	u16 iface = 0, bfs, clk = 0, adn;
++	int fs = 48000 << 7, i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	switch (bfs) {
++	case 2:
++		clk |= 0x1 << 2;
++		break;
++	case 4:
++		clk |= 0x2 << 2;
++		break;
++	case 8:
++		clk |= 0x3 << 2;
++		break;
++	case 16:
++		clk |= 0x4 << 2;
++		break;
++	case 32:
++		clk |= 0x5 << 2;
++		break;
++	}
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		clk |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0010;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0008;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x00018;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0020;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0040;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x0060;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0180;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0100;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0080;
++		break;
++	}
++
++	/* filter coefficient */
++	adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1;
++	switch (rtd->codec_dai->dai_runtime.pcmrate) {
++	case SNDRV_PCM_RATE_8000:
++		adn |= 0x5 << 1;
++		fs = 8000 << 7;
++		break;
++	case SNDRV_PCM_RATE_11025:
++		adn |= 0x4 << 1;
++		fs = 11025 << 7;
++		break;
++	case SNDRV_PCM_RATE_16000:
++		adn |= 0x3 << 1;
++		fs = 16000 << 7;
++		break;
++	case SNDRV_PCM_RATE_22050:
++		adn |= 0x2 << 1;
++		fs = 22050 << 7;
++		break;
++	case SNDRV_PCM_RATE_32000:
++		adn |= 0x1 << 1;
++		fs = 32000 << 7;
++		break;
++	case SNDRV_PCM_RATE_44100:
++		fs = 44100 << 7;
++		break;
++	}
++
++	/* do we need to enable the PLL */
++	if(dai->pll_in)
++		set_pll(codec, dai->pll_in, dai->pll_out);
++
++	/* divide the clock to 256 fs */
++	for(i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if (dai->clk_div == mclk_div[i]) {
++			clk |= i << 5;
++			clk &= 0xff;
++			goto set;
++		}
++	}
++
++set:
++	/* set iface */
++	wm8510_write(codec, WM8510_IFACE, iface);
++	wm8510_write(codec, WM8510_CLOCK, clk);
++
++	return 0;
++}
++
++static int wm8510_hw_free(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	set_pll(codec, 0, 0);
++	return 0;
++}
++
++static int wm8510_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf;
++	if(mute)
++		wm8510_write(codec, WM8510_DAC, mute_reg | 0x40);
++	else
++		wm8510_write(codec, WM8510_DAC, mute_reg);
++	return 0;
++}
++
++/* liam need to make this lower power with dapm */
++static int wm8510_dapm_event(struct snd_soc_codec *codec, int event)
++{
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, clk and osc on, dac unmute, active */
++		wm8510_write(codec, WM8510_POWER1, 0x1ff);
++		wm8510_write(codec, WM8510_POWER2, 0x1ff);
++		wm8510_write(codec, WM8510_POWER3, 0x1ff);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, dac mute, inactive */
++
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8510_write(codec, WM8510_POWER1, 0x0);
++		wm8510_write(codec, WM8510_POWER2, 0x0);
++		wm8510_write(codec, WM8510_POWER3, 0x0);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8510_dai = {
++	.name = "WM8510 HiFi",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 1,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 1,
++	},
++	.config_sysclk = wm8510_config_sysclk,
++	.digital_mute = wm8510_mute,
++	.ops = {
++		.prepare = wm8510_pcm_prepare,
++		.hw_free = wm8510_hw_free,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8510_modes),
++		.mode = wm8510_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8510_dai);
++
++static int wm8510_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;
++
++	wm8510_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8510_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8510_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8510_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8510 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8510_init(struct snd_soc_device *socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "WM8510";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8510_read_reg_cache;
++	codec->write = wm8510_write;
++	codec->dapm_event = wm8510_dapm_event;
++	codec->dai = &wm8510_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8510_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8510_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8510_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8510_reg);
++
++	wm8510_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8510_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8510_add_controls(codec);
++	wm8510_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 struct snd_soc_device *wm8510_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8510 2 wire address is 0x1a
++ */
++#define I2C_DRIVERID_WM8510 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8510_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8510_socdev;
++	struct wm8510_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++	i2c_set_clientdata(i2c, codec);
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if(ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8510_init(socdev);
++	if(ret < 0) {
++		err("failed to initialise WM8510\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++}
++
++static int wm8510_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++	i2c_detach_client(client);
++	kfree(codec->reg_cache);
++	kfree(client);
++	return 0;
++}
++
++static int wm8510_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8510_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8510_i2c_driver = {
++	.driver = {
++		.name = "WM8510 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8510,
++	.attach_adapter = wm8510_i2c_attach,
++	.detach_client =  wm8510_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8510",
++	.driver = &wm8510_i2c_driver,
++};
++#endif
++
++static int wm8510_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8510_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8510 Audio Codec %s", WM8510_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);
++
++	wm8510_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8510_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8510_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)
++		wm8510_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8510_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8510 = {
++	.probe = 	wm8510_probe,
++	.remove = 	wm8510_remove,
++	.suspend = 	wm8510_suspend,
++	.resume =	wm8510_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
++
++MODULE_DESCRIPTION("ASoC WM8510 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8510.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8510.h
+@@ -0,0 +1,64 @@
++/*
++ * wm8510.h  --  WM8510 Soc Audio driver
++ *
++ * 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 _WM8510_H
++#define _WM8510_H
++
++/* WM8510 register space */
++
++#define WM8510_RESET		0x0
++#define WM8510_POWER1		0x1
++#define WM8510_POWER2		0x2
++#define WM8510_POWER3		0x3
++#define WM8510_IFACE		0x4
++#define WM8510_COMP			0x5
++#define WM8510_CLOCK		0x6
++#define WM8510_ADD			0x7
++#define WM8510_GPIO			0x8
++#define WM8510_DAC			0xa
++#define WM8510_DACVOL		0xb
++#define WM8510_ADC			0xe
++#define WM8510_ADCVOL		0xf
++#define WM8510_EQ1			0x12
++#define WM8510_EQ2			0x13
++#define WM8510_EQ3			0x14
++#define WM8510_EQ4			0x15
++#define WM8510_EQ5			0x16
++#define WM8510_DACLIM1		0x18
++#define WM8510_DACLIM2		0x19
++#define WM8510_NOTCH1		0x1b
++#define WM8510_NOTCH2		0x1c
++#define WM8510_NOTCH3		0x1d
++#define WM8510_NOTCH4		0x1e
++#define WM8510_ALC1			0x20
++#define WM8510_ALC2			0x21
++#define WM8510_ALC3			0x22
++#define WM8510_NGATE		0x23
++#define WM8510_PLLN			0x24
++#define WM8510_PLLK1		0x25
++#define WM8510_PLLK2		0x26
++#define WM8510_PLLK3		0x27
++#define WM8510_ATTEN		0x28
++#define WM8510_INPUT		0x2c
++#define WM8510_INPPGA		0x2d
++#define WM8510_ADCBOOST		0x2f
++#define WM8510_OUTPUT		0x31
++#define WM8510_SPKMIX		0x32
++#define WM8510_SPKVOL		0x36
++#define WM8510_MONOMIX		0x38
++
++#define WM8510_CACHEREGNUM 	57
++
++struct wm8510_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8510_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8510;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/imx/imx-ac97.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx-ac97.c
+@@ -0,0 +1,281 @@
++/*
++ * imx-ssi.c  --  SSI driver for Freescale IMX
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Based on mxc-alsa-mc13783 (C) 2006 Freescale.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    29th Aug 2006   Initial version.
++ *
++ */
++
++#define IMX_AC97_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)
++
++/* may need to expand this */
++static struct snd_soc_dai_mode imx_ssi_ac97_modes[] = {
++	{0, 0,	SNDRV_PCM_FMTBIT_S16_LE,	IMX_AC97_RATES},
++	{0, 0,	SNDRV_PCM_FMTBIT_S18_3LE,	IMX_AC97_RATES},
++	{0, 0,	SNDRV_PCM_FMTBIT_S20_3LE,	IMX_AC97_RATES},
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_out = {
++	.name			= "SSI1 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = emi_2_per,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_STX0,
++		.event_id = DMA_REQ_SSI1_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_in = {
++	.name			= "SSI1 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_SRX0,
++		.event_id = DMA_REQ_SSI1_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_out = {
++	.name			= "SSI2 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_STX0,
++		.event_id = DMA_REQ_SSI2_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_in = {
++	.name			= "SSI2 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_SRX0,
++		.event_id = DMA_REQ_SSI2_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static unsigned short imx_ssi_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
++{
++}
++
++static void imx_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
++{
++}
++
++static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
++{
++}
++
++static void imx_ssi_ac97_cold_reset(struct snd_ac97 *ac97)
++{
++}
++
++struct snd_ac97_bus_ops soc_ac97_ops = {
++	.read	= imx_ssi_ac97_read,
++	.write	= imx_ssi_ac97_write,
++	.warm_reset	= imx_ssi_ac97_warm_reset,
++	.reset	= imx_ssi_ac97_cold_reset,
++};
++
++
++static intimx_ssi1_ac97_probe(struct platform_device *pdev)
++{
++	int ret;
++
++
++	return ret;
++}
++
++static void imx_ssi1_ac97_remove(struct platform_device *pdev)
++{
++	/* shutdown SSI */
++		if(rtd->cpu_dai->id == 0)
++			SSI1_SCR &= ~SSI_SCR_SSIEN;
++		else
++			SSI2_SCR &= ~SSI_SCR_SSIEN;
++	}
++
++}
++
++static int imx_ssi1_ac97_prepare(struct snd_pcm_substream *substream)
++{
++	// set vra
++}
++
++static int imx_ssi_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (!rtd->cpu_dai->active) {
++
++	}
++
++	return 0;
++}
++
++static int imx_ssi1_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++			SSI1_SCR |= SSI_SCR_TE;
++			SSI1_SIER |= SSI_SIER_TDMAE;
++		} else {
++			SSI1_SCR |= SSI_SCR_RE;
++			SSI1_SIER |= SSI_SIER_RDMAE;
++		}
++		SSI1_SCR |= SSI_SCR_SSIEN;
++
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR |= SSI_SCR_TE;
++		else
++			SSI1_SCR |= SSI_SCR_RE;
++	break
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR &= ~SSI_SCR_TE;
++		else
++			SSI1_SCR &= ~SSI_SCR_RE;
++	break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void imx_ssi_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++
++}
++
++#ifdef CONFIG_PM
++static int imx_ssi_suspend(struct platform_device *dev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR &= ~SSI_SCR_SSIEN;
++	else
++		SSI2_SCR &= ~SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++static int imx_ssi_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR |= SSI_SCR_SSIEN;
++	else
++		SSI2_SCR |= SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++#else
++#define imx_ssi_suspend	NULL
++#define imx_ssi_resume	NULL
++#endif
++
++static unsigned int imx_ssi_config_ac97_sysclk(struct snd_soc_cpu_dai *iface,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	return clk;
++}
++
++struct snd_soc_cpu_dai imx_ssi_ac97_dai = {
++	.name = "imx-ac97-1",
++	.id = 0,
++	.type = SND_SOC_DAI_AC97,
++	.suspend = imx_ssi_suspend,
++	.resume = imx_ssi_resume,
++	.config_sysclk = imx_ssi_ac97_config_sysclk,
++	.playback = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.ops = {
++		.probe = imx_ac97_probe,
++		.remove = imx_ac97_shutdown,
++		.trigger = imx_ssi1_trigger,
++		.prepare = imx_ssi_ac97_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_ssi_ac97_modes),
++		.mode = imx_ssi_ac97_modes,},
++},
++{
++	.name = "imx-ac97-2",
++	.id = 1,
++	.type = SND_SOC_DAI_AC97,
++	.suspend = imx_ssi_suspend,
++	.resume = imx_ssi_resume,
++	.config_sysclk = imx_ssi_ac97_config_sysclk,
++	.playback = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.ops = {
++		.probe = imx_ac97_probe,
++		.remove = imx_ac97_shutdown,
++		.trigger = imx_ssi1_trigger,
++		.prepare = imx_ssi_ac97_prepare,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_ssi_ac97_modes),
++		.mode = imx_ssi_ac97_modes,},
++};
++
++EXPORT_SYMBOL_GPL(imx_ssi_ac97_dai);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("i.MX ASoC AC97 driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/imx/imx-i2s.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx-i2s.c
+@@ -0,0 +1,473 @@
++/*
++ * imx-ssi.c  --  SSI driver for Freescale IMX
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  Based on mxc-alsa-mc13783 (C) 2006 Freescale.
++ *
++ *  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.
++ *
++ *  Revision history
++ *    29th Aug 2006   Initial version.
++ *
++ */
++
++#define IMX_SSI_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J |\
++	SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_DSP__A |\
++	SND_SOC_DAIFMT_DSP_B  | SND_SOC_DAIFMT_CBS_CFS |\
++	SND_SOC_DAIFMT_CBM_CFS |  SND_SOC_DAIFMT_CBS_CFM |\
++	SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF)
++
++#define IMX_SSI_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define IMX_SSI_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 | SNDRV_PCM_RATE_88200 | \
++	SNDRV_PCM_RATE_96000)
++
++#define IMX_SSI_BITS \
++	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
++	SNDRV_PCM_FMTBIT_S24_LE)
++
++static struct snd_soc_dai_mode imx_ssi_pcm_modes[] = {
++
++	/* frame master and clock slave mode */
++	{
++		.fmt = IMX_SSI_DAIFMT | SND_SOC_DAIFMT_CBM_CFS,
++		.tdm = SND_SOC_DAITDM_LRDW(0,0),
++		.pcmfmt = IMX_SSI_BITS,
++		.pcmrate = IMX_SSI_RATES,
++		.pcmdir = IMX_SSI_DIR,
++		.flags =  SND_SOC_DAI_BFS_RCW,
++		.fs = SND_SOC_FS_ALL,
++		.bfs = SND_SOC_FSBW(1) | SND_SOC_FSBW(2),
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_out = {
++	.name			= "SSI1 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = emi_2_per,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_STX0,
++		.event_id = DMA_REQ_SSI1_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi1_pcm_stereo_in = {
++	.name			= "SSI1 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI1_SRX0,
++		.event_id = DMA_REQ_SSI1_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_out = {
++	.name			= "SSI2 PCM Stereo out",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_TXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_STX0,
++		.event_id = DMA_REQ_SSI2_TX1,
++		.peripheral_type = SSI,
++	},
++};
++
++static imx_pcm_dma_params_t imx_ssi2_pcm_stereo_in = {
++	.name			= "SSI2 PCM Stereo in",
++	.params = {
++		.bd_number = 1,
++		.transfer_type = per_2_emi,
++		.watermark_level = SDMA_RXFIFO_WATERMARK,
++		.word_size = TRANSFER_16BIT, // maybe add this in setup func
++		.per_address = SSI2_SRX0,
++		.event_id = DMA_REQ_SSI2_RX1,
++		.peripheral_type = SSI,
++	},
++};
++
++
++static int imx_ssi_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	if (!rtd->cpu_dai->active) {
++
++	}
++
++	return 0;
++}
++
++static int imx_ssi1_hw_tx_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 bfs, div;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
++
++	SSI1_STCR = 0;
++	SSI1_STCCR = 0;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		SSI1_STCR |= SSI_STCR_TSCKP | SSI_STCR_TFSI |
++			SSI_STCR_TEFS | SSI_STCR_TXBIT0;
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		SSI1_STCR |= SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TXBIT0;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		SSI1_STCR |= SSI_STCR_TEFS; // data 1 bit after sync
++	case SND_SOC_DAIFMT_DSP_A:
++		SSI1_STCR |= SSI_STCR_TFSL; // frame is 1 bclk long
++
++		/* DAI clock inversion */
++		switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++		case SND_SOC_DAIFMT_IB_IF:
++			SSI1_STCR |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
++			break;
++		case SND_SOC_DAIFMT_IB_NF:
++			SSI1_STCR |= SSI_STCR_TSCKP;
++			break;
++		case SND_SOC_DAIFMT_NB_IF:
++			SSI1_STCR |= SSI_STCR_TFSI;
++			break;
++		}
++		break;
++	}
++
++	/* DAI data (word) size */
++	switch(rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		SSI1_STCCR |= SSI_STCCR_WL(16);
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		SSI1_STCCR |= SSI_STCCR_WL(20);
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		SSI1_STCCR |= SSI_STCCR_WL(24);
++		break;
++	}
++
++	/* DAI clock master masks */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK){
++	case SND_SOC_DAIFMT_CBM_CFM:
++		SSI1_STCR |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		SSI1_STCR |= SSI_STCR_TFDIR;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		SSI1_STCR |= SSI_STCR_TXDIR;
++		break;
++	}
++
++	/* DAI BCLK ratio to SYSCLK / MCLK */
++	/* prescaler modulus - todo */
++	switch (bfs) {
++	case 2:
++		break;
++	case 4:
++		break;
++	case 8:
++		break;
++	case 16:
++		break;
++	}
++
++	/* TDM - todo, only fifo 0 atm */
++	SSI1_STCR |= SSI_STCR_TFEN0;
++	SSI1_STCCR |= SSI_STCCR_DC(params_channels(params));
++
++	return 0;
++}
++
++static int imx_ssi1_hw_rx_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 bfs, div;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
++
++	SSI1_SRCR = 0;
++	SSI1_SRCCR = 0;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		SSI1_SRCR |= SSI_SRCR_RSCKP | SSI_SRCR_RFSI |
++			SSI_STCR_REFS | SSI_STCR_RXBIT0;
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		SSI1_SRCR |= SSI_SRCR_RSCKP | SSI_SRCR_RFSI | SSI_SRCR_RXBIT0;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		SSI1_SRCR |= SSI_SRCR_REFS; // data 1 bit after sync
++	case SND_SOC_DAIFMT_DSP_A:
++		SSI1_SRCR |= SSI_SRCR_RFSL; // frame is 1 bclk long
++
++		/* DAI clock inversion */
++		switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++		case SND_SOC_DAIFMT_IB_IF:
++			SSI1_SRCR |= SSI_SRCR_TFSI | SSI_SRCR_TSCKP;
++			break;
++		case SND_SOC_DAIFMT_IB_NF:
++			SSI1_SRCR |= SSI_SRCR_RSCKP;
++			break;
++		case SND_SOC_DAIFMT_NB_IF:
++			SSI1_SRCR |= SSI_SRCR_RFSI;
++			break;
++		}
++		break;
++	}
++
++	/* DAI data (word) size */
++	switch(rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(16);
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(20);
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		SSI1_SRCCR |= SSI_SRCCR_WL(24);
++		break;
++	}
++
++	/* DAI clock master masks */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK){
++	case SND_SOC_DAIFMT_CBM_CFM:
++		SSI1_SRCR |= SSI_SRCR_RFDIR | SSI_SRCR_RXDIR;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		SSI1_SRCR |= SSI_SRCR_RFDIR;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		SSI1_SRCR |= SSI_SRCR_RXDIR;
++		break;
++	}
++
++	/* DAI BCLK ratio to SYSCLK / MCLK */
++	/* prescaler modulus - todo */
++	switch (bfs) {
++	case 2:
++		break;
++	case 4:
++		break;
++	case 8:
++		break;
++	case 16:
++		break;
++	}
++
++	/* TDM - todo, only fifo 0 atm */
++	SSI1_SRCR |= SSI_SRCR_RFEN0;
++	SSI1_SRCCR |= SSI_SRCCR_DC(params_channels(params));
++
++	return 0;
++}
++
++static int imx_ssi1_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	/* clear register if not enabled */
++	if(!(SSI1_SCR & SSI_SCR_SSIEN))
++		SSI1_SCR = 0;
++
++	/* async */
++	if (rtd->cpu_dai->flags & SND_SOC_DAI_ASYNC)
++		SSI1_SCR |= SSI_SCR_SYN;
++
++	/* DAI mode */
++	switch(rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++	case SND_SOC_DAIFMT_LEFT_J:
++		SSI1_SCR |= SSI_SCR_NET;
++		break;
++	}
++
++	/* TDM  - to complete */
++
++	/* Tx/Rx config */
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		return imx_ssi1_hw_tx_params(substream, params);
++	} else {
++		return imx_ssi1_hw_rx_params(substream, params);
++	}
++}
++
++
++
++static int imx_ssi1_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++			SSI1_SCR |= SSI_SCR_TE;
++			SSI1_SIER |= SSI_SIER_TDMAE;
++		} else {
++			SSI1_SCR |= SSI_SCR_RE;
++			SSI1_SIER |= SSI_SIER_RDMAE;
++		}
++		SSI1_SCR |= SSI_SCR_SSIEN;
++
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR |= SSI_SCR_TE;
++		else
++			SSI1_SCR |= SSI_SCR_RE;
++	break
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++			SSI1_SCR &= ~SSI_SCR_TE;
++		else
++			SSI1_SCR &= ~SSI_SCR_RE;
++	break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void imx_ssi_shutdown(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++	/* shutdown SSI */
++	if (!rtd->cpu_dai->active) {
++		if(rtd->cpu_dai->id == 0)
++			SSI1_SCR &= ~SSI_SCR_SSIEN;
++		else
++			SSI2_SCR &= ~SSI_SCR_SSIEN;
++	}
++}
++
++#ifdef CONFIG_PM
++static int imx_ssi_suspend(struct platform_device *dev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR &= ~SSI_SCR_SSIEN;
++	else
++		SSI2_SCR &= ~SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++static int imx_ssi_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++	if(!dai->active)
++		return 0;
++
++	if(rtd->cpu_dai->id == 0)
++		SSI1_SCR |= SSI_SCR_SSIEN;
++	else
++		SSI2_SCR |= SSI_SCR_SSIEN;
++
++	return 0;
++}
++
++#else
++#define imx_ssi_suspend	NULL
++#define imx_ssi_resume	NULL
++#endif
++
++static unsigned int imx_ssi_config_pcm_sysclk(struct snd_soc_cpu_dai *iface,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	return clk;
++}
++
++struct snd_soc_cpu_dai imx_ssi_pcm_dai = {
++	.name = "imx-i2s-1",
++	.id = 0,
++	.type = SND_SOC_DAI_I2S,
++	.suspend = imx_ssi_suspend,
++	.resume = imx_ssi_resume,
++	.config_sysclk = imx_ssi_config_pcm_sysclk,
++	.playback = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.startup = imx_ssi_startup,
++		.shutdown = imx_ssi_shutdown,
++		.trigger = imx_ssi1_trigger,
++		.hw_params = imx_ssi1_pcm_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_ssi_modes),
++		.mode = imx_ssi_modes,},
++},
++{
++	.name = "imx-i2s-2",
++	.id = 1,
++	.type = SND_SOC_DAI_I2S,
++	.suspend = imx_ssi_suspend,
++	.resume = imx_ssi_resume,
++	.config_sysclk = imx_ssi_config_pcm_sysclk,
++	.playback = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 1,
++		.channels_max = 2,},
++	.ops = {
++		.startup = imx_ssi_startup,
++		.shutdown = imx_ssi_shutdown,
++		.trigger = imx_ssi1_trigger,
++		.hw_params = imx_ssi1_pcm_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(imx_ssi_modes),
++		.mode = imx_ssi_modes,},
++};
++
++
++EXPORT_SYMBOL_GPL(imx_ssi_i2s_dai);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("i.MX ASoC I2S driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/include/linux/i2c-id.h
+===================================================================
+--- linux-2.6.17/include/linux/i2c-id.h.orig	2006-11-25 00:15:33.571185017 +0100
++++ linux-2.6.17/include/linux/i2c-id.h	2006-11-25 00:17:31.017877925 +0100
+@@ -113,6 +113,9 @@
+ #define I2C_DRIVERID_PCF8563	83	/* Philips PCF8563 RTC		*/
+ #define I2C_DRIVERID_RS5C372	84	/* Ricoh RS5C372 RTC		*/
+ 
++#define I2C_DRIVERID_WM8731    89      /* Wolfson WM8731 audio codec */
++#define I2C_DRIVERID_WM8750    90      /* Wolfson WM8750 audio codec */
++
+ #define I2C_DRIVERID_I2CDEV	900
+ #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
+ #define I2C_DRIVERID_ALERT      903    /* SMBus Alert Responder Client  */
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8976.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8976.c
+@@ -0,0 +1,953 @@
++/*
++ * wm8976.c  --  WM8976 ALSA Soc Audio driver
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ *
++ * 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/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.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 "wm8976.h"
++
++#define AUDIO_NAME "wm8976"
++#define WM8976_VERSION "0.2"
++
++/*
++ * Debug
++ */
++
++#define WM8976_DEBUG 0
++
++#ifdef WM8976_DEBUG
++#define dbg(format, arg...) \
++	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...) do {} while (0)
++#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)
++
++struct snd_soc_codec_device soc_codec_dev_wm8976;
++
++/*
++ * wm8976 register cache
++ * We can't read the WM8976 register space when we are
++ * using 2 wire for device control, so we cache them instead.
++ */
++static const u16 wm8976_reg[WM8976_CACHEREGNUM] = {
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0050, 0x0000, 0x0140, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x00ff,
++    0x00ff, 0x0000, 0x0100, 0x00ff,
++    0x00ff, 0x0000, 0x012c, 0x002c,
++    0x002c, 0x002c, 0x002c, 0x0000,
++    0x0032, 0x0000, 0x0000, 0x0000,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0038, 0x000b, 0x0032, 0x0000,
++    0x0008, 0x000c, 0x0093, 0x00e9,
++    0x0000, 0x0000, 0x0000, 0x0000,
++    0x0033, 0x0010, 0x0010, 0x0100,
++    0x0100, 0x0002, 0x0001, 0x0001,
++    0x0039, 0x0039, 0x0039, 0x0039,
++    0x0001, 0x0001,
++};
++
++#define WM8976_DAIFMT \
++	(SND_SOC_DAIFMT_I2S  | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
++    SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_DSP_B  | SND_SOC_DAIFMT_NB_NF   | \
++    SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF  | SND_SOC_DAIFMT_IB_IF)
++
++#define WM8976_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define WM8976_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)
++
++#define WM8976_PCM_FORMATS \
++	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++	SNDRV_PCM_FORMAT_S24_3LE | SNDRV_PCM_FORMAT_S24_LE  | \
++    SNDRV_PCM_FORMAT_S32_LE)
++
++#define WM8976_BCLK \
++	(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | SND_SOC_FSBD(8) |\
++    SND_SOC_FSBD(16) | SND_SOC_FSBD(32))
++
++static struct snd_soc_dai_mode wm8976_modes[] = {
++	/* codec frame and clock master modes */
++	{
++		.fmt = WM8976_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
++		.pcmfmt = WM8976_PCM_FORMATS,
++		.pcmrate = WM8976_RATES,
++		.pcmdir = WM8976_DIR,
++		.flags = SND_SOC_DAI_BFS_DIV,
++		.fs = 256,
++		.bfs = WM8976_BCLK,
++	},
++
++	/* codec frame and clock slave modes */
++	{
++		.fmt = WM8976_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++        .pcmfmt = WM8976_PCM_FORMATS,
++        .pcmrate = WM8976_RATES,
++        .pcmdir = WM8976_DIR,
++        .fs = SND_SOC_FS_ALL,
++        .bfs = SND_SOC_FSB_ALL,
++	},
++};
++
++/*
++ * read wm8976 register cache
++ */
++static inline unsigned int wm8976_read_reg_cache(struct snd_soc_codec  *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg == WM8976_RESET)
++		return 0;
++	if (reg >= WM8976_CACHEREGNUM)
++		return -1;
++	return cache[reg];
++}
++
++/*
++ * write wm8976 register cache
++ */
++static inline void wm8976_write_reg_cache(struct snd_soc_codec  *codec,
++	u16 reg, unsigned int value)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg >= WM8976_CACHEREGNUM)
++		return;
++	cache[reg] = value;
++}
++
++/*
++ * write to the WM8976 register space
++ */
++static int wm8976_write(struct snd_soc_codec  *codec, unsigned int reg,
++	unsigned int value)
++{
++	u8 data[2];
++
++	/* data is
++	 *   D15..D9 WM8976 register offset
++	 *   D8...D0 register data
++	 */
++	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
++	data[1] = value & 0x00ff;
++
++	wm8976_write_reg_cache (codec, reg, value);
++	if (codec->hw_write(codec->control_data, data, 2) == 2)
++		return 0;
++	else
++		return -1;
++}
++
++#define wm8976_reset(c)	wm8976_write(c, WM8976_RESET, 0)
++
++static const char *wm8976_companding[] = {"Off", "NC", "u-law", "A-law" };
++static const char *wm8976_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
++static const char *wm8976_eqmode[] = {"Capture", "Playback" };
++static const char *wm8976_bw[] = {"Narrow", "Wide" };
++static const char *wm8976_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" };
++static const char *wm8976_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" };
++static const char *wm8976_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" };
++static const char *wm8976_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" };
++static const char *wm8976_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" };
++static const char *wm8976_alc[] =
++    {"ALC both on", "ALC left only", "ALC right only", "Limiter" };
++
++static const struct soc_enum wm8976_enum[] = {
++	SOC_ENUM_SINGLE(WM8976_COMP, 1, 4, wm8976_companding), /* adc */
++	SOC_ENUM_SINGLE(WM8976_COMP, 3, 4, wm8976_companding), /* dac */
++	SOC_ENUM_SINGLE(WM8976_DAC,  4, 4, wm8976_deemp),
++	SOC_ENUM_SINGLE(WM8976_EQ1,  8, 2, wm8976_eqmode),
++
++	SOC_ENUM_SINGLE(WM8976_EQ1,  5, 4, wm8976_eq1),
++	SOC_ENUM_SINGLE(WM8976_EQ2,  8, 2, wm8976_bw),
++	SOC_ENUM_SINGLE(WM8976_EQ2,  5, 4, wm8976_eq2),
++	SOC_ENUM_SINGLE(WM8976_EQ3,  8, 2, wm8976_bw),
++
++	SOC_ENUM_SINGLE(WM8976_EQ3,  5, 4, wm8976_eq3),
++	SOC_ENUM_SINGLE(WM8976_EQ4,  8, 2, wm8976_bw),
++	SOC_ENUM_SINGLE(WM8976_EQ4,  5, 4, wm8976_eq4),
++	SOC_ENUM_SINGLE(WM8976_EQ5,  8, 2, wm8976_bw),
++
++	SOC_ENUM_SINGLE(WM8976_EQ5,  5, 4, wm8976_eq5),
++	SOC_ENUM_SINGLE(WM8976_ALC3,  8, 2, wm8976_alc),
++};
++
++static const struct snd_kcontrol_new wm8976_snd_controls[] = {
++SOC_SINGLE("Digital Loopback Switch", WM8976_COMP, 0, 1, 0),
++
++SOC_ENUM("ADC Companding", wm8976_enum[0]),
++SOC_ENUM("DAC Companding", wm8976_enum[1]),
++
++SOC_SINGLE("Jack Detection Enable", WM8976_JACK1, 6, 1, 0),
++
++SOC_DOUBLE("DAC Inversion Switch", WM8976_DAC, 0, 1, 1, 0),
++
++SOC_DOUBLE_R("Headphone Playback Volume", WM8976_DACVOLL, WM8976_DACVOLR, 0, 127, 0),
++
++SOC_SINGLE("High Pass Filter Switch", WM8976_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Filter Switch", WM8976_ADC, 8, 1, 0),
++SOC_SINGLE("High Pass Cut Off", WM8976_ADC, 4, 7, 0),
++
++SOC_DOUBLE("ADC Inversion Switch", WM8976_ADC, 0, 1, 1, 0),
++
++SOC_SINGLE("Capture Volume", WM8976_ADCVOL,  0, 127, 0),
++
++SOC_ENUM("Equaliser Function", wm8976_enum[3]),
++SOC_ENUM("EQ1 Cut Off", wm8976_enum[4]),
++SOC_SINGLE("EQ1 Volume", WM8976_EQ1,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ2 Bandwith", wm8976_enum[5]),
++SOC_ENUM("EQ2 Cut Off", wm8976_enum[6]),
++SOC_SINGLE("EQ2 Volume", WM8976_EQ2,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ3 Bandwith", wm8976_enum[7]),
++SOC_ENUM("EQ3 Cut Off", wm8976_enum[8]),
++SOC_SINGLE("EQ3 Volume", WM8976_EQ3,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ4 Bandwith", wm8976_enum[9]),
++SOC_ENUM("EQ4 Cut Off", wm8976_enum[10]),
++SOC_SINGLE("EQ4 Volume", WM8976_EQ4,  0, 31, 1),
++
++SOC_ENUM("Equaliser EQ5 Bandwith", wm8976_enum[11]),
++SOC_ENUM("EQ5 Cut Off", wm8976_enum[12]),
++SOC_SINGLE("EQ5 Volume", WM8976_EQ5,  0, 31, 1),
++
++SOC_SINGLE("DAC Playback Limiter Switch", WM8976_DACLIM1,  8, 1, 0),
++SOC_SINGLE("DAC Playback Limiter Decay", WM8976_DACLIM1,  4, 15, 0),
++SOC_SINGLE("DAC Playback Limiter Attack", WM8976_DACLIM1,  0, 15, 0),
++
++SOC_SINGLE("DAC Playback Limiter Threshold", WM8976_DACLIM2,  4, 7, 0),
++SOC_SINGLE("DAC Playback Limiter Boost", WM8976_DACLIM2,  0, 15, 0),
++
++SOC_SINGLE("ALC Enable Switch", WM8976_ALC1,  8, 1, 0),
++SOC_SINGLE("ALC Capture Max Gain", WM8976_ALC1,  3, 7, 0),
++SOC_SINGLE("ALC Capture Min Gain", WM8976_ALC1,  0, 7, 0),
++
++SOC_SINGLE("ALC Capture ZC Switch", WM8976_ALC2,  8, 1, 0),
++SOC_SINGLE("ALC Capture Hold", WM8976_ALC2,  4, 7, 0),
++SOC_SINGLE("ALC Capture Target", WM8976_ALC2,  0, 15, 0),
++
++SOC_ENUM("ALC Capture Mode", wm8976_enum[13]),
++SOC_SINGLE("ALC Capture Decay", WM8976_ALC3,  4, 15, 0),
++SOC_SINGLE("ALC Capture Attack", WM8976_ALC3,  0, 15, 0),
++
++SOC_SINGLE("ALC Capture Noise Gate Switch", WM8976_NGATE,  3, 1, 0),
++SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8976_NGATE,  0, 7, 0),
++
++SOC_SINGLE("Capture PGA ZC Switch", WM8976_INPPGA,  7, 1, 0),
++SOC_SINGLE("Capture PGA Volume", WM8976_INPPGA,  0, 63, 0),
++
++SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8976_HPVOLL,  WM8976_HPVOLR, 7, 1, 0),
++SOC_DOUBLE_R("Headphone Playback Switch", WM8976_HPVOLL,  WM8976_HPVOLR, 6, 1, 1),
++SOC_DOUBLE_R("Headphone Playback Volume", WM8976_HPVOLL,  WM8976_HPVOLR, 0, 63, 0),
++
++SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8976_SPKVOLL,  WM8976_SPKVOLR, 7, 1, 0),
++SOC_DOUBLE_R("Speaker Playback Switch", WM8976_SPKVOLL,  WM8976_SPKVOLR, 6, 1, 1),
++SOC_DOUBLE_R("Speaker Playback Volume", WM8976_SPKVOLL,  WM8976_SPKVOLR, 0, 63, 0),
++
++SOC_SINGLE("Capture Boost(+20dB)", WM8976_ADCBOOST, 8, 1, 0),
++};
++
++/* add non dapm controls */
++static int wm8976_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm8976_snd_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm8976_snd_controls[i],codec, NULL));
++		if (err < 0)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Left Output Mixer */
++static const snd_kcontrol_new_t wm8976_left_mixer_controls[] = {
++SOC_DAPM_SINGLE("Right PCM Playback Switch", WM8976_OUTPUT, 6, 1, 1),
++SOC_DAPM_SINGLE("Left PCM Playback Switch", WM8976_MIXL, 0, 1, 1),
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8976_MIXL, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8976_MIXL, 5, 1, 0),
++};
++
++/* Right Output Mixer */
++static const snd_kcontrol_new_t wm8976_right_mixer_controls[] = {
++SOC_DAPM_SINGLE("Left PCM Playback Switch", WM8976_OUTPUT, 5, 1, 1),
++SOC_DAPM_SINGLE("Right PCM Playback Switch", WM8976_MIXR, 0, 1, 1),
++SOC_DAPM_SINGLE("Line Bypass Switch", WM8976_MIXR, 1, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", WM8976_MIXR, 5, 1, 0),
++};
++
++/* Left AUX Input boost vol */
++static const snd_kcontrol_new_t wm8976_laux_boost_controls =
++SOC_DAPM_SINGLE("Aux Volume", WM8976_ADCBOOST, 0, 3, 0);
++
++/* Left Input boost vol */
++static const snd_kcontrol_new_t wm8976_lmic_boost_controls =
++SOC_DAPM_SINGLE("Input Volume", WM8976_ADCBOOST, 4, 3, 0);
++
++/* Left Aux In to PGA */
++static const snd_kcontrol_new_t wm8976_laux_capture_boost_controls =
++SOC_DAPM_SINGLE("Capture Switch", WM8976_ADCBOOST,  8, 1, 0);
++
++/* Left Input P In to PGA */
++static const snd_kcontrol_new_t wm8976_lmicp_capture_boost_controls =
++SOC_DAPM_SINGLE("Input P Capture Boost Switch", WM8976_INPUT,  0, 1, 0);
++
++/* Left Input N In to PGA */
++static const snd_kcontrol_new_t wm8976_lmicn_capture_boost_controls =
++SOC_DAPM_SINGLE("Input N Capture Boost Switch", WM8976_INPUT,  1, 1, 0);
++
++// TODO Widgets
++static const struct snd_soc_dapm_widget wm8976_dapm_widgets[] = {
++#if 0
++//SND_SOC_DAPM_MUTE("Mono Mute", WM8976_MONOMIX, 6, 0),
++//SND_SOC_DAPM_MUTE("Speaker Mute", WM8976_SPKMIX, 6, 0),
++
++SND_SOC_DAPM_MIXER("Speaker Mixer", WM8976_POWER3, 2, 0,
++	&wm8976_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm8976_speaker_mixer_controls)),
++SND_SOC_DAPM_MIXER("Mono Mixer", WM8976_POWER3, 3, 0,
++	&wm8976_mono_mixer_controls[0],
++	ARRAY_SIZE(wm8976_mono_mixer_controls)),
++SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8976_POWER3, 0, 0),
++SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8976_POWER3, 0, 0),
++SND_SOC_DAPM_PGA("Aux Input", WM8976_POWER1, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkN Out", WM8976_POWER3, 5, 0, NULL, 0),
++SND_SOC_DAPM_PGA("SpkP Out", WM8976_POWER3, 6, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", WM8976_POWER3, 7, 0, NULL, 0),
++SND_SOC_DAPM_PGA("Mic PGA", WM8976_POWER2, 2, 0, NULL, 0),
++
++SND_SOC_DAPM_PGA("Aux Boost", SND_SOC_NOPM, 0, 0,
++	&wm8976_aux_boost_controls, 1),
++SND_SOC_DAPM_PGA("Mic Boost", SND_SOC_NOPM, 0, 0,
++	&wm8976_mic_boost_controls, 1),
++SND_SOC_DAPM_SWITCH("Capture Boost", SND_SOC_NOPM, 0, 0,
++	&wm8976_capture_boost_controls),
++
++SND_SOC_DAPM_MIXER("Boost Mixer", WM8976_POWER2, 4, 0, NULL, 0),
++
++SND_SOC_DAPM_MICBIAS("Mic Bias", WM8976_POWER1, 4, 0),
++
++SND_SOC_DAPM_INPUT("MICN"),
++SND_SOC_DAPM_INPUT("MICP"),
++SND_SOC_DAPM_INPUT("AUX"),
++SND_SOC_DAPM_OUTPUT("MONOOUT"),
++SND_SOC_DAPM_OUTPUT("SPKOUTP"),
++SND_SOC_DAPM_OUTPUT("SPKOUTN"),
++#endif
++};
++
++static const char *audio_map[][3] = {
++	/* Mono output mixer */
++	{"Mono Mixer", "PCM Playback Switch", "DAC"},
++	{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Speaker output mixer */
++	{"Speaker Mixer", "PCM Playback Switch", "DAC"},
++	{"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
++	{"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
++
++	/* Outputs */
++	{"Mono Out", NULL, "Mono Mixer"},
++	{"MONOOUT", NULL, "Mono Out"},
++	{"SpkN Out", NULL, "Speaker Mixer"},
++	{"SpkP Out", NULL, "Speaker Mixer"},
++	{"SPKOUTN", NULL, "SpkN Out"},
++	{"SPKOUTP", NULL, "SpkP Out"},
++
++	/* Boost Mixer */
++	{"Boost Mixer", NULL, "ADC"},
++	{"Capture Boost Switch", "Aux Capture Boost Switch", "AUX"},
++	{"Aux Boost", "Aux Volume", "Boost Mixer"},
++	{"Capture Boost", "Capture Switch", "Boost Mixer"},
++	{"Mic Boost", "Mic Volume", "Boost Mixer"},
++
++	/* Inputs */
++	{"MICP", NULL, "Mic Boost"},
++	{"MICN", NULL, "Mic PGA"},
++	{"Mic PGA", NULL, "Capture Boost"},
++	{"AUX", NULL, "Aux Input"},
++
++    /*  */
++
++	/* terminator */
++	{NULL, NULL, NULL},
++};
++
++static int wm8976_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for(i = 0; i < ARRAY_SIZE(wm8976_dapm_widgets); i++) {
++		snd_soc_dapm_new_control(codec, &wm8976_dapm_widgets[i]);
++	}
++
++	/* set up audio path map */
++	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;
++}
++
++struct pll_ {
++	unsigned int in_hz, out_hz;
++	unsigned int pre:4; /* prescale - 1 */
++	unsigned int n:4;
++	unsigned int k;
++};
++
++struct pll_ pll[] = {
++	{12000000, 11289600, 0, 7, 0x86c220},
++	{12000000, 12288000, 0, 8, 0x3126e8},
++	{13000000, 11289600, 0, 6, 0xf28bd4},
++	{13000000, 12288000, 0, 7, 0x8fd525},
++	{12288000, 11289600, 0, 7, 0x59999a},
++	{11289600, 12288000, 0, 8, 0x80dee9},
++	/* TODO: liam - add more entries */
++};
++
++static int set_pll(struct snd_soc_codec *codec, unsigned int in,
++	unsigned int out)
++{
++	int i;
++	u16 reg;
++
++	if(out == 0) {
++		reg = wm8976_read_reg_cache(codec, WM8976_POWER1);
++		wm8976_write(codec, WM8976_POWER1, reg & 0x1df);
++		return 0;
++	}
++
++	for(i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (in == pll[i].in_hz && out == pll[i].out_hz) {
++			wm8976_write(codec, WM8976_PLLN, (pll[i].pre << 4) | pll[i].n);
++			wm8976_write(codec, WM8976_PLLK1, pll[i].k >> 18);
++			wm8976_write(codec, WM8976_PLLK1, (pll[i].k >> 9) && 0x1ff);
++			wm8976_write(codec, WM8976_PLLK1, pll[i].k && 0x1ff);
++			reg = wm8976_read_reg_cache(codec, WM8976_POWER1);
++			wm8976_write(codec, WM8976_POWER1, reg | 0x020);
++			return 0;
++		}
++	}
++	return -EINVAL;
++}
++
++/* mclk dividers * 2 */
++static unsigned char mclk_div[] = {2, 3, 4, 6, 8, 12, 16, 24};
++
++/* we need 256FS to drive the DAC's and ADC's */
++static unsigned int wm8976_config_sysclk(struct snd_soc_codec_dai *dai,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	int i, j, best_clk = info->fs * info->rate;
++
++	/* can we run at this clk without the PLL ? */
++	for (i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if ((best_clk >> 1) * mclk_div[i] == clk) {
++			dai->pll_in = 0;
++			dai->clk_div = mclk_div[i];
++			dai->mclk = best_clk;
++			return dai->mclk;
++		}
++	}
++
++	/* now check for PLL support */
++	for (i = 0; i < ARRAY_SIZE(pll); i++) {
++		if (pll[i].in_hz == clk) {
++			for (j = 0; j < ARRAY_SIZE(mclk_div); j++) {
++				if (pll[i].out_hz == mclk_div[j] * (best_clk >> 1)) {
++					dai->pll_in = clk;
++					dai->pll_out = pll[i].out_hz;
++					dai->clk_div = mclk_div[j];
++					dai->mclk = best_clk;
++					return dai->mclk;
++				}
++			}
++		}
++	}
++
++	/* this clk is not supported */
++	return 0;
++}
++
++static int wm8976_pcm_prepare(snd_pcm_substream_t *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct snd_soc_codec_dai *dai = rtd->codec_dai;
++	u16 iface = 0, bfs, clk = 0, adn;
++	int fs = 48000 << 7, i;
++
++	bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
++	switch (bfs) {
++	case 2:
++		clk |= 0x1 << 2;
++		break;
++	case 4:
++		clk |= 0x2 << 2;
++		break;
++	case 8:
++		clk |= 0x3 << 2;
++		break;
++	case 16:
++		clk |= 0x4 << 2;
++		break;
++	case 32:
++		clk |= 0x5 << 2;
++		break;
++	}
++
++	/* set master/slave audio interface */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		clk |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		break;
++	}
++
++	/* interface format */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		iface |= 0x0010;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		iface |= 0x0008;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		iface |= 0x00018;
++		break;
++	}
++
++	/* bit size */
++	switch (rtd->codec_dai->dai_runtime.pcmfmt) {
++	case SNDRV_PCM_FMTBIT_S16_LE:
++		break;
++	case SNDRV_PCM_FMTBIT_S20_3LE:
++		iface |= 0x0020;
++		break;
++	case SNDRV_PCM_FMTBIT_S24_LE:
++		iface |= 0x0040;
++		break;
++	case SNDRV_PCM_FMTBIT_S32_LE:
++		iface |= 0x0060;
++		break;
++	}
++
++	/* clock inversion */
++	switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		iface |= 0x0180;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		iface |= 0x0100;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		iface |= 0x0080;
++		break;
++	}
++
++	/* filter coefficient */
++	adn = wm8976_read_reg_cache(codec, WM8976_ADD) & 0x1f1;
++	switch (rtd->codec_dai->dai_runtime.pcmrate) {
++	case SNDRV_PCM_RATE_8000:
++		adn |= 0x5 << 1;
++		fs = 8000 << 7;
++		break;
++	case SNDRV_PCM_RATE_11025:
++		adn |= 0x4 << 1;
++		fs = 11025 << 7;
++		break;
++	case SNDRV_PCM_RATE_16000:
++		adn |= 0x3 << 1;
++		fs = 16000 << 7;
++		break;
++	case SNDRV_PCM_RATE_22050:
++		adn |= 0x2 << 1;
++		fs = 22050 << 7;
++		break;
++	case SNDRV_PCM_RATE_32000:
++		adn |= 0x1 << 1;
++		fs = 32000 << 7;
++		break;
++	case SNDRV_PCM_RATE_44100:
++		fs = 44100 << 7;
++		break;
++	}
++
++	/* do we need to enable the PLL */
++	if(dai->pll_in)
++		set_pll(codec, dai->pll_in, dai->pll_out);
++
++	/* divide the clock to 256 fs */
++	for(i = 0; i < ARRAY_SIZE(mclk_div); i++) {
++		if (dai->clk_div == mclk_div[i]) {
++			clk |= i << 5;
++			clk &= 0xff;
++			goto set;
++		}
++	}
++
++set:
++	/* set iface */
++	wm8976_write(codec, WM8976_IFACE, iface);
++	wm8976_write(codec, WM8976_CLOCK, clk);
++
++	return 0;
++}
++
++static int wm8976_hw_free(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	set_pll(codec, 0, 0);
++	return 0;
++}
++
++static int wm8976_mute(struct snd_soc_codec *codec,
++	struct snd_soc_codec_dai *dai, int mute)
++{
++	u16 mute_reg = wm8976_read_reg_cache(codec, WM8976_DAC) & 0xffbf;
++	if(mute)
++		wm8976_write(codec, WM8976_DAC, mute_reg | 0x40);
++	else
++		wm8976_write(codec, WM8976_DAC, mute_reg);
++
++	return 0;
++}
++
++/* TODO: liam need to make this lower power with dapm */
++static int wm8976_dapm_event(struct snd_soc_codec *codec, int event)
++{
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* vref/mid, clk and osc on, dac unmute, active */
++		wm8976_write(codec, WM8976_POWER1, 0x1ff);
++		wm8976_write(codec, WM8976_POWER2, 0x1ff);
++		wm8976_write(codec, WM8976_POWER3, 0x1ff);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* everything off except vref/vmid, dac mute, inactive */
++
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* everything off, dac mute, inactive */
++		wm8976_write(codec, WM8976_POWER1, 0x0);
++		wm8976_write(codec, WM8976_POWER2, 0x0);
++		wm8976_write(codec, WM8976_POWER3, 0x0);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++struct snd_soc_codec_dai wm8976_dai = {
++	.name = "WM8976 HiFi",
++	.playback = {
++		.stream_name = "Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++	},
++	.capture = {
++		.stream_name = "Capture",
++		.channels_min = 1,
++		.channels_max = 1,
++	},
++	.config_sysclk = wm8976_config_sysclk,
++	.digital_mute = wm8976_mute,
++	.ops = {
++		.prepare = wm8976_pcm_prepare,
++		.hw_free = wm8976_hw_free,
++	},
++	.caps = {
++		.num_modes = ARRAY_SIZE(wm8976_modes),
++		.mode = wm8976_modes,
++	},
++};
++EXPORT_SYMBOL_GPL(wm8976_dai);
++
++static int wm8976_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;
++
++	wm8976_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++	return 0;
++}
++
++static int wm8976_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	int i;
++	u8 data[2];
++	u16 *cache = codec->reg_cache;
++
++	/* Sync reg_cache with the hardware */
++	for (i = 0; i < ARRAY_SIZE(wm8976_reg); i++) {
++		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
++		data[1] = cache[i] & 0x00ff;
++		codec->hw_write(codec->control_data, data, 2);
++	}
++	wm8976_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8976_dapm_event(codec, codec->suspend_dapm_state);
++	return 0;
++}
++
++/*
++ * initialise the WM8976 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int wm8976_init(struct snd_soc_device* socdev)
++{
++	struct snd_soc_codec *codec = socdev->codec;
++	int ret = 0;
++
++	codec->name = "WM8976";
++	codec->owner = THIS_MODULE;
++	codec->read = wm8976_read_reg_cache;
++	codec->write = wm8976_write;
++	codec->dapm_event = wm8976_dapm_event;
++	codec->dai = &wm8976_dai;
++	codec->num_dai = 1;
++	codec->reg_cache_size = ARRAY_SIZE(wm8976_reg);
++	codec->reg_cache =
++			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8976_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL)
++		return -ENOMEM;
++	memcpy(codec->reg_cache, wm8976_reg,
++		sizeof(u16) * ARRAY_SIZE(wm8976_reg));
++	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm8976_reg);
++
++	wm8976_reset(codec);
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if(ret < 0) {
++		kfree(codec->reg_cache);
++		return ret;
++	}
++
++	/* power on device */
++	wm8976_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++	wm8976_add_controls(codec);
++	wm8976_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 struct snd_soc_device *wm8976_socdev;
++
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++/*
++ * WM8976 2 wire address is 0x1a
++ */
++#define I2C_DRIVERID_WM8976 0xfefe /* liam -  need a proper id */
++
++static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
++
++/* Magic definition of all other variables and things */
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver wm8976_i2c_driver;
++static struct i2c_client client_template;
++
++/* If the i2c layer weren't so broken, we could pass this kind of data
++   around */
++
++static int wm8976_codec_probe(struct i2c_adapter *adap, int addr, int kind)
++{
++	struct snd_soc_device *socdev = wm8976_socdev;
++	struct wm8976_setup_data *setup = socdev->codec_data;
++	struct snd_soc_codec *codec = socdev->codec;
++	struct i2c_client *i2c;
++	int ret;
++
++	if (addr != setup->i2c_address)
++		return -ENODEV;
++
++	client_template.adapter = adap;
++	client_template.addr = addr;
++
++	i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
++	if (i2c == NULL){
++		kfree(codec);
++		return -ENOMEM;
++	}
++	memcpy(i2c, &client_template, sizeof(struct i2c_client));
++
++	i2c_set_clientdata(i2c, codec);
++
++	codec->control_data = i2c;
++
++	ret = i2c_attach_client(i2c);
++	if(ret < 0) {
++		err("failed to attach codec at addr %x\n", addr);
++		goto err;
++	}
++
++	ret = wm8976_init(socdev);
++	if(ret < 0) {
++		err("failed to initialise WM8976\n");
++		goto err;
++	}
++	return ret;
++
++err:
++	kfree(codec);
++	kfree(i2c);
++	return ret;
++
++}
++
++static int wm8976_i2c_detach(struct i2c_client *client)
++{
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
++
++	i2c_detach_client(client);
++
++	kfree(codec->reg_cache);
++	kfree(client);
++
++	return 0;
++}
++
++static int wm8976_i2c_attach(struct i2c_adapter *adap)
++{
++	return i2c_probe(adap, &addr_data, wm8976_codec_probe);
++}
++
++/* corgi i2c codec control layer */
++static struct i2c_driver wm8976_i2c_driver = {
++	.driver = {
++		.name = "WM8976 I2C Codec",
++		.owner = THIS_MODULE,
++	},
++	.id =             I2C_DRIVERID_WM8976,
++	.attach_adapter = wm8976_i2c_attach,
++	.detach_client =  wm8976_i2c_detach,
++	.command =        NULL,
++};
++
++static struct i2c_client client_template = {
++	.name =   "WM8976",
++	.driver = &wm8976_i2c_driver,
++};
++#endif
++
++static int wm8976_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct wm8976_setup_data *setup;
++	struct snd_soc_codec *codec;
++	int ret = 0;
++
++	info("WM8976 Audio Codec %s", WM8976_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);
++
++	wm8976_socdev = socdev;
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	if (setup->i2c_address) {
++		normal_i2c[0] = setup->i2c_address;
++		codec->hw_write = (hw_write_t)i2c_master_send;
++		ret = i2c_add_driver(&wm8976_i2c_driver);
++		if (ret != 0)
++			printk(KERN_ERR "can't add i2c driver");
++	}
++#else
++	/* Add other interfaces here */
++#endif
++	return ret;
++}
++
++/* power down chip */
++static int wm8976_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)
++		wm8976_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++	snd_soc_free_pcms(socdev);
++	snd_soc_dapm_free(socdev);
++#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++	i2c_del_driver(&wm8976_i2c_driver);
++#endif
++	kfree(codec);
++
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm8976 = {
++	.probe = 	wm8976_probe,
++	.remove = 	wm8976_remove,
++	.suspend = 	wm8976_suspend,
++	.resume =	wm8976_resume,
++};
++
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm8976);
++
++MODULE_DESCRIPTION("ASoC WM8976 driver");
++MODULE_AUTHOR("Graeme Gregory");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/codecs/wm8976.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/codecs/wm8976.h
+@@ -0,0 +1,73 @@
++/*
++ * wm8976.h  --  WM8976 Soc Audio driver
++ *
++ * 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 _WM8976_H
++#define _WM8976_H
++
++/* WM8976 register space */
++
++#define WM8976_RESET		0x0
++#define WM8976_POWER1		0x1
++#define WM8976_POWER2		0x2
++#define WM8976_POWER3		0x3
++#define WM8976_IFACE		0x4
++#define WM8976_COMP			0x5
++#define WM8976_CLOCK		0x6
++#define WM8976_ADD			0x7
++#define WM8976_GPIO			0x8
++#define WM8976_JACK1        0x9
++#define WM8976_DAC			0xa
++#define WM8976_DACVOLL	    0xb
++#define WM8976_DACVOLR      0xc
++#define WM8976_JACK2        0xd
++#define WM8976_ADC			0xe
++#define WM8976_ADCVOL		0xf
++#define WM8976_EQ1			0x12
++#define WM8976_EQ2			0x13
++#define WM8976_EQ3			0x14
++#define WM8976_EQ4			0x15
++#define WM8976_EQ5			0x16
++#define WM8976_DACLIM1		0x18
++#define WM8976_DACLIM2		0x19
++#define WM8976_NOTCH1		0x1b
++#define WM8976_NOTCH2		0x1c
++#define WM8976_NOTCH3		0x1d
++#define WM8976_NOTCH4		0x1e
++#define WM8976_ALC1			0x20
++#define WM8976_ALC2			0x21
++#define WM8976_ALC3			0x22
++#define WM8976_NGATE		0x23
++#define WM8976_PLLN			0x24
++#define WM8976_PLLK1		0x25
++#define WM8976_PLLK2		0x26
++#define WM8976_PLLK3		0x27
++#define WM8976_3D           0x29
++#define WM8976_BEEP         0x2b
++#define WM8976_INPUT		0x2c
++#define WM8976_INPPGA	  	0x2d
++#define WM8976_ADCBOOST		0x2f
++#define WM8976_OUTPUT		0x31
++#define WM8976_MIXL	        0x32
++#define WM8976_MIXR         0x33
++#define WM8976_HPVOLL		0x34
++#define WM8976_HPVOLR       0x35
++#define WM8976_SPKVOLL      0x36
++#define WM8976_SPKVOLR      0x37
++#define WM8976_OUT3MIX		0x38
++#define WM8976_MONOMIX      0x39
++
++#define WM8976_CACHEREGNUM 	58
++
++struct wm8976_setup_data {
++	unsigned short i2c_address;
++};
++
++extern struct snd_soc_codec_dai wm8976_dai;
++extern struct snd_soc_codec_device soc_codec_dev_wm8976;
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/imx/imx21-pcm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx21-pcm.c
+@@ -0,0 +1,454 @@
++/*
++ * linux/sound/arm/mxc-pcm.c -- ALSA SoC interface for the Freescale i.MX CPU's
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ * Based on pxa2xx-pcm.c by	Nicolas Pitre, (C) 2004 MontaVista Software, Inc.
++ * and on mxc-alsa-mc13783 (C) 2006 Freescale.
++ *
++ * 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.
++ *
++ *  Revision history
++ *    29th Aug 2006   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <asm/dma.h>
++#include <asm/hardware.h>
++
++#include "imx-pcm.h"
++
++/* debug */
++#define IMX_DEBUG 0
++#if IMX_DEBUG
++#define dbg(format, arg...) printk(format, ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++
++static const struct snd_pcm_hardware mxc_pcm_hardware = {
++	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
++				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
++				   SNDRV_PCM_INFO_MMAP |
++				   SNDRV_PCM_INFO_MMAP_VALID |
++				   SNDRV_PCM_INFO_PAUSE |
++				   SNDRV_PCM_INFO_RESUME),
++	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
++					SNDRV_PCM_FMTBIT_S24_LE,
++	.buffer_bytes_max	= 32 * 1024,
++	.period_bytes_min	= 64,
++	.period_bytes_max	= 8 * 1024,
++	.periods_min		= 2,
++	.periods_max		= 255,
++	.fifo_size		= 0,
++};
++
++struct mxc_runtime_data {
++	int dma_ch;
++	struct mxc_pcm_dma_param *dma_params;
++};
++
++/*!
++  * This function stops the current dma transfert for playback
++  * and clears the dma pointers.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  */
++static void audio_stop_dma(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int dma_size = frames_to_bytes(runtime, runtime->period_size);
++	unsigned int offset  dma_size * s->periods;
++	unsigned long flags;
++
++	spin_lock_irqsave(&prtd->dma_lock, flags);
++
++	dbg("MXC : audio_stop_dma active = 0\n");
++	prtd->active = 0;
++	prtd->period = 0;
++	prtd->periods = 0;
++
++	/* this stops the dma channel and clears the buffer ptrs */
++	mxc_dma_stop(prtd->dma_wchannel);
++	if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_TO_DEVICE);
++	else
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_FROM_DEVICE);
++
++	spin_unlock_irqrestore(&prtd->dma_lock, flags);
++}
++
++/*!
++  * This function is called whenever a new audio block needs to be
++  * transferred to mc13783. The function receives the address and the size
++  * of the new block and start a new DMA transfer.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  */
++static int dma_new_period(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime =  substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int dma_size;
++	unsigned int offset;
++	int ret=0;
++	dma_request_t sdma_request;
++
++	if (prtd->active){
++		memset(&sdma_request, 0, sizeof(dma_request_t));
++		dma_size = frames_to_bytes(runtime, runtime->period_size);
++	    dbg("s->period (%x) runtime->periods (%d)\n",
++			s->period,runtime->periods);
++		dbg("runtime->period_size (%d) dma_size (%d)\n",
++			(unsigned int)runtime->period_size,
++			runtime->dma_bytes);
++
++       	offset = dma_size * prtd->period;
++		snd_assert(dma_size <= DMA_BUF_SIZE, );
++		if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++			sdma_request.sourceAddr = (char*)(dma_map_single(NULL,
++				runtime->dma_area + offset, dma_size, DMA_TO_DEVICE));
++		else
++			sdma_request.destAddr = (char*)(dma_map_single(NULL,
++				runtime->dma_area + offset, dma_size, DMA_FROM_DEVICE));
++		sdma_request.count = dma_size;
++
++		dbg("MXC: Start DMA offset (%d) size (%d)\n", offset,
++						 runtime->dma_bytes);
++
++       	mxc_dma_set_config(prtd->dma_wchannel, &sdma_request, 0);
++		if((ret = mxc_dma_start(prtd->dma_wchannel)) < 0) {
++			dbg("audio_process_dma: cannot queue DMA buffer\
++							(%i)\n", ret);
++			return err;
++		}
++		prtd->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
++		prtd->period++;
++		prtd->period %= runtime->periods;
++    }
++	return ret;
++}
++
++
++/*!
++  * This is a callback which will be called
++  * when a TX transfer finishes. The call occurs
++  * in interrupt context.
++  *
++  * @param	dat	pointer to the structure of the current stream.
++  *
++  */
++static void audio_dma_irq(void *data)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_pcm_runtime *runtime;
++	struct mxc_runtime_data *prtd;
++	unsigned int dma_size;
++	unsigned int previous_period;
++	unsigned int offset;
++
++	substream = data;
++	runtime = substream->runtime;
++	prtd = runtime->private_data;
++	previous_period  = prtd->periods;
++	dma_size = frames_to_bytes(runtime, runtime->period_size);
++	offset = dma_size * previous_period;
++
++	prtd->tx_spin = 0;
++	prtd->periods++;
++	prtd->periods %= runtime->periods;
++
++	/*
++	  * Give back to the CPU the access to the non cached memory
++	  */
++	if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_TO_DEVICE);
++	else
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_FROM_DEVICE);
++	/*
++	  * If we are getting a callback for an active stream then we inform
++	  * the PCM middle layer we've finished a period
++	  */
++ 	if (prtd->active)
++		snd_pcm_period_elapsed(substream);
++
++	/*
++	  * Trig next DMA transfer
++	  */
++	dma_new_period(substream);
++}
++
++/*!
++  * This function configures the hardware to allow audio
++  * playback operations. It is called by ALSA framework.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  * @return              0 on success, -1 otherwise.
++  */
++static int
++snd_mxc_prepare(struct snd_pcm_substream *substream)
++{
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int ret = 0;
++	prtd->period = 0;
++	prtd->periods = 0;
++
++	dma_channel_params params;
++	int channel = 0; // passed in ?
++
++	if ((ret  = mxc_request_dma(&channel, "ALSA TX SDMA") < 0)){
++		dbg("error requesting a write dma channel\n");
++		return ret;
++	}
++
++	/* configure DMA params */
++	memset(&params, 0, sizeof(dma_channel_params));
++	params.bd_number = 1;
++	params.arg = s;
++	params.callback = callback;
++	params.transfer_type = emi_2_per;
++	params.watermark_level = SDMA_TXFIFO_WATERMARK;
++	params.word_size = TRANSFER_16BIT;
++	//dbg(KERN_ERR "activating connection SSI1 - SDMA\n");
++	params.per_address = SSI1_BASE_ADDR;
++	params.event_id = DMA_REQ_SSI1_TX1;
++	params.peripheral_type = SSI;
++
++	/* set up chn with params */
++	mxc_dma_setup_channel(channel, &params);
++	s->dma_wchannel = channel;
++
++	return ret;
++}
++
++static int mxc_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	int ret;
++
++	if((ret=snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
++		return ret;
++	runtime->dma_addr = virt_to_phys(runtime->dma_area);
++
++	return ret;
++}
++
++static int mxc_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_pages(substream);
++}
++
++static int mxc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct mxc_runtime_data *prtd = substream->runtime->private_data;
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		prtd->tx_spin = 0;
++		/* requested stream startup */
++		prtd->active = 1;
++        ret = dma_new_period(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++		/* requested stream shutdown */
++		ret = audio_stop_dma(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++		prtd->active = 0;
++		prtd->periods = 0;
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++		prtd->active = 1;
++		prtd->tx_spin = 0;
++		ret = dma_new_period(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		prtd->active = 0;
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		prtd->active = 1;
++		if (prtd->old_offset) {
++			prtd->tx_spin = 0;
++            ret = dma_new_period(substream);
++		}
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t mxc_pcm_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int offset = 0;
++
++	/* tx_spin value is used here to check if a transfert is active */
++	if (prtd->tx_spin){
++		offset = (runtime->period_size * (prtd->periods)) +
++						(runtime->period_size >> 1);
++		if (offset >= runtime->buffer_size)
++			offset = runtime->period_size >> 1;
++	} else {
++		offset = (runtime->period_size * (s->periods));
++		if (offset >= runtime->buffer_size)
++			offset = 0;
++	}
++
++	return offset;
++}
++
++
++static int mxc_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd;
++	int ret;
++
++	snd_soc_set_runtime_hwparams(substream, &mxc_pcm_hardware);
++
++	if ((err = snd_pcm_hw_constraint_integer(runtime,
++					SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
++		return err;
++	if ((err = snd_pcm_hw_constraint_list(runtime, 0,
++			SNDRV_PCM_HW_PARAM_RATE, &hw_playback_rates)) < 0)
++		return err;
++	msleep(10); // liam - why
++
++	/* setup DMA controller for playback */
++	if((err = configure_write_channel(&mxc_mc13783->s[SNDRV_PCM_STREAM_PLAYBACK],
++					audio_dma_irq)) < 0 )
++		return err;
++
++	if((prtd = kzalloc(sizeof(struct mxc_runtime_data), GFP_KERNEL)) == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	runtime->private_data = prtd;
++	return 0;
++
++ err1:
++	kfree(prtd);
++ out:
++	return ret;
++}
++
++static int mxc_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++
++//	mxc_mc13783_t *chip;
++	audio_stream_t *s;
++	device_data_t* device;
++	int ssi;
++
++	//chip = snd_pcm_substream_chip(substream);
++	s = &chip->s[substream->pstr->stream];
++	device = &s->stream_device;
++	ssi = device->ssi;
++
++	//disable_stereodac();
++
++	ssi_transmit_enable(ssi, false);
++	ssi_interrupt_disable(ssi, ssi_tx_dma_interrupt_enable);
++	ssi_tx_fifo_enable(ssi, ssi_fifo_0, false);
++	ssi_enable(ssi, false);
++
++	chip->s[substream->pstr->stream].stream = NULL;
++
++	return 0;
++}
++
++static int
++mxc_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++				     runtime->dma_area,
++				     runtime->dma_addr,
++				     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops mxc_pcm_ops = {
++	.open		= mxc_pcm_open,
++	.close		= mxc_pcm_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= mxc_pcm_hw_params,
++	.hw_free	= mxc_pcm_hw_free,
++	.prepare	= mxc_pcm_prepare,
++	.trigger	= mxc_pcm_trigger,
++	.pointer	= mxc_pcm_pointer,
++	.mmap		= mxc_pcm_mmap,
++};
++
++static u64 mxc_pcm_dmamask = 0xffffffff;
++
++int mxc_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
++	struct snd_pcm *pcm)
++{
++	int ret = 0;
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &mxc_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = 0xffffffff;
++
++	if (dai->playback.channels_min) {
++		ret = mxc_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			goto out;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = mxc_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			goto out;
++	}
++ out:
++	return ret;
++}
++
++struct snd_soc_platform mxc_soc_platform = {
++	.name		= "mxc-audio",
++	.pcm_ops 	= &mxc_pcm_ops,
++	.pcm_new	= mxc_pcm_new,
++	.pcm_free	= mxc_pcm_free_dma_buffers,
++};
++
++EXPORT_SYMBOL_GPL(mxc_soc_platform);
++
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_DESCRIPTION("Freescale i.MX PCM DMA module");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/imx/imx21-pcm.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx21-pcm.h
+@@ -0,0 +1,237 @@
++/*
++ * mxc-pcm.h :- ASoC platform header for Freescale i.MX
++ *
++ * 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 _MXC_PCM_H
++#define _MXC_PCM_H
++
++struct {
++	char *name;			/* stream identifier */
++	dma_channel_params dma_params;
++} mxc_pcm_dma_param;
++
++extern struct snd_soc_cpu_dai mxc_ssi_dai[3];
++
++/* platform data */
++extern struct snd_soc_platform mxc_soc_platform;
++extern struct snd_ac97_bus_ops mxc_ac97_ops;
++
++/* temp until imx-regs.h is up2date */
++#define SSI1_STX0   __REG(IMX_SSI1_BASE + 0x00)
++#define SSI1_STX0_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x00)
++#define SSI1_STX1   __REG(IMX_SSI1_BASE + 0x04)
++#define SSI1_STX1_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x04)
++#define SSI1_SRX0   __REG(IMX_SSI1_BASE + 0x08)
++#define SSI1_SRX0_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x08)
++#define SSI1_SRX1   __REG(IMX_SSI1_BASE + 0x0c)
++#define SSI1_SRX1_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x0c)
++#define SSI1_SCR    __REG(IMX_SSI1_BASE + 0x10)
++#define SSI1_SISR   __REG(IMX_SSI1_BASE + 0x14)
++#define SSI1_SIER   __REG(IMX_SSI1_BASE + 0x18)
++#define SSI1_STCR   __REG(IMX_SSI1_BASE + 0x1c)
++#define SSI1_SRCR   __REG(IMX_SSI1_BASE + 0x20)
++#define SSI1_STCCR  __REG(IMX_SSI1_BASE + 0x24)
++#define SSI1_SRCCR  __REG(IMX_SSI1_BASE + 0x28)
++#define SSI1_SFCSR  __REG(IMX_SSI1_BASE + 0x2c)
++#define SSI1_STR    __REG(IMX_SSI1_BASE + 0x30)
++#define SSI1_SOR    __REG(IMX_SSI1_BASE + 0x34)
++#define SSI1_SACNT  __REG(IMX_SSI1_BASE + 0x38)
++#define SSI1_SACADD __REG(IMX_SSI1_BASE + 0x3c)
++#define SSI1_SACDAT __REG(IMX_SSI1_BASE + 0x40)
++#define SSI1_SATAG  __REG(IMX_SSI1_BASE + 0x44)
++#define SSI1_STMSK  __REG(IMX_SSI1_BASE + 0x48)
++#define SSI1_SRMSK  __REG(IMX_SSI1_BASE + 0x4c)
++
++#define SSI2_STX0   __REG(IMX_SSI2_BASE + 0x00)
++#define SSI2_STX0_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x00)
++#define SSI2_STX1   __REG(IMX_SSI2_BASE + 0x04)
++#define SSI2_STX1_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x04)
++#define SSI2_SRX0   __REG(IMX_SSI2_BASE + 0x08)
++#define SSI2_SRX0_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x08)
++#define SSI2_SRX1   __REG(IMX_SSI2_BASE + 0x0c)
++#define SSI2_SRX1_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x0c)
++#define SSI2_SCR    __REG(IMX_SSI2_BASE + 0x10)
++#define SSI2_SISR   __REG(IMX_SSI2_BASE + 0x14)
++#define SSI2_SIER   __REG(IMX_SSI2_BASE + 0x18)
++#define SSI2_STCR   __REG(IMX_SSI2_BASE + 0x1c)
++#define SSI2_SRCR   __REG(IMX_SSI2_BASE + 0x20)
++#define SSI2_STCCR  __REG(IMX_SSI2_BASE + 0x24)
++#define SSI2_SRCCR  __REG(IMX_SSI2_BASE + 0x28)
++#define SSI2_SFCSR  __REG(IMX_SSI2_BASE + 0x2c)
++#define SSI2_STR    __REG(IMX_SSI2_BASE + 0x30)
++#define SSI2_SOR    __REG(IMX_SSI2_BASE + 0x34)
++#define SSI2_SACNT  __REG(IMX_SSI2_BASE + 0x38)
++#define SSI2_SACADD __REG(IMX_SSI2_BASE + 0x3c)
++#define SSI2_SACDAT __REG(IMX_SSI2_BASE + 0x40)
++#define SSI2_SATAG  __REG(IMX_SSI2_BASE + 0x44)
++#define SSI2_STMSK  __REG(IMX_SSI2_BASE + 0x48)
++#define SSI2_SRMSK  __REG(IMX_SSI2_BASE + 0x4c)
++
++#define SSI_SCR_CLK_IST        (1 << 9)
++#define SSI_SCR_TCH_EN         (1 << 8)
++#define SSI_SCR_SYS_CLK_EN     (1 << 7)
++#define SSI_SCR_I2S_MODE_NORM  (0 << 5)
++#define SSI_SCR_I2S_MODE_MSTR  (1 << 5)
++#define SSI_SCR_I2S_MODE_SLAVE (2 << 5)
++#define SSI_SCR_SYN            (1 << 4)
++#define SSI_SCR_NET            (1 << 3)
++#define SSI_SCR_RE             (1 << 2)
++#define SSI_SCR_TE             (1 << 1)
++#define SSI_SCR_SSIEN          (1 << 0)
++
++#define SSI_SISR_CMDAU         (1 << 18)
++#define SSI_SISR_CMDDU         (1 << 17)
++#define SSI_SISR_RXT           (1 << 16)
++#define SSI_SISR_RDR1          (1 << 15)
++#define SSI_SISR_RDR0          (1 << 14)
++#define SSI_SISR_TDE1          (1 << 13)
++#define SSI_SISR_TDE0          (1 << 12)
++#define SSI_SISR_ROE1          (1 << 11)
++#define SSI_SISR_ROE0          (1 << 10)
++#define SSI_SISR_TUE1          (1 << 9)
++#define SSI_SISR_TUE0          (1 << 8)
++#define SSI_SISR_TFS           (1 << 7)
++#define SSI_SISR_RFS           (1 << 6)
++#define SSI_SISR_TLS           (1 << 5)
++#define SSI_SISR_RLS           (1 << 4)
++#define SSI_SISR_RFF1          (1 << 3)
++#define SSI_SISR_RFF0          (1 << 2)
++#define SSI_SISR_TFE1          (1 << 1)
++#define SSI_SISR_TFE0          (1 << 0)
++
++#define SSI_SIER_RDMAE         (1 << 22)
++#define SSI_SIER_RIE           (1 << 21)
++#define SSI_SIER_TDMAE         (1 << 20)
++#define SSI_SIER_TIE           (1 << 19)
++#define SSI_SIER_CMDAU_EN      (1 << 18)
++#define SSI_SIER_CMDDU_EN      (1 << 17)
++#define SSI_SIER_RXT_EN        (1 << 16)
++#define SSI_SIER_RDR1_EN       (1 << 15)
++#define SSI_SIER_RDR0_EN       (1 << 14)
++#define SSI_SIER_TDE1_EN       (1 << 13)
++#define SSI_SIER_TDE0_EN       (1 << 12)
++#define SSI_SIER_ROE1_EN       (1 << 11)
++#define SSI_SIER_ROE0_EN       (1 << 10)
++#define SSI_SIER_TUE1_EN       (1 << 9)
++#define SSI_SIER_TUE0_EN       (1 << 8)
++#define SSI_SIER_TFS_EN        (1 << 7)
++#define SSI_SIER_RFS_EN        (1 << 6)
++#define SSI_SIER_TLS_EN        (1 << 5)
++#define SSI_SIER_RLS_EN        (1 << 4)
++#define SSI_SIER_RFF1_EN       (1 << 3)
++#define SSI_SIER_RFF0_EN       (1 << 2)
++#define SSI_SIER_TFE1_EN       (1 << 1)
++#define SSI_SIER_TFE0_EN       (1 << 0)
++
++#define SSI_STCR_TXBIT0        (1 << 9)
++#define SSI_STCR_TFEN1         (1 << 8)
++#define SSI_STCR_TFEN0         (1 << 7)
++#define SSI_STCR_TFDIR         (1 << 6)
++#define SSI_STCR_TXDIR         (1 << 5)
++#define SSI_STCR_TSHFD         (1 << 4)
++#define SSI_STCR_TSCKP         (1 << 3)
++#define SSI_STCR_TFSI          (1 << 2)
++#define SSI_STCR_TFSL          (1 << 1)
++#define SSI_STCR_TEFS          (1 << 0)
++
++#define SSI_SRCR_RXBIT0        (1 << 9)
++#define SSI_SRCR_RFEN1         (1 << 8)
++#define SSI_SRCR_RFEN0         (1 << 7)
++#define SSI_SRCR_RFDIR         (1 << 6)
++#define SSI_SRCR_RXDIR         (1 << 5)
++#define SSI_SRCR_RSHFD         (1 << 4)
++#define SSI_SRCR_RSCKP         (1 << 3)
++#define SSI_SRCR_RFSI          (1 << 2)
++#define SSI_SRCR_RFSL          (1 << 1)
++#define SSI_SRCR_REFS          (1 << 0)
++
++#define SSI_STCCR_DIV2         (1 << 18)
++#define SSI_STCCR_PSR          (1 << 15)
++#define SSI_STCCR_WL(x)        ((((x) - 2) >> 1) << 13)
++#define SSI_STCCR_DC(x)        (((x) & 0x1f) << 8)
++#define SSI_STCCR_PM(x)        (((x) & 0xff) << 0)
++
++#define SSI_SRCCR_DIV2         (1 << 18)
++#define SSI_SRCCR_PSR          (1 << 15)
++#define SSI_SRCCR_WL(x)        ((((x) - 2) >> 1) << 13)
++#define SSI_SRCCR_DC(x)        (((x) & 0x1f) << 8)
++#define SSI_SRCCR_PM(x)        (((x) & 0xff) << 0)
++
++
++#define SSI_SFCSR_RFCNT1(x)   (((x) & 0xf) << 28)
++#define SSI_SFCSR_TFCNT1(x)   (((x) & 0xf) << 24)
++#define SSI_SFCSR_RFWM1(x)    (((x) & 0xf) << 20)
++#define SSI_SFCSR_TFWM1(x)    (((x) & 0xf) << 16)
++#define SSI_SFCSR_RFCNT0(x)   (((x) & 0xf) << 12)
++#define SSI_SFCSR_TFCNT0(x)   (((x) & 0xf) <<  8)
++#define SSI_SFCSR_RFWM0(x)    (((x) & 0xf) <<  4)
++#define SSI_SFCSR_TFWM0(x)    (((x) & 0xf) <<  0)
++
++#define SSI_STR_TEST          (1 << 15)
++#define SSI_STR_RCK2TCK       (1 << 14)
++#define SSI_STR_RFS2TFS       (1 << 13)
++#define SSI_STR_RXSTATE(x)    (((x) & 0xf) << 8)
++#define SSI_STR_TXD2RXD       (1 <<  7)
++#define SSI_STR_TCK2RCK       (1 <<  6)
++#define SSI_STR_TFS2RFS       (1 <<  5)
++#define SSI_STR_TXSTATE(x)    (((x) & 0xf) << 0)
++
++#define SSI_SOR_CLKOFF        (1 << 6)
++#define SSI_SOR_RX_CLR        (1 << 5)
++#define SSI_SOR_TX_CLR        (1 << 4)
++#define SSI_SOR_INIT          (1 << 3)
++#define SSI_SOR_WAIT(x)       (((x) & 0x3) << 1)
++#define SSI_SOR_SYNRST        (1 << 0)
++
++#define SSI_SACNT_FRDIV(x)    (((x) & 0x3f) << 5)
++#define SSI_SACNT_WR          (x << 4)
++#define SSI_SACNT_RD          (x << 3)
++#define SSI_SACNT_TIF         (x << 2)
++#define SSI_SACNT_FV          (x << 1)
++#define SSI_SACNT_A97EN       (x << 0)
++
++
++/* AUDMUX registers */
++#define AUDMUX_HPCR1         __REG(IMX_AUDMUX_BASE + 0x00)
++#define AUDMUX_HPCR2         __REG(IMX_AUDMUX_BASE + 0x04)
++#define AUDMUX_HPCR3         __REG(IMX_AUDMUX_BASE + 0x08)
++#define AUDMUX_PPCR1         __REG(IMX_AUDMUX_BASE + 0x10)
++#define AUDMUX_PPCR2         __REG(IMX_AUDMUX_BASE + 0x14)
++#define AUDMUX_PPCR3         __REG(IMX_AUDMUX_BASE + 0x18)
++
++#define AUDMUX_HPCR_TFSDIR         (1 << 31)
++#define AUDMUX_HPCR_TCLKDIR        (1 << 30)
++#define AUDMUX_HPCR_TFCSEL_TX      (0 << 26)
++#define AUDMUX_HPCR_TFCSEL_RX      (8 << 26)
++#define AUDMUX_HPCR_TFCSEL(x)      (((x) & 0x7) << 26)
++#define AUDMUX_HPCR_RFSDIR         (1 << 25)
++#define AUDMUX_HPCR_RCLKDIR        (1 << 24)
++#define AUDMUX_HPCR_RFCSEL_TX      (0 << 20)
++#define AUDMUX_HPCR_RFCSEL_RX      (8 << 20)
++#define AUDMUX_HPCR_RFCSEL(x)      (((x) & 0x7) << 20)
++#define AUDMUX_HPCR_RXDSEL(x)      (((x) & 0x7) << 13)
++#define AUDMUX_HPCR_SYN            (1 << 12)
++#define AUDMUX_HPCR_TXRXEN         (1 << 10)
++#define AUDMUX_HPCR_INMEN          (1 <<  8)
++#define AUDMUX_HPCR_INMMASK(x)     (((x) & 0xff) << 0)
++
++#define AUDMUX_PPCR_TFSDIR         (1 << 31)
++#define AUDMUX_PPCR_TCLKDIR        (1 << 30)
++#define AUDMUX_PPCR_TFCSEL_TX      (0 << 26)
++#define AUDMUX_PPCR_TFCSEL_RX      (8 << 26)
++#define AUDMUX_PPCR_TFCSEL(x)      (((x) & 0x7) << 26)
++#define AUDMUX_PPCR_RFSDIR         (1 << 25)
++#define AUDMUX_PPCR_RCLKDIR        (1 << 24)
++#define AUDMUX_PPCR_RFCSEL_TX      (0 << 20)
++#define AUDMUX_PPCR_RFCSEL_RX      (8 << 20)
++#define AUDMUX_PPCR_RFCSEL(x)      (((x) & 0x7) << 20)
++#define AUDMUX_PPCR_RXDSEL(x)      (((x) & 0x7) << 13)
++#define AUDMUX_PPCR_SYN            (1 << 12)
++#define AUDMUX_PPCR_TXRXEN         (1 << 10)
++
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/imx/imx31-pcm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx31-pcm.c
+@@ -0,0 +1,454 @@
++/*
++ * linux/sound/arm/mxc-pcm.c -- ALSA SoC interface for the Freescale i.MX CPU's
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ * Based on pxa2xx-pcm.c by	Nicolas Pitre, (C) 2004 MontaVista Software, Inc.
++ * and on mxc-alsa-mc13783 (C) 2006 Freescale.
++ *
++ * 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.
++ *
++ *  Revision history
++ *    29th Aug 2006   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <asm/dma.h>
++#include <asm/hardware.h>
++
++#include "imx-pcm.h"
++
++/* debug */
++#define IMX_DEBUG 0
++#if IMX_DEBUG
++#define dbg(format, arg...) printk(format, ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++
++static const struct snd_pcm_hardware mxc_pcm_hardware = {
++	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
++				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
++				   SNDRV_PCM_INFO_MMAP |
++				   SNDRV_PCM_INFO_MMAP_VALID |
++				   SNDRV_PCM_INFO_PAUSE |
++				   SNDRV_PCM_INFO_RESUME),
++	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
++					SNDRV_PCM_FMTBIT_S24_LE,
++	.buffer_bytes_max	= 32 * 1024,
++	.period_bytes_min	= 64,
++	.period_bytes_max	= 8 * 1024,
++	.periods_min		= 2,
++	.periods_max		= 255,
++	.fifo_size		= 0,
++};
++
++struct mxc_runtime_data {
++	int dma_ch;
++	struct mxc_pcm_dma_param *dma_params;
++};
++
++/*!
++  * This function stops the current dma transfert for playback
++  * and clears the dma pointers.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  */
++static void audio_stop_dma(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int dma_size = frames_to_bytes(runtime, runtime->period_size);
++	unsigned int offset  dma_size * s->periods;
++	unsigned long flags;
++
++	spin_lock_irqsave(&prtd->dma_lock, flags);
++
++	dbg("MXC : audio_stop_dma active = 0\n");
++	prtd->active = 0;
++	prtd->period = 0;
++	prtd->periods = 0;
++
++	/* this stops the dma channel and clears the buffer ptrs */
++	mxc_dma_stop(prtd->dma_wchannel);
++	if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_TO_DEVICE);
++	else
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_FROM_DEVICE);
++
++	spin_unlock_irqrestore(&prtd->dma_lock, flags);
++}
++
++/*!
++  * This function is called whenever a new audio block needs to be
++  * transferred to mc13783. The function receives the address and the size
++  * of the new block and start a new DMA transfer.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  */
++static int dma_new_period(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime =  substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int dma_size;
++	unsigned int offset;
++	int ret=0;
++	dma_request_t sdma_request;
++
++	if (prtd->active){
++		memset(&sdma_request, 0, sizeof(dma_request_t));
++		dma_size = frames_to_bytes(runtime, runtime->period_size);
++	    dbg("s->period (%x) runtime->periods (%d)\n",
++			s->period,runtime->periods);
++		dbg("runtime->period_size (%d) dma_size (%d)\n",
++			(unsigned int)runtime->period_size,
++			runtime->dma_bytes);
++
++       	offset = dma_size * prtd->period;
++		snd_assert(dma_size <= DMA_BUF_SIZE, );
++		if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++			sdma_request.sourceAddr = (char*)(dma_map_single(NULL,
++				runtime->dma_area + offset, dma_size, DMA_TO_DEVICE));
++		else
++			sdma_request.destAddr = (char*)(dma_map_single(NULL,
++				runtime->dma_area + offset, dma_size, DMA_FROM_DEVICE));
++		sdma_request.count = dma_size;
++
++		dbg("MXC: Start DMA offset (%d) size (%d)\n", offset,
++						 runtime->dma_bytes);
++
++       	mxc_dma_set_config(prtd->dma_wchannel, &sdma_request, 0);
++		if((ret = mxc_dma_start(prtd->dma_wchannel)) < 0) {
++			dbg("audio_process_dma: cannot queue DMA buffer\
++							(%i)\n", ret);
++			return err;
++		}
++		prtd->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
++		prtd->period++;
++		prtd->period %= runtime->periods;
++    }
++	return ret;
++}
++
++
++/*!
++  * This is a callback which will be called
++  * when a TX transfer finishes. The call occurs
++  * in interrupt context.
++  *
++  * @param	dat	pointer to the structure of the current stream.
++  *
++  */
++static void audio_dma_irq(void *data)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_pcm_runtime *runtime;
++	struct mxc_runtime_data *prtd;
++	unsigned int dma_size;
++	unsigned int previous_period;
++	unsigned int offset;
++
++	substream = data;
++	runtime = substream->runtime;
++	prtd = runtime->private_data;
++	previous_period  = prtd->periods;
++	dma_size = frames_to_bytes(runtime, runtime->period_size);
++	offset = dma_size * previous_period;
++
++	prtd->tx_spin = 0;
++	prtd->periods++;
++	prtd->periods %= runtime->periods;
++
++	/*
++	  * Give back to the CPU the access to the non cached memory
++	  */
++	if(substream == SNDRV_PCM_STREAM_PLAYBACK)
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_TO_DEVICE);
++	else
++		dma_unmap_single(NULL, runtime->dma_addr + offset, dma_size,
++							DMA_FROM_DEVICE);
++	/*
++	  * If we are getting a callback for an active stream then we inform
++	  * the PCM middle layer we've finished a period
++	  */
++ 	if (prtd->active)
++		snd_pcm_period_elapsed(substream);
++
++	/*
++	  * Trig next DMA transfer
++	  */
++	dma_new_period(substream);
++}
++
++/*!
++  * This function configures the hardware to allow audio
++  * playback operations. It is called by ALSA framework.
++  *
++  * @param	substream	pointer to the structure of the current stream.
++  *
++  * @return              0 on success, -1 otherwise.
++  */
++static int
++snd_mxc_prepare(struct snd_pcm_substream *substream)
++{
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	int ret = 0;
++	prtd->period = 0;
++	prtd->periods = 0;
++
++	dma_channel_params params;
++	int channel = 0; // passed in ?
++
++	if ((ret  = mxc_request_dma(&channel, "ALSA TX SDMA") < 0)){
++		dbg("error requesting a write dma channel\n");
++		return ret;
++	}
++
++	/* configure DMA params */
++	memset(&params, 0, sizeof(dma_channel_params));
++	params.bd_number = 1;
++	params.arg = s;
++	params.callback = callback;
++	params.transfer_type = emi_2_per;
++	params.watermark_level = SDMA_TXFIFO_WATERMARK;
++	params.word_size = TRANSFER_16BIT;
++	//dbg(KERN_ERR "activating connection SSI1 - SDMA\n");
++	params.per_address = SSI1_BASE_ADDR;
++	params.event_id = DMA_REQ_SSI1_TX1;
++	params.peripheral_type = SSI;
++
++	/* set up chn with params */
++	mxc_dma_setup_channel(channel, &params);
++	s->dma_wchannel = channel;
++
++	return ret;
++}
++
++static int mxc_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	int ret;
++
++	if((ret=snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
++		return ret;
++	runtime->dma_addr = virt_to_phys(runtime->dma_area);
++
++	return ret;
++}
++
++static int mxc_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_pages(substream);
++}
++
++static int mxc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct mxc_runtime_data *prtd = substream->runtime->private_data;
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		prtd->tx_spin = 0;
++		/* requested stream startup */
++		prtd->active = 1;
++        ret = dma_new_period(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++		/* requested stream shutdown */
++		ret = audio_stop_dma(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++		prtd->active = 0;
++		prtd->periods = 0;
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++		prtd->active = 1;
++		prtd->tx_spin = 0;
++		ret = dma_new_period(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		prtd->active = 0;
++		break;
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		prtd->active = 1;
++		if (prtd->old_offset) {
++			prtd->tx_spin = 0;
++            ret = dma_new_period(substream);
++		}
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t mxc_pcm_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++	unsigned int offset = 0;
++
++	/* tx_spin value is used here to check if a transfert is active */
++	if (prtd->tx_spin){
++		offset = (runtime->period_size * (prtd->periods)) +
++						(runtime->period_size >> 1);
++		if (offset >= runtime->buffer_size)
++			offset = runtime->period_size >> 1;
++	} else {
++		offset = (runtime->period_size * (s->periods));
++		if (offset >= runtime->buffer_size)
++			offset = 0;
++	}
++
++	return offset;
++}
++
++
++static int mxc_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd;
++	int ret;
++
++	snd_soc_set_runtime_hwparams(substream, &mxc_pcm_hardware);
++
++	if ((err = snd_pcm_hw_constraint_integer(runtime,
++					SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
++		return err;
++	if ((err = snd_pcm_hw_constraint_list(runtime, 0,
++			SNDRV_PCM_HW_PARAM_RATE, &hw_playback_rates)) < 0)
++		return err;
++	msleep(10); // liam - why
++
++	/* setup DMA controller for playback */
++	if((err = configure_write_channel(&mxc_mc13783->s[SNDRV_PCM_STREAM_PLAYBACK],
++					audio_dma_irq)) < 0 )
++		return err;
++
++	if((prtd = kzalloc(sizeof(struct mxc_runtime_data), GFP_KERNEL)) == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	runtime->private_data = prtd;
++	return 0;
++
++ err1:
++	kfree(prtd);
++ out:
++	return ret;
++}
++
++static int mxc_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct mxc_runtime_data *prtd = runtime->private_data;
++
++//	mxc_mc13783_t *chip;
++	audio_stream_t *s;
++	device_data_t* device;
++	int ssi;
++
++	//chip = snd_pcm_substream_chip(substream);
++	s = &chip->s[substream->pstr->stream];
++	device = &s->stream_device;
++	ssi = device->ssi;
++
++	//disable_stereodac();
++
++	ssi_transmit_enable(ssi, false);
++	ssi_interrupt_disable(ssi, ssi_tx_dma_interrupt_enable);
++	ssi_tx_fifo_enable(ssi, ssi_fifo_0, false);
++	ssi_enable(ssi, false);
++
++	chip->s[substream->pstr->stream].stream = NULL;
++
++	return 0;
++}
++
++static int
++mxc_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++				     runtime->dma_area,
++				     runtime->dma_addr,
++				     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops mxc_pcm_ops = {
++	.open		= mxc_pcm_open,
++	.close		= mxc_pcm_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= mxc_pcm_hw_params,
++	.hw_free	= mxc_pcm_hw_free,
++	.prepare	= mxc_pcm_prepare,
++	.trigger	= mxc_pcm_trigger,
++	.pointer	= mxc_pcm_pointer,
++	.mmap		= mxc_pcm_mmap,
++};
++
++static u64 mxc_pcm_dmamask = 0xffffffff;
++
++int mxc_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
++	struct snd_pcm *pcm)
++{
++	int ret = 0;
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &mxc_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = 0xffffffff;
++
++	if (dai->playback.channels_min) {
++		ret = mxc_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			goto out;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = mxc_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			goto out;
++	}
++ out:
++	return ret;
++}
++
++struct snd_soc_platform mxc_soc_platform = {
++	.name		= "mxc-audio",
++	.pcm_ops 	= &mxc_pcm_ops,
++	.pcm_new	= mxc_pcm_new,
++	.pcm_free	= mxc_pcm_free_dma_buffers,
++};
++
++EXPORT_SYMBOL_GPL(mxc_soc_platform);
++
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_DESCRIPTION("Freescale i.MX PCM DMA module");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/imx/imx31-pcm.h
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/imx/imx31-pcm.h
+@@ -0,0 +1,237 @@
++/*
++ * mxc-pcm.h :- ASoC platform header for Freescale i.MX
++ *
++ * 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 _MXC_PCM_H
++#define _MXC_PCM_H
++
++struct {
++	char *name;			/* stream identifier */
++	dma_channel_params dma_params;
++} mxc_pcm_dma_param;
++
++extern struct snd_soc_cpu_dai mxc_ssi_dai[3];
++
++/* platform data */
++extern struct snd_soc_platform mxc_soc_platform;
++extern struct snd_ac97_bus_ops mxc_ac97_ops;
++
++/* temp until imx-regs.h is up2date */
++#define SSI1_STX0   __REG(IMX_SSI1_BASE + 0x00)
++#define SSI1_STX0_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x00)
++#define SSI1_STX1   __REG(IMX_SSI1_BASE + 0x04)
++#define SSI1_STX1_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x04)
++#define SSI1_SRX0   __REG(IMX_SSI1_BASE + 0x08)
++#define SSI1_SRX0_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x08)
++#define SSI1_SRX1   __REG(IMX_SSI1_BASE + 0x0c)
++#define SSI1_SRX1_PHYS   __PHYS_REG(IMX_SSI1_BASE + 0x0c)
++#define SSI1_SCR    __REG(IMX_SSI1_BASE + 0x10)
++#define SSI1_SISR   __REG(IMX_SSI1_BASE + 0x14)
++#define SSI1_SIER   __REG(IMX_SSI1_BASE + 0x18)
++#define SSI1_STCR   __REG(IMX_SSI1_BASE + 0x1c)
++#define SSI1_SRCR   __REG(IMX_SSI1_BASE + 0x20)
++#define SSI1_STCCR  __REG(IMX_SSI1_BASE + 0x24)
++#define SSI1_SRCCR  __REG(IMX_SSI1_BASE + 0x28)
++#define SSI1_SFCSR  __REG(IMX_SSI1_BASE + 0x2c)
++#define SSI1_STR    __REG(IMX_SSI1_BASE + 0x30)
++#define SSI1_SOR    __REG(IMX_SSI1_BASE + 0x34)
++#define SSI1_SACNT  __REG(IMX_SSI1_BASE + 0x38)
++#define SSI1_SACADD __REG(IMX_SSI1_BASE + 0x3c)
++#define SSI1_SACDAT __REG(IMX_SSI1_BASE + 0x40)
++#define SSI1_SATAG  __REG(IMX_SSI1_BASE + 0x44)
++#define SSI1_STMSK  __REG(IMX_SSI1_BASE + 0x48)
++#define SSI1_SRMSK  __REG(IMX_SSI1_BASE + 0x4c)
++
++#define SSI2_STX0   __REG(IMX_SSI2_BASE + 0x00)
++#define SSI2_STX0_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x00)
++#define SSI2_STX1   __REG(IMX_SSI2_BASE + 0x04)
++#define SSI2_STX1_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x04)
++#define SSI2_SRX0   __REG(IMX_SSI2_BASE + 0x08)
++#define SSI2_SRX0_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x08)
++#define SSI2_SRX1   __REG(IMX_SSI2_BASE + 0x0c)
++#define SSI2_SRX1_PHYS   __PHYS_REG(IMX_SSI2_BASE + 0x0c)
++#define SSI2_SCR    __REG(IMX_SSI2_BASE + 0x10)
++#define SSI2_SISR   __REG(IMX_SSI2_BASE + 0x14)
++#define SSI2_SIER   __REG(IMX_SSI2_BASE + 0x18)
++#define SSI2_STCR   __REG(IMX_SSI2_BASE + 0x1c)
++#define SSI2_SRCR   __REG(IMX_SSI2_BASE + 0x20)
++#define SSI2_STCCR  __REG(IMX_SSI2_BASE + 0x24)
++#define SSI2_SRCCR  __REG(IMX_SSI2_BASE + 0x28)
++#define SSI2_SFCSR  __REG(IMX_SSI2_BASE + 0x2c)
++#define SSI2_STR    __REG(IMX_SSI2_BASE + 0x30)
++#define SSI2_SOR    __REG(IMX_SSI2_BASE + 0x34)
++#define SSI2_SACNT  __REG(IMX_SSI2_BASE + 0x38)
++#define SSI2_SACADD __REG(IMX_SSI2_BASE + 0x3c)
++#define SSI2_SACDAT __REG(IMX_SSI2_BASE + 0x40)
++#define SSI2_SATAG  __REG(IMX_SSI2_BASE + 0x44)
++#define SSI2_STMSK  __REG(IMX_SSI2_BASE + 0x48)
++#define SSI2_SRMSK  __REG(IMX_SSI2_BASE + 0x4c)
++
++#define SSI_SCR_CLK_IST        (1 << 9)
++#define SSI_SCR_TCH_EN         (1 << 8)
++#define SSI_SCR_SYS_CLK_EN     (1 << 7)
++#define SSI_SCR_I2S_MODE_NORM  (0 << 5)
++#define SSI_SCR_I2S_MODE_MSTR  (1 << 5)
++#define SSI_SCR_I2S_MODE_SLAVE (2 << 5)
++#define SSI_SCR_SYN            (1 << 4)
++#define SSI_SCR_NET            (1 << 3)
++#define SSI_SCR_RE             (1 << 2)
++#define SSI_SCR_TE             (1 << 1)
++#define SSI_SCR_SSIEN          (1 << 0)
++
++#define SSI_SISR_CMDAU         (1 << 18)
++#define SSI_SISR_CMDDU         (1 << 17)
++#define SSI_SISR_RXT           (1 << 16)
++#define SSI_SISR_RDR1          (1 << 15)
++#define SSI_SISR_RDR0          (1 << 14)
++#define SSI_SISR_TDE1          (1 << 13)
++#define SSI_SISR_TDE0          (1 << 12)
++#define SSI_SISR_ROE1          (1 << 11)
++#define SSI_SISR_ROE0          (1 << 10)
++#define SSI_SISR_TUE1          (1 << 9)
++#define SSI_SISR_TUE0          (1 << 8)
++#define SSI_SISR_TFS           (1 << 7)
++#define SSI_SISR_RFS           (1 << 6)
++#define SSI_SISR_TLS           (1 << 5)
++#define SSI_SISR_RLS           (1 << 4)
++#define SSI_SISR_RFF1          (1 << 3)
++#define SSI_SISR_RFF0          (1 << 2)
++#define SSI_SISR_TFE1          (1 << 1)
++#define SSI_SISR_TFE0          (1 << 0)
++
++#define SSI_SIER_RDMAE         (1 << 22)
++#define SSI_SIER_RIE           (1 << 21)
++#define SSI_SIER_TDMAE         (1 << 20)
++#define SSI_SIER_TIE           (1 << 19)
++#define SSI_SIER_CMDAU_EN      (1 << 18)
++#define SSI_SIER_CMDDU_EN      (1 << 17)
++#define SSI_SIER_RXT_EN        (1 << 16)
++#define SSI_SIER_RDR1_EN       (1 << 15)
++#define SSI_SIER_RDR0_EN       (1 << 14)
++#define SSI_SIER_TDE1_EN       (1 << 13)
++#define SSI_SIER_TDE0_EN       (1 << 12)
++#define SSI_SIER_ROE1_EN       (1 << 11)
++#define SSI_SIER_ROE0_EN       (1 << 10)
++#define SSI_SIER_TUE1_EN       (1 << 9)
++#define SSI_SIER_TUE0_EN       (1 << 8)
++#define SSI_SIER_TFS_EN        (1 << 7)
++#define SSI_SIER_RFS_EN        (1 << 6)
++#define SSI_SIER_TLS_EN        (1 << 5)
++#define SSI_SIER_RLS_EN        (1 << 4)
++#define SSI_SIER_RFF1_EN       (1 << 3)
++#define SSI_SIER_RFF0_EN       (1 << 2)
++#define SSI_SIER_TFE1_EN       (1 << 1)
++#define SSI_SIER_TFE0_EN       (1 << 0)
++
++#define SSI_STCR_TXBIT0        (1 << 9)
++#define SSI_STCR_TFEN1         (1 << 8)
++#define SSI_STCR_TFEN0         (1 << 7)
++#define SSI_STCR_TFDIR         (1 << 6)
++#define SSI_STCR_TXDIR         (1 << 5)
++#define SSI_STCR_TSHFD         (1 << 4)
++#define SSI_STCR_TSCKP         (1 << 3)
++#define SSI_STCR_TFSI          (1 << 2)
++#define SSI_STCR_TFSL          (1 << 1)
++#define SSI_STCR_TEFS          (1 << 0)
++
++#define SSI_SRCR_RXBIT0        (1 << 9)
++#define SSI_SRCR_RFEN1         (1 << 8)
++#define SSI_SRCR_RFEN0         (1 << 7)
++#define SSI_SRCR_RFDIR         (1 << 6)
++#define SSI_SRCR_RXDIR         (1 << 5)
++#define SSI_SRCR_RSHFD         (1 << 4)
++#define SSI_SRCR_RSCKP         (1 << 3)
++#define SSI_SRCR_RFSI          (1 << 2)
++#define SSI_SRCR_RFSL          (1 << 1)
++#define SSI_SRCR_REFS          (1 << 0)
++
++#define SSI_STCCR_DIV2         (1 << 18)
++#define SSI_STCCR_PSR          (1 << 15)
++#define SSI_STCCR_WL(x)        ((((x) - 2) >> 1) << 13)
++#define SSI_STCCR_DC(x)        (((x) & 0x1f) << 8)
++#define SSI_STCCR_PM(x)        (((x) & 0xff) << 0)
++
++#define SSI_SRCCR_DIV2         (1 << 18)
++#define SSI_SRCCR_PSR          (1 << 15)
++#define SSI_SRCCR_WL(x)        ((((x) - 2) >> 1) << 13)
++#define SSI_SRCCR_DC(x)        (((x) & 0x1f) << 8)
++#define SSI_SRCCR_PM(x)        (((x) & 0xff) << 0)
++
++
++#define SSI_SFCSR_RFCNT1(x)   (((x) & 0xf) << 28)
++#define SSI_SFCSR_TFCNT1(x)   (((x) & 0xf) << 24)
++#define SSI_SFCSR_RFWM1(x)    (((x) & 0xf) << 20)
++#define SSI_SFCSR_TFWM1(x)    (((x) & 0xf) << 16)
++#define SSI_SFCSR_RFCNT0(x)   (((x) & 0xf) << 12)
++#define SSI_SFCSR_TFCNT0(x)   (((x) & 0xf) <<  8)
++#define SSI_SFCSR_RFWM0(x)    (((x) & 0xf) <<  4)
++#define SSI_SFCSR_TFWM0(x)    (((x) & 0xf) <<  0)
++
++#define SSI_STR_TEST          (1 << 15)
++#define SSI_STR_RCK2TCK       (1 << 14)
++#define SSI_STR_RFS2TFS       (1 << 13)
++#define SSI_STR_RXSTATE(x)    (((x) & 0xf) << 8)
++#define SSI_STR_TXD2RXD       (1 <<  7)
++#define SSI_STR_TCK2RCK       (1 <<  6)
++#define SSI_STR_TFS2RFS       (1 <<  5)
++#define SSI_STR_TXSTATE(x)    (((x) & 0xf) << 0)
++
++#define SSI_SOR_CLKOFF        (1 << 6)
++#define SSI_SOR_RX_CLR        (1 << 5)
++#define SSI_SOR_TX_CLR        (1 << 4)
++#define SSI_SOR_INIT          (1 << 3)
++#define SSI_SOR_WAIT(x)       (((x) & 0x3) << 1)
++#define SSI_SOR_SYNRST        (1 << 0)
++
++#define SSI_SACNT_FRDIV(x)    (((x) & 0x3f) << 5)
++#define SSI_SACNT_WR          (x << 4)
++#define SSI_SACNT_RD          (x << 3)
++#define SSI_SACNT_TIF         (x << 2)
++#define SSI_SACNT_FV          (x << 1)
++#define SSI_SACNT_A97EN       (x << 0)
++
++
++/* AUDMUX registers */
++#define AUDMUX_HPCR1         __REG(IMX_AUDMUX_BASE + 0x00)
++#define AUDMUX_HPCR2         __REG(IMX_AUDMUX_BASE + 0x04)
++#define AUDMUX_HPCR3         __REG(IMX_AUDMUX_BASE + 0x08)
++#define AUDMUX_PPCR1         __REG(IMX_AUDMUX_BASE + 0x10)
++#define AUDMUX_PPCR2         __REG(IMX_AUDMUX_BASE + 0x14)
++#define AUDMUX_PPCR3         __REG(IMX_AUDMUX_BASE + 0x18)
++
++#define AUDMUX_HPCR_TFSDIR         (1 << 31)
++#define AUDMUX_HPCR_TCLKDIR        (1 << 30)
++#define AUDMUX_HPCR_TFCSEL_TX      (0 << 26)
++#define AUDMUX_HPCR_TFCSEL_RX      (8 << 26)
++#define AUDMUX_HPCR_TFCSEL(x)      (((x) & 0x7) << 26)
++#define AUDMUX_HPCR_RFSDIR         (1 << 25)
++#define AUDMUX_HPCR_RCLKDIR        (1 << 24)
++#define AUDMUX_HPCR_RFCSEL_TX      (0 << 20)
++#define AUDMUX_HPCR_RFCSEL_RX      (8 << 20)
++#define AUDMUX_HPCR_RFCSEL(x)      (((x) & 0x7) << 20)
++#define AUDMUX_HPCR_RXDSEL(x)      (((x) & 0x7) << 13)
++#define AUDMUX_HPCR_SYN            (1 << 12)
++#define AUDMUX_HPCR_TXRXEN         (1 << 10)
++#define AUDMUX_HPCR_INMEN          (1 <<  8)
++#define AUDMUX_HPCR_INMMASK(x)     (((x) & 0xff) << 0)
++
++#define AUDMUX_PPCR_TFSDIR         (1 << 31)
++#define AUDMUX_PPCR_TCLKDIR        (1 << 30)
++#define AUDMUX_PPCR_TFCSEL_TX      (0 << 26)
++#define AUDMUX_PPCR_TFCSEL_RX      (8 << 26)
++#define AUDMUX_PPCR_TFCSEL(x)      (((x) & 0x7) << 26)
++#define AUDMUX_PPCR_RFSDIR         (1 << 25)
++#define AUDMUX_PPCR_RCLKDIR        (1 << 24)
++#define AUDMUX_PPCR_RFCSEL_TX      (0 << 20)
++#define AUDMUX_PPCR_RFCSEL_RX      (8 << 20)
++#define AUDMUX_PPCR_RFCSEL(x)      (((x) & 0x7) << 20)
++#define AUDMUX_PPCR_RXDSEL(x)      (((x) & 0x7) << 13)
++#define AUDMUX_PPCR_SYN            (1 << 12)
++#define AUDMUX_PPCR_TXRXEN         (1 << 10)
++
++
++#endif
+Index: linux-2.6-pxa-new/sound/soc/s3c24xx/s3c24xx-i2s.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/s3c24xx/s3c24xx-i2s.c
+@@ -0,0 +1,271 @@
++/*
++ * s3c24xx-i2s.c  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Graeme Gregory
++ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    10th Nov 2006   Initial version.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/arch/regs-iis.h>
++#include <asm/arch/regs-gpio.h>
++#include <asm/arch/regs-clock.h>
++#include <asm/arch/audio.h>
++#include <asm/dma.h>
++#include <asm/arch/dma.h>
++
++#include "s3c24xx-pcm.h"
++
++/* used to disable sysclk if external crystal is used */
++static int extclk = 0;
++module_param(extclk, int, 0);
++MODULE_PARM_DESC(extclk, "set to 1 to disable s3c24XX i2s sysclk");
++
++#define S3C24XX_I2S_DAIFMT \
++	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
++
++#define S3C24XX_I2S_DIR \
++	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
++
++#define S3C24XX_I2S_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++
++/* priv is divider */
++static struct snd_soc_dai_mode s3c24xx_i2s_modes[] =
++{
++	/* s3c24xx I2S frame and clock master modes */
++	{
++		.fmt = S3C24XX_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
++		.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
++		.pcmrate = SNDRV_PCM_RATE_44100,
++		.pcmdir = S3C24XX_I2S_DIR,
++		.flags = SND_SOC_DAI_BFS_RATE,
++		.fs = 384,
++		.bfs = 32,
++		.priv = 0x00
++	},
++};
++
++static struct s3c2410_dma_client s3c24xx_dma_client_out = {
++	.name = "I2S PCM Stereo out"
++};
++
++static struct s3c2410_dma_client s3c24xx_dma_client_in = {
++	.name = "I2S PCM Stereo in"
++};
++
++static s3c24xx_pcm_dma_params_t s3c24xx_i2s_pcm_stereo_out = {
++	.client		= &s3c24xx_dma_client_out,
++	.channel	= DMACH_I2S_OUT,
++	.dma_addr	= S3C2410_PA_IIS+S3C2410_IISFIFO
++};
++
++static s3c24xx_pcm_dma_params_t s3c24xx_i2s_pcm_stereo_in = {
++	.client		= &s3c24xx_dma_client_in,
++	.channel	= DMACH_I2S_IN,
++	.dma_addr	= S3C2410_PA_IIS+S3C2410_IISFIFO
++};
++
++
++struct s3c24xx_i2s_port {
++	int master;
++};
++static struct s3c24xx_i2s_port s3c24xx_i2s;
++
++/* Empty for the s3c24xx platforms */
++static int s3c24xx_i2s_startup(struct snd_pcm_substream *substream)
++{
++	return 0;
++}
++
++static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	unsigned long iiscon;
++	unsigned long iismod;
++	unsigned long iisfcon;
++
++	s3c24xx_i2s.master = 0;
++	if(rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
++		s3c24xx_i2s.master = 1;
++
++	/* Configure the I2S pins in correct mode */
++	s3c2410_gpio_cfgpin(S3C2410_GPE0,S3C2410_GPE0_I2SLRCK);
++	if (s3c24xx_i2s.master && !extclk){
++		printk("Setting Clock Output as we are Master\n");
++		s3c2410_gpio_cfgpin(S3C2410_GPE1,S3C2410_GPE1_I2SSCLK);
++	}
++	s3c2410_gpio_cfgpin(S3C2410_GPE2,S3C2410_GPE2_CDCLK);
++	s3c2410_gpio_cfgpin(S3C2410_GPE3,S3C2410_GPE3_I2SSDI);
++	s3c2410_gpio_cfgpin(S3C2410_GPE4,S3C2410_GPE4_I2SSDO);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++	{
++		rtd->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
++	}
++	else
++	{
++		rtd->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in;
++	}
++
++	/* Working copies of registers */
++	iiscon=readl(S3C24XX_VA_IIS+S3C2410_IISCON);
++	iismod=readl(S3C24XX_VA_IIS+S3C2410_IISMOD);
++	iisfcon=readl(S3C24XX_VA_IIS+S3C2410_IISFCON);
++	/* is port used by another stream */
++	if (!(iiscon & S3C2410_IISCON_IISEN)) {
++
++		/* Clear the registers */
++
++		iismod |= S3C2410_IISMOD_32FS | S3C2410_IISMOD_384FS;
++
++		if (!s3c24xx_i2s.master)
++			iismod |= S3C2410_IISMOD_SLAVE;
++
++		if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_LEFT_J)
++			iismod |= S3C2410_IISMOD_MSB;
++	}
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++	{
++		iismod |= S3C2410_IISMOD_TXMODE;
++		iiscon |= S3C2410_IISCON_TXDMAEN;
++		iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE;
++	}
++	else
++	{
++		iismod |= S3C2410_IISMOD_RXMODE;
++		iiscon |= S3C2410_IISCON_RXDMAEN;
++		iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE;
++	}
++
++	writel(iiscon, S3C24XX_VA_IIS+S3C2410_IISCON);
++	writel(iismod, S3C24XX_VA_IIS+S3C2410_IISMOD);
++	writel(iisfcon, S3C24XX_VA_IIS+S3C2410_IISFCON);
++
++	printk("IISCON: %lx IISMOD: %lx", iiscon, iismod);
++
++	return 0;
++}
++
++static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++	unsigned long iiscon;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		/* Enable the IIS unit */
++		iiscon = readl(S3C24XX_VA_IIS+S3C2410_IISCON);
++		iiscon |= S3C2410_IISCON_IISEN;
++		writel(iiscon, S3C24XX_VA_IIS+S3C2410_IISCON);
++		break;
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void s3c24xx_i2s_shutdown(struct snd_pcm_substream *substream)
++{
++	unsigned long iismod, iiscon;
++
++	iismod=readl(S3C24XX_VA_IIS+S3C2410_IISMOD);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		iismod &= ~S3C2410_IISMOD_TXMODE;
++	} else {
++		iismod &= ~S3C2410_IISMOD_RXMODE;
++	}
++
++	writel(iismod,S3C24XX_VA_IIS+S3C2410_IISMOD);
++
++	iiscon=readl(S3C24XX_VA_IIS+S3C2410_IISCON);
++
++	if (iismod & ( S3C2410_IISMOD_TXMODE | S3C2410_IISMOD_RXMODE )) {
++		iiscon &= ! S3C2410_IISCON_IISEN;
++		writel(iiscon,S3C24XX_VA_IIS+S3C2410_IISCON);
++	}
++}
++
++#ifdef CONFIG_PM
++static int s3c24xx_i2s_suspend(struct platform_device *dev,
++	struct snd_soc_cpu_dai *dai)
++{
++}
++
++static int s3c24xx_i2s_resume(struct platform_device *pdev,
++	struct snd_soc_cpu_dai *dai)
++{
++}
++
++#else
++#define s3c24xx_i2s_suspend	NULL
++#define s3c24xx_i2s_resume	NULL
++#endif
++
++/* s3c24xx I2S sysclock is always 384 FS */
++static unsigned int s3c24xx_i2s_config_sysclk(struct snd_soc_cpu_dai *iface,
++	struct snd_soc_clock_info *info, unsigned int clk)
++{
++	return info->rate * 384;
++}
++
++struct snd_soc_cpu_dai s3c24xx_i2s_dai = {
++	.name = "s3c24xx-i2s",
++	.id = 0,
++	.type = SND_SOC_DAI_I2S,
++	.suspend = s3c24xx_i2s_suspend,
++	.resume = s3c24xx_i2s_resume,
++	.config_sysclk = s3c24xx_i2s_config_sysclk,
++	.playback = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.capture = {
++		.channels_min = 2,
++		.channels_max = 2,},
++	.ops = {
++		.startup = s3c24xx_i2s_startup,
++		.shutdown = s3c24xx_i2s_shutdown,
++		.trigger = s3c24xx_i2s_trigger,
++		.hw_params = s3c24xx_i2s_hw_params,},
++	.caps = {
++		.num_modes = ARRAY_SIZE(s3c24xx_i2s_modes),
++		.mode = s3c24xx_i2s_modes,},
++};
++
++EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
++
++/* Module information */
++MODULE_AUTHOR("Graeme Gregory, graeme.gregory at wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/s3c24xx/s3c24xx-pcm.c
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/s3c24xx/s3c24xx-pcm.c
+@@ -0,0 +1,362 @@
++/*
++ * s3c24xx-pcm.c  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2005 Wolfson Microelectronics PLC.
++ * Author: Graeme Gregory
++ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ *  Revision history
++ *    10th Nov 2006   Initial version.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/dma.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/arch/dma.h>
++#include <asm/arch/audio.h>
++
++#include "s3c24xx-pcm.h"
++
++static const struct snd_pcm_hardware s3c24xx_pcm_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,
++        .period_bytes_min       = 32,
++        .period_bytes_max       = 8192,
++        .periods_min            = 1,
++        .periods_max            = 8192,
++        .buffer_bytes_max       = 256 * 1024,
++		.fifo_size				= 32,
++};
++
++struct s3c24xx_runtime_data {
++	dma_addr_t dma_buffer;
++	dma_addr_t dma_buffer_end;
++	size_t period_size;
++	dma_addr_t period_ptr;
++	s3c24xx_pcm_dma_params_t *params;
++};
++
++/* Move the pointer onto the next period, dealing with wrap around.
++ */
++void static next_period(struct s3c24xx_runtime_data *prtd)
++{
++	prtd->period_ptr+=prtd->period_size;
++	if(prtd->period_ptr>=prtd->dma_buffer_end)
++	{
++		prtd->period_ptr=prtd->dma_buffer;
++	}
++}
++
++void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
++							void *dev_id, int size,
++							enum s3c2410_dma_buffresult result)
++{
++	struct snd_pcm_substream *substream = dev_id;
++	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
++
++	if(result==S3C2410_RES_OK)
++	{
++		next_period(prtd);
++		s3c2410_dma_enqueue(prtd->params->channel, substream, prtd->period_ptr, prtd->period_size);
++	}
++	snd_pcm_period_elapsed(substream);
++
++}
++
++static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct s3c24xx_runtime_data *prtd = runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	s3c24xx_pcm_dma_params_t *dma = rtd->cpu_dai->dma_data;
++	int ret;
++
++	printk("Entered s3c24xx hw_params\n");
++
++	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
++	runtime->dma_bytes = params_buffer_bytes(params);
++
++	prtd->params=dma;
++	if(ret=s3c2410_dma_request(prtd->params->channel,
++								prtd->params->client,NULL))
++	{
++		printk("Failed to get dma channel %d for %s\n",prtd->params->channel,
++				prtd->params->client->name);
++		return ret;
++	}
++
++	//s3c2410_dma_setflags(prtd->params->channel,S3C2410_DMAF_AUTOSTART);
++	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++	{
++		s3c2410_dma_devconfig(prtd->params->channel, S3C2410_DMASRC_MEM,
++								S3C2410_DISRCC_INC | S3C2410_DISRCC_APB,
++								prtd->params->dma_addr);
++	}
++	else
++	{
++		s3c2410_dma_devconfig(prtd->params->channel, S3C2410_DMASRC_HW,
++								S3C2410_DISRCC_INC | S3C2410_DISRCC_APB,
++								prtd->params->dma_addr);
++	}
++
++	s3c2410_dma_config(prtd->params->channel,2,S3C2410_DCON_HANDSHAKE);
++
++	s3c2410_dma_set_buffdone_fn(prtd->params->channel, s3c24xx_audio_buffdone);
++
++	prtd->dma_buffer = runtime->dma_addr;
++	prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
++	prtd->period_size = params_period_bytes(params);
++
++	return 0;
++}
++
++static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
++
++	printk("Entered s3c24xx hw_free\n");
++
++	return 0;
++}
++
++static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
++
++	printk("Entered s3c24xx prepare\n");
++
++	/* Set the period that is to be queued in DMA */
++	prtd->period_ptr = prtd->dma_buffer;
++
++	/* queue the first period */
++	s3c2410_dma_enqueue(prtd->params->channel, substream, prtd->period_ptr, prtd->period_size);
++
++	/* Move to next period to be queued */
++	next_period(prtd);
++
++	/* queue the second buffer */
++	s3c2410_dma_enqueue(prtd->params->channel, substream, prtd->period_ptr, prtd->period_size);
++
++
++	return 0;
++}
++
++static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
++	int ret = 0;
++
++	printk("Entered s3c24xx trigger\n");
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
++		break;
++
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct s3c24xx_runtime_data *prtd = runtime->private_data;
++	dma_addr_t dst,src;
++	snd_pcm_uframes_t x;
++
++	printk("Entered s3c24xx pointer\n");
++
++	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
++
++	printk("DMA Position: %lx, %lx\n", src, dst);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++	{
++		x = bytes_to_frames(runtime, src - prtd->dma_buffer);
++	}
++	else
++	{
++		x = bytes_to_frames(runtime, dst - prtd->dma_buffer);
++	}
++
++	if (x == runtime->buffer_size)
++		x=0;
++	return x;
++
++}
++
++static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct s3c24xx_runtime_data *prtd;
++	int ret;
++
++	printk("Entered s3c24xx open\n");
++
++	snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
++
++	if((prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL)) == NULL)
++	{
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	runtime->private_data = prtd;
++	return 0;
++
++out:
++	return ret;
++}
++
++static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct s3c24xx_runtime_data *prtd = runtime->private_data;
++
++	printk("Entered s3c24xx close\n");
++
++	s3c2410_dma_free(prtd->params->channel, prtd->params->client);
++
++	return 0;
++}
++
++static int
++s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	printk("Entered s3c24xx mmap\n");
++
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++                                     runtime->dma_area,
++                                     runtime->dma_addr,
++                                     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops s3c24xx_pcm_ops = {
++	.open		= s3c24xx_pcm_open,
++	.close		= s3c24xx_pcm_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= s3c24xx_pcm_hw_params,
++	.hw_free	= s3c24xx_pcm_hw_free,
++	.prepare	= s3c24xx_pcm_prepare,
++	.trigger	= s3c24xx_pcm_trigger,
++	.pointer	= s3c24xx_pcm_pointer,
++	.mmap		= s3c24xx_pcm_mmap,
++};
++
++static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
++{
++	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
++	struct snd_dma_buffer *buf = &substream->dma_buffer;
++	size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
++
++	printk("Entered s3c24xx preaccolate_dma_buffer\n");
++
++	buf->dev.type = SNDRV_DMA_TYPE_DEV;
++	buf->dev.dev = pcm->card->dev;
++	buf->private_data = NULL;
++	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
++					   &buf->addr, GFP_KERNEL);
++	if (!buf->area)
++		return -ENOMEM;
++	buf->bytes = size;
++	return 0;
++}
++
++static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_dma_buffer *buf;
++	int stream;
++
++	printk("Entered s3c24xx free_dma_buffers\n");
++
++	for (stream = 0; stream < 2; stream++) {
++		substream = pcm->streams[stream].substream;
++		if (!substream)
++			continue;
++
++		buf = &substream->dma_buffer;
++		if (!buf->area)
++			continue;
++
++		dma_free_writecombine(pcm->card->dev, buf->bytes,
++				      buf->area, buf->addr);
++		buf->area = NULL;
++	}
++}
++
++static u64 s3c24xx_pcm_dmamask = 0xffffffff;
++
++int s3c24xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
++	struct snd_pcm *pcm)
++{
++	int ret = 0;
++
++	printk("Entered s3c24xx new\n");
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &s3c24xx_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = 0xffffffff;
++
++	if (dai->playback.channels_min) {
++		ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			goto out;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			goto out;
++	}
++ out:
++	return ret;
++}
++
++struct snd_soc_platform s3c24xx_soc_platform = {
++	.name		= "s3c24xx-audio",
++	.pcm_ops 	= &s3c24xx_pcm_ops,
++	.pcm_new	= s3c24xx_pcm_new,
++	.pcm_free	= s3c24xx_pcm_free_dma_buffers,
++};
++
++EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
++
++MODULE_AUTHOR("Graeme Gregory");
++MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
++MODULE_LICENSE("GPL");
+Index: linux-2.6-pxa-new/sound/soc/s3c24xx/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/s3c24xx/Kconfig
+@@ -0,0 +1,26 @@
++menu "SoC Audio for the Atmel AT91"
++
++config SND_S3C24XX_SOC
++	tristate "SoC Audio for the Samsung S3C24xx System-on-Chip"
++	depends on ARCH_S3C2410 && SND
++	select SND_PCM
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the Samsung S3C24xx.
++
++config SND_S3C24XX_SOC_I2S
++	tristate
++
++config SND_S3C24XX_SOC_AC97
++	tristate
++
++# graeme - add mach dep
++config SND_S3C24XX_SOC_SMDK2440
++	tristate "SoC I2S Audio support for SMDK2440"
++	depends on SND_S3C24XX_SOC
++	select SND_S3C24XX_SOC_I2S
++	select SND_SOC_UDA1380
++	help
++	  Say Y if you want to add support for SoC audio on
++
++endmenu
+Index: linux-2.6-pxa-new/sound/soc/s3c24xx/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6-pxa-new/sound/soc/s3c24xx/Makefile
+@@ -0,0 +1,11 @@
++# S3C24xx Platform Support
++snd-soc-s3c24xx-objs := s3c24xx-pcm.o
++snd-soc-at91-i2s-objs := s3c24xx-i2s.o
++
++obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
++obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
++
++# S3C24xx Machine Support
++snd-soc-smdk2440-uda1380-objs := smdk2440_uda1380.o
++
++obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2440) += snd-soc-smdk2440-uda1380.o

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/connectplus-remove-ide-HACK.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/connectplus-remove-ide-HACK.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/connectplus-remove-ide-HACK.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,12 @@
+Index: linux-2.6.13/drivers/ide/legacy/ide-cs.c
+===================================================================
+--- linux-2.6.13.orig/drivers/ide/legacy/ide-cs.c	2005-09-01 22:43:46.000000000 +0100
++++ linux-2.6.13/drivers/ide/legacy/ide-cs.c	2005-09-01 22:45:46.000000000 +0100
+@@ -488,7 +488,6 @@
+ 	PCMCIA_DEVICE_PROD_ID123("KODAK Picture Card       ", "KODAK  ", "V100K", 0x94a0d8f3, 0xe4fc3ea0, 0xe5e7eed4),
+ 	PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+ 	PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
+-	PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
+ 	PCMCIA_DEVICE_NULL,
+ };
+ MODULE_DEVICE_TABLE(pcmcia, ide_ids);

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-akita
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-akita	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-akita	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1572 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Thu Mar 23 22:11:12 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_PXA_SHARPSL_25x is not set
+CONFIG_PXA_SHARPSL_27x=y
+CONFIG_MACH_AKITA=y
+CONFIG_MACH_SPITZ=y
+CONFIG_MACH_BORZOI=y
+CONFIG_PXA27x=y
+# CONFIG_PXA_KEYS is not set
+CONFIG_IWMMXT=y
+CONFIG_PXA_SHARP_Cxx00=y
+CONFIG_PXA_SSP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+CONFIG_KEXEC=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_CORGI is not set
+CONFIG_KEYBOARD_SPITZ=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_SPITZ=y
+# CONFIG_LEDS_TOSA is not set
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_BACKLIGHT_HP680 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_DETECT is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=m
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2xx_SOC=m
+CONFIG_SND_PXA2xx_SOC_I2S=m
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8753 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9713 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9712 is not set
+# CONFIG_SND_PXA2xx_SOC_CORGI is not set
+CONFIG_SND_PXA2xx_SOC_SPITZ=m
+# CONFIG_SND_PXA2xx_SOC_TOSA is not set
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+# CONFIG_SND_SOC_WM8731 is not set
+CONFIG_SND_SOC_WM8750=m
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+# CONFIG_SND_SOC_WM9712 is not set
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=m
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-c7x0
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-c7x0	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-c7x0	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1608 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Mon May 22 09:00:01 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+# CONFIG_MACH_POODLE is not set
+CONFIG_MACH_CORGI=y
+CONFIG_MACH_SHEPHERD=y
+CONFIG_MACH_HUSKY=y
+# CONFIG_MACH_TOSA is not set
+CONFIG_PXA25x=y
+# CONFIG_PXA_KEYS is not set
+CONFIG_PXA_SHARP_C7xx=y
+CONFIG_PXA_SSP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+CONFIG_KEXEC=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_CORGI=y
+# CONFIG_KEYBOARD_SPITZ is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_CORGI=y
+# CONFIG_LEDS_TOSA is not set
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_PXA is not set
+CONFIG_FB_W100=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_BACKLIGHT_HP680 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_DETECT is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=m
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2xx_SOC=m
+CONFIG_SND_PXA2xx_SOC_I2S=m
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8753 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9713 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9712 is not set
+CONFIG_SND_PXA2xx_SOC_CORGI=m
+# CONFIG_SND_PXA2xx_SOC_SPITZ is not set
+# CONFIG_SND_PXA2xx_SOC_TOSA is not set
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+CONFIG_SND_SOC_WM8731=m
+# CONFIG_SND_SOC_WM8750 is not set
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+# CONFIG_SND_SOC_WM9712 is not set
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+# CONFIG_USB_PXA2XX_SMALL is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-collie
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-collie	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-collie	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1641 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Tue Jul  4 16:35:35 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_SA1100_CERF is not set
+CONFIG_SA1100_COLLIE=y
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HACKKIT is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_SA1100=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+
+#
+# Processor Features
+#
+CONFIG_KEXEC=y
+CONFIG_SHARP_LOCOMO=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+CONFIG_ISA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_NODES_SHIFT=2
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 mem=32M fbcon=rotate:1 dyntick=enable quiet"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_SA1100_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIUSB is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+CONFIG_MTD_OBSOLETE_CHIPS=y
+CONFIG_MTD_SHARP=y
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_LOCOMO=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+CONFIG_MCP=y
+CONFIG_MCP_SA11X0=y
+CONFIG_MCP_UCB1200=y
+# CONFIG_MCP_UCB1200_AUDIO is not set
+CONFIG_MCP_UCB1200_TS=m
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LOCOMO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# V4L USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_OHAND_CLUT224 is not set
+CONFIG_LOGO_OZ240_CLUT224=y
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_LOCOMO=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=m
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ANYDATA=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_SA1100=y
+CONFIG_USB_SA1100=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-hx2000
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-hx2000	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-hx2000	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1028 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc1-git7
+# Sat Nov 19 23:13:51 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_MACH_HX2750=y
+CONFIG_PXA27x=y
+CONFIG_PXA_KEYS=y
+CONFIG_PXA_SSP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_AIRO is not set
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_TSC2101=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_SA1100_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multi-Function Devices
+#
+CONFIG_MFD_TSC2101=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+CONFIG_BACKLIGHT_HX2750=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-poodle
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-poodle	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-poodle	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1655 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Jul 10 23:38:56 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+CONFIG_MACH_POODLE=y
+# CONFIG_MACH_CORGI is not set
+# CONFIG_MACH_SHEPHERD is not set
+# CONFIG_MACH_HUSKY is not set
+# CONFIG_MACH_TOSA is not set
+CONFIG_PXA25x=y
+# CONFIG_PXA_KEYS is not set
+CONFIG_PXA_SSP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+CONFIG_KEXEC=y
+CONFIG_SHARP_LOCOMO=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2  fbcon=rotate:1 dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_LOCOMO=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_CORGI is not set
+# CONFIG_KEYBOARD_SPITZ is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_LOCOMO=y
+# CONFIG_LEDS_TOSA is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# V4L USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_USB_DSBR=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_OHAND_CLUT224 is not set
+CONFIG_LOGO_OZ240_CLUT224=y
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_LOCOMO=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=m
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2xx_SOC=m
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8731 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8753 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8974 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9713 is not set
+# CONFIG_SND_MAINSTONE_BASEBAND is not set
+# CONFIG_SND_MAINSTONE_BLUETOOTH is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9712 is not set
+# CONFIG_SND_PXA2xx_SOC_CORGI is not set
+# CONFIG_SND_PXA2xx_SOC_SPITZ is not set
+CONFIG_SND_PXA2xx_SOC_POODLE=m
+# CONFIG_SND_PXA2xx_SOC_TOSA is not set
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+CONFIG_SND_SOC_WM8731=m
+# CONFIG_SND_SOC_WM8750 is not set
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM8974 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+# CONFIG_SND_SOC_WM9712 is not set
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+# CONFIG_USB_PXA2XX_SMALL is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemuarm
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemuarm	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemuarm	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1193 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sat Aug 26 22:45:02 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+CONFIG_ARCH_VERSATILE=y
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Versatile platform type
+#
+CONFIG_ARCH_VERSATILE_PB=y
+# CONFIG_MACH_VERSATILE_AB is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_KEXEC is not set
+CONFIG_ARM_VIC=y
+CONFIG_ICST307=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_AFS_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+# CONFIG_LEDS_CLASS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGERS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+CONFIG_USB_WACOM=y
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemux86
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemux86	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-qemux86	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1566 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Oct 16 19:42:42 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+CONFIG_M386=y
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_INTEL_USERCOPY=y
+# CONFIG_HPET_TIMER is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_NONFATAL=y
+CONFIG_X86_MCE_P4THERMAL=y
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_HOTPLUG_CPU is not set
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_ASUS is not set
+CONFIG_ACPI_IBM=m
+# CONFIG_ACPI_IBM_DOCK is not set
+# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+# CONFIG_IP_NF_FTP is not set
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_NETBIOS_NS is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=y
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_CS5535 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_DPT_I2O=m
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_MV is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+CONFIG_SCSI_SATA_SX4=m
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIL24 is not set
+CONFIG_SCSI_SATA_SIS=m
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_IPR=m
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=y
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# Protocol Drivers
+#
+# CONFIG_IEEE1394_VIDEO1394 is not set
+# CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+# CONFIG_IEEE1394_DV1394 is not set
+CONFIG_IEEE1394_RAWIO=y
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=y
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_AMD64 is not set
+CONFIG_AGP_INTEL=y
+# CONFIG_AGP_NVIDIA is not set
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_SWORKS is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_EFFICEON is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_I810 is not set
+# CONFIG_DRM_I830 is not set
+# CONFIG_DRM_I915 is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multi-Function Devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=y
+CONFIG_FB_VESA=y
+# CONFIG_FB_VESA_STD is not set
+CONFIG_FB_VESA_TNG=y
+CONFIG_FB_VESA_DEFAULT_MODE="640x480-32 at 60"
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_ADLIB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_PHIDGETKIT is not set
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_STACK_BACKTRACE_COLS=2
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_KTIME_SCALAR=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-spitz
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-spitz	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-spitz	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1603 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sun Sep  3 23:29:17 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_PXA_SHARPSL_25x is not set
+CONFIG_PXA_SHARPSL_27x=y
+CONFIG_MACH_AKITA=y
+CONFIG_MACH_SPITZ=y
+CONFIG_MACH_BORZOI=y
+CONFIG_PXA27x=y
+# CONFIG_PXA_KEYS is not set
+CONFIG_IWMMXT=y
+CONFIG_PXA_SHARP_Cxx00=y
+CONFIG_PXA_SSP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+CONFIG_KEXEC=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/hda1 rootfstype=ext3 rw  fbcon=rotate:1 dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_CORGI is not set
+CONFIG_KEYBOARD_SPITZ=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_SPITZ=y
+# CONFIG_LEDS_TOSA is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_OHAND_CLUT224 is not set
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+CONFIG_LOGO_OZ640_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_DETECT is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=m
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2xx_SOC=m
+CONFIG_SND_PXA2xx_SOC_I2S=m
+CONFIG_SND_PXA2xx_SOC_SPITZ=m
+
+#
+# SoC Audio for the Atmel AT91
+#
+
+#
+# SoC Audio for the Freescale i.MX
+#
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+# CONFIG_SND_SOC_WM8731 is not set
+CONFIG_SND_SOC_WM8750=m
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM8974 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+# CONFIG_SND_SOC_WM9712 is not set
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=m
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-tosa
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-tosa	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/defconfig-tosa	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,1608 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16-rc5-git5
+# Tue Mar 14 09:05:26 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+# CONFIG_MACH_POODLE is not set
+# CONFIG_MACH_CORGI is not set
+# CONFIG_MACH_SHEPHERD is not set
+# CONFIG_MACH_HUSKY is not set
+CONFIG_MACH_TOSA=y
+CONFIG_PXA25x=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+CONFIG_KEXEC=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+CONFIG_TOSHIBA_TC6393XB=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_TMIO=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_SHARPSL is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_CORGI is not set
+# CONFIG_KEYBOARD_SPITZ is not set
+CONFIG_KEYBOARD_TOSA=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_CORGI is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_WM97XX=y
+# CONFIG_TOUCHSCREEN_WM9705 is not set
+CONFIG_TOUCHSCREEN_WM9712=y
+# CONFIG_TOUCHSCREEN_WM9713 is not set
+# CONFIG_TOUCHSCREEN_WM97XX_PXA is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TOSA=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_PXA is not set
+# CONFIG_FB_W100 is not set
+CONFIG_FB_TMIO=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_BACKLIGHT_HP680 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_BUS=y
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=y
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2xx_SOC=y
+CONFIG_SND_PXA2xx_SOC_AC97=y
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM8753 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9713 is not set
+# CONFIG_SND_PXA2xx_SOC_MAINSTONE_WM9712 is not set
+# CONFIG_SND_PXA2xx_SOC_CORGI is not set
+# CONFIG_SND_PXA2xx_SOC_SPITZ is not set
+CONFIG_SND_PXA2xx_SOC_TOSA=y
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+# CONFIG_SND_SOC_WM8731 is not set
+# CONFIG_SND_SOC_WM8750 is not set
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+CONFIG_SND_SOC_WM9712=y
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+# CONFIG_USB_PXA2XX_SMALL is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_ALLOCATOR=y

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/hrw-pcmcia-ids-r5.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/hrw-pcmcia-ids-r5.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/hrw-pcmcia-ids-r5.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,63 @@
+From: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+Few cards informations submitted by OpenZaurus users.
+
+Seagate 8GB microdrive:
+ product info: "SEAGATE", "ST1"
+ manfid 0x0111, 0x0000
+
+One CF card:
+ product info: "SAMSUNG", "04/05/06", "", ""
+ manfid : 0x0000, 0x0000
+
+Ridata 8GB Pro 150X Compact Flash Card:
+ product info: "SMI VENDOR", "SMI PRODUCT", ""
+ manfid: 0x000a, 0x0000
+
+ product info: "M-Systems", "CF500", ""
+ manfid: 0x000a, 0x0000
+
+ product info: "TRANSCEND", "TS4GCF120", ""
+ manfid: 0x000a, 0x0000
+
+Signed-off-by: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+ drivers/ide/legacy/ide-cs.c   |    5 +++++
+ drivers/net/pcmcia/pcnet_cs.c |    2 ++
+ 2 files changed, 7 insertions(+)
+
+Index: linux-2.6.18/drivers/ide/legacy/ide-cs.c
+===================================================================
+--- linux-2.6.18.orig/drivers/ide/legacy/ide-cs.c	2006-12-06 00:55:51.000000000 +0000
++++ linux-2.6.18/drivers/ide/legacy/ide-cs.c	2006-12-06 00:55:55.000000000 +0000
+@@ -398,12 +398,17 @@ static struct pcmcia_device_id ide_ids[]
+ 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
+ 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
+ 	PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
++	PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
+ 	PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
+ 	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
+ 	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
+ 	PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
++	PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
++	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
++	PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
+ 	PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
+ 	PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
++	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
+ 	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
+ 	PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+ 	PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
+Index: linux-2.6.18/drivers/net/pcmcia/pcnet_cs.c
+===================================================================
+--- linux-2.6.18.orig/drivers/net/pcmcia/pcnet_cs.c	2006-09-20 04:42:06.000000000 +0100
++++ linux-2.6.18/drivers/net/pcmcia/pcnet_cs.c	2006-12-06 00:57:27.000000000 +0000
+@@ -1770,6 +1770,8 @@ static struct pcmcia_device_id pcnet_ids
+ 	PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
+ 	PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
+ 		0xb4be14e3, 0x43ac239b, 0x0877b627),
++	PCMCIA_DEVICE_PROD_ID123("Ethernet", "CF Size PC Card", "1.0",
++		0x00b2e941, 0x43ac239b, 0x0877b627),
+ 	PCMCIA_DEVICE_NULL
+ };
+ MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/orinoco-remove-all-which-are-in-hostap-HACK.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/orinoco-remove-all-which-are-in-hostap-HACK.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/orinoco-remove-all-which-are-in-hostap-HACK.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,88 @@
+This patch should resolve problem when people get eth0 (orinoco_cs) instead of wlan0 (hostap_cs)
+with their WiFi cards.
+
+Patch will NEVER been accepted upstream.
+
+Signed-off-by: Marcin Juszkiewicz <openembedded at hrw.one.pl>
+
+Index: linux/drivers/net/wireless/orinoco_cs.c
+===================================================================
+--- linux.orig/drivers/net/wireless/orinoco_cs.c	2006-08-23 16:04:10.000000000 +0200
++++ linux/drivers/net/wireless/orinoco_cs.c	2006-08-23 16:17:43.000000000 +0200
+@@ -453,33 +453,21 @@
+ 	"Pavel Roskin <proski at gnu.org>, et al)";
+ 
+ static struct pcmcia_device_id orinoco_cs_ids[] = {
+-	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+-	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+-	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
+-	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
+ 	PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
+ 	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
+ 	PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+-	PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+ 	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
+-	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+-	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+-	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+ 	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
+-	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
+ 	PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+ 	PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+-	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
+ 	PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
+ 	PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
+ 	PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
+-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
+-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
+ 	PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
+ 	PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
+ 	PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
+@@ -487,31 +475,25 @@
+ 	PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
+ 	PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+ 	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+-	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
+ 	PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+ 	PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
+ 	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
+-	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
+ 	PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+-	PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+ 	PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
+ 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
+ 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ 	PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
+ 	PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
+-	PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
+ 	PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+ 	PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
+ 	PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
+ 	PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+ 	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ 	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
+-	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
+ 	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
+ 	PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+ 	PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
+ 	PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+-	PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
+ 	PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
+ 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
+ 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
+@@ -529,10 +511,8 @@
+ 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
+ 	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
+ 	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
+-	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
+ 	PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ 	PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
+-	PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
+ 	PCMCIA_DEVICE_NULL,
+ };
+ MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/pxa-serial-hack.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/pxa-serial-hack.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/pxa-serial-hack.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,73 @@
+Index: linux-2.6.14/drivers/serial/8250.c
+===================================================================
+--- linux-2.6.14.orig/drivers/serial/8250.c	2005-11-07 18:10:50.000000000 +0000
++++ linux-2.6.14/drivers/serial/8250.c	2005-11-07 19:01:21.000000000 +0000
+@@ -2333,7 +2333,12 @@
+ 	.devfs_name		= "tts/",
+ 	.dev_name		= "ttyS",
+ 	.major			= TTY_MAJOR,
++#ifdef CONFIG_SERIAL_PXA
++	.minor			= 64 + 3,
++	.name_base		= 3,
++#else
+ 	.minor			= 64,
++#endif
+ 	.nr			= UART_NR,
+ 	.cons			= SERIAL8250_CONSOLE,
+ };
+Index: linux-2.6.14/drivers/serial/serial_core.c
+===================================================================
+--- linux-2.6.14.orig/drivers/serial/serial_core.c	2005-11-07 18:10:50.000000000 +0000
++++ linux-2.6.14/drivers/serial/serial_core.c	2005-11-07 19:01:21.000000000 +0000
+@@ -2126,6 +2126,7 @@
+ 	normal->driver_name	= drv->driver_name;
+ 	normal->devfs_name	= drv->devfs_name;
+ 	normal->name		= drv->dev_name;
++	normal->name_base	= drv->name_base;
+ 	normal->major		= drv->major;
+ 	normal->minor_start	= drv->minor;
+ 	normal->type		= TTY_DRIVER_TYPE_SERIAL;
+Index: linux-2.6.14/include/linux/serial_core.h
+===================================================================
+--- linux-2.6.14.orig/include/linux/serial_core.h	2005-11-07 18:10:56.000000000 +0000
++++ linux-2.6.14/include/linux/serial_core.h	2005-11-07 19:01:21.000000000 +0000
+@@ -322,6 +322,7 @@
+ 	const char		*driver_name;
+ 	const char		*dev_name;
+ 	const char		*devfs_name;
++	int			 name_base;
+ 	int			 major;
+ 	int			 minor;
+ 	int			 nr;
+Index: linux-2.6.14/drivers/serial/serial_cs.c
+===================================================================
+--- linux-2.6.14.orig/drivers/serial/serial_cs.c	2005-10-28 01:02:08.000000000 +0100
++++ linux-2.6.14/drivers/serial/serial_cs.c	2005-11-07 19:01:21.000000000 +0000
+@@ -294,7 +294,7 @@
+ 			kio_addr_t iobase, int irq)
+ {
+ 	struct uart_port port;
+-	int line;
++	int line, linestart;
+ 
+ 	memset(&port, 0, sizeof (struct uart_port));
+ 	port.iobase = iobase;
+@@ -311,10 +311,16 @@
+ 		return -EINVAL;
+ 	}
+ 
++#if CONFIG_SERIAL_PXA
++	linestart = 3;
++#else
++	linestart = 0;
++#endif
++
+ 	info->line[info->ndev] = line;
+-	sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
++	sprintf(info->node[info->ndev].dev_name, "ttyS%d", line+linestart);
+ 	info->node[info->ndev].major = TTY_MAJOR;
+-	info->node[info->ndev].minor = 0x40 + line;
++	info->node[info->ndev].minor = 0x40 + line + linestart;
+ 	if (info->ndev > 0)
+ 		info->node[info->ndev - 1].next = &info->node[info->ndev];
+ 	info->ndev++;

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,155 @@
+
+From: Petr Vandrovec <vandrove at vc.cvut.cz>
+
+Patch below adds support for using different prescaler than 16 for 16c950
+chips.  This is needed for using Fujitsu-Siemens Connect2Air compact-flash
+card, which comes (apparently) with 806kHz clocks, and so you have to
+program prescaler for division by 7, and DLAB to 1, to get 115200Bd.  
+
+To get card properly running you also have to add lines below to
+/etc/pcmcia/serial.opts so kernel knows that base speed is not 115200 but
+50400 (50400 * 16 = 806400; 806400 / 7 = 115200).  As I've found no code
+specifying baud_rate in serial_cs, I assume that specifying it in
+serial.opts is right way to do this type of things.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER maximum possible
+baud rate passed to uart code was uartclk / 16 while correct value for
+these devices (and for 16c950) is uartclk / 4.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER devices with
+baud_rate 19200 or 9600 spd_cust did not work correctly.  Not that such
+devices exist, but we should not ignore spd_cust, user probably knows why
+he asked for spd_cust.
+
+serial.opts:
+
+case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in
+'0279,950b-2-GPRS Modem---')
+    SERIAL_OPTS="baud_base 50400"
+    ;;
+esac
+
+Cc: David Woodhouse <dwmw2 at infradead.org>
+Signed-off-by: Andrew Morton <akpm at osdl.org>
+---
+
+ drivers/serial/8250.c |   82 +++++++++++++++++++++++++++++++++++++++-----------
+ 1 files changed, 64 insertions(+), 18 deletions(-)
+
+diff -puN drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver drivers/serial/8250.c
+--- devel/drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver	2005-09-12 03:34:57.000000000 -0700
++++ devel-akpm/drivers/serial/8250.c	2005-09-12 03:34:57.000000000 -0700
+@@ -1653,24 +1653,58 @@ static void serial8250_shutdown(struct u
+ 		serial_unlink_irq_chain(up);
+ }
+ 
+-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud,
++					   unsigned int *prescaler)
+ {
+-	unsigned int quot;
+-
+-	/*
+-	 * Handle magic divisors for baud rates above baud_base on
+-	 * SMSC SuperIO chips.
++        /*
++	 * Use special handling only if user did not supply its own divider.
++	 * spd_cust is defined in terms of baud_base, so always use default
++	 * prescaler when spd_cust is requested.
+ 	 */
+-	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-	    baud == (port->uartclk/4))
+-		quot = 0x8001;
+-	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-		 baud == (port->uartclk/8))
+-		quot = 0x8002;
+-	else
+-		quot = uart_get_divisor(port, baud);
+ 
+-	return quot;
++	*prescaler = 16;
++        if (baud != 38400 || (port->flags & UPF_SPD_MASK) != UPF_SPD_CUST) {
++		unsigned int quot = port->uartclk / baud;
++
++		/*
++		 * Handle magic divisors for baud rates above baud_base on
++		 * SMSC SuperIO chips.
++		 */
++		if (port->flags & UPF_MAGIC_MULTIPLIER) {
++			if (quot == 4) {
++				return 0x8001;
++			} else if (quot == 8) {
++				return 0x8002;
++			}
++		}
++		if (port->type == PORT_16C950) {
++			/*
++			 * This computes TCR value (4 to 16), not CPR value (which can
++			 * be between 1.000 and 31.875) - chip I have uses XTAL of
++			 * 806400Hz, and so a division by 7 is required to get 115200Bd.
++			 * I'm leaving CPR disabled for now, until someone will
++			 * hit even more exotic XTAL (it is needed to get 500kbps
++			 * or 1000kbps from 18.432MHz XTAL, but I have no device
++			 * which would benefit from doing that).
++			 *
++			 * If we can use divide by 16, use it.  Otherwise look for
++			 * better prescaler, from 15 to 4.  If quotient cannot
++			 * be divided by any integer value between 4 and 15, use 4.
++			 */
++			if (quot & 0x0F) {
++				unsigned int div;
++
++				for (div = 15; div > 4; div--) {
++					if (quot % div == 0) {
++						break;
++					}
++				}
++				*prescaler = div;
++				return quot / div;
++			}
++		}
++	}
++	return uart_get_divisor(port, baud);
+ }
+ 
+ static void
+@@ -1680,7 +1714,7 @@ serial8250_set_termios(struct uart_port 
+ 	struct uart_8250_port *up = (struct uart_8250_port *)port;
+ 	unsigned char cval, fcr = 0;
+ 	unsigned long flags;
+-	unsigned int baud, quot;
++	unsigned int baud, quot, prescaler;
+ 
+ 	switch (termios->c_cflag & CSIZE) {
+ 	case CS5:
+@@ -1712,8 +1746,13 @@ serial8250_set_termios(struct uart_port 
+ 	/*
+ 	 * Ask the core to calculate the divisor for us.
+ 	 */
+-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+-	quot = serial8250_get_divisor(port, baud);
++
++	if (port->type == PORT_16C950 || (port->flags & UPF_MAGIC_MULTIPLIER)) {
++		baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
++	} else {
++		baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++	}
++	quot = serial8250_get_divisor(port, baud, &prescaler);
+ 
+ 	/*
+ 	 * Oxford Semi 952 rev B workaround
+@@ -1817,6 +1856,13 @@ serial8250_set_termios(struct uart_port 
+ 	serial_outp(up, UART_DLM, quot >> 8);		/* MS of divisor */
+ 
+ 	/*
++	 * Program prescaler for 16C950 chips.
++	 */
++	if (up->port.type == PORT_16C950) {
++		serial_icr_write(up, UART_TCR, prescaler == 16 ? 0 : prescaler);
++	}
++
++	/*
+ 	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+ 	 * is written without DLAB set, this mode will be disabled.
+ 	 */
+_

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/squashfs3.0-2.6.15.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/squashfs3.0-2.6.15.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/squashfs3.0-2.6.15.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,4174 @@
+diff --new-file -urp linux-2.6.15/fs/Kconfig linux-2.6.15-squashfs3.0/fs/Kconfig
+--- linux-2.6.15/fs/Kconfig	2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/fs/Kconfig	2006-03-07 21:12:37.000000000 +0000
+@@ -1151,6 +1151,71 @@ config CRAMFS
+ 
+ 	  If unsure, say N.
+ 
++config SQUASHFS
++	tristate "SquashFS 3.0 - Squashed file system support"
++	select ZLIB_INFLATE
++	help
++	  Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
++	  System).  Squashfs is a highly compressed read-only filesystem for Linux.
++	  It uses zlib compression to compress both files, inodes and directories.
++	  Inodes in the system are very small and all blocks are packed to minimise
++	  data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
++	  SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
++	  uid/gid information, hard links and timestamps.
++
++	  Squashfs is intended for general read-only filesystem use, for archival
++	  use (i.e. in cases where a .tar.gz file may be used), and in embedded
++	  systems where low overhead is needed.  Further information and filesystem tools
++	  are available from http://squashfs.sourceforge.net.
++
++	  If you want to compile this as a module ( = code which can be
++	  inserted in and removed from the running kernel whenever you want),
++	  say M here and read <file:Documentation/modules.txt>.  The module
++	  will be called squashfs.  Note that the root file system (the one
++	  containing the directory /) cannot be compiled as a module.
++
++	  If unsure, say N.
++
++config SQUASHFS_EMBEDDED
++
++	bool "Additional options for memory-constrained systems" 
++	depends on SQUASHFS
++	default n
++	help
++	  Saying Y here allows you to specify cache sizes and how Squashfs
++	  allocates memory.  This is only intended for memory constrained
++	  systems.
++
++	  If unsure, say N.
++
++config SQUASHFS_FRAGMENT_CACHE_SIZE
++	int "Number of fragments cached" if SQUASHFS_EMBEDDED
++	depends on SQUASHFS
++	default "3"
++	help
++	  By default SquashFS caches the last 3 fragments read from
++	  the filesystem.  Increasing this amount may mean SquashFS
++	  has to re-read fragments less often from disk, at the expense
++	  of extra system memory.  Decreasing this amount will mean
++	  SquashFS uses less memory at the expense of extra reads from disk.
++
++	  Note there must be at least one cached fragment.  Anything
++	  much more than three will probably not make much difference.
++
++config SQUASHFS_VMALLOC
++	bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
++	depends on SQUASHFS
++	default n
++	help
++	  By default SquashFS uses kmalloc to obtain fragment cache memory.
++	  Kmalloc memory is the standard kernel allocator, but it can fail
++	  on memory constrained systems.  Because of the way Vmalloc works,
++	  Vmalloc can succeed when kmalloc fails.  Specifying this option
++	  will make SquashFS always use Vmalloc to allocate the
++	  fragment cache memory.
++
++	  If unsure, say N.
++
+ config VXFS_FS
+ 	tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+ 	help
+diff --new-file -urp linux-2.6.15/fs/Makefile linux-2.6.15-squashfs3.0/fs/Makefile
+--- linux-2.6.15/fs/Makefile	2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/fs/Makefile	2006-03-07 21:12:37.000000000 +0000
+@@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before
+ obj-$(CONFIG_JBD)		+= jbd/
+ obj-$(CONFIG_EXT2_FS)		+= ext2/
+ obj-$(CONFIG_CRAMFS)		+= cramfs/
++obj-$(CONFIG_SQUASHFS)		+= squashfs/
+ obj-$(CONFIG_RAMFS)		+= ramfs/
+ obj-$(CONFIG_HUGETLBFS)		+= hugetlbfs/
+ obj-$(CONFIG_CODA_FS)		+= coda/
+diff --new-file -urp linux-2.6.15/fs/squashfs/inode.c linux-2.6.15-squashfs3.0/fs/squashfs/inode.c
+--- linux-2.6.15/fs/squashfs/inode.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/inode.c	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,2127 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++#include "squashfs.h"
++
++static void squashfs_put_super(struct super_block *);
++static int squashfs_statfs(struct super_block *, struct kstatfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct inode *squashfs_alloc_inode(struct super_block *sb);
++static void squashfs_destroy_inode(struct inode *inode);
++static int init_inodecache(void);
++static void destroy_inodecache(void);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
++				struct nameidata *);
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
++static long long read_blocklist(struct inode *inode, int index,
++				int readahead_blks, char *block_list,
++				unsigned short **block_p, unsigned int *bsize);
++static struct super_block *squashfs_get_sb(struct file_system_type *, int,
++				const char *, void *);
++
++
++static z_stream stream;
++
++static struct file_system_type squashfs_fs_type = {
++	.owner = THIS_MODULE,
++	.name = "squashfs",
++	.get_sb = squashfs_get_sb,
++	.kill_sb = kill_block_super,
++	.fs_flags = FS_REQUIRES_DEV
++};
++
++static unsigned char squashfs_filetype_table[] = {
++	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_ops = {
++	.alloc_inode = squashfs_alloc_inode,
++	.destroy_inode = squashfs_destroy_inode,
++	.statfs = squashfs_statfs,
++	.put_super = squashfs_put_super,
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
++	.readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops = {
++	.readpage = squashfs_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
++	.readpage = squashfs_readpage4K
++};
++
++static struct file_operations squashfs_dir_ops = {
++	.read = generic_read_dir,
++	.readdir = squashfs_readdir
++};
++
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
++	.lookup = squashfs_lookup
++};
++
++
++static struct buffer_head *get_block_length(struct super_block *s,
++				int *cur_index, int *offset, int *c_byte)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	unsigned short temp;
++	struct buffer_head *bh;
++
++	if (!(bh = sb_bread(s, *cur_index)))
++		goto out;
++
++	if (msblk->devblksize - *offset == 1) {
++		if (msblk->swap)
++			((unsigned char *) &temp)[1] = *((unsigned char *)
++				(bh->b_data + *offset));
++		else
++			((unsigned char *) &temp)[0] = *((unsigned char *)
++				(bh->b_data + *offset));
++		brelse(bh);
++		if (!(bh = sb_bread(s, ++(*cur_index))))
++			goto out;
++		if (msblk->swap)
++			((unsigned char *) &temp)[0] = *((unsigned char *)
++				bh->b_data); 
++		else
++			((unsigned char *) &temp)[1] = *((unsigned char *)
++				bh->b_data); 
++		*c_byte = temp;
++		*offset = 1;
++	} else {
++		if (msblk->swap) {
++			((unsigned char *) &temp)[1] = *((unsigned char *)
++				(bh->b_data + *offset));
++			((unsigned char *) &temp)[0] = *((unsigned char *)
++				(bh->b_data + *offset + 1)); 
++		} else {
++			((unsigned char *) &temp)[0] = *((unsigned char *)
++				(bh->b_data + *offset));
++			((unsigned char *) &temp)[1] = *((unsigned char *)
++				(bh->b_data + *offset + 1)); 
++		}
++		*c_byte = temp;
++		*offset += 2;
++	}
++
++	if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++		if (*offset == msblk->devblksize) {
++			brelse(bh);
++			if (!(bh = sb_bread(s, ++(*cur_index))))
++				goto out;
++			*offset = 0;
++		}
++		if (*((unsigned char *) (bh->b_data + *offset)) !=
++						SQUASHFS_MARKER_BYTE) {
++			ERROR("Metadata block marker corrupt @ %x\n",
++						*cur_index);
++			brelse(bh);
++			goto out;
++		}
++		(*offset)++;
++	}
++	return bh;
++
++out:
++	return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++			long long index, unsigned int length,
++			long long *next_index)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++			msblk->devblksize_log2) + 2];
++	unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++	unsigned int cur_index = index >> msblk->devblksize_log2;
++	int bytes, avail_bytes, b = 0, k;
++	char *c_buffer;
++	unsigned int compressed;
++	unsigned int c_byte = length;
++
++	if (c_byte) {
++		bytes = msblk->devblksize - offset;
++		compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++		c_buffer = compressed ? msblk->read_data : buffer;
++		c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++					? "" : "un", (unsigned int) c_byte);
++
++		if (!(bh[0] = sb_getblk(s, cur_index)))
++			goto block_release;
++
++		for (b = 1; bytes < c_byte; b++) {
++			if (!(bh[b] = sb_getblk(s, ++cur_index)))
++				goto block_release;
++			bytes += msblk->devblksize;
++		}
++		ll_rw_block(READ, b, bh);
++	} else {
++		if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++								&c_byte)))
++			goto read_failure;
++
++		bytes = msblk->devblksize - offset;
++		compressed = SQUASHFS_COMPRESSED(c_byte);
++		c_buffer = compressed ? msblk->read_data : buffer;
++		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++					? "" : "un", (unsigned int) c_byte);
++
++		for (b = 1; bytes < c_byte; b++) {
++			if (!(bh[b] = sb_getblk(s, ++cur_index)))
++				goto block_release;
++			bytes += msblk->devblksize;
++		}
++		ll_rw_block(READ, b - 1, bh + 1);
++	}
++
++	if (compressed)
++		down(&msblk->read_data_mutex);
++
++	for (bytes = 0, k = 0; k < b; k++) {
++		avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++					msblk->devblksize - offset :
++					c_byte - bytes;
++		wait_on_buffer(bh[k]);
++		if (!buffer_uptodate(bh[k]))
++			goto block_release;
++		memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++		bytes += avail_bytes;
++		offset = 0;
++		brelse(bh[k]);
++	}
++
++	/*
++	 * uncompress block
++	 */
++	if (compressed) {
++		int zlib_err;
++
++		stream.next_in = c_buffer;
++		stream.avail_in = c_byte;
++		stream.next_out = buffer;
++		stream.avail_out = msblk->read_size;
++
++		if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
++				((zlib_err = zlib_inflate(&stream, Z_FINISH))
++				 != Z_STREAM_END) || ((zlib_err =
++				zlib_inflateEnd(&stream)) != Z_OK)) {
++			ERROR("zlib_fs returned unexpected result 0x%x\n",
++				zlib_err);
++			bytes = 0;
++		} else
++			bytes = stream.total_out;
++		
++		up(&msblk->read_data_mutex);
++	}
++
++	if (next_index)
++		*next_index = index + c_byte + (length ? 0 :
++				(SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++				 ? 3 : 2));
++	return bytes;
++
++block_release:
++	while (--b >= 0)
++		brelse(bh[b]);
++
++read_failure:
++	ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++	return 0;
++}
++
++
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
++				long long block, unsigned int offset,
++				int length, long long *next_block,
++				unsigned int *next_offset)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	int n, i, bytes, return_length = length;
++	long long next_index;
++
++	TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++	while ( 1 ) {
++		for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 
++			if (msblk->block_cache[i].block == block)
++				break; 
++		
++		down(&msblk->block_cache_mutex);
++
++		if (i == SQUASHFS_CACHED_BLKS) {
++			/* read inode header block */
++			for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++					n ; n --, i = (i + 1) %
++					SQUASHFS_CACHED_BLKS)
++				if (msblk->block_cache[i].block !=
++							SQUASHFS_USED_BLK)
++					break;
++
++			if (n == 0) {
++				wait_queue_t wait;
++
++				init_waitqueue_entry(&wait, current);
++				add_wait_queue(&msblk->waitq, &wait);
++				set_current_state(TASK_UNINTERRUPTIBLE);
++ 				up(&msblk->block_cache_mutex);
++				schedule();
++				set_current_state(TASK_RUNNING);
++				remove_wait_queue(&msblk->waitq, &wait);
++				continue;
++			}
++			msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++			if (msblk->block_cache[i].block ==
++							SQUASHFS_INVALID_BLK) {
++				if (!(msblk->block_cache[i].data =
++						kmalloc(SQUASHFS_METADATA_SIZE,
++						GFP_KERNEL))) {
++					ERROR("Failed to allocate cache"
++							"block\n");
++					up(&msblk->block_cache_mutex);
++					goto out;
++				}
++			}
++	
++			msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++			up(&msblk->block_cache_mutex);
++
++			if (!(msblk->block_cache[i].length =
++						squashfs_read_data(s,
++						msblk->block_cache[i].data,
++						block, 0, &next_index))) {
++				ERROR("Unable to read cache block [%llx:%x]\n",
++						block, offset);
++				goto out;
++			}
++
++			down(&msblk->block_cache_mutex);
++			wake_up(&msblk->waitq);
++			msblk->block_cache[i].block = block;
++			msblk->block_cache[i].next_index = next_index;
++			TRACE("Read cache block [%llx:%x]\n", block, offset);
++		}
++
++		if (msblk->block_cache[i].block != block) {
++			up(&msblk->block_cache_mutex);
++			continue;
++		}
++
++		if ((bytes = msblk->block_cache[i].length - offset) >= length) {
++			if (buffer)
++				memcpy(buffer, msblk->block_cache[i].data +
++						offset, length);
++			if (msblk->block_cache[i].length - offset == length) {
++				*next_block = msblk->block_cache[i].next_index;
++				*next_offset = 0;
++			} else {
++				*next_block = block;
++				*next_offset = offset + length;
++			}
++			up(&msblk->block_cache_mutex);
++			goto finish;
++		} else {
++			if (buffer) {
++				memcpy(buffer, msblk->block_cache[i].data +
++						offset, bytes);
++				buffer += bytes;
++			}
++			block = msblk->block_cache[i].next_index;
++			up(&msblk->block_cache_mutex);
++			length -= bytes;
++			offset = 0;
++		}
++	}
++
++finish:
++	return return_length;
++out:
++	return 0;
++}
++
++
++static int get_fragment_location(struct super_block *s, unsigned int fragment,
++				long long *fragment_start_block,
++				unsigned int *fragment_size)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	long long start_block =
++		msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
++	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++	struct squashfs_fragment_entry fragment_entry;
++
++	if (msblk->swap) {
++		struct squashfs_fragment_entry sfragment_entry;
++
++		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++					start_block, offset,
++					sizeof(sfragment_entry), &start_block,
++					&offset))
++			goto out;
++		SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
++	} else
++		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++					start_block, offset,
++					sizeof(fragment_entry), &start_block,
++					&offset))
++			goto out;
++
++	*fragment_start_block = fragment_entry.start_block;
++	*fragment_size = fragment_entry.size;
++
++	return 1;
++
++out:
++	return 0;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++					squashfs_fragment_cache *fragment)
++{
++	down(&msblk->fragment_mutex);
++	fragment->locked --;
++	wake_up(&msblk->fragment_wait_queue);
++	up(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++					*s, long long start_block,
++					int length)
++{
++	int i, n, nf;
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++
++	while ( 1 ) {
++		down(&msblk->fragment_mutex);
++
++		for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++				msblk->fragment[i].block != start_block; i++);
++
++		if (i == SQUASHFS_CACHED_FRAGMENTS) {
++			nf = (msblk->next_fragment + 1) % 
++				SQUASHFS_CACHED_FRAGMENTS;
++			for (i = msblk->next_fragment, n =
++				SQUASHFS_CACHED_FRAGMENTS; n &&
++				msblk->fragment[i].locked; n--, i = (i + 1) %
++				SQUASHFS_CACHED_FRAGMENTS);
++
++			if (n == 0) {
++				wait_queue_t wait;
++
++				init_waitqueue_entry(&wait, current);
++				add_wait_queue(&msblk->fragment_wait_queue,
++									&wait);
++				set_current_state(TASK_UNINTERRUPTIBLE);
++				up(&msblk->fragment_mutex);
++				schedule();
++				set_current_state(TASK_RUNNING);
++				remove_wait_queue(&msblk->fragment_wait_queue,
++									&wait);
++				continue;
++			}
++			msblk->next_fragment = nf;
++			
++			if (msblk->fragment[i].data == NULL)
++				if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++						(SQUASHFS_FILE_MAX_SIZE))) {
++					ERROR("Failed to allocate fragment "
++							"cache block\n");
++					up(&msblk->fragment_mutex);
++					goto out;
++				}
++
++			msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++			msblk->fragment[i].locked = 1;
++			up(&msblk->fragment_mutex);
++
++			if (!(msblk->fragment[i].length = squashfs_read_data(s,
++						msblk->fragment[i].data,
++						start_block, length, NULL))) {
++				ERROR("Unable to read fragment cache block "
++							"[%llx]\n", start_block);
++				msblk->fragment[i].locked = 0;
++				goto out;
++			}
++
++			msblk->fragment[i].block = start_block;
++			TRACE("New fragment %d, start block %lld, locked %d\n",
++						i, msblk->fragment[i].block,
++						msblk->fragment[i].locked);
++			break;
++		}
++
++		msblk->fragment[i].locked++;
++		up(&msblk->fragment_mutex);
++		TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++						msblk->fragment[i].block,
++						msblk->fragment[i].locked);
++		break;
++	}
++
++	return &msblk->fragment[i];
++
++out:
++	return NULL;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++		struct squashfs_base_inode_header *inodeb)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct inode *i = new_inode(s);
++
++	if (i) {
++		i->i_ino = inodeb->inode_number;
++		i->i_mtime.tv_sec = inodeb->mtime;
++		i->i_atime.tv_sec = inodeb->mtime;
++		i->i_ctime.tv_sec = inodeb->mtime;
++		i->i_uid = msblk->uid[inodeb->uid];
++		i->i_mode = inodeb->mode;
++		i->i_size = 0;
++		if (inodeb->guid == SQUASHFS_GUIDS)
++			i->i_gid = i->i_uid;
++		else
++			i->i_gid = msblk->guid[inodeb->guid];
++	}
++
++	return i;
++}
++
++
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
++{
++	struct inode *i;
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	long long block = SQUASHFS_INODE_BLK(inode) +
++		sblk->inode_table_start;
++	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++	long long next_block;
++	unsigned int next_offset;
++	union squashfs_inode_header id, sid;
++	struct squashfs_base_inode_header *inodeb = &id.base,
++					  *sinodeb = &sid.base;
++
++	TRACE("Entered squashfs_iget\n");
++
++	if (msblk->swap) {
++		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++					offset, sizeof(*sinodeb), &next_block,
++					&next_offset))
++			goto failed_read;
++		SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
++					sizeof(*sinodeb));
++	} else
++		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++					offset, sizeof(*inodeb), &next_block,
++					&next_offset))
++			goto failed_read;
++
++	switch(inodeb->inode_type) {
++		case SQUASHFS_FILE_TYPE: {
++			unsigned int frag_size;
++			long long frag_blk;
++			struct squashfs_reg_inode_header *inodep = &id.reg;
++			struct squashfs_reg_inode_header *sinodep = &sid.reg;
++				
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			frag_blk = SQUASHFS_INVALID_BLK;
++			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++					!get_fragment_location(s,
++					inodep->fragment, &frag_blk, &frag_size))
++				goto failed_read;
++				
++			if((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = 1;
++			i->i_size = inodep->file_size;
++			i->i_fop = &generic_ro_fops;
++			i->i_mode |= S_IFREG;
++			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++			i->i_blksize = PAGE_CACHE_SIZE;
++			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++			SQUASHFS_I(i)->offset = next_offset;
++			if (sblk->block_size > 4096)
++				i->i_data.a_ops = &squashfs_aops;
++			else
++				i->i_data.a_ops = &squashfs_aops_4K;
++
++			TRACE("File inode %x:%x, start_block %llx, "
++					"block_list_start %llx, offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->start_block, next_block,
++					next_offset);
++			break;
++		}
++		case SQUASHFS_LREG_TYPE: {
++			unsigned int frag_size;
++			long long frag_blk;
++			struct squashfs_lreg_inode_header *inodep = &id.lreg;
++			struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++				
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			frag_blk = SQUASHFS_INVALID_BLK;
++			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++					!get_fragment_location(s,
++					inodep->fragment, &frag_blk, &frag_size))
++				goto failed_read;
++				
++			if((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_size = inodep->file_size;
++			i->i_fop = &generic_ro_fops;
++			i->i_mode |= S_IFREG;
++			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++			i->i_blksize = PAGE_CACHE_SIZE;
++			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++			SQUASHFS_I(i)->offset = next_offset;
++			if (sblk->block_size > 4096)
++				i->i_data.a_ops = &squashfs_aops;
++			else
++				i->i_data.a_ops = &squashfs_aops_4K;
++
++			TRACE("File inode %x:%x, start_block %llx, "
++					"block_list_start %llx, offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->start_block, next_block,
++					next_offset);
++			break;
++		}
++		case SQUASHFS_DIR_TYPE: {
++			struct squashfs_dir_inode_header *inodep = &id.dir;
++			struct squashfs_dir_inode_header *sinodep = &sid.dir;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_size = inodep->file_size;
++			i->i_op = &squashfs_dir_inode_ops;
++			i->i_fop = &squashfs_dir_ops;
++			i->i_mode |= S_IFDIR;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->offset = inodep->offset;
++			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++			TRACE("Directory inode %x:%x, start_block %x, offset "
++					"%x\n", SQUASHFS_INODE_BLK(inode),
++					offset, inodep->start_block,
++					inodep->offset);
++			break;
++		}
++		case SQUASHFS_LDIR_TYPE: {
++			struct squashfs_ldir_inode_header *inodep = &id.ldir;
++			struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
++						sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_size = inodep->file_size;
++			i->i_op = &squashfs_dir_inode_ops;
++			i->i_fop = &squashfs_dir_ops;
++			i->i_mode |= S_IFDIR;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->offset = inodep->offset;
++			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++			SQUASHFS_I(i)->u.s2.directory_index_offset =
++								next_offset;
++			SQUASHFS_I(i)->u.s2.directory_index_count =
++								inodep->i_count;
++			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++			TRACE("Long directory inode %x:%x, start_block %x, "
++					"offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->start_block, inodep->offset);
++			break;
++		}
++		case SQUASHFS_SYMLINK_TYPE: {
++			struct squashfs_symlink_inode_header *inodep =
++								&id.symlink;
++			struct squashfs_symlink_inode_header *sinodep =
++								&sid.symlink;
++	
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
++								sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_size = inodep->symlink_size;
++			i->i_op = &page_symlink_inode_operations;
++			i->i_data.a_ops = &squashfs_symlink_aops;
++			i->i_mode |= S_IFLNK;
++			SQUASHFS_I(i)->start_block = next_block;
++			SQUASHFS_I(i)->offset = next_offset;
++
++			TRACE("Symbolic link inode %x:%x, start_block %llx, "
++					"offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					next_block, next_offset);
++			break;
++		 }
++		 case SQUASHFS_BLKDEV_TYPE:
++		 case SQUASHFS_CHRDEV_TYPE: {
++			struct squashfs_dev_inode_header *inodep = &id.dev;
++			struct squashfs_dev_inode_header *sinodep = &sid.dev;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
++			} else	
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_mode |= (inodeb->inode_type ==
++					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
++					S_IFBLK;
++			init_special_inode(i, i->i_mode,
++					old_decode_dev(inodep->rdev));
++
++			TRACE("Device inode %x:%x, rdev %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->rdev);
++			break;
++		 }
++		 case SQUASHFS_FIFO_TYPE:
++		 case SQUASHFS_SOCKET_TYPE: {
++			struct squashfs_ipc_inode_header *inodep = &id.ipc;
++			struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
++			} else	
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
++				goto failed_read1;
++
++			i->i_nlink = inodep->nlink;
++			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++							? S_IFIFO : S_IFSOCK;
++			init_special_inode(i, i->i_mode, 0);
++			break;
++		 }
++		 default:
++			ERROR("Unknown inode type %d in squashfs_iget!\n",
++					inodeb->inode_type);
++			goto failed_read1;
++	}
++	
++	insert_inode_hash(i);
++	return i;
++
++failed_read:
++	ERROR("Unable to read inode [%llx:%x]\n", block, offset);
++
++failed_read1:
++	return NULL;
++}
++
++
++static int read_fragment_index_table(struct super_block *s)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++
++	/* Allocate fragment index table */
++	if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
++					(sblk->fragments), GFP_KERNEL))) {
++		ERROR("Failed to allocate uid/gid table\n");
++		return 0;
++	}
++   
++	if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
++					!squashfs_read_data(s, (char *)
++					msblk->fragment_index,
++					sblk->fragment_table_start,
++					SQUASHFS_FRAGMENT_INDEX_BYTES
++					(sblk->fragments) |
++					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++		ERROR("unable to read fragment index table\n");
++		return 0;
++	}
++
++	if (msblk->swap) {
++		int i;
++		long long fragment;
++
++		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
++									i++) {
++			SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++						&msblk->fragment_index[i], 1);
++			msblk->fragment_index[i] = fragment;
++		}
++	}
++
++	return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++	struct squashfs_super_block *sblk = &msblk->sblk;
++
++	msblk->iget = squashfs_iget;
++	msblk->read_blocklist = read_blocklist;
++	msblk->read_fragment_index_table = read_fragment_index_table;
++
++	if (sblk->s_major == 1) {
++		if (!squashfs_1_0_supported(msblk)) {
++			SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++				"are unsupported\n");
++			SERROR("Please recompile with "
++				"Squashfs 1.0 support enabled\n");
++			return 0;
++		}
++	} else if (sblk->s_major == 2) {
++		if (!squashfs_2_0_supported(msblk)) {
++			SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++				"are unsupported\n");
++			SERROR("Please recompile with "
++				"Squashfs 2.0 support enabled\n");
++			return 0;
++		}
++	} else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++			SQUASHFS_MINOR) {
++		SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++				"filesystem\n", sblk->s_major, sblk->s_minor);
++		SERROR("Please update your kernel\n");
++		return 0;
++	}
++
++	return 1;
++}
++
++
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)
++{
++	struct squashfs_sb_info *msblk;
++	struct squashfs_super_block *sblk;
++	int i;
++	char b[BDEVNAME_SIZE];
++	struct inode *root;
++
++	TRACE("Entered squashfs_read_superblock\n");
++
++	if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
++						GFP_KERNEL))) {
++		ERROR("Failed to allocate superblock\n");
++		goto failure;
++	}
++	memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
++	msblk = s->s_fs_info;
++	sblk = &msblk->sblk;
++	
++	msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
++	msblk->devblksize_log2 = ffz(~msblk->devblksize);
++
++	init_MUTEX(&msblk->read_data_mutex);
++	init_MUTEX(&msblk->read_page_mutex);
++	init_MUTEX(&msblk->block_cache_mutex);
++	init_MUTEX(&msblk->fragment_mutex);
++	init_MUTEX(&msblk->meta_index_mutex);
++	
++	init_waitqueue_head(&msblk->waitq);
++	init_waitqueue_head(&msblk->fragment_wait_queue);
++
++	if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++					sizeof(struct squashfs_super_block) |
++					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++		SERROR("unable to read superblock\n");
++		goto failed_mount;
++	}
++
++	/* Check it is a SQUASHFS superblock */
++	msblk->swap = 0;
++	if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++		if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++			struct squashfs_super_block ssblk;
++
++			WARNING("Mounting a different endian SQUASHFS "
++				"filesystem on %s\n", bdevname(s->s_bdev, b));
++
++			SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++			memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++			msblk->swap = 1;
++		} else  {
++			SERROR("Can't find a SQUASHFS superblock on %s\n",
++							bdevname(s->s_bdev, b));
++			goto failed_mount;
++		}
++	}
++
++	/* Check the MAJOR & MINOR versions */
++	if(!supported_squashfs_filesystem(msblk, silent))
++		goto failed_mount;
++
++	TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
++	TRACE("Inodes are %scompressed\n",
++					SQUASHFS_UNCOMPRESSED_INODES
++					(sblk->flags) ? "un" : "");
++	TRACE("Data is %scompressed\n",
++					SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++					? "un" : "");
++	TRACE("Check data is %s present in the filesystem\n",
++					SQUASHFS_CHECK_DATA(sblk->flags) ?
++					"" : "not");
++	TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++	TRACE("Block size %d\n", sblk->block_size);
++	TRACE("Number of inodes %d\n", sblk->inodes);
++	if (sblk->s_major > 1)
++		TRACE("Number of fragments %d\n", sblk->fragments);
++	TRACE("Number of uids %d\n", sblk->no_uids);
++	TRACE("Number of gids %d\n", sblk->no_guids);
++	TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++	TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++	if (sblk->s_major > 1)
++		TRACE("sblk->fragment_table_start %llx\n",
++					sblk->fragment_table_start);
++	TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++	s->s_flags |= MS_RDONLY;
++	s->s_op = &squashfs_ops;
++
++	/* Init inode_table block pointer array */
++	if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++					SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++		ERROR("Failed to allocate block cache\n");
++		goto failed_mount;
++	}
++
++	for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++		msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++	msblk->next_cache = 0;
++
++	/* Allocate read_data block */
++	msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
++					SQUASHFS_METADATA_SIZE :
++					sblk->block_size;
++
++	if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
++		ERROR("Failed to allocate read_data block\n");
++		goto failed_mount;
++	}
++
++	/* Allocate read_page block */
++	if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++		ERROR("Failed to allocate read_page block\n");
++		goto failed_mount;
++	}
++
++	/* Allocate uid and gid tables */
++	if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++					sizeof(unsigned int), GFP_KERNEL))) {
++		ERROR("Failed to allocate uid/gid table\n");
++		goto failed_mount;
++	}
++	msblk->guid = msblk->uid + sblk->no_uids;
++   
++	if (msblk->swap) {
++		unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++		if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++					((sblk->no_uids + sblk->no_guids) *
++					 sizeof(unsigned int)) |
++					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++			ERROR("unable to read uid/gid table\n");
++			goto failed_mount;
++		}
++
++		SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++			sblk->no_guids), (sizeof(unsigned int) * 8));
++	} else
++		if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++					((sblk->no_uids + sblk->no_guids) *
++					 sizeof(unsigned int)) |
++					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++			ERROR("unable to read uid/gid table\n");
++			goto failed_mount;
++		}
++
++
++	if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++		goto allocate_root;
++
++	if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++				SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++		ERROR("Failed to allocate fragment block cache\n");
++		goto failed_mount;
++	}
++
++	for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++		msblk->fragment[i].locked = 0;
++		msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++		msblk->fragment[i].data = NULL;
++	}
++
++	msblk->next_fragment = 0;
++
++	/* Allocate fragment index table */
++	if (msblk->read_fragment_index_table(s) == 0)
++		goto failed_mount;
++
++allocate_root:
++	if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
++		goto failed_mount;
++
++	if ((s->s_root = d_alloc_root(root)) == NULL) {
++		ERROR("Root inode create failed\n");
++		iput(root);
++		goto failed_mount;
++	}
++
++	TRACE("Leaving squashfs_read_super\n");
++	return 0;
++
++failed_mount:
++	kfree(msblk->fragment_index);
++	kfree(msblk->fragment);
++	kfree(msblk->uid);
++	kfree(msblk->read_page);
++	kfree(msblk->read_data);
++	kfree(msblk->block_cache);
++	kfree(msblk->fragment_index_2);
++	kfree(s->s_fs_info);
++	s->s_fs_info = NULL;
++	return -EINVAL;
++
++failure:
++	return -ENOMEM;
++}
++
++
++static int squashfs_statfs(struct super_block *s, struct kstatfs *buf)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++
++	TRACE("Entered squashfs_statfs\n");
++
++	buf->f_type = SQUASHFS_MAGIC;
++	buf->f_bsize = sblk->block_size;
++	buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++	buf->f_bfree = buf->f_bavail = 0;
++	buf->f_files = sblk->inodes;
++	buf->f_ffree = 0;
++	buf->f_namelen = SQUASHFS_NAME_LEN;
++
++	return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++	struct inode *inode = page->mapping->host;
++	int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++	long long block = SQUASHFS_I(inode)->start_block;
++	int offset = SQUASHFS_I(inode)->offset;
++	void *pageaddr = kmap(page);
++
++	TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++				"%llx, offset %x\n", page->index,
++				SQUASHFS_I(inode)->start_block,
++				SQUASHFS_I(inode)->offset);
++
++	for (length = 0; length < index; length += bytes) {
++		if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++				block, offset, PAGE_CACHE_SIZE, &block,
++				&offset))) {
++			ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++					offset);
++			goto skip_read;
++		}
++	}
++
++	if (length != index) {
++		ERROR("(squashfs_symlink_readpage) length != index\n");
++		bytes = 0;
++		goto skip_read;
++	}
++
++	bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++					i_size_read(inode) - length;
++
++	if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++					offset, bytes, &block, &offset)))
++		ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++	kunmap(page);
++	SetPageUptodate(page);
++	unlock_page(page);
++
++	return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++	struct meta_index *meta = NULL;
++	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++	int i;
++
++	down(&msblk->meta_index_mutex);
++
++	TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++	if(msblk->meta_index == NULL)
++		goto not_allocated;
++
++	for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++		if (msblk->meta_index[i].inode_number == inode->i_ino &&
++				msblk->meta_index[i].offset >= offset &&
++				msblk->meta_index[i].offset <= index &&
++				msblk->meta_index[i].locked == 0) {
++			TRACE("locate_meta_index: entry %d, offset %d\n", i,
++					msblk->meta_index[i].offset);
++			meta = &msblk->meta_index[i];
++			offset = meta->offset;
++		}
++
++	if (meta)
++		meta->locked = 1;
++
++not_allocated:
++	up(&msblk->meta_index_mutex);
++
++	return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++	struct meta_index *meta = NULL;
++	int i;
++
++	down(&msblk->meta_index_mutex);
++
++	TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++	if(msblk->meta_index == NULL) {
++		if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++					SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++			ERROR("Failed to allocate meta_index\n");
++			goto failed;
++		}
++		for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++			msblk->meta_index[i].inode_number = 0;
++			msblk->meta_index[i].locked = 0;
++		}
++		msblk->next_meta_index = 0;
++	}
++
++	for(i = SQUASHFS_META_NUMBER; i &&
++			msblk->meta_index[msblk->next_meta_index].locked; i --)
++		msblk->next_meta_index = (msblk->next_meta_index + 1) %
++			SQUASHFS_META_NUMBER;
++
++	if(i == 0) {
++		TRACE("empty_meta_index: failed!\n");
++		goto failed;
++	}
++
++	TRACE("empty_meta_index: returned meta entry %d, %p\n",
++			msblk->next_meta_index,
++			&msblk->meta_index[msblk->next_meta_index]);
++
++	meta = &msblk->meta_index[msblk->next_meta_index];
++	msblk->next_meta_index = (msblk->next_meta_index + 1) %
++			SQUASHFS_META_NUMBER;
++
++	meta->inode_number = inode->i_ino;
++	meta->offset = offset;
++	meta->skip = skip;
++	meta->entries = 0;
++	meta->locked = 1;
++
++failed:
++	up(&msblk->meta_index_mutex);
++	return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++	meta->locked = 0;
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++		long long *start_block, int *offset)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	unsigned int *block_listp;
++	int block = 0;
++	
++	if (msblk->swap) {
++		char sblock_list[blocks << 2];
++
++		if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++				*offset, blocks << 2, start_block, offset)) {
++			ERROR("Unable to read block list [%llx:%x]\n",
++				*start_block, *offset);
++			goto failure;
++		}
++		SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++				((unsigned int *)sblock_list), blocks);
++	} else
++		if (!squashfs_get_cached_block(s, block_list, *start_block,
++				*offset, blocks << 2, start_block, offset)) {
++			ERROR("Unable to read block list [%llx:%x]\n",
++				*start_block, *offset);
++			goto failure;
++		}
++
++	for (block_listp = (unsigned int *) block_list; blocks;
++				block_listp++, blocks --)
++		block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++	return block;
++
++failure:
++	return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++	int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++	return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++		long long *index_block, int *index_offset,
++		long long *data_block, char *block_list)
++{
++	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++	int offset = 0;
++	struct meta_index *meta;
++	struct meta_entry *meta_entry;
++	long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++	int cur_offset = SQUASHFS_I(inode)->offset;
++	long long cur_data_block = SQUASHFS_I(inode)->start_block;
++	int i;
++ 
++	index /= SQUASHFS_META_INDEXES * skip;
++
++	while ( offset < index ) {
++		meta = locate_meta_index(inode, index, offset + 1);
++
++		if (meta == NULL) {
++			if ((meta = empty_meta_index(inode, offset + 1,
++							skip)) == NULL)
++				goto all_done;
++		} else {
++			offset = index < meta->offset + meta->entries ? index :
++				meta->offset + meta->entries - 1;
++			meta_entry = &meta->meta_entry[offset - meta->offset];
++			cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++			cur_offset = meta_entry->offset;
++			cur_data_block = meta_entry->data_block;
++			TRACE("get_meta_index: offset %d, meta->offset %d, "
++				"meta->entries %d\n", offset, meta->offset,
++				meta->entries);
++			TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++				" data_block 0x%llx\n", cur_index_block,
++				cur_offset, cur_data_block);
++		}
++
++		for (i = meta->offset + meta->entries; i <= index &&
++				i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++			int blocks = skip * SQUASHFS_META_INDEXES;
++
++			while (blocks) {
++				int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++					blocks;
++				int res = read_block_index(inode->i_sb, block,
++					block_list, &cur_index_block,
++					&cur_offset);
++
++				if (res == -1)
++					goto failed;
++
++				cur_data_block += res;
++				blocks -= block;
++			}
++
++			meta_entry = &meta->meta_entry[i - meta->offset];
++			meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++			meta_entry->offset = cur_offset;
++			meta_entry->data_block = cur_data_block;
++			meta->entries ++;
++			offset ++;
++		}
++
++		TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++				meta->offset, meta->entries);
++
++		release_meta_index(inode, meta);
++	}
++
++all_done:
++	*index_block = cur_index_block;
++	*index_offset = cur_offset;
++	*data_block = cur_data_block;
++
++	return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++	release_meta_index(inode, meta);
++	return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++				int readahead_blks, char *block_list,
++				unsigned short **block_p, unsigned int *bsize)
++{
++	long long block_ptr;
++	int offset;
++	long long block;
++	int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++		block_list);
++
++	TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++		       " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++		       block);
++
++	if(res == -1)
++		goto failure;
++
++	index -= res;
++
++	while ( index ) {
++		int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++		int res = read_block_index(inode->i_sb, blocks, block_list,
++			&block_ptr, &offset);
++		if (res == -1)
++			goto failure;
++		block += res;
++		index -= blocks;
++	}
++
++	if (read_block_index(inode->i_sb, 1, block_list,
++			&block_ptr, &offset) == -1)
++		goto failure;
++	*bsize = *((unsigned int *) block_list);
++
++	return block;
++
++failure:
++	return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++	struct inode *inode = page->mapping->host;
++	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	unsigned char block_list[SIZE];
++	long long block;
++	unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++	int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++ 	void *pageaddr;
++	struct squashfs_fragment_cache *fragment = NULL;
++	char *data_ptr = msblk->read_page;
++	
++	int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++	int start_index = page->index & ~mask;
++	int end_index = start_index | mask;
++
++	TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++					page->index,
++					SQUASHFS_I(inode)->start_block);
++
++	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++					PAGE_CACHE_SHIFT))
++		goto skip_read;
++
++	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++					|| index < (i_size_read(inode) >>
++					sblk->block_log)) {
++		if ((block = (msblk->read_blocklist)(inode, index, 1,
++					block_list, NULL, &bsize)) == 0)
++			goto skip_read;
++
++		down(&msblk->read_page_mutex);
++		
++		if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++					block, bsize, NULL))) {
++			ERROR("Unable to read page, block %llx, size %x\n", block,
++					bsize);
++			up(&msblk->read_page_mutex);
++			goto skip_read;
++		}
++	} else {
++		if ((fragment = get_cached_fragment(inode->i_sb,
++					SQUASHFS_I(inode)->
++					u.s1.fragment_start_block,
++					SQUASHFS_I(inode)->u.s1.fragment_size))
++					== NULL) {
++			ERROR("Unable to read page, block %llx, size %x\n",
++					SQUASHFS_I(inode)->
++					u.s1.fragment_start_block,
++					(int) SQUASHFS_I(inode)->
++					u.s1.fragment_size);
++			goto skip_read;
++		}
++		bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++					(i_size_read(inode) & (sblk->block_size
++					- 1));
++		byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++		data_ptr = fragment->data;
++	}
++
++	for (i = start_index; i <= end_index && byte_offset < bytes;
++					i++, byte_offset += PAGE_CACHE_SIZE) {
++		struct page *push_page;
++		int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++					PAGE_CACHE_SIZE : bytes - byte_offset;
++
++		TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++					bytes, i, byte_offset, available_bytes);
++
++		if (i == page->index)  {
++			pageaddr = kmap_atomic(page, KM_USER0);
++			memcpy(pageaddr, data_ptr + byte_offset,
++					available_bytes);
++			memset(pageaddr + available_bytes, 0,
++					PAGE_CACHE_SIZE - available_bytes);
++			kunmap_atomic(pageaddr, KM_USER0);
++			flush_dcache_page(page);
++			SetPageUptodate(page);
++			unlock_page(page);
++		} else if ((push_page =
++				grab_cache_page_nowait(page->mapping, i))) {
++ 			pageaddr = kmap_atomic(push_page, KM_USER0);
++
++			memcpy(pageaddr, data_ptr + byte_offset,
++					available_bytes);
++			memset(pageaddr + available_bytes, 0,
++					PAGE_CACHE_SIZE - available_bytes);
++			kunmap_atomic(pageaddr, KM_USER0);
++			flush_dcache_page(push_page);
++			SetPageUptodate(push_page);
++			unlock_page(push_page);
++			page_cache_release(push_page);
++		}
++	}
++
++	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++					|| index < (i_size_read(inode) >>
++					sblk->block_log))
++		up(&msblk->read_page_mutex);
++	else
++		release_cached_fragment(msblk, fragment);
++
++	return 0;
++
++skip_read:
++	pageaddr = kmap_atomic(page, KM_USER0);
++	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++	kunmap_atomic(pageaddr, KM_USER0);
++	flush_dcache_page(page);
++	SetPageUptodate(page);
++	unlock_page(page);
++
++	return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++	struct inode *inode = page->mapping->host;
++	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	unsigned char block_list[SIZE];
++	long long block;
++	unsigned int bsize, bytes = 0;
++ 	void *pageaddr;
++	
++	TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++					page->index,
++					SQUASHFS_I(inode)->start_block);
++
++	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++					PAGE_CACHE_SHIFT)) {
++		pageaddr = kmap_atomic(page, KM_USER0);
++		goto skip_read;
++	}
++
++	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++					|| page->index < (i_size_read(inode) >>
++					sblk->block_log)) {
++		block = (msblk->read_blocklist)(inode, page->index, 1,
++					block_list, NULL, &bsize);
++
++		down(&msblk->read_page_mutex);
++		bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++					bsize, NULL);
++		pageaddr = kmap_atomic(page, KM_USER0);
++		if (bytes)
++			memcpy(pageaddr, msblk->read_page, bytes);
++		else
++			ERROR("Unable to read page, block %llx, size %x\n",
++					block, bsize);
++		up(&msblk->read_page_mutex);
++	} else {
++		struct squashfs_fragment_cache *fragment =
++			get_cached_fragment(inode->i_sb,
++					SQUASHFS_I(inode)->
++					u.s1.fragment_start_block,
++					SQUASHFS_I(inode)-> u.s1.fragment_size);
++		pageaddr = kmap_atomic(page, KM_USER0);
++		if (fragment) {
++			bytes = i_size_read(inode) & (sblk->block_size - 1);
++			memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++					u.s1.fragment_offset, bytes);
++			release_cached_fragment(msblk, fragment);
++		} else
++			ERROR("Unable to read page, block %llx, size %x\n",
++					SQUASHFS_I(inode)->
++					u.s1.fragment_start_block, (int)
++					SQUASHFS_I(inode)-> u.s1.fragment_size);
++	}
++
++skip_read:
++	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++	kunmap_atomic(pageaddr, KM_USER0);
++	flush_dcache_page(page);
++	SetPageUptodate(page);
++	unlock_page(page);
++
++	return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long 
++				*next_block, unsigned int *next_offset,
++				long long index_start,
++				unsigned int index_offset, int i_count,
++				long long f_pos)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	int i, length = 0;
++	struct squashfs_dir_index index;
++
++	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++					i_count, (unsigned int) f_pos);
++
++	f_pos =- 3;
++	if (f_pos == 0)
++		goto finish;
++
++	for (i = 0; i < i_count; i++) {
++		if (msblk->swap) {
++			struct squashfs_dir_index sindex;
++			squashfs_get_cached_block(s, (char *) &sindex,
++					index_start, index_offset,
++					sizeof(sindex), &index_start,
++					&index_offset);
++			SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
++		} else
++			squashfs_get_cached_block(s, (char *) &index,
++					index_start, index_offset,
++					sizeof(index), &index_start,
++					&index_offset);
++
++		if (index.index > f_pos)
++			break;
++
++		squashfs_get_cached_block(s, NULL, index_start, index_offset,
++					index.size + 1, &index_start,
++					&index_offset);
++
++		length = index.index;
++		*next_block = index.start_block + sblk->directory_table_start;
++	}
++
++	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++	return length + 3;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++				*next_block, unsigned int *next_offset,
++				long long index_start,
++				unsigned int index_offset, int i_count,
++				const char *name, int size)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	int i, length = 0;
++	char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
++	struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
++	char str[SQUASHFS_NAME_LEN + 1];
++
++	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++	strncpy(str, name, size);
++	str[size] = '\0';
++
++	for (i = 0; i < i_count; i++) {
++		if (msblk->swap) {
++			struct squashfs_dir_index sindex;
++			squashfs_get_cached_block(s, (char *) &sindex,
++					index_start, index_offset,
++					sizeof(sindex), &index_start,
++					&index_offset);
++			SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++		} else
++			squashfs_get_cached_block(s, (char *) index,
++					index_start, index_offset,
++					sizeof(struct squashfs_dir_index),
++					&index_start, &index_offset);
++
++		squashfs_get_cached_block(s, index->name, index_start,
++					index_offset, index->size + 1,
++					&index_start, &index_offset);
++
++		index->name[index->size + 1] = '\0';
++
++		if (strcmp(index->name, str) > 0)
++			break;
++
++		length = index->index;
++		*next_block = index->start_block + sblk->directory_table_start;
++	}
++
++	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++	return length + 3;
++}
++
++		
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++	struct inode *i = file->f_dentry->d_inode;
++	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	long long next_block = SQUASHFS_I(i)->start_block +
++		sblk->directory_table_start;
++	int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++		dir_count;
++	struct squashfs_dir_header dirh;
++	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
++	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++	TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++	while(file->f_pos < 3) {
++		char *name;
++		int size, i_ino;
++
++		if(file->f_pos == 0) {
++			name = ".";
++			size = 1;
++			i_ino = i->i_ino;
++		} else {
++			name = "..";
++			size = 2;
++			i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++		}
++		TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++				(unsigned int) dirent, name, size, (int)
++				file->f_pos, i_ino,
++				squashfs_filetype_table[1]);
++
++		if (filldir(dirent, name, size,
++				file->f_pos, i_ino,
++				squashfs_filetype_table[1]) < 0) {
++				TRACE("Filldir returned less than 0\n");
++				goto finish;
++		}
++		file->f_pos += size;
++		dirs_read++;
++	}
++
++	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_start,
++				SQUASHFS_I(i)->u.s2.directory_index_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_count,
++				file->f_pos);
++
++	while (length < i_size_read(i)) {
++		/* read directory header */
++		if (msblk->swap) {
++			struct squashfs_dir_header sdirh;
++			
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++					next_block, next_offset, sizeof(sdirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(sdirh);
++			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++		} else {
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++					next_block, next_offset, sizeof(dirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(dirh);
++		}
++
++		dir_count = dirh.count + 1;
++		while (dir_count--) {
++			if (msblk->swap) {
++				struct squashfs_dir_entry sdire;
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						&sdire, next_block, next_offset,
++						sizeof(sdire), &next_block,
++						&next_offset))
++					goto failed_read;
++				
++				length += sizeof(sdire);
++				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++			} else {
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						dire, next_block, next_offset,
++						sizeof(*dire), &next_block,
++						&next_offset))
++					goto failed_read;
++
++				length += sizeof(*dire);
++			}
++
++			if (!squashfs_get_cached_block(i->i_sb, dire->name,
++						next_block, next_offset,
++						dire->size + 1, &next_block,
++						&next_offset))
++				goto failed_read;
++
++			length += dire->size + 1;
++
++			if (file->f_pos >= length)
++				continue;
++
++			dire->name[dire->size + 1] = '\0';
++
++			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
++					(unsigned int) dirent, dire->name,
++					dire->size + 1, (int) file->f_pos,
++					dirh.start_block, dire->offset,
++					dirh.inode_number + dire->inode_number,
++					squashfs_filetype_table[dire->type]);
++
++			if (filldir(dirent, dire->name, dire->size + 1,
++					file->f_pos,
++					dirh.inode_number + dire->inode_number,
++					squashfs_filetype_table[dire->type])
++					< 0) {
++				TRACE("Filldir returned less than 0\n");
++				goto finish;
++			}
++			file->f_pos = length;
++			dirs_read++;
++		}
++	}
++
++finish:
++	return dirs_read;
++
++failed_read:
++	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++		next_offset);
++	return 0;
++}
++
++
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
++				struct nameidata *nd)
++{
++	const unsigned char *name = dentry->d_name.name;
++	int len = dentry->d_name.len;
++	struct inode *inode = NULL;
++	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	long long next_block = SQUASHFS_I(i)->start_block +
++				sblk->directory_table_start;
++	int next_offset = SQUASHFS_I(i)->offset, length = 0,
++				dir_count;
++	struct squashfs_dir_header dirh;
++	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
++	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++	TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++	if (len > SQUASHFS_NAME_LEN)
++		goto exit_loop;
++
++	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_start,
++				SQUASHFS_I(i)->u.s2.directory_index_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_count, name,
++				len);
++
++	while (length < i_size_read(i)) {
++		/* read directory header */
++		if (msblk->swap) {
++			struct squashfs_dir_header sdirh;
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++					next_block, next_offset, sizeof(sdirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(sdirh);
++			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++		} else {
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++					next_block, next_offset, sizeof(dirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(dirh);
++		}
++
++		dir_count = dirh.count + 1;
++		while (dir_count--) {
++			if (msblk->swap) {
++				struct squashfs_dir_entry sdire;
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						&sdire, next_block,next_offset,
++						sizeof(sdire), &next_block,
++						&next_offset))
++					goto failed_read;
++				
++				length += sizeof(sdire);
++				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++			} else {
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						dire, next_block,next_offset,
++						sizeof(*dire), &next_block,
++						&next_offset))
++					goto failed_read;
++
++				length += sizeof(*dire);
++			}
++
++			if (!squashfs_get_cached_block(i->i_sb, dire->name,
++					next_block, next_offset, dire->size + 1,
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += dire->size + 1;
++
++			if (name[0] < dire->name[0])
++				goto exit_loop;
++
++			if ((len == dire->size + 1) && !strncmp(name,
++						dire->name, len)) {
++				squashfs_inode_t ino =
++					SQUASHFS_MKINODE(dirh.start_block,
++					dire->offset);
++
++				TRACE("calling squashfs_iget for directory "
++					"entry %s, inode %x:%x, %d\n", name,
++					dirh.start_block, dire->offset,
++					dirh.inode_number + dire->inode_number);
++
++				inode = (msblk->iget)(i->i_sb, ino);
++
++				goto exit_loop;
++			}
++		}
++	}
++
++exit_loop:
++	d_add(dentry, inode);
++	return ERR_PTR(0);
++
++failed_read:
++	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++		next_offset);
++	goto exit_loop;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++	int i;
++
++	if (s->s_fs_info) {
++		struct squashfs_sb_info *sbi = s->s_fs_info;
++		if (sbi->block_cache)
++			for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++				if (sbi->block_cache[i].block !=
++							SQUASHFS_INVALID_BLK)
++					kfree(sbi->block_cache[i].data);
++		if (sbi->fragment)
++			for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 
++				SQUASHFS_FREE(sbi->fragment[i].data);
++		kfree(sbi->fragment);
++		kfree(sbi->block_cache);
++		kfree(sbi->read_data);
++		kfree(sbi->read_page);
++		kfree(sbi->uid);
++		kfree(sbi->fragment_index);
++		kfree(sbi->fragment_index_2);
++		kfree(sbi->meta_index);
++		kfree(s->s_fs_info);
++		s->s_fs_info = NULL;
++	}
++}
++
++
++static struct super_block *squashfs_get_sb(struct file_system_type *fs_type,
++				int flags, const char *dev_name, void *data)
++{
++	return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++	int err = init_inodecache();
++	if (err)
++		goto out;
++
++	printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
++		"Phillip Lougher\n");
++
++	if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++		ERROR("Failed to allocate zlib workspace\n");
++		destroy_inodecache();
++		err = -ENOMEM;
++		goto out;
++	}
++
++	if ((err = register_filesystem(&squashfs_fs_type))) {
++		vfree(stream.workspace);
++		destroy_inodecache();
++	}
++
++out:
++	return err;
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++	vfree(stream.workspace);
++	unregister_filesystem(&squashfs_fs_type);
++	destroy_inodecache();
++}
++
++
++static kmem_cache_t * squashfs_inode_cachep;
++
++
++static struct inode *squashfs_alloc_inode(struct super_block *sb)
++{
++	struct squashfs_inode_info *ei;
++	ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL);
++	if (!ei)
++		return NULL;
++	return &ei->vfs_inode;
++}
++
++
++static void squashfs_destroy_inode(struct inode *inode)
++{
++	kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
++}
++
++
++static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
++{
++	struct squashfs_inode_info *ei = foo;
++
++	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
++							SLAB_CTOR_CONSTRUCTOR)
++		inode_init_once(&ei->vfs_inode);
++}
++ 
++
++static int __init init_inodecache(void)
++{
++	squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
++	     sizeof(struct squashfs_inode_info),
++	     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++	     init_once, NULL);
++	if (squashfs_inode_cachep == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++
++static void destroy_inodecache(void)
++{
++	if (kmem_cache_destroy(squashfs_inode_cachep))
++		printk(KERN_INFO "squashfs_inode_cache: not all structures "
++			"were freed\n");
++}
++
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip at lougher.org.uk>");
++MODULE_LICENSE("GPL");
+diff --new-file -urp linux-2.6.15/fs/squashfs/Makefile linux-2.6.15-squashfs3.0/fs/squashfs/Makefile
+--- linux-2.6.15/fs/squashfs/Makefile	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/Makefile	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,7 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++obj-$(CONFIG_SQUASHFS) += squashfs.o
++squashfs-y += inode.o
++squashfs-y += squashfs2_0.o
+diff --new-file -urp linux-2.6.15/fs/squashfs/squashfs2_0.c linux-2.6.15-squashfs3.0/fs/squashfs/squashfs2_0.c
+--- linux-2.6.15/fs/squashfs/squashfs2_0.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/squashfs2_0.c	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,758 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs2_0.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/init.h>
++#include <linux/dcache.h>
++#include <linux/wait.h>
++#include <linux/zlib.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++#include "squashfs.h"
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
++				struct nameidata *);
++
++static struct file_operations squashfs_dir_ops_2 = {
++	.read = generic_read_dir,
++	.readdir = squashfs_readdir_2
++};
++
++static struct inode_operations squashfs_dir_inode_ops_2 = {
++	.lookup = squashfs_lookup_2
++};
++
++static unsigned char squashfs_filetype_table[] = {
++	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static int read_fragment_index_table_2(struct super_block *s)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++
++	if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
++					(sblk->fragments), GFP_KERNEL))) {
++		ERROR("Failed to allocate uid/gid table\n");
++		return 0;
++	}
++   
++	if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
++					!squashfs_read_data(s, (char *)
++					msblk->fragment_index_2,
++					sblk->fragment_table_start,
++					SQUASHFS_FRAGMENT_INDEX_BYTES_2
++					(sblk->fragments) |
++					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++		ERROR("unable to read fragment index table\n");
++		return 0;
++	}
++
++	if (msblk->swap) {
++		int i;
++		unsigned int fragment;
++
++		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
++									i++) {
++			SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
++						&msblk->fragment_index_2[i], 1);
++			msblk->fragment_index_2[i] = fragment;
++		}
++	}
++
++	return 1;
++}
++
++
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
++				long long *fragment_start_block,
++				unsigned int *fragment_size)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	long long start_block =
++		msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
++	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
++	struct squashfs_fragment_entry_2 fragment_entry;
++
++	if (msblk->swap) {
++		struct squashfs_fragment_entry_2 sfragment_entry;
++
++		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++					start_block, offset,
++					sizeof(sfragment_entry), &start_block,
++					&offset))
++			goto out;
++		SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
++	} else
++		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++					start_block, offset,
++					sizeof(fragment_entry), &start_block,
++					&offset))
++			goto out;
++
++	*fragment_start_block = fragment_entry.start_block;
++	*fragment_size = fragment_entry.size;
++
++	return 1;
++
++out:
++	return 0;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++		struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	struct inode *i = new_inode(s);
++
++	if (i) {
++		i->i_ino = ino;
++		i->i_mtime.tv_sec = sblk->mkfs_time;
++		i->i_atime.tv_sec = sblk->mkfs_time;
++		i->i_ctime.tv_sec = sblk->mkfs_time;
++		i->i_uid = msblk->uid[inodeb->uid];
++		i->i_mode = inodeb->mode;
++		i->i_nlink = 1;
++		i->i_size = 0;
++		if (inodeb->guid == SQUASHFS_GUIDS)
++			i->i_gid = i->i_uid;
++		else
++			i->i_gid = msblk->guid[inodeb->guid];
++	}
++
++	return i;
++}
++
++
++static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
++{
++	struct inode *i;
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	unsigned int block = SQUASHFS_INODE_BLK(inode) +
++		sblk->inode_table_start;
++	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++	unsigned int ino = SQUASHFS_MK_VFS_INODE(block
++		- sblk->inode_table_start, offset);
++	long long next_block;
++	unsigned int next_offset;
++	union squashfs_inode_header_2 id, sid;
++	struct squashfs_base_inode_header_2 *inodeb = &id.base,
++					  *sinodeb = &sid.base;
++
++	TRACE("Entered squashfs_iget\n");
++
++	if (msblk->swap) {
++		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++					offset, sizeof(*sinodeb), &next_block,
++					&next_offset))
++			goto failed_read;
++		SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
++					sizeof(*sinodeb));
++	} else
++		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++					offset, sizeof(*inodeb), &next_block,
++					&next_offset))
++			goto failed_read;
++
++	switch(inodeb->inode_type) {
++		case SQUASHFS_FILE_TYPE: {
++			struct squashfs_reg_inode_header_2 *inodep = &id.reg;
++			struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
++			long long frag_blk;
++			unsigned int frag_size;
++				
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			frag_blk = SQUASHFS_INVALID_BLK;
++			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++					!get_fragment_location_2(s,
++					inodep->fragment, &frag_blk, &frag_size))
++				goto failed_read;
++				
++			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_size = inodep->file_size;
++			i->i_fop = &generic_ro_fops;
++			i->i_mode |= S_IFREG;
++			i->i_mtime.tv_sec = inodep->mtime;
++			i->i_atime.tv_sec = inodep->mtime;
++			i->i_ctime.tv_sec = inodep->mtime;
++			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++			i->i_blksize = PAGE_CACHE_SIZE;
++			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++			SQUASHFS_I(i)->offset = next_offset;
++			if (sblk->block_size > 4096)
++				i->i_data.a_ops = &squashfs_aops;
++			else
++				i->i_data.a_ops = &squashfs_aops_4K;
++
++			TRACE("File inode %x:%x, start_block %x, "
++					"block_list_start %llx, offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->start_block, next_block,
++					next_offset);
++			break;
++		}
++		case SQUASHFS_DIR_TYPE: {
++			struct squashfs_dir_inode_header_2 *inodep = &id.dir;
++			struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_size = inodep->file_size;
++			i->i_op = &squashfs_dir_inode_ops_2;
++			i->i_fop = &squashfs_dir_ops_2;
++			i->i_mode |= S_IFDIR;
++			i->i_mtime.tv_sec = inodep->mtime;
++			i->i_atime.tv_sec = inodep->mtime;
++			i->i_ctime.tv_sec = inodep->mtime;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->offset = inodep->offset;
++			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++			SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++			TRACE("Directory inode %x:%x, start_block %x, offset "
++					"%x\n", SQUASHFS_INODE_BLK(inode),
++					offset, inodep->start_block,
++					inodep->offset);
++			break;
++		}
++		case SQUASHFS_LDIR_TYPE: {
++			struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
++			struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
++						sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_size = inodep->file_size;
++			i->i_op = &squashfs_dir_inode_ops_2;
++			i->i_fop = &squashfs_dir_ops_2;
++			i->i_mode |= S_IFDIR;
++			i->i_mtime.tv_sec = inodep->mtime;
++			i->i_atime.tv_sec = inodep->mtime;
++			i->i_ctime.tv_sec = inodep->mtime;
++			SQUASHFS_I(i)->start_block = inodep->start_block;
++			SQUASHFS_I(i)->offset = inodep->offset;
++			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++			SQUASHFS_I(i)->u.s2.directory_index_offset =
++								next_offset;
++			SQUASHFS_I(i)->u.s2.directory_index_count =
++								inodep->i_count;
++			SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++			TRACE("Long directory inode %x:%x, start_block %x, "
++					"offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->start_block, inodep->offset);
++			break;
++		}
++		case SQUASHFS_SYMLINK_TYPE: {
++			struct squashfs_symlink_inode_header_2 *inodep =
++								&id.symlink;
++			struct squashfs_symlink_inode_header_2 *sinodep =
++								&sid.symlink;
++	
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
++								sinodep);
++			} else
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_size = inodep->symlink_size;
++			i->i_op = &page_symlink_inode_operations;
++			i->i_data.a_ops = &squashfs_symlink_aops;
++			i->i_mode |= S_IFLNK;
++			SQUASHFS_I(i)->start_block = next_block;
++			SQUASHFS_I(i)->offset = next_offset;
++
++			TRACE("Symbolic link inode %x:%x, start_block %llx, "
++					"offset %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					next_block, next_offset);
++			break;
++		 }
++		 case SQUASHFS_BLKDEV_TYPE:
++		 case SQUASHFS_CHRDEV_TYPE: {
++			struct squashfs_dev_inode_header_2 *inodep = &id.dev;
++			struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
++
++			if (msblk->swap) {
++				if (!squashfs_get_cached_block(s, (char *)
++						sinodep, block, offset,
++						sizeof(*sinodep), &next_block,
++						&next_offset))
++					goto failed_read;
++				SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
++			} else	
++				if (!squashfs_get_cached_block(s, (char *)
++						inodep, block, offset,
++						sizeof(*inodep), &next_block,
++						&next_offset))
++					goto failed_read;
++
++			if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_mode |= (inodeb->inode_type ==
++					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
++					S_IFBLK;
++			init_special_inode(i, i->i_mode,
++					old_decode_dev(inodep->rdev));
++
++			TRACE("Device inode %x:%x, rdev %x\n",
++					SQUASHFS_INODE_BLK(inode), offset,
++					inodep->rdev);
++			break;
++		 }
++		 case SQUASHFS_FIFO_TYPE:
++		 case SQUASHFS_SOCKET_TYPE: {
++			if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
++				goto failed_read1;
++
++			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++							? S_IFIFO : S_IFSOCK;
++			init_special_inode(i, i->i_mode, 0);
++			break;
++		 }
++		 default:
++			ERROR("Unknown inode type %d in squashfs_iget!\n",
++					inodeb->inode_type);
++			goto failed_read1;
++	}
++	
++	insert_inode_hash(i);
++	return i;
++
++failed_read:
++	ERROR("Unable to read inode [%x:%x]\n", block, offset);
++
++failed_read1:
++	return NULL;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long 
++				*next_block, unsigned int *next_offset,
++				long long index_start,
++				unsigned int index_offset, int i_count,
++				long long f_pos)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	int i, length = 0;
++	struct squashfs_dir_index_2 index;
++
++	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++					i_count, (unsigned int) f_pos);
++
++	if (f_pos == 0)
++		goto finish;
++
++	for (i = 0; i < i_count; i++) {
++		if (msblk->swap) {
++			struct squashfs_dir_index_2 sindex;
++			squashfs_get_cached_block(s, (char *) &sindex,
++					index_start, index_offset,
++					sizeof(sindex), &index_start,
++					&index_offset);
++			SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
++		} else
++			squashfs_get_cached_block(s, (char *) &index,
++					index_start, index_offset,
++					sizeof(index), &index_start,
++					&index_offset);
++
++		if (index.index > f_pos)
++			break;
++
++		squashfs_get_cached_block(s, NULL, index_start, index_offset,
++					index.size + 1, &index_start,
++					&index_offset);
++
++		length = index.index;
++		*next_block = index.start_block + sblk->directory_table_start;
++	}
++
++	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++	return length;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++				*next_block, unsigned int *next_offset,
++				long long index_start,
++				unsigned int index_offset, int i_count,
++				const char *name, int size)
++{
++	struct squashfs_sb_info *msblk = s->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	int i, length = 0;
++	char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
++	struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
++	char str[SQUASHFS_NAME_LEN + 1];
++
++	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++	strncpy(str, name, size);
++	str[size] = '\0';
++
++	for (i = 0; i < i_count; i++) {
++		if (msblk->swap) {
++			struct squashfs_dir_index_2 sindex;
++			squashfs_get_cached_block(s, (char *) &sindex,
++					index_start, index_offset,
++					sizeof(sindex), &index_start,
++					&index_offset);
++			SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
++		} else
++			squashfs_get_cached_block(s, (char *) index,
++					index_start, index_offset,
++					sizeof(struct squashfs_dir_index_2),
++					&index_start, &index_offset);
++
++		squashfs_get_cached_block(s, index->name, index_start,
++					index_offset, index->size + 1,
++					&index_start, &index_offset);
++
++		index->name[index->size + 1] = '\0';
++
++		if (strcmp(index->name, str) > 0)
++			break;
++
++		length = index->index;
++		*next_block = index->start_block + sblk->directory_table_start;
++	}
++
++	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++	return length;
++}
++
++		
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
++{
++	struct inode *i = file->f_dentry->d_inode;
++	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	long long next_block = SQUASHFS_I(i)->start_block +
++		sblk->directory_table_start;
++	int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
++		dir_count;
++	struct squashfs_dir_header_2 dirh;
++	char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
++	struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++
++	TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
++
++	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_start,
++				SQUASHFS_I(i)->u.s2.directory_index_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_count,
++				file->f_pos);
++
++	while (length < i_size_read(i)) {
++		/* read directory header */
++		if (msblk->swap) {
++			struct squashfs_dir_header_2 sdirh;
++			
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++					next_block, next_offset, sizeof(sdirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(sdirh);
++			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++		} else {
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++					next_block, next_offset, sizeof(dirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(dirh);
++		}
++
++		dir_count = dirh.count + 1;
++		while (dir_count--) {
++			if (msblk->swap) {
++				struct squashfs_dir_entry_2 sdire;
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						&sdire, next_block, next_offset,
++						sizeof(sdire), &next_block,
++						&next_offset))
++					goto failed_read;
++				
++				length += sizeof(sdire);
++				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++			} else {
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						dire, next_block, next_offset,
++						sizeof(*dire), &next_block,
++						&next_offset))
++					goto failed_read;
++
++				length += sizeof(*dire);
++			}
++
++			if (!squashfs_get_cached_block(i->i_sb, dire->name,
++						next_block, next_offset,
++						dire->size + 1, &next_block,
++						&next_offset))
++				goto failed_read;
++
++			length += dire->size + 1;
++
++			if (file->f_pos >= length)
++				continue;
++
++			dire->name[dire->size + 1] = '\0';
++
++			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
++					(unsigned int) dirent, dire->name,
++					dire->size + 1, (int) file->f_pos,
++					dirh.start_block, dire->offset,
++					squashfs_filetype_table[dire->type]);
++
++			if (filldir(dirent, dire->name, dire->size + 1,
++					file->f_pos, SQUASHFS_MK_VFS_INODE(
++					dirh.start_block, dire->offset),
++					squashfs_filetype_table[dire->type])
++					< 0) {
++				TRACE("Filldir returned less than 0\n");
++				goto finish;
++			}
++			file->f_pos = length;
++			dirs_read++;
++		}
++	}
++
++finish:
++	return dirs_read;
++
++failed_read:
++	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++		next_offset);
++	return 0;
++}
++
++
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
++				struct nameidata *nd)
++{
++	const unsigned char *name = dentry->d_name.name;
++	int len = dentry->d_name.len;
++	struct inode *inode = NULL;
++	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++	struct squashfs_super_block *sblk = &msblk->sblk;
++	long long next_block = SQUASHFS_I(i)->start_block +
++				sblk->directory_table_start;
++	int next_offset = SQUASHFS_I(i)->offset, length = 0,
++				dir_count;
++	struct squashfs_dir_header_2 dirh;
++	char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
++	struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
++	int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
++
++	TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++	if (len > SQUASHFS_NAME_LEN)
++		goto exit_loop;
++
++	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_start,
++				SQUASHFS_I(i)->u.s2.directory_index_offset,
++				SQUASHFS_I(i)->u.s2.directory_index_count, name,
++				len);
++
++	while (length < i_size_read(i)) {
++		/* read directory header */
++		if (msblk->swap) {
++			struct squashfs_dir_header_2 sdirh;
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++					next_block, next_offset, sizeof(sdirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(sdirh);
++			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++		} else {
++			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++					next_block, next_offset, sizeof(dirh),
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += sizeof(dirh);
++		}
++
++		dir_count = dirh.count + 1;
++		while (dir_count--) {
++			if (msblk->swap) {
++				struct squashfs_dir_entry_2 sdire;
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						&sdire, next_block,next_offset,
++						sizeof(sdire), &next_block,
++						&next_offset))
++					goto failed_read;
++				
++				length += sizeof(sdire);
++				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++			} else {
++				if (!squashfs_get_cached_block(i->i_sb, (char *)
++						dire, next_block,next_offset,
++						sizeof(*dire), &next_block,
++						&next_offset))
++					goto failed_read;
++
++				length += sizeof(*dire);
++			}
++
++			if (!squashfs_get_cached_block(i->i_sb, dire->name,
++					next_block, next_offset, dire->size + 1,
++					&next_block, &next_offset))
++				goto failed_read;
++
++			length += dire->size + 1;
++
++			if (sorted && name[0] < dire->name[0])
++				goto exit_loop;
++
++			if ((len == dire->size + 1) && !strncmp(name,
++						dire->name, len)) {
++				squashfs_inode_t ino =
++					SQUASHFS_MKINODE(dirh.start_block,
++					dire->offset);
++
++				TRACE("calling squashfs_iget for directory "
++					"entry %s, inode %x:%x, %lld\n", name,
++					dirh.start_block, dire->offset, ino);
++
++				inode = (msblk->iget)(i->i_sb, ino);
++
++				goto exit_loop;
++			}
++		}
++	}
++
++exit_loop:
++	d_add(dentry, inode);
++	return ERR_PTR(0);
++
++failed_read:
++	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++		next_offset);
++	goto exit_loop;
++}
++
++
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++	struct squashfs_super_block *sblk = &msblk->sblk;
++
++	msblk->iget = squashfs_iget_2;
++	msblk->read_fragment_index_table = read_fragment_index_table_2;
++
++	sblk->bytes_used = sblk->bytes_used_2;
++	sblk->uid_start = sblk->uid_start_2;
++	sblk->guid_start = sblk->guid_start_2;
++	sblk->inode_table_start = sblk->inode_table_start_2;
++	sblk->directory_table_start = sblk->directory_table_start_2;
++	sblk->fragment_table_start = sblk->fragment_table_start_2;
++
++	return 1;
++}
+diff --new-file -urp linux-2.6.15/fs/squashfs/squashfs.h linux-2.6.15-squashfs3.0/fs/squashfs/squashfs.h
+--- linux-2.6.15/fs/squashfs/squashfs.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/fs/squashfs/squashfs.h	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,86 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs.h
++ */
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#endif
++
++#ifdef SQUASHFS_TRACE
++#define TRACE(s, args...)	printk(KERN_NOTICE "SQUASHFS: "s, ## args)
++#else
++#define TRACE(s, args...)	{}
++#endif
++
++#define ERROR(s, args...)	printk(KERN_ERR "SQUASHFS error: "s, ## args)
++
++#define SERROR(s, args...)	do { \
++				if (!silent) \
++				printk(KERN_ERR "SQUASHFS error: "s, ## args);\
++				} while(0)
++
++#define WARNING(s, args...)	printk(KERN_WARNING "SQUASHFS: "s, ## args)
++
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
++{
++	return list_entry(inode, struct squashfs_inode_info, vfs_inode);
++}
++
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
++#define SQSH_EXTERN
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++				long long index, unsigned int length,
++				long long *next_index);
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
++				long long block, unsigned int offset,
++				int length, long long *next_block,
++				unsigned int *next_offset);
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++					squashfs_fragment_cache *fragment);
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++					*s, long long start_block,
++					int length);
++extern struct address_space_operations squashfs_symlink_aops;
++extern struct address_space_operations squashfs_aops;
++extern struct address_space_operations squashfs_aops_4K;
++extern struct inode_operations squashfs_dir_inode_ops;
++#else
++#define SQSH_EXTERN static
++#endif
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
++{
++	return 0;
++}
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++	return 0;
++}
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs.h
+--- linux-2.6.15/include/linux/squashfs_fs.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs.h	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,911 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef	CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a)		vmalloc(a)
++#define SQUASHFS_FREE(a)		vfree(a)
++#else
++#define SQUASHFS_ALLOC(a)		kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a)		kfree(a)
++#endif
++#define SQUASHFS_CACHED_FRAGMENTS	CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE	
++#define SQUASHFS_MAJOR			3
++#define SQUASHFS_MINOR			0
++#define SQUASHFS_MAGIC			0x73717368
++#define SQUASHFS_MAGIC_SWAP		0x68737173
++#define SQUASHFS_START			0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE		8192
++#define SQUASHFS_METADATA_LOG		13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE		65536
++#define SQUASHFS_FILE_LOG		16
++
++#define SQUASHFS_FILE_MAX_SIZE		65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS			256
++#define SQUASHFS_GUIDS			255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN		256
++
++#define SQUASHFS_INVALID		((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG		((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK		((long long) -1)
++#define SQUASHFS_USED_BLK		((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI			0
++#define SQUASHFS_NOD			1
++#define SQUASHFS_CHECK			2
++#define SQUASHFS_NOF			3
++#define SQUASHFS_NO_FRAG		4
++#define SQUASHFS_ALWAYS_FRAG		5
++#define SQUASHFS_DUPLICATE		6
++
++#define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, \
++						SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, \
++						SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
++						SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, \
++						SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
++						SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, \
++						SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, \
++						SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++		duplicate_checking)	(noi | (nod << 1) | (check_data << 2) \
++		| (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++		(duplicate_checking << 6))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE		1
++#define SQUASHFS_FILE_TYPE		2
++#define SQUASHFS_SYMLINK_TYPE		3
++#define SQUASHFS_BLKDEV_TYPE		4
++#define SQUASHFS_CHRDEV_TYPE		5
++#define SQUASHFS_FIFO_TYPE		6
++#define SQUASHFS_SOCKET_TYPE		7
++#define SQUASHFS_LDIR_TYPE		8
++#define SQUASHFS_LREG_TYPE		9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES			5
++#define SQUASHFS_IPC_TYPE		0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT		(1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++		(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	(((B) & \
++	~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++	~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops.  Inodes consist of a compressed block number, and an
++ * uncompressed  offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B)		((squashfs_inode_t)(((squashfs_inode_t) (A)\
++					<< 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + \
++					((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a)		((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A)	(A * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / \
++					SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % \
++						SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + \
++					SQUASHFS_METADATA_SIZE - 1) / \
++					SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) *\
++						sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS		8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG	64
++
++#define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << \
++					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE		0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES	31
++#define SQUASHFS_META_NUMBER	8
++#define SQUASHFS_SLOTS		4
++
++struct meta_entry {
++	long long		data_block;
++	unsigned int		index_block;
++	unsigned short		offset;
++	unsigned short		pad;
++};
++
++struct meta_index {
++	unsigned int		inode_number;
++	unsigned int		offset;
++	unsigned short		entries;
++	unsigned short		skip;
++	unsigned short		locked;
++	unsigned short		pad;
++	struct meta_entry	meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long		squashfs_block_t;
++typedef long long		squashfs_inode_t;
++
++struct squashfs_super_block {
++	unsigned int		s_magic;
++	unsigned int		inodes;
++	unsigned int		bytes_used_2;
++	unsigned int		uid_start_2;
++	unsigned int		guid_start_2;
++	unsigned int		inode_table_start_2;
++	unsigned int		directory_table_start_2;
++	unsigned int		s_major:16;
++	unsigned int		s_minor:16;
++	unsigned int		block_size_1:16;
++	unsigned int		block_log:16;
++	unsigned int		flags:8;
++	unsigned int		no_uids:8;
++	unsigned int		no_guids:8;
++	unsigned int		mkfs_time /* time of filesystem creation */;
++	squashfs_inode_t	root_inode;
++	unsigned int		block_size;
++	unsigned int		fragments;
++	unsigned int		fragment_table_start_2;
++	long long		bytes_used;
++	long long		uid_start;
++	long long		guid_start;
++	long long		inode_table_start;
++	long long		directory_table_start;
++	long long		fragment_table_start;
++	long long		unused;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++	unsigned int		index;
++	unsigned int		start_block;
++	unsigned char		size;
++	unsigned char		name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER		\
++	unsigned int		inode_type:4;	\
++	unsigned int		mode:12;	\
++	unsigned int		uid:8;		\
++	unsigned int		guid:8;		\
++	unsigned int		mtime;		\
++	unsigned int 		inode_number;
++
++struct squashfs_base_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++	unsigned short		rdev;
++} __attribute__ ((packed));
++	
++struct squashfs_symlink_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++	unsigned short		symlink_size;
++	char			symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	squashfs_block_t	start_block;
++	unsigned int		fragment;
++	unsigned int		offset;
++	unsigned int		file_size;
++	unsigned short		block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++	squashfs_block_t	start_block;
++	unsigned int		fragment;
++	unsigned int		offset;
++	long long		file_size;
++	unsigned short		block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++	unsigned int		file_size:19;
++	unsigned int		offset:13;
++	unsigned int		start_block;
++	unsigned int		parent_inode;
++} __attribute__  ((packed));
++
++struct squashfs_ldir_inode_header {
++	SQUASHFS_BASE_INODE_HEADER;
++	unsigned int		nlink;
++	unsigned int		file_size:27;
++	unsigned int		offset:13;
++	unsigned int		start_block;
++	unsigned int		i_count:16;
++	unsigned int		parent_inode;
++	struct squashfs_dir_index	index[0];
++} __attribute__  ((packed));
++
++union squashfs_inode_header {
++	struct squashfs_base_inode_header	base;
++	struct squashfs_dev_inode_header	dev;
++	struct squashfs_symlink_inode_header	symlink;
++	struct squashfs_reg_inode_header	reg;
++	struct squashfs_lreg_inode_header	lreg;
++	struct squashfs_dir_inode_header	dir;
++	struct squashfs_ldir_inode_header	ldir;
++	struct squashfs_ipc_inode_header	ipc;
++};
++	
++struct squashfs_dir_entry {
++	unsigned int		offset:13;
++	unsigned int		type:3;
++	unsigned int		size:8;
++	int			inode_number:16;
++	char			name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++	unsigned int		count:8;
++	unsigned int		start_block;
++	unsigned int		inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++	long long		start_block;
++	unsigned int		size;
++	unsigned int		unused;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa.  These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++	int bits;\
++	int b_pos;\
++	unsigned long long val;\
++	unsigned char *s;\
++	unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++	SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++	SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++	SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++	SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++	SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++	SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++	SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++	SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++	SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++	SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++	SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++	SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++	SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++	SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++	SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++	SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++	SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++	SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++	SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++	SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++	SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++	SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++	SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++	SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++	SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++	SQUASHFS_SWAP((s)->unused, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++	SQUASHFS_MEMSET(s, d, n);\
++	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++	SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_ipc_inode_header))\
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_dev_inode_header)); \
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++	SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_symlink_inode_header));\
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++	SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_reg_inode_header));\
++	SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++	SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++	SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_lreg_inode_header));\
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++	SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++	SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_dir_inode_header));\
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++	SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++	SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++	SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++			sizeof(struct squashfs_ldir_inode_header));\
++	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++	SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++	SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++	SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++	SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++	SQUASHFS_SWAP((s)->index, d, 0, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++	SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++	SQUASHFS_SWAP((s)->count, d, 0, 8);\
++	SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++	SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++	SQUASHFS_SWAP((s)->type, d, 13, 3);\
++	SQUASHFS_SWAP((s)->size, d, 16, 8);\
++	SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++	SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++	SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++	int entry;\
++	int bit_position;\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, n * 2);\
++	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++			16)\
++		SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++	int entry;\
++	int bit_position;\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, n * 4);\
++	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++			32)\
++		SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++	int entry;\
++	int bit_position;\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, n * 8);\
++	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++			64)\
++		SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++	int entry;\
++	int bit_position;\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, n * bits / 8);\
++	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++			bits)\
++		SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++	unsigned int		type:4;
++	unsigned int		offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++	unsigned short		rdev;
++} __attribute__ ((packed));
++	
++struct squashfs_symlink_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++	unsigned short		symlink_size;
++	char			symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++	unsigned int		mtime;
++	unsigned int		start_block;
++	unsigned int		file_size:32;
++	unsigned short		block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:4; /* index into uid table */
++	unsigned int		guid:4; /* index into guid table */
++	unsigned int		file_size:19;
++	unsigned int		offset:13;
++	unsigned int		mtime;
++	unsigned int		start_block:24;
++} __attribute__  ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++	SQUASHFS_MEMSET(s, d, n);\
++	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++	SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++			sizeof(struct squashfs_ipc_inode_header_1));\
++	SQUASHFS_SWAP((s)->type, d, 24, 4);\
++	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++			sizeof(struct squashfs_dev_inode_header_1));\
++	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++			sizeof(struct squashfs_symlink_inode_header_1));\
++	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++			sizeof(struct squashfs_reg_inode_header_1));\
++	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++			sizeof(struct squashfs_dir_inode_header_1));\
++	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++	unsigned int		index:27;
++	unsigned int		start_block:29;
++	unsigned char		size;
++	unsigned char		name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++	unsigned short		rdev;
++} __attribute__ ((packed));
++	
++struct squashfs_symlink_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++	unsigned short		symlink_size;
++	char			symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++	unsigned int		mtime;
++	unsigned int		start_block;
++	unsigned int		fragment;
++	unsigned int		offset;
++	unsigned int		file_size:32;
++	unsigned short		block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++	unsigned int		file_size:19;
++	unsigned int		offset:13;
++	unsigned int		mtime;
++	unsigned int		start_block:24;
++} __attribute__  ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++	unsigned int		inode_type:4;
++	unsigned int		mode:12; /* protection */
++	unsigned int		uid:8; /* index into uid table */
++	unsigned int		guid:8; /* index into guid table */
++	unsigned int		file_size:27;
++	unsigned int		offset:13;
++	unsigned int		mtime;
++	unsigned int		start_block:24;
++	unsigned int		i_count:16;
++	struct squashfs_dir_index_2	index[0];
++} __attribute__  ((packed));
++
++union squashfs_inode_header_2 {
++	struct squashfs_base_inode_header_2	base;
++	struct squashfs_dev_inode_header_2	dev;
++	struct squashfs_symlink_inode_header_2	symlink;
++	struct squashfs_reg_inode_header_2	reg;
++	struct squashfs_dir_inode_header_2	dir;
++	struct squashfs_ldir_inode_header_2	ldir;
++	struct squashfs_ipc_inode_header_2	ipc;
++};
++	
++struct squashfs_dir_header_2 {
++	unsigned int		count:8;
++	unsigned int		start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++	unsigned int		offset:13;
++	unsigned int		type:3;
++	unsigned int		size:8;
++	char			name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++	unsigned int		start_block;
++	unsigned int		size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++	SQUASHFS_MEMSET(s, d, n);\
++	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++	SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++			sizeof(struct squashfs_dev_inode_header_2)); \
++	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++			sizeof(struct squashfs_symlink_inode_header_2));\
++	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++			sizeof(struct squashfs_reg_inode_header_2));\
++	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++	SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++			sizeof(struct squashfs_dir_inode_header_2));\
++	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++			sizeof(struct squashfs_ldir_inode_header_2));\
++	SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++	SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++	SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++	SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++	SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++	SQUASHFS_SWAP((s)->index, d, 0, 27);\
++	SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++	SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++	SQUASHFS_SWAP((s)->count, d, 0, 8);\
++	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++	SQUASHFS_SWAP((s)->type, d, 13, 3);\
++	SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++	SQUASHFS_SWAP_START\
++	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++	SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A)	(A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) / \
++					SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) % \
++						SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A)	((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++					SQUASHFS_METADATA_SIZE - 1) / \
++					SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)	(SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++						sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++	/* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++		tbits, b_pos)
++#else
++	/* convert from big endian to little endian */ 
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++		tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++	b_pos = pos % 8;\
++	val = 0;\
++	s = (unsigned char *)p + (pos / 8);\
++	d = ((unsigned char *) &val) + 7;\
++	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++		*d-- = *s++;\
++	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
++
++#endif
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs_i.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_i.h
+--- linux-2.6.15/include/linux/squashfs_fs_i.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_i.h	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,45 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_i.h
++ */
++
++struct squashfs_inode_info {
++	long long	start_block;
++	unsigned int	offset;
++	union {
++		struct {
++			long long	fragment_start_block;
++			unsigned int	fragment_size;
++			unsigned int	fragment_offset;
++			long long	block_list_start;
++		} s1;
++		struct {
++			long long	directory_index_start;
++			unsigned int	directory_index_offset;
++			unsigned int	directory_index_count;
++			unsigned int	parent_inode;
++		} s2;
++	} u;
++	struct inode	vfs_inode;
++};
++#endif
+diff --new-file -urp linux-2.6.15/include/linux/squashfs_fs_sb.h linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_sb.h
+--- linux-2.6.15/include/linux/squashfs_fs_sb.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.15-squashfs3.0/include/linux/squashfs_fs_sb.h	2006-03-07 21:12:37.000000000 +0000
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006
++ * Phillip Lougher <phillip at lougher.org.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,
++ * or (at your option) any later version.
++ *
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++	long long	block;
++	int		length;
++	long long	next_index;
++	char		*data;
++};
++
++struct squashfs_fragment_cache {
++	long long	block;
++	int		length;
++	unsigned int	locked;
++	char		*data;
++};
++
++struct squashfs_sb_info {
++	struct squashfs_super_block	sblk;
++	int			devblksize;
++	int			devblksize_log2;
++	int			swap;
++	struct squashfs_cache	*block_cache;
++	struct squashfs_fragment_cache	*fragment;
++	int			next_cache;
++	int			next_fragment;
++	int			next_meta_index;
++	unsigned int		*uid;
++	unsigned int		*guid;
++	long long		*fragment_index;
++	unsigned int		*fragment_index_2;
++	unsigned int		read_size;
++	char			*read_data;
++	char			*read_page;
++	struct semaphore	read_data_mutex;
++	struct semaphore	read_page_mutex;
++	struct semaphore	block_cache_mutex;
++	struct semaphore	fragment_mutex;
++	struct semaphore	meta_index_mutex;
++	wait_queue_head_t	waitq;
++	wait_queue_head_t	fragment_wait_queue;
++	struct meta_index	*meta_index;
++	struct inode		*(*iget)(struct super_block *s,  squashfs_inode_t \
++				inode);
++	long long		(*read_blocklist)(struct inode *inode, int \
++				index, int readahead_blks, char *block_list, \
++				unsigned short **block_p, unsigned int *bsize);
++	int			(*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+diff --new-file -urp linux-2.6.15/init/do_mounts_rd.c linux-2.6.15-squashfs3.0/init/do_mounts_rd.c
+--- linux-2.6.15/init/do_mounts_rd.c	2006-03-01 22:37:27.000000000 +0000
++++ linux-2.6.15-squashfs3.0/init/do_mounts_rd.c	2006-03-07 21:12:37.000000000 +0000
+@@ -5,6 +5,7 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+ #include <linux/cramfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/initrd.h>
+ #include <linux/string.h>
+ 
+@@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in
+  * numbers could not be found.
+  *
+  * We currently check for the following magic numbers:
++ *      squashfs
+  * 	minix
+  * 	ext2
+  *	romfs
+@@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start
+ 	struct ext2_super_block *ext2sb;
+ 	struct romfs_super_block *romfsb;
+ 	struct cramfs_super *cramfsb;
++	struct squashfs_super_block *squashfsb;
+ 	int nblocks = -1;
+ 	unsigned char *buf;
+ 
+@@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start
+ 	ext2sb = (struct ext2_super_block *) buf;
+ 	romfsb = (struct romfs_super_block *) buf;
+ 	cramfsb = (struct cramfs_super *) buf;
++	squashfsb = (struct squashfs_super_block *) buf;
+ 	memset(buf, 0xe5, size);
+ 
+ 	/*
+@@ -101,6 +105,15 @@ identify_ramdisk_image(int fd, int start
+ 		goto done;
+ 	}
+ 
++	/* squashfs is at block zero too */
++	if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++		printk(KERN_NOTICE
++		       "RAMDISK: squashfs filesystem found at block %d\n",
++		       start_block);
++		nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++		goto done;
++	}
++
+ 	/*
+ 	 * Read block 1 to test for minix and ext2 superblock
+ 	 */

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/tosa-lcdnoise-r0.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/tosa-lcdnoise-r0.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/tosa-lcdnoise-r0.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,157 @@
+Index: linux-tosa/arch/arm/mach-pxa/tosa.c
+===================================================================
+--- linux-tosa.orig/arch/arm/mach-pxa/tosa.c	2006-08-29 16:52:59.000000000 +0100
++++ linux-tosa/arch/arm/mach-pxa/tosa.c	2006-08-29 16:55:25.959706776 +0100
+@@ -2,6 +2,7 @@
+  *  Support for Sharp SL-C6000x PDAs
+  *  Model: (Tosa)
+  *
++ *  Copyright (c) 2006 Wolfson Microelectronics PLC.
+  *  Copyright (c) 2005 Dirk Opfer
+  *
+  *	Based on code written by Sharp/Lineo for 2.4 kernels
+@@ -46,6 +47,8 @@
+ #include <asm/hardware/tmio.h>
+ #include <asm/mach/sharpsl_param.h>
+ 
++#include <linux/wm97xx.h>
++
+ #include "generic.h"
+ 
+ /*
+@@ -428,6 +431,16 @@
+     },
+ };
+ 
++
++/*
++ * Tosa Touchscreen device
++ */
++
++static struct wm97xx_machinfo tosa_ts_machinfo = {
++    .get_hsync_time   = tosa_get_hsync_time,
++    .wait_hsync       = tosa_wait_hsync,
++};
++
+ /*
+  * Tosa Blueooth
+  */
+@@ -457,6 +470,7 @@
+ 	GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET);
+ 
+ 	mdelay(1000);
++    wm97xx_unset_machinfo();
+ }
+ 
+ static void tosa_restart(void)
+@@ -501,6 +515,8 @@
+ 	platform_scoop_config = &tosa_pcmcia_config;
+ 
+ 	platform_add_devices(devices, ARRAY_SIZE(devices));
++
++    wm97xx_set_machinfo(&tosa_ts_machinfo);
+ }
+ 
+ static void __init fixup_tosa(struct machine_desc *desc,
+Index: linux-tosa/arch/arm/mach-pxa/tosa_lcd.c
+===================================================================
+--- linux-tosa.orig/arch/arm/mach-pxa/tosa_lcd.c	2006-08-29 16:52:59.000000000 +0100
++++ linux-tosa/arch/arm/mach-pxa/tosa_lcd.c	2006-08-29 16:55:32.818664056 +0100
+@@ -1,6 +1,7 @@
+ /*
+  *  LCD / Backlight control code for Sharp SL-6000x (tosa)
+  *
++ *  Copyright (c) 2006      Wolfson Microelectronics PLC.
+  *  Copyright (c) 2005		Dirk Opfer
+  *
+  *  This program is free software; you can redistribute it and/or modify
+@@ -59,6 +60,8 @@
+ static struct ssp_dev tosa_nssp_dev;
+ static struct ssp_state tosa_nssp_state;
+ static spinlock_t tosa_nssp_lock;
++static int blanked;
++static unsigned long hsync_time;
+ 
+ static unsigned short normal_i2c[] = {
+ 	DAC_BASE,
+@@ -130,6 +133,17 @@
+ 	pxa_nssp_output(TG_GPOSR,0x02);		/* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
+ }
+ 
++static unsigned long calc_hsync_time(const struct fb_videomode *mode) {
++    /* The 25 and 44 'magic numbers' are from Sharp's 2.4 patches */
++    if (mode->yres == 640) {
++        return 25;
++    }
++    if (mode->yres == 320) {
++        return 44;
++    }
++    return 0;
++}
++
+ static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode)
+ {
+ 	const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
+@@ -154,6 +168,8 @@
+ 		/* set common voltage */
+ 		i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj);
+ 
++    blanked = 0;
++    hsync_time = calc_hsync_time(mode);
+ }
+ 
+ static void tosa_lcd_tg_off(struct device *dev)
+@@ -172,6 +188,8 @@
+ 	
+ 	/* L3V Off */
+ 	reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); 
++
++    blanked = 1;
+ }
+ 
+ static int tosa_detect_client(struct i2c_adapter* adapter, int address, int kind) {
+@@ -238,6 +256,23 @@
+ 	return 0;
+ }
+ 
++unsigned long tosa_get_hsync_time(void)
++{
++/* This method should eventually contain the correct algorithm for calculating
++   the hsync_time */
++    if (blanked)
++        return 0;
++    else
++        return hsync_time;
++}
++
++void tosa_wait_hsync(void)
++{
++    /* Waits for a rising edge on the VGA line */
++    while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0);
++    while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0);
++}
++
+ static struct i2c_driver tosa_driver={
+ 	.id		= TOSA_LCD_I2C_DEVICEID,
+ 	.attach_adapter	= tosa_attach_adapter,
+Index: linux-tosa/include/asm-arm/arch-pxa/tosa.h
+===================================================================
+--- linux-tosa.orig/include/asm-arm/arch-pxa/tosa.h	2006-08-29 16:52:59.000000000 +0100
++++ linux-tosa/include/asm-arm/arch-pxa/tosa.h	2006-08-29 16:55:12.442761664 +0100
+@@ -1,6 +1,7 @@
+ /*
+  * Hardware specific definitions for Sharp SL-C6000x series of PDAs
+  *
++ * Copyright (c) 2006 Wolfson Microelectronics PLC.
+  * Copyright (c) 2005 Dirk Opfer
+  *
+  * Based on Sharp's 2.4 kernel patches
+@@ -187,4 +188,8 @@
+ extern struct platform_device tosascoop_jc_device;
+ extern struct platform_device tosascoop_device;
+ extern struct platform_device tc6393_device;
++
++unsigned long tosa_get_hsync_time(void);
++void tosa_wait_hsync(void);
++
+ #endif /* _ASM_ARCH_TOSA_H_ */

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/versatile-change-fb-orientation.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/versatile-change-fb-orientation.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/versatile-change-fb-orientation.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,15 @@
+Index: linux-2.6.17/arch/arm/mach-versatile/core.c
+===================================================================
+--- linux-2.6.17.orig/arch/arm/mach-versatile/core.c
++++ linux-2.6.17/arch/arm/mach-versatile/core.c
+@@ -396,8 +396,8 @@ static struct clcd_panel vga = {
+ 	.mode		= {
+ 		.name		= "VGA",
+ 		.refresh	= 60,
+-		.xres		= 640,
+-		.yres		= 480,
++		.xres		= 480,
++		.yres		= 640,
+ 		.pixclock	= 39721,
+ 		.left_margin	= 40,
+ 		.right_margin	= 24,

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/vesafb-tng-1.0-rc2-git-20060629.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/vesafb-tng-1.0-rc2-git-20060629.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/vesafb-tng-1.0-rc2-git-20060629.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,3089 @@
+# Patch generated against a6047eef1c465c38aacfbdab193161b3f0cd144
+---
+# Documentation/fb/vesafb.txt   |  250 ++++--
+# arch/i386/boot/video.S        |   12 
+# drivers/video/Kconfig         |   56 +
+# drivers/video/Makefile        |    6 
+# drivers/video/fbmem.c         |    1 
+# drivers/video/modedb.c        |    1 
+# drivers/video/vesafb-thread.c |  727 +++++++++++++++++++
+# drivers/video/vesafb-tng.c    | 1598 ++++++++++++++++++++++++++++++++++++++++++
+# include/linux/sched.h         |    2 
+# include/video/vesa.h          |  150 +++
+# kernel/fork.c                 |   35 
+# mm/memory.c                   |    1 
+# mm/mmap.c                     |    1 
+# 13 files changed, 2748 insertions(+), 92 deletions(-)
+#
+--- linux-2.6.17.orig/Documentation/fb/vesafb.txt
++++ linux-2.6.17/Documentation/fb/vesafb.txt
+@@ -2,16 +2,18 @@
+ What is vesafb?
+ ===============
+ 
+-This is a generic driver for a graphic framebuffer on intel boxes.
++Vesafb is a generic framebuffer driver for x86 and x86_64 boxes.
+ 
+-The idea is simple:  Turn on graphics mode at boot time with the help
+-of the BIOS, and use this as framebuffer device /dev/fb0, like the m68k
+-(and other) ports do.
++VESA BIOS Extensions Version 2.0 are required, because we need access to
++a linear frame buffer. VBE 3.0 is required if you want to use modes with a
++higher (than the standard 60 Hz) refresh rate.
+ 
+-This means we decide at boot time whenever we want to run in text or
+-graphics mode.  Switching mode later on (in protected mode) is
+-impossible; BIOS calls work in real mode only.  VESA BIOS Extensions
+-Version 2.0 are required, because we need a linear frame buffer.
++The VESA framebuffer driver comes in two flavors - the standard 'vesafb'
++and 'vesafb-tng'. Vesafb-tng is available only on 32-bit x86 due to the
++technology it uses (vm86). Vesafb-tng has more features than vesafb
++(adjusting the refresh rate on VBE 3.0 compliant boards, switching the
++video mode without rebooting, selecting a mode by providing its
++modedb name, and more).
+ 
+ Advantages:
+ 
+@@ -29,26 +31,35 @@ Disadvantages:
+ How to use it?
+ ==============
+ 
+-Switching modes is done using the vga=... boot parameter.  Read
+-Documentation/svga.txt for details.
++If you are running a 32-bit x86 system and you decide to use vesafb-tng,
++you can either compile the driver into the kernel or use it as a module.
++The graphics mode you want to use is in both cases specified using the
++standard modedb format.
+ 
+-You should compile in both vgacon (for text mode) and vesafb (for
+-graphics mode). Which of them takes over the console depends on
+-whenever the specified mode is text or graphics.
++If your system doesn't support vm86 calls, things get a little more tricky.
++Since on such systems you can't do BIOS calls from protected mode in which
++kernel runs, you have to decide at boot time whenever you want to run in text
++or in graphics mode. Switching mode later on is impossible. Switching modes
++is done using the vga=... boot parameter.  Read Documentation/svga.txt for
++details. Below is a more detailed description of what to do on systems using
++the standard vesafb driver.
+ 
+-The graphic modes are NOT in the list which you get if you boot with
+-vga=ask and hit return. The mode you wish to use is derived from the
+-VESA mode number. Here are those VESA mode numbers:
++You should compile in both vgacon (for text mode) and vesafb (for graphics
++mode). Which of them takes over the console depends on whenever the
++specified mode is text or graphics.
++
++The graphic modes are NOT in the list which you get if you boot with vga=ask
++and hit return. The mode you wish to use is derived from the VESA mode number.
++Here are those VESA mode numbers:
+ 
+     | 640x480  800x600  1024x768 1280x1024
+ ----+-------------------------------------
+-256 |  0x101    0x103    0x105    0x107   
+-32k |  0x110    0x113    0x116    0x119   
+-64k |  0x111    0x114    0x117    0x11A   
+-16M |  0x112    0x115    0x118    0x11B   
++256 |  0x101    0x103    0x105    0x107
++32k |  0x110    0x113    0x116    0x119
++64k |  0x111    0x114    0x117    0x11A
++16M |  0x112    0x115    0x118    0x11B
+ 
+-The video mode number of the Linux kernel is the VESA mode number plus
+-0x200.
++The video mode number of the Linux kernel is the VESA mode number plus 0x200.
+  
+  Linux_kernel_mode_number = VESA_mode_number + 0x200
+ 
+@@ -56,15 +67,15 @@ So the table for the Kernel mode numbers
+ 
+     | 640x480  800x600  1024x768 1280x1024
+ ----+-------------------------------------
+-256 |  0x301    0x303    0x305    0x307   
+-32k |  0x310    0x313    0x316    0x319   
+-64k |  0x311    0x314    0x317    0x31A   
+-16M |  0x312    0x315    0x318    0x31B   
++256 |  0x301    0x303    0x305    0x307
++32k |  0x310    0x313    0x316    0x319
++64k |  0x311    0x314    0x317    0x31A
++16M |  0x312    0x315    0x318    0x31B
+ 
+-To enable one of those modes you have to specify "vga=ask" in the
+-lilo.conf file and rerun LILO. Then you can type in the desired
+-mode at the "vga=ask" prompt. For example if you like to use 
+-1024x768x256 colors you have to say "305" at this prompt.
++To enable one of those modes you have to specify "vga=ask" in the lilo.conf
++file and rerun LILO. Then you can type in the desired mode at the "vga=ask"
++prompt. For example if you like to use 1024x768x256 colors you have to say
++"305" at this prompt.
+ 
+ If this does not work, this might be because your BIOS does not support
+ linear framebuffers or because it does not support this mode at all.
+@@ -72,11 +83,12 @@ Even if your board does, it might be the
+ Extensions v2.0 are required, 1.2 is NOT sufficient.  You will get a
+ "bad mode number" message if something goes wrong.
+ 
+-1. Note: LILO cannot handle hex, for booting directly with 
++1. Note: LILO cannot handle hex, for booting directly with
+          "vga=mode-number" you have to transform the numbers to decimal.
+ 2. Note: Some newer versions of LILO appear to work with those hex values,
+          if you set the 0x in front of the numbers.
+ 
++
+ X11
+ ===
+ 
+@@ -84,98 +96,164 @@ XF68_FBDev should work just fine, but it
+ another (accelerated) X-Server like XF86_SVGA might or might not work.
+ It depends on X-Server and graphics board.
+ 
+-The X-Server must restore the video mode correctly, else you end up
++The X-Server must restore the video mode correctly, or else you end up
+ with a broken console (and vesafb cannot do anything about this).
++With vesafb-tng chances are that the console will be restored properly
++even if the X server messes up the video mode.
+ 
+ 
+ Refresh rates
+ =============
+ 
+-There is no way to change the vesafb video mode and/or timings after
+-booting linux.  If you are not happy with the 60 Hz refresh rate, you
+-have these options:
++With VBE 3.0 compatible BIOSes and vesafb-tng it is possible to change
++the refresh rate either at boot time (by specifying the @<rr> part of
++the mode name) or later, using the fbset utility.
+ 
+- * configure and load the DOS-Tools for your the graphics board (if
+-   available) and boot linux with loadlin.
+- * use a native driver (matroxfb/atyfb) instead if vesafb.  If none
++If you want to use the default BIOS refresh rate while switching modes
++on a running system, set pixclock to 0.
++
++With VBE 2.0 there is no way to change the mode timings after booting
++Linux. If you are not happy with the 60 Hz refresh rate, you have
++the following options:
++
++ * Configure and load the DOS tools for your the graphics board (if
++   available) and boot Linux with loadlin.
++ * Use a native driver (matroxfb/atyfb) instead of vesafb.  If none
+    is available, write a new one!
+- * VBE 3.0 might work too.  I have neither a gfx board with VBE 3.0
+-   support nor the specs, so I have not checked this yet.
++ * Use a BIOS editor to change the default refresh rate (such an
++   editor does exist at least for ATI Radeon BIOSes).
++ * If you're running a non-vm86 and VBE 3.0 compatible system, you can
++   use a kernel patch (vesafb-rrc) to hard-code some mode timings in
++   the kernel and use these while setting the video mode at boot time.
++
++Note that there are some boards (nVidia 59**, 57** and newer models)
++claiming that their Video BIOS is VBE 3.0 compliant, while ignoring the
++CRTC values provided by software such as vesafb-tng. You'll not be able
++to adjust the refresh rate if you're using one of these boards.
+ 
+ 
+ Configuration
+ =============
+ 
+-The VESA BIOS provides protected mode interface for changing
+-some parameters.  vesafb can use it for palette changes and
+-to pan the display.  It is turned off by default because it
+-seems not to work with some BIOS versions, but there are options
+-to turn it on.
++The VESA BIOS provides protected mode interface for changing some parameters.
++vesafb can use it for palette changes and to pan the display. It is turned
++off by default because it seems not to work with some BIOS versions, but
++there are options to turn it on.
+ 
+-You can pass options to vesafb using "video=vesafb:option" on
+-the kernel command line.  Multiple options should be separated
+-by comma, like this: "video=vesafb:ypan,invers"
++You can pass options to vesafb using "video=vesafb:option" on the kernel
++command line. Multiple options should be separated by a comma, like this:
++"video=vesafb:ypan,1024x768-32 at 85"
+ 
+-Accepted options:
++Note that vesafb-tng still uses the "video=vesafb:option" format of the
++kernel command line video parameter. "video=vesafb-tng:xxx" is incorrect.
+ 
+-invers	no comment...
++Accepted options (both vesafb and vesafb-tng):
+ 
+-ypan	enable display panning using the VESA protected mode 
+-	interface.  The visible screen is just a window of the
+-	video memory, console scrolling is done by changing the
+-	start of the window.
+-	pro:	* scrolling (fullscreen) is fast, because there is
+-		  no need to copy around data.
+-		* You'll get scrollback (the Shift-PgUp thing),
+-		  the video memory can be used as scrollback buffer
+-	kontra: * scrolling only parts of the screen causes some
+-		  ugly flicker effects (boot logo flickers for
+-		  example).
++ypan    Enable display panning using the VESA protected mode interface
++        The visible screen is just a window of the video memory,
++        console scrolling is done by changing the start of the window.
++        pro:    * scrolling (fullscreen) is fast, because there is
++                  no need to copy around data.
++                * you'll get scrollback (the Shift-PgUp thing),
++                  the video memory can be used as scrollback buffer
++        con:    * scrolling only parts of the screen causes some
++                  ugly flicker effects (boot logo flickers for
++                  example).
+ 
+-ywrap	Same as ypan, but assumes your gfx board can wrap-around 
+-	the video memory (i.e. starts reading from top if it
+-	reaches the end of video memory).  Faster than ypan.
++ywrap   Same as ypan, but assumes your gfx board can wrap-around the video
++        memory (i.e. starts reading from top if it reaches the end of
++        video memory). Faster than ypan.
+ 
+-redraw	scroll by redrawing the affected part of the screen, this
+-	is the safe (and slow) default.
++redraw  Scroll by redrawing the affected part of the screen, this is the
++        safe (and slow) default.
+ 
++vgapal  Use the standard VGA registers for palette changes.
+ 
+-vgapal	Use the standard vga registers for palette changes.
+-	This is the default.
+-pmipal	Use the protected mode interface for palette changes.
++pmipal  Use the protected mode interface for palette changes.
++        This is the default is the protected mode interface is available.
+ 
+-mtrr:n	setup memory type range registers for the vesafb framebuffer
+-	where n:
+-	      0 - disabled (equivalent to nomtrr) (default)
+-	      1 - uncachable
+-	      2 - write-back
+-	      3 - write-combining
+-	      4 - write-through
++mtrr:n  Setup memory type range registers for the vesafb framebuffer
++        where n:
++              0 - disabled (equivalent to nomtrr) (default)
++              1 - uncachable
++              2 - write-back
++              3 - write-combining
++              4 - write-through
+ 
+-	If you see the following in dmesg, choose the type that matches the
+-	old one. In this example, use "mtrr:2".
++        If you see the following in dmesg, choose the type that matches
++        the old one. In this example, use "mtrr:2".
+ ...
+ mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
+ ...
+ 
+-nomtrr  disable mtrr
++nomtrr  Do not use memory type range registers for vesafb.
+ 
+ vremap:n
+         remap 'n' MiB of video RAM. If 0 or not specified, remap memory
+-	according to video mode. (2.5.66 patch/idea by Antonino Daplas
+-	reversed to give override possibility (allocate more fb memory
+-	than the kernel would) to 2.4 by tmb at iki.fi)
++        according to video mode. (2.5.66 patch/idea by Antonino Daplas
++        reversed to give override possibility (allocate more fb memory
++        than the kernel would) to 2.4 by tmb at iki.fi)
+ 
+ vtotal:n
+         if the video BIOS of your card incorrectly determines the total
+         amount of video RAM, use this option to override the BIOS (in MiB).
+ 
+-Have fun!
++Options accepted only by vesafb-tng:
+ 
+-  Gerd
++<mode>  The mode you want to set, in the standard modedb format. Refer to
++        modedb.txt for a detailed description. If you specify a mode that is
++        not supported by your board's BIOS, vesafb-tng will attempt to set a
++        similar mode. The list of supported modes can be found in
++        /proc/fbx/modes, where x is the framebuffer number (usually 0).
++        When vesafb-tng is compiled as a module, the mode string should be
++        provided as a value of the parameter 'mode'.
++
++vbemode:x
++        Force the use of VBE mode x. The mode will only be set if it's
++        found in the VBE-provided list of supported modes.
++        NOTE: The mode number 'x' should be specified in VESA mode number
++        notation, not the Linux kernel one (eg. 257 instead of 769).
++        HINT: If you use this option because normal <mode> parameter does
++        not work for you and you use a X server, you'll probably want to
++        set the 'nocrtc' option to ensure that the video mode is properly
++        restored after console <-> X switches.
++
++nocrtc  Do not use CRTC timings while setting the video mode. This option
++        makes sence only with VBE 3.0 compliant systems. Use it if you have
++        problems with modes set in the standard way. Note that using this
++		option means that any refresh rate adjustments will be ignored
++		and the refresh rate will stay at your BIOS default (60 Hz).
++
++noedid  Do not try to fetch and use EDID-provided modes.
++
++noblank Disable hardware blanking.
++
++gtf     Force the use of VESA's GTF (Generalized Timing Formula). Specifying
++        this will cause vesafb to skip its internal modedb and EDID-modedb
++        and jump straight to the GTF part of the code (normally used only if
++        everything else failed). This can be useful if you want to get as
++        much as possible from your graphics board but your BIOS doesn't
++        support modes with the refresh rates you require. Note that you may 
++		need to specify the maxhf, maxvf and maxclk parameters if they are not
++        provided by the EDID block.
++
++Additionally, the following parameters may be provided. They all override the
++EDID-provided values and BIOS defaults. Refer to your monitor's specs to get
++the correct values for maxhf, maxvf and maxclk for your hardware.
++
++maxhf:n     Maximum horizontal frequency (in kHz).
++maxvf:n     Maximum vertical frequency (in Hz).
++maxclk:n    Maximum pixel clock (in MHz).
++
++Have fun!
+ 
+ --
++Original document for the vesafb driver by
+ Gerd Knorr <kraxel at goldbach.in-berlin.de>
+ 
+-Minor (mostly typo) changes 
+-by Nico Schmoigl <schmoigl at rumms.uni-mannheim.de>
++Minor (mostly typo) changes by
++Nico Schmoigl <schmoigl at rumms.uni-mannheim.de>
++
++Extended documentation for vm86, VBE 3.0 and vesafb-tng by
++Michal Januszewski <spock at gentoo.org>
++
+--- linux-2.6.17.orig/arch/i386/boot/video.S
++++ linux-2.6.17/arch/i386/boot/video.S
+@@ -165,10 +165,12 @@ basret:	ret
+ # parameters in the default 80x25 mode -- these are set directly,
+ # because some very obscure BIOSes supply insane values.
+ mode_params:
++#ifdef CONFIG_FB_VESA_STD
+ #ifdef CONFIG_VIDEO_SELECT
+ 	cmpb	$0, graphic_mode
+ 	jnz	mopar_gr
+ #endif
++#endif
+ 	movb	$0x03, %ah			# Read cursor position
+ 	xorb	%bh, %bh
+ 	int	$0x10
+@@ -201,6 +203,7 @@ mopar2: movb	%al, %fs:(PARAM_VIDEO_LINES
+ 	ret
+ 
+ #ifdef CONFIG_VIDEO_SELECT
++#ifdef CONFIG_FB_VESA_STD
+ # Fetching of VESA frame buffer parameters
+ mopar_gr:
+ 	leaw	modelist+1024, %di
+@@ -283,6 +286,7 @@ dac_done:
+ 	movw	%es, %fs:(PARAM_VESAPM_SEG)
+ 	movw	%di, %fs:(PARAM_VESAPM_OFF)
+ no_pm:	ret
++#endif
+ 
+ # The video mode menu
+ mode_menu:
+@@ -497,10 +501,12 @@ mode_set:
+ 	
+ 	cmpb	$VIDEO_FIRST_V7>>8, %ah
+ 	jz	setv7
+-	
++
++#ifdef CONFIG_FB_VESA_STD
+ 	cmpb	$VIDEO_FIRST_VESA>>8, %ah
+ 	jnc	check_vesa
+-	
++#endif	
++
+ 	orb	%ah, %ah
+ 	jz	setmenu
+ 	
+@@ -572,6 +578,7 @@ setr1:	lodsw
+ 	movw	-4(%si), %ax			# Fetch mode ID
+ 	jmp	_m_s
+ 
++#ifdef CONFIG_FB_VESA_STD
+ check_vesa:
+ 	leaw	modelist+1024, %di
+ 	subb	$VIDEO_FIRST_VESA>>8, %bh
+@@ -605,6 +612,7 @@ check_vesa:
+ 	ret
+ 
+ _setbad:	jmp	setbad          	# Ugly...
++#endif
+ 
+ # Recalculate vertical display end registers -- this fixes various
+ # inconsistencies of extended modes on many adapters. Called when
+--- linux-2.6.17.orig/drivers/video/Kconfig
++++ linux-2.6.17/drivers/video/Kconfig
+@@ -472,8 +472,22 @@ config FB_TGA
+ 	  cards. Say Y if you have one of those.
+ 
+ config FB_VESA
+-	bool "VESA VGA graphics support"
+-	depends on (FB = y) && X86
++	tristate "VESA VGA graphics support"
++	depends on (FB = y) && (X86 || X86_64)
++	help
++	  This is the frame buffer device driver for generic VESA 2.0
++	  compliant graphic cards. The older VESA 1.2 cards are not supported.
++	  You will get a boot time penguin logo at no additional cost. Please
++	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
++
++choice 
++	prompt "VESA driver type"
++	depends on FB_VESA
++	default FB_VESA_STD if X86_64
++	default FB_VESA_TNG if X86
++
++config FB_VESA_STD
++	bool "vesafb"
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+@@ -481,7 +495,43 @@ config FB_VESA
+ 	  This is the frame buffer device driver for generic VESA 2.0
+ 	  compliant graphic cards. The older VESA 1.2 cards are not supported.
+ 	  You will get a boot time penguin logo at no additional cost. Please
+-	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
++	  read <file:Documentation/fb/vesafb.txt>. Choose this driver if you
++	  are experiencing problems with vesafb-tng or if you own a 64-bit system.
++
++	  Note that this driver cannot be compiled as a module.
++
++config FB_VESA_TNG
++	bool "vesafb-tng"
++	depends on !X86_64
++	select FB_MODE_HELPERS
++	select FB_CFB_FILLRECT
++	select FB_CFB_COPYAREA
++	select FB_CFB_IMAGEBLIT
++	help
++	  This is the frame buffer device driver for generic VESA 2.0 
++	  compliant graphic cards. It is capable of taking advantage of 
++	  VBE 3.0 features. With this driver you will be able to adjust
++	  the refresh rate (VBE 3.0 compliant boards only) and change
++	  the graphic mode on-the-fly.
++	  
++	  You will also get a boot time penguin logo at no additional cost. Please
++	  read <file:Documentation/fb/vesafb.txt>.
++
++endchoice
++
++config FB_VESA_DEFAULT_MODE
++	string "VESA default mode"
++	depends on FB_VESA_TNG
++	default "640x480 at 60"
++	help 
++	  This option is used to determine the default mode vesafb is
++	  supposed to switch to in case no mode is provided as a kernel
++	  command line parameter.
++
++config VIDEO_SELECT
++	bool
++	depends on FB_VESA
++	default y
+ 
+ config VIDEO_SELECT
+ 	bool
+--- linux-2.6.17.orig/drivers/video/Makefile
++++ linux-2.6.17/drivers/video/Makefile
+@@ -97,7 +97,11 @@ obj-$(CONFIG_FB_IMX)              += imx
+ obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.o
+ 
+ # Platform or fallback drivers go here
+-obj-$(CONFIG_FB_VESA)             += vesafb.o
++ifeq ($(CONFIG_FB_VESA_STD),y)
++  obj-y				  += vesafb.o
++else
++  obj-$(CONFIG_FB_VESA)		  += vesafb-thread.o vesafb-tng.o
++endif
+ obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+ obj-$(CONFIG_FB_OF)               += offb.o
+ 
+--- linux-2.6.17.orig/drivers/video/fbmem.c
++++ linux-2.6.17/drivers/video/fbmem.c
+@@ -1438,6 +1438,7 @@ fbmem_init(void)
+ 		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
+ 		fb_class = NULL;
+ 	}
++
+ 	return 0;
+ }
+ 
+--- linux-2.6.17.orig/drivers/video/modedb.c
++++ linux-2.6.17/drivers/video/modedb.c
+@@ -671,6 +671,7 @@ void fb_var_to_videomode(struct fb_video
+ {
+ 	u32 pixclock, hfreq, htotal, vtotal;
+ 
++	mode->refresh = 0;
+ 	mode->name = NULL;
+ 	mode->xres = var->xres;
+ 	mode->yres = var->yres;
+--- /dev/null
++++ linux-2.6.17/drivers/video/vesafb-thread.c
+@@ -0,0 +1,727 @@
++/*
++ * Framebuffer driver for VBE 2.0+ compliant graphic boards.
++ * Kernel thread and vm86 routines.
++ *
++ * (c) 2004-2006 Michal Januszewski <spock at gentoo.org>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++#include <linux/completion.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/signal.h>
++#include <linux/suspend.h>
++#include <linux/unistd.h>
++#include <video/vesa.h>
++#include <video/edid.h>
++#include <asm/mman.h>
++#include <asm/page.h>
++#include <asm/vm86.h>
++#include <asm/thread_info.h>
++#include <asm/uaccess.h>
++#include <asm/mmu_context.h>
++#include "edid.h"
++
++#ifdef MODULE
++int errno;
++#endif
++
++static DECLARE_COMPLETION(vesafb_th_completion);
++static DECLARE_MUTEX(vesafb_task_list_sem);
++static LIST_HEAD(vesafb_task_list);
++static DECLARE_WAIT_QUEUE_HEAD(vesafb_wait);
++
++static struct vm86_struct vm86;
++static int vesafb_pid = 0;
++
++_syscall3(int,ioperm,unsigned long, a, unsigned long, b, unsigned long, c);
++_syscall1(int,vm86old,struct vm86_struct __user*, v86);
++
++#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
++#define VM86_PUSHW(x)					\
++do { 							\
++	vm86.regs.esp -= 2; 				\
++	*(u16*)(STACK_ADDR + vm86.regs.esp) = x;	\
++} while(0);
++
++/* Stack, the return code and buffers will be put into
++ * one contiguous memory chunk:
++ *
++ * [ STACK | RET_CODE | BUFFER ]
++ *
++ * Some video BIOSes (sis6326) try to store data somewhere
++ * in 0x7000-0x7fff, so we zeromap more memory to be safe.
++ */
++#define IVTBDA_SIZE 	PAGE_SIZE
++#define RET_CODE_SIZE	0x0010
++#define STACK_SIZE	0x0500
++#define BUFFER_SIZE	0x10000
++
++/* The amount of memory that will be allocated should be a multiple
++ * of PAGE_SIZE. */
++#define __MEM_SIZE 	(RET_CODE_SIZE + STACK_SIZE + BUFFER_SIZE)
++#define REAL_MEM_SIZE	(((__MEM_SIZE / PAGE_SIZE) + 1) * PAGE_SIZE)
++
++#define IVTBDA_ADDR	0x00000
++#define STACK_ADDR	(IVTBDA_ADDR + IVTBDA_SIZE)
++#define RET_CODE_ADDR	(STACK_ADDR + STACK_SIZE)
++#define BUF_ADDR	(RET_CODE_ADDR + RET_CODE_SIZE)
++
++#define FLAG_D 		(1 << 10)
++
++/* Segment prefix opcodes */
++enum {
++	P_CS = 0x2e,
++	P_SS = 0x36,
++	P_DS = 0x3e,
++	P_ES = 0x26,
++	P_FS = 0x64,
++	P_GS = 0x65
++};
++
++/* Emulated vm86 ins instruction */
++static void vm86_ins(int size)
++{
++	u32 edx, edi;
++	edx = vm86.regs.edx & 0xffff;
++	edi = (vm86.regs.edi & 0xffff) + (u32)(vm86.regs.es << 4);
++
++	if (vm86.regs.eflags & FLAG_D)
++		asm volatile ("std\n");
++	else
++		asm volatile ("cld\n");
++
++	switch (size) {
++	case 4:
++		asm volatile ("insl\n" : "=D" (edi) : "d" (edx), "0" (edi));
++		break;
++	case 2:
++		asm volatile ("insw\n" : "=D" (edi) : "d" (edx), "0" (edi));
++		break;
++	case 1:
++		asm volatile ("insb\n" : "=D" (edi) : "d" (edx), "0" (edi));
++		break;
++	}
++
++	if (vm86.regs.eflags & FLAG_D)
++		asm volatile ("cld\n");
++
++	edi -= (u32)(vm86.regs.es << 4);
++
++	vm86.regs.edi &= 0xffff0000;
++	vm86.regs.edi |= edi & 0xffff;
++}
++
++static void vm86_rep_ins(int size)
++{
++	u16 cx = vm86.regs.ecx;
++	while (cx--)
++		vm86_ins(size);
++
++	vm86.regs.ecx &= 0xffff0000;
++}
++
++/* Emulated vm86 outs instruction */
++static void vm86_outs(int size, int segment)
++{
++	u32 edx, esi, base;
++
++	edx = vm86.regs.edx & 0xffff;
++	esi = vm86.regs.esi & 0xffff;
++
++	switch (segment) {
++	case P_CS: base = vm86.regs.cs; break;
++	case P_SS: base = vm86.regs.ss; break;
++	case P_ES: base = vm86.regs.es; break;
++	case P_FS: base = vm86.regs.fs; break;
++	case P_GS: base = vm86.regs.gs; break;
++	default:   base = vm86.regs.ds; break;
++	}
++
++	esi += base << 4;
++
++	if (vm86.regs.eflags & FLAG_D)
++		asm volatile ("std\n");
++	else
++		asm volatile ("cld\n");
++
++	switch (size) {
++	case 4:
++		asm volatile ("outsl\n" : "=S" (esi) : "d" (edx), "0" (esi));
++		break;
++	case 2:
++		asm volatile ("outsw\n" : "=S" (esi) : "d" (edx), "0" (esi));
++		break;
++	case 1:
++		asm volatile ("outsb\n" : "=S" (esi) : "d" (edx), "0" (esi));
++		break;
++	}
++
++	if (vm86.regs.eflags & FLAG_D)
++		asm volatile ("cld");
++
++	esi -= base << 4;
++	vm86.regs.esi &= 0xffff0000;
++	vm86.regs.esi |= (esi & 0xffff);
++}
++
++static void vm86_rep_outs(int size, int segment)
++{
++	u16 cx = vm86.regs.ecx;
++	while (cx--)
++		vm86_outs(size, segment);
++
++	vm86.regs.ecx &= 0xffff0000;
++}
++
++static int vm86_do_unknown(void)
++{
++	u8 data32 = 0, segment = P_DS, rep = 0;
++	u8 *instr;
++	int ret = 0, i = 0;
++
++	instr = (u8*)((vm86.regs.cs << 4) + vm86.regs.eip);
++
++	while (1) {
++		switch(instr[i]) {
++		case 0x66:	/* operand size prefix */
++			data32 = 1 - data32;
++			i++;
++			break;
++		case 0xf2:	/* repnz */
++		case 0xf3:	/* rep */
++			rep = 1;
++			i++;
++			break;
++		case P_CS:	/* segment prefix */
++		case P_SS:
++		case P_DS:
++		case P_ES:
++		case P_FS:
++		case P_GS:
++			segment = instr[i];
++			i++;
++			break;
++		case 0xf0:	/* LOCK - ignored */
++		case 0x67:	/* address size prefix - ignored */
++			i++;
++			break;
++		case 0x6c:	/* insb */
++			if (rep)
++				vm86_rep_ins(1);
++			else
++				vm86_ins(1);
++			i++;
++			goto out;
++		case 0x6d:	/* insw / insd */
++			if (rep) {
++				if (data32)
++					vm86_rep_ins(4);
++				else
++					vm86_rep_ins(2);
++			} else {
++				if (data32)
++					vm86_ins(4);
++				else
++					vm86_ins(2);
++			}
++			i++;
++			goto out;
++		case 0x6e:	/* outsb */
++			if (rep)
++				vm86_rep_outs(1, segment);
++			else
++				vm86_outs(1, segment);
++			i++;
++			goto out;
++		case 0x6f:	/* outsw / outsd */
++			if (rep) {
++				if (data32)
++					vm86_rep_outs(4, segment);
++				else
++					vm86_rep_outs(2, segment);
++			} else {
++				if (data32)
++					vm86_outs(4, segment);
++				else
++					vm86_outs(2, segment);
++			}
++			i++;
++			goto out;
++		case 0xe4:	/* inb xx */
++			asm volatile (
++				"inb %w1, %b0"
++				: "=a" (vm86.regs.eax)
++				: "d" (instr[i+1]), "0" (vm86.regs.eax));
++			i += 2;
++			goto out;
++		case 0xe5:	/* inw xx / ind xx */
++			if (data32) {
++				asm volatile (
++					"inl %w1, %0"
++					: "=a" (vm86.regs.eax)
++					: "d" (instr[i+1]),
++					  "0" (vm86.regs.eax));
++			} else {
++				asm volatile (
++					"inw %w1, %w0"
++					: "=a" (vm86.regs.eax)
++					: "d" (instr[i+1]),
++					  "0" (vm86.regs.eax));
++			}
++			i += 2;
++			goto out;
++
++		case 0xec:	/* inb dx */
++			asm volatile (
++				"inb %w1, %b0"
++	 			: "=a" (vm86.regs.eax)
++				: "d" (vm86.regs.edx), "0" (vm86.regs.eax));
++			i++;
++			goto out;
++		case 0xed:	/* inw dx / ind dx */
++			if (data32) {
++				asm volatile (
++					"inl %w1, %0"
++					: "=a" (vm86.regs.eax)
++					: "d" (vm86.regs.edx));
++			} else {
++				asm volatile (
++					"inw %w1, %w0"
++					: "=a" (vm86.regs.eax)
++					: "d" (vm86.regs.edx));
++			}
++			i++;
++			goto out;
++		case 0xe6:	/* outb xx */
++			asm volatile (
++				"outb %b0, %w1"
++				: /* no return value */
++				: "a" (vm86.regs.eax), "d" (instr[i+1]));
++			i += 2;
++			goto out;
++		case 0xe7:	/* outw xx / outd xx */
++			if (data32) {
++				asm volatile (
++					"outl %0, %w1"
++					: /* no return value */
++					: "a" (vm86.regs.eax),
++					  "d" (instr[i+1]));
++			} else {
++				asm volatile (
++					"outw %w0, %w1"
++					: /* no return value */
++					: "a" (vm86.regs.eax),
++					  "d" (instr[i+1]));
++			}
++			i += 2;
++			goto out;
++		case 0xee:	/* outb dx */
++			asm volatile (
++				"outb %b0, %w1"
++				: /* no return value */
++				: "a" (vm86.regs.eax), "d" (vm86.regs.edx));
++			i++;
++			goto out;
++		case 0xef:	/* outw dx / outd dx */
++			if (data32) {
++				asm volatile (
++					"outl %0, %w1"
++					: /* no return value */
++					: "a" (vm86.regs.eax),
++					  "d" (vm86.regs.edx));
++			} else {
++				asm volatile (
++					"outw %w0, %w1"
++					: /* no return value */
++					: "a" (vm86.regs.eax),
++					  "d" (vm86.regs.edx));
++			}
++			i++;
++			goto out;
++		default:
++			printk(KERN_ERR "vesafb: BUG, opcode 0x%x emulation "
++					"not supported (EIP: 0x%lx)\n",
++					instr[i], (u32)(vm86.regs.cs << 4) +
++					vm86.regs.eip);
++			ret = 1;
++			goto out;
++		}
++	}
++out: 	vm86.regs.eip += i;
++	return ret;
++}
++
++void vesafb_do_vm86(struct vm86_regs *regs)
++{
++	unsigned int ret;
++	u8 *retcode = (void*)RET_CODE_ADDR;
++
++	memset(&vm86,0,sizeof(vm86));
++	memcpy(&vm86.regs, regs, sizeof(struct vm86_regs));
++
++	/* The return code */
++	retcode[0] = 0xcd;  		/* int opcode */
++	retcode[1] = 0xff;		/* int number (255) */
++
++        /* We use int 0xff to get back to protected mode */
++	memset(&vm86.int_revectored, 0, sizeof(vm86.int_revectored));
++        ((unsigned char *)&vm86.int_revectored)[0xff / 8] |= (1 << (0xff % 8));
++
++	/*
++	 * We want to call int 0x10, so we set:
++	 *   CS = 0x42 = 0x10 * 4 + 2
++	 *   IP = 0x40 = 0x10 * 4
++	 * and SS:ESP. It's up to the caller to set the rest of the registers.
++	 */
++	vm86.regs.eflags = DEFAULT_VM86_FLAGS;
++	vm86.regs.cs = *(unsigned short *)0x42;
++	vm86.regs.eip = *(unsigned short *)0x40;
++	vm86.regs.ss = (STACK_ADDR >> 4);
++	vm86.regs.esp = ((STACK_ADDR & 0x0000f) + STACK_SIZE);
++
++	/* These will be fetched off the stack when we come to an iret in the
++	 * int's 0x10 code. */
++	VM86_PUSHW(DEFAULT_VM86_FLAGS);
++	VM86_PUSHW((RET_CODE_ADDR >> 4));	/* return code segment */
++	VM86_PUSHW((RET_CODE_ADDR & 0x0000f));	/* return code offset */
++
++	while(1) {
++		ret = vm86old(&vm86);
++
++		if (VM86_TYPE(ret) == VM86_INTx) {
++			int vint = VM86_ARG(ret);
++
++			/* If exit from vm86 was caused by int 0xff, then
++			 * we're done.. */
++			if (vint == 0xff)
++				goto out;
++
++			/* .. otherwise, we have to call the int handler
++			 * manually */
++			VM86_PUSHW(vm86.regs.eflags);
++			VM86_PUSHW(vm86.regs.cs);
++			VM86_PUSHW(vm86.regs.eip);
++
++			vm86.regs.cs = *(u16 *)((vint << 2) + 2);
++			vm86.regs.eip = *(u16 *)(vint << 2);
++			vm86.regs.eflags &= ~(VIF_MASK | TF_MASK);
++		} else if (VM86_TYPE(ret) == VM86_UNKNOWN) {
++			if (vm86_do_unknown())
++				goto out;
++		} else {
++			printk(KERN_ERR "vesafb: BUG, returned from "
++					"vm86 with %x (EIP: 0x%lx)\n",
++					ret, (u32)(vm86.regs.cs << 4) +
++					vm86.regs.eip);
++			goto out;
++		}
++	}
++
++out:	/* copy the registers' state back to the caller's struct */
++	memcpy(regs, &vm86.regs, sizeof(struct vm86_regs));
++}
++
++static int vesafb_remap_pfn_range(unsigned long start, unsigned long end,
++				  unsigned long pgoff, unsigned long prot,
++				  int type)
++{
++	struct vm_area_struct *vma;
++	struct mm_struct *mm = current->mm;
++	int ret = 0;
++
++	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
++	if (!vma)
++		return -ENOMEM;
++	memset(vma, 0, sizeof(*vma));
++	down_write(&mm->mmap_sem);
++	vma->vm_mm = mm;
++	vma->vm_start = start;
++	vma->vm_end = end;
++	vma->vm_flags = VM_READ | VM_WRITE | VM_EXEC;
++	vma->vm_flags |= mm->def_flags;
++	vma->vm_page_prot.pgprot = prot;
++	vma->vm_pgoff = pgoff;
++
++	if ((ret = insert_vm_struct(mm, vma))) {
++		up_write(&mm->mmap_sem);
++		kmem_cache_free(vm_area_cachep, vma);
++		return ret;
++	}
++
++	if (type) {
++		ret = zeromap_page_range(vma,
++					 vma->vm_start,
++					 vma->vm_end - vma->vm_start,
++					 vma->vm_page_prot);
++	} else {
++		vma->vm_flags |= VM_SHARED;
++		ret = remap_pfn_range(vma,
++				      vma->vm_start,
++				      vma->vm_pgoff,
++				      vma->vm_end - vma->vm_start,
++				      vma->vm_page_prot);
++	}
++	up_write(&mm->mmap_sem);
++	return ret;
++}
++
++static inline int vesafb_init_mem(void)
++{
++	int ret = 0;
++
++	/* The memory chunks we're remapping here should be multiples
++	 * of PAGE_SIZE. */
++	ret += vesafb_remap_pfn_range(0x00000, IVTBDA_SIZE, 0,
++				      PROT_READ | PROT_EXEC | PROT_WRITE, 0);
++	ret += vesafb_remap_pfn_range(IVTBDA_SIZE, REAL_MEM_SIZE, 0,
++				      PROT_READ | PROT_EXEC | PROT_WRITE, 1);
++	ret += vesafb_remap_pfn_range(0x9f000, 0x100000, 
++				      0x9f000 >> PAGE_SHIFT,
++				      PROT_READ | PROT_EXEC | PROT_WRITE, 0);
++	if (ret)
++		printk(KERN_ERR "vesafb thread: memory remapping failed\n");
++
++	return ret;
++}
++
++#define vesafb_get_string(str) \
++{ 									\
++	/* The address is in the form ssssoooo, where oooo = offset,	\
++	 * ssss = segment */						\
++	addr = ((p_vbe(tsk->buf)->str & 0xffff0000) >> 12) +		\
++		(p_vbe(tsk->buf)->str & 0x0000ffff);			\
++									\
++	/* The data is in ROM which is shared between processes, so we 	\
++	 * just translate the real mode address into one visible from 	\
++	 * kernel space */						\
++	if (addr >= 0xa0000) {						\
++		p_vbe(tsk->buf)->str = (u32) __va(addr);		\
++									\
++	/* The data is in the buffer, we just have to convert the	\
++	 * address so that it points into the buffer user provided. */	\
++	} else if (addr > BUF_ADDR && addr < BUF_ADDR +			\
++		   sizeof(struct vesafb_vbe_ib)) {			\
++		addr -= BUF_ADDR;					\
++		p_vbe(tsk->buf)->str = (u32) (tsk->buf + addr);		\
++									\
++	/* This should never happen: someone was insane enough to put	\
++	 * the data somewhere in RAM.. */				\
++	} else {							\
++		p_vbe(tsk->buf)->str = (u32) "";			\
++	}								\
++}
++
++void vesafb_handle_getvbeib(struct vesafb_task *tsk)
++{
++	int addr, res;
++
++	tsk->regs.es  = (BUF_ADDR >> 4);
++	tsk->regs.edi = (BUF_ADDR & 0x000f);
++	strncpy(p_vbe(BUF_ADDR)->vbe_signature, "VBE2", 4);
++
++	vesafb_do_vm86(&tsk->regs);
++	memcpy(tsk->buf, (void*)(BUF_ADDR), sizeof(struct vesafb_vbe_ib));
++
++	/* The OEM fields were not defined prior to VBE 2.0 */
++	if (p_vbe(tsk->buf)->vbe_version >= 0x200) {
++		vesafb_get_string(oem_string_ptr);
++		vesafb_get_string(oem_vendor_name_ptr);
++		vesafb_get_string(oem_product_name_ptr);
++		vesafb_get_string(oem_product_rev_ptr);
++	}
++
++	/* This is basically the same as vesafb_get_string() */
++	addr = ((p_vbe(tsk->buf)->mode_list_ptr & 0xffff0000) >> 12) +
++		(p_vbe(tsk->buf)->mode_list_ptr & 0x0000ffff);
++
++	if (addr >= 0xa0000) {
++		p_vbe(tsk->buf)->mode_list_ptr = (u32) __va(addr);
++	} else if (addr > BUF_ADDR && addr < BUF_ADDR +
++		   sizeof(struct vesafb_vbe_ib)) {
++		addr -= BUF_ADDR;
++		p_vbe(tsk->buf)->mode_list_ptr = (u32) (tsk->buf + addr);
++	} else {
++		res = 0;
++		printk(KERN_WARNING "vesafb: warning, copying modelist "
++				    "from somewhere in RAM!\n");
++		while (*(u16*)(addr+res) != 0xffff &&
++		       res < (sizeof(p_vbe(tsk->buf)->reserved) - 2)) {
++			*(u16*) ((u32)&(p_vbe(tsk->buf)->reserved) + res) =
++				*(u16*)(addr+res);
++			res += 2;
++		}
++		*(u16*) ((u32)&(p_vbe(tsk->buf)->reserved) + res) = 0xffff;
++	}
++}
++
++int vesafb_handle_tasks(void)
++{
++	struct vesafb_task *tsk;
++	struct list_head *curr, *next;
++	int ret = 0;
++
++	down(&vesafb_task_list_sem);
++	list_for_each_safe(curr, next, &vesafb_task_list) {
++		tsk = list_entry(curr, struct vesafb_task, node);
++
++		if (tsk->flags & TF_EXIT) {
++			ret = 1;
++			goto task_done;
++		}
++		if (tsk->flags & TF_GETVBEIB) {
++			vesafb_handle_getvbeib(tsk);
++			goto task_done;
++		}
++		/* Do we need to store a pointer to the buffer in ES:EDI? */
++		if (tsk->flags & TF_BUF_DI) {
++			tsk->regs.es  = (BUF_ADDR >> 4);
++			tsk->regs.edi = (BUF_ADDR & 0x000f);
++		}
++		/* Sometimes the pointer has to be in ES:EBX. */
++		if (tsk->flags & TF_BUF_BX) {
++			tsk->regs.es  = (BUF_ADDR >> 4);
++			tsk->regs.ebx = (BUF_ADDR & 0x000f);
++		}
++		if (tsk->flags & (TF_BUF_DI | TF_BUF_BX))
++			memcpy((void*)BUF_ADDR, tsk->buf, tsk->buf_len);
++
++		vesafb_do_vm86(&tsk->regs);
++
++		if (tsk->flags & TF_RETURN_BUF)
++			memcpy(tsk->buf, (void*)BUF_ADDR, tsk->buf_len);
++
++task_done:	list_del(curr);
++		complete(&tsk->done);
++	}
++
++	/* If we're going to kill this thread, don't allow any elements
++	 * to be added to the task list. */
++	if (!ret)
++		up(&vesafb_task_list_sem);
++
++	return ret;
++}
++
++/*
++ * This 'hybrid' thread serves as a backend for vesafb-tng, handling all vm86
++ * calls. It is started as a kernel thread. It then creates its own mm struct,
++ * thus separating itself from any userspace processes. At this moment, it
++ * stops being a kernel thread (kernel threads have mm = NULL) and becomes
++ * a 'hybrid' thread -- one that has full access to kernel space, yet runs
++ * with its own address space.
++ *
++ * This is necessary because in order to make vm86 calls some parts of the
++ * first 1MB of RAM have to be setup to mimic the real mode. These are:
++ *  - interrupt vector table	[0x00000-0x003ff]
++ *  - BIOS data area		[0x00400-0x004ff]
++ *  - Extended BIOS data area	[0x9fc00-0x9ffff]
++ *  - the video RAM		[0xa0000-0xbffff]
++ *  - video BIOS		[0xc0000-0xcffff]
++ *  - motherboard BIOS		[0xf0000-0xfffff]
++ */
++int vesafb_thread(void *unused)
++{
++	int err = 0;
++
++	set_fs(KERNEL_DS);
++	daemonize("vesafb");
++
++	if (set_new_mm()) {
++		err = -ENOMEM;
++		goto thr_end;
++	}
++	if (vesafb_init_mem()) {
++		err = -ENOMEM;
++		goto thr_end;
++	}
++
++	DPRINTK("started vesafb thread\n");
++
++	/* Having an IO bitmap makes things faster as we avoid GPFs
++	 * when running vm86 code. We can live if it fails, though,
++	 * so don't bother checking for errors. */
++	ioperm(0,1024,1);
++	set_user_nice(current, -10);
++
++	complete(&vesafb_th_completion);
++
++	while (1) {
++		if (vesafb_handle_tasks())
++			break;
++		wait_event_interruptible(vesafb_wait,
++					 !list_empty(&vesafb_task_list));
++		try_to_freeze();
++	}
++
++out:	DPRINTK("exiting the vesafb thread\n");
++	vesafb_pid = -1;
++
++	/* Now that all callers know this thread is no longer running
++	 * (pid < 0), allow them to continue. */
++	up(&vesafb_task_list_sem);
++	return err;
++thr_end:
++	down(&vesafb_task_list_sem);
++	complete(&vesafb_th_completion);
++	goto out;	
++}
++
++int vesafb_queue_task(struct vesafb_task *tsk)
++{
++	down(&vesafb_task_list_sem);
++	if (vesafb_pid < 0)
++		return -1;
++	list_add_tail(&tsk->node, &vesafb_task_list);
++	up(&vesafb_task_list_sem);
++	wake_up(&vesafb_wait);
++	return 0;
++}
++
++int vesafb_wait_for_thread(void)
++{
++	/* PID 0 means that the thread is still initializing. */
++	if (vesafb_pid < 0)
++		return -1;
++	wait_for_completion(&vesafb_th_completion);
++	return 0;
++}
++
++int __init vesafb_init_thread(void)
++{
++	vesafb_pid = kernel_thread(vesafb_thread,NULL,0);
++	return 0;
++}
++
++#ifdef MODULE
++void __exit vesafb_kill_thread(void)
++{
++	struct vesafb_task *tsk;
++	if (vesafb_pid <= 0)
++		return;
++
++	vesafb_create_task(tsk);
++	if (!tsk)
++		return;
++	tsk->flags |= TF_EXIT;
++	vesafb_queue_task(tsk);
++	vesafb_wait_for_task(tsk);
++	kfree(tsk);
++	return;
++}
++module_exit(vesafb_kill_thread);
++#endif
++module_init(vesafb_init_thread);
++
++EXPORT_SYMBOL_GPL(vesafb_queue_task);
++EXPORT_SYMBOL_GPL(vesafb_wait_for_thread);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michal Januszewski");
++
+--- /dev/null
++++ linux-2.6.17/drivers/video/vesafb-tng.c
+@@ -0,0 +1,1598 @@
++/*
++ * Framebuffer driver for VBE 2.0+ compliant graphic boards
++ *
++ * (c) 2004-2006 Michal Januszewski <spock at gentoo.org>
++ *     Based upon vesafb code by Gerd Knorr <kraxel at goldbach.in-berlin.de>
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/completion.h>
++#include <linux/platform_device.h>
++#include <video/edid.h>
++#include <video/vesa.h>
++#include <video/vga.h>
++#include <asm/io.h>
++#include <asm/mtrr.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include "edid.h"
++
++#define dac_reg	(0x3c8)
++#define dac_val	(0x3c9)
++
++#define VESAFB_NEED_EXACT_RES 	1
++#define VESAFB_NEED_EXACT_DEPTH 2
++
++/* --------------------------------------------------------------------- */
++
++static struct fb_var_screeninfo vesafb_defined __initdata = {
++	.activate	= FB_ACTIVATE_NOW,
++	.height		= 0,
++	.width		= 0,
++	.right_margin	= 32,
++	.upper_margin	= 16,
++	.lower_margin	= 4,
++	.vsync_len	= 4,
++	.vmode		= FB_VMODE_NONINTERLACED,
++};
++
++static struct fb_fix_screeninfo vesafb_fix __initdata = {
++	.id	= "VESA VGA",
++	.type	= FB_TYPE_PACKED_PIXELS,
++	.accel	= FB_ACCEL_NONE,
++};
++
++static int  mtrr       = 0;	/* disable mtrr by default */
++static int  blank      = 1;     /* enable blanking by default */
++static int  ypan       = 0;	/* 0 - nothing, 1 - ypan, 2 - ywrap */
++static int  pmi_setpal = 1;	/* pmi for palette changes */
++static u16  *pmi_base  = NULL;  /* protected mode interface location */
++static void (*pmi_start)(void) = NULL;
++static void (*pmi_pal)(void)   = NULL;
++static struct vesafb_vbe_ib  vbe_ib;
++static struct vesafb_mode_ib *vbe_modes;
++static int                   vbe_modes_cnt = 0;
++static struct fb_info	     *vesafb_info = NULL;
++static int  nocrtc		    = 0; /* ignore CRTC settings */
++static int  noedid       __initdata = 0; /* don't try DDC transfers */
++static int  vram_remap   __initdata = 0; /* set amount of memory to be used */
++static int  vram_total   __initdata = 0; /* set total amount of memory */
++static u16  maxclk       __initdata = 0; /* maximum pixel clock */
++static u16  maxvf        __initdata = 0; /* maximum vertical frequency */
++static u16  maxhf        __initdata = 0; /* maximum horizontal frequency */
++static int  gtf          __initdata = 0; /* forces use of the GTF */
++static char *mode_option __initdata = NULL;
++static u16  vbemode      __initdata = 0;
++
++/* --------------------------------------------------------------------- */
++
++static int vesafb_find_vbe_mode(int xres, int yres, int depth,
++				unsigned char flags)
++{
++	int i, match = -1, h = 0, d = 0x7fffffff;
++
++	for (i = 0; i < vbe_modes_cnt; i++) {
++		h = abs(vbe_modes[i].x_res - xres) +
++		    abs(vbe_modes[i].y_res - yres) +
++		    abs(depth - vbe_modes[i].depth);
++		if (h == 0)
++			return i;
++		if (h < d || (h == d && vbe_modes[i].depth > depth)) {
++			d = h;
++			match = i;
++		}
++	}
++	i = 1;
++
++	if (flags & VESAFB_NEED_EXACT_DEPTH && vbe_modes[match].depth != depth)
++		i = 0;
++	if (flags & VESAFB_NEED_EXACT_RES && d > 24)
++		i = 0;
++	if (i != 0)
++		return match;
++	else
++		return -1;
++}
++
++static int vesafb_pan_display(struct fb_var_screeninfo *var,
++                              struct fb_info *info)
++{
++	int offset;
++
++	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
++
++	/* It turns out it's not the best idea to do panning via vm86,
++	 * so we only allow it if we have a PMI. */
++	if (pmi_start) {
++		__asm__ __volatile__(
++			"call *(%%edi)"
++			: /* no return value */
++			: "a" (0x4f07),         /* EAX */
++			  "b" (0),              /* EBX */
++			  "c" (offset),         /* ECX */
++			  "d" (offset >> 16),   /* EDX */
++			  "D" (&pmi_start));    /* EDI */
++	}
++	return 0;
++}
++
++static int vesafb_blank(int blank, struct fb_info *info)
++{
++	struct vesafb_task *tsk;
++	int err = 1;
++
++	if (vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
++		int loop = 10000;
++		u8 seq = 0, crtc17 = 0;
++
++		if (blank == FB_BLANK_POWERDOWN) {
++			seq = 0x20;
++			crtc17 = 0x00;
++			err = 0;
++		} else {
++			seq = 0x00;
++			crtc17 = 0x80;
++			err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
++		}
++
++		vga_wseq(NULL, 0x00, 0x01);
++		seq |= vga_rseq(NULL, 0x01) & ~0x20;
++		vga_wseq(NULL, 0x00, seq);
++
++		crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
++		while (loop--);
++		vga_wcrt(NULL, 0x17, crtc17);
++		vga_wseq(NULL, 0x00, 0x03);
++	} else {
++		vesafb_create_task (tsk);
++		if (!tsk)
++			return -ENOMEM;
++		tsk->regs.eax = 0x4f10;
++		switch (blank) {
++		case FB_BLANK_UNBLANK:
++			tsk->regs.ebx = 0x0001;
++			break;
++		case FB_BLANK_NORMAL:
++			tsk->regs.ebx = 0x0101;	/* standby */
++			break;
++		case FB_BLANK_POWERDOWN:
++			tsk->regs.ebx = 0x0401;	/* powerdown */
++			break;
++		default:
++			goto out;
++		}
++		tsk->flags = TF_CALL;
++		if (!vesafb_queue_task (tsk))
++			vesafb_wait_for_task(tsk);
++
++		if ((tsk->regs.eax & 0xffff) == 0x004f)
++			err = 0;
++out:		kfree(tsk);
++	}
++	return err;
++}
++
++static int vesafb_setpalette(struct vesafb_pal_entry *entries, int count,
++			     int start, struct fb_info *info)
++{
++	struct vesafb_task *tsk;
++	int i = ((struct vesafb_par*)info->par)->mode_idx;
++	int ret = 0;
++
++	/* We support palette modifications for 8 bpp modes only, so
++	 * there can never be more than 256 entries. */
++	if (start + count > 256)
++		return -EINVAL;
++
++	/* Use VGA registers if mode is VGA-compatible. */
++	if (i >= 0 && i < vbe_modes_cnt &&
++	    vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
++		for (i = 0; i < count; i++) {
++			outb_p(start + i,        dac_reg);
++			outb_p(entries[i].red,   dac_val);
++			outb_p(entries[i].green, dac_val);
++			outb_p(entries[i].blue,  dac_val);
++		}
++	} else if (pmi_setpal) {
++		__asm__ __volatile__(
++		"call *(%%esi)"
++		: /* no return value */
++		: "a" (0x4f09),         /* EAX */
++		  "b" (0),              /* EBX */
++		  "c" (count),          /* ECX */
++		  "d" (start),          /* EDX */
++		  "D" (entries),        /* EDI */
++		  "S" (&pmi_pal));      /* ESI */
++	} else {
++		vesafb_create_task (tsk);
++		if (!tsk)
++			return -ENOMEM;
++		tsk->regs.eax = 0x4f09;
++		tsk->regs.ebx = 0x0;
++		tsk->regs.ecx = count;
++		tsk->regs.edx = start;
++		tsk->buf = entries;
++		tsk->buf_len = sizeof(struct vesafb_pal_entry) * count;
++		tsk->flags = TF_CALL | TF_BUF_DI;
++
++		if (!vesafb_queue_task (tsk))
++			vesafb_wait_for_task(tsk);
++		if ((tsk->regs.eax & 0xffff) != 0x004f)
++			ret = 1;
++		kfree(tsk);
++	}
++	return ret;
++}
++
++static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
++			    unsigned blue, unsigned transp,
++			    struct fb_info *info)
++{
++	struct vesafb_pal_entry entry;
++	int shift = 16 - info->var.green.length;
++	int ret = 0;
++
++	if (regno >= info->cmap.len)
++		return -EINVAL;
++
++	if (info->var.bits_per_pixel == 8) {
++		entry.red   = red   >> shift;
++		entry.green = green >> shift;
++		entry.blue  = blue  >> shift;
++		entry.pad   = 0;
++
++		ret = vesafb_setpalette(&entry, 1, regno, info);
++	} else if (regno < 16) {
++		switch (info->var.bits_per_pixel) {
++		case 16:
++			if (info->var.red.offset == 10) {
++				/* 1:5:5:5 */
++				((u32*) (info->pseudo_palette))[regno] =
++						((red   & 0xf800) >>  1) |
++						((green & 0xf800) >>  6) |
++						((blue  & 0xf800) >> 11);
++			} else {
++				/* 0:5:6:5 */
++				((u32*) (info->pseudo_palette))[regno] =
++						((red   & 0xf800)      ) |
++						((green & 0xfc00) >>  5) |
++						((blue  & 0xf800) >> 11);
++			}
++			break;
++
++		case 24:
++		case 32:
++			red   >>= 8;
++			green >>= 8;
++			blue  >>= 8;
++			((u32 *)(info->pseudo_palette))[regno] =
++				(red   << info->var.red.offset)   |
++				(green << info->var.green.offset) |
++				(blue  << info->var.blue.offset);
++			break;
++		}
++	}
++	return ret;
++}
++
++static int vesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
++{
++	struct vesafb_pal_entry *entries;
++	int shift = 16 - info->var.green.length;
++	int i, ret = 0;
++
++	if (info->var.bits_per_pixel == 8) {
++		if (cmap->start + cmap->len > info->cmap.start +
++		    info->cmap.len || cmap->start < info->cmap.start)
++			return -EINVAL;
++
++		entries = vmalloc(sizeof(struct vesafb_pal_entry) * cmap->len);
++		if (!entries)
++			return -ENOMEM;
++		for (i = 0; i < cmap->len; i++) {
++			entries[i].red   = cmap->red[i]   >> shift;
++			entries[i].green = cmap->green[i] >> shift;
++			entries[i].blue  = cmap->blue[i]  >> shift;
++			entries[i].pad   = 0;
++		}
++		ret = vesafb_setpalette(entries, cmap->len, cmap->start, info);
++		vfree(entries);
++	} else {
++		/* For modes with bpp > 8, we only set the pseudo palette in
++		 * the fb_info struct. We rely on vesafb_setcolreg to do all
++		 * sanity checking. */
++		for (i = 0; i < cmap->len; i++) {
++			ret += vesafb_setcolreg(cmap->start + i, cmap->red[i],
++						cmap->green[i], cmap->blue[i],
++						0, info);
++		}
++	}
++	return ret;
++}
++
++static int vesafb_set_par(struct fb_info *info)
++{
++	struct vesafb_par *par = (struct vesafb_par *) info->par;
++	struct vesafb_task *tsk;
++	struct vesafb_crtc_ib *crtc = NULL;
++	struct vesafb_mode_ib *mode = NULL;
++	int i, err = 0, depth = info->var.bits_per_pixel;
++
++	if (depth > 8 && depth != 32)
++		depth = info->var.red.length + info->var.green.length +
++			info->var.blue.length;
++
++	i = vesafb_find_vbe_mode(info->var.xres, info->var.yres, depth,
++				 VESAFB_NEED_EXACT_RES |
++				 VESAFB_NEED_EXACT_DEPTH);
++	if (i >= 0)
++		mode = &vbe_modes[i];
++	else
++		return -EINVAL;
++
++	vesafb_create_task (tsk);
++	if (!tsk)
++		return -ENOMEM;
++	tsk->regs.eax = 0x4f02;
++	tsk->regs.ebx = mode->mode_id | 0x4000;		/* use LFB */
++	tsk->flags = TF_CALL;
++
++	if (vbe_ib.vbe_version >= 0x0300 && !nocrtc &&
++	    info->var.pixclock != 0) {
++		tsk->regs.ebx |= 0x0800; 		/* use CRTC data */
++		tsk->flags |= TF_BUF_DI;
++		crtc = kmalloc(sizeof(struct vesafb_crtc_ib), GFP_KERNEL);
++		if (!crtc) {
++			err = -ENOMEM;
++			goto out;
++		}
++		crtc->horiz_start = info->var.xres + info->var.right_margin;
++		crtc->horiz_end	  = crtc->horiz_start + info->var.hsync_len;
++		crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
++
++		crtc->vert_start  = info->var.yres + info->var.lower_margin;
++		crtc->vert_end    = crtc->vert_start + info->var.vsync_len;
++		crtc->vert_total  = crtc->vert_end + info->var.upper_margin;
++
++		crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
++		crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
++				     (crtc->vert_total * crtc->horiz_total)));
++		crtc->flags = 0;
++
++		if (info->var.vmode & FB_VMODE_DOUBLE)
++			crtc->flags |= 0x1;
++		if (info->var.vmode & FB_VMODE_INTERLACED)
++			crtc->flags |= 0x2;
++		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
++			crtc->flags |= 0x4;
++		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
++			crtc->flags |= 0x8;
++		memcpy(&par->crtc, crtc, sizeof(struct vesafb_crtc_ib));
++	} else
++		memset(&par->crtc, 0, sizeof(struct vesafb_crtc_ib));
++
++	tsk->buf = (void*)crtc;
++	tsk->buf_len = sizeof(struct vesafb_crtc_ib);
++
++	if (vesafb_queue_task (tsk)) {
++		err = -EINVAL;
++		goto out;
++	}
++	vesafb_wait_for_task(tsk);
++
++	if ((tsk->regs.eax & 0xffff) != 0x004f) {
++		printk(KERN_ERR "vesafb: mode switch failed (eax: 0x%lx)\n",
++				tsk->regs.eax);
++		err = -EINVAL;
++		goto out;
++	}
++	par->mode_idx = i;
++
++	/* For 8bpp modes, always try to set the DAC to 8 bits. */
++	if (vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
++	    mode->bits_per_pixel <= 8) {
++		vesafb_reset_task(tsk);
++		tsk->flags = TF_CALL;
++		tsk->regs.eax = 0x4f08;
++		tsk->regs.ebx = 0x0800;
++
++		if (!vesafb_queue_task (tsk))
++			vesafb_wait_for_task(tsk);
++
++		if ((tsk->regs.eax & 0xffff) != 0x004f ||
++		    ((tsk->regs.ebx & 0xff00) >> 8) != 8) {
++			/* We've failed to set the DAC palette format -
++			 * time to correct var. */
++			info->var.red.length    = 6;
++			info->var.green.length  = 6;
++			info->var.blue.length   = 6;
++		}
++	}
++
++	info->fix.visual = (info->var.bits_per_pixel == 8) ?
++		           FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
++	info->fix.line_length = mode->bytes_per_scan_line;
++
++	DPRINTK("set new mode %dx%d-%d (0x%x)\n",
++		info->var.xres, info->var.yres, info->var.bits_per_pixel,
++		mode->mode_id);
++
++out:	if (crtc != NULL)
++		kfree(crtc);
++	kfree(tsk);
++
++	return err;
++}
++
++static void vesafb_setup_var(struct fb_var_screeninfo *var, struct fb_info *info,
++			     struct vesafb_mode_ib *mode)
++{
++	var->xres = mode->x_res;
++	var->yres = mode->y_res;
++	var->xres_virtual = mode->x_res;
++	var->yres_virtual = (ypan) ?
++			      info->fix.smem_len / mode->bytes_per_scan_line :
++			      mode->y_res;
++	var->xoffset = 0;
++	var->yoffset = 0;
++	var->bits_per_pixel = mode->bits_per_pixel;
++
++	if (var->bits_per_pixel == 15)
++		var->bits_per_pixel = 16;
++
++	if (var->bits_per_pixel > 8) {
++		var->red.offset    = mode->red_off;
++		var->red.length    = mode->red_len;
++		var->green.offset  = mode->green_off;
++		var->green.length  = mode->green_len;
++		var->blue.offset   = mode->blue_off;
++		var->blue.length   = mode->blue_len;
++		var->transp.offset = mode->rsvd_off;
++		var->transp.length = mode->rsvd_len;
++
++		DPRINTK("directcolor: size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
++			mode->rsvd_len,
++			mode->red_len,
++			mode->green_len,
++			mode->blue_len,
++			mode->rsvd_off,
++			mode->red_off,
++			mode->green_off,
++			mode->blue_off);
++	} else {
++		var->red.offset    = 0;
++		var->green.offset  = 0;
++		var->blue.offset   = 0;
++		var->transp.offset = 0;
++
++		/* We're assuming that we can switch the DAC to 8 bits. If
++		 * this proves to be incorrect, we'll update the fields
++		 * later in set_par(). */
++		if (vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
++			var->red.length    = 8;
++			var->green.length  = 8;
++			var->blue.length   = 8;
++			var->transp.length = 0;
++		} else {
++			var->red.length    = 6;
++			var->green.length  = 6;
++			var->blue.length   = 6;
++			var->transp.length = 0;
++		}
++	}
++}
++
++static void inline vesafb_check_limits(struct fb_var_screeninfo *var,
++		 		       struct fb_info *info)
++{
++	struct fb_videomode *mode;
++
++	if (!var->pixclock)
++		return;
++	if (vbe_ib.vbe_version < 0x0300) {
++		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
++		return;
++	}
++	if (!fb_validate_mode(var, info))
++		return;
++	mode = fb_find_best_mode(var, &info->modelist);
++	if (mode) {
++		DPRINTK("find_best_mode: %d %d @ %d (vmode: %d)\n",
++			mode->xres, mode->yres, mode->refresh, mode->vmode);
++		if (mode->xres == var->xres && mode->yres == var->yres &&
++		    !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
++			fb_videomode_to_var(var, mode);
++			return;
++		}
++	}
++	if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
++		return;
++	/* Use default refresh rate */
++	var->pixclock = 0;
++}
++
++static int vesafb_check_var(struct fb_var_screeninfo *var,
++			    struct fb_info *info)
++{
++	int match = -1;
++	int depth = var->red.length + var->green.length + var->blue.length;
++
++	/* Various apps will use bits_per_pixel to set the color depth,
++	 * which is theoretically incorrect, but which we'll try to handle
++	 * here. */
++	if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
++		depth = var->bits_per_pixel;
++	match = vesafb_find_vbe_mode(var->xres, var->yres, depth,
++				     VESAFB_NEED_EXACT_RES);
++
++	if (match == -1) {
++		DPRINTK("vesafb: mode %dx%d-%d not found\n", var->xres,
++			var->yres, depth);
++		return -EINVAL;
++	}
++
++	vesafb_setup_var(var, info, &vbe_modes[match]);
++	DPRINTK("found mode 0x%x (%dx%d-%dbpp)\n",
++		vbe_modes[match].mode_id, vbe_modes[match].x_res,
++		vbe_modes[match].y_res, vbe_modes[match].depth);
++
++	/* Check whether we have remapped enough memory for this mode. */
++	if (var->yres * vbe_modes[match].bytes_per_scan_line >
++	    info->fix.smem_len) {
++		return -EINVAL;
++	}
++
++	if ((var->vmode & FB_VMODE_DOUBLE) &&
++	    !(vbe_modes[match].mode_attr & 0x100))
++		var->vmode &= ~FB_VMODE_DOUBLE;
++	if ((var->vmode & FB_VMODE_INTERLACED) &&
++	    !(vbe_modes[match].mode_attr & 0x200))
++		var->vmode &= ~FB_VMODE_INTERLACED;
++	vesafb_check_limits(var, info);
++	return 0;
++}
++
++static int vesafb_open(struct fb_info *info, int user)
++{
++	struct vesafb_task *tsk = NULL;
++	struct vesafb_par *par = info->par;
++	int cnt = atomic_read(&par->ref_count);
++
++	if (!cnt) {
++		vesafb_create_task(tsk);
++		if (!tsk)
++			goto out;
++
++		/* Get the VBE state buffer size. We want all available
++		 * hardware state data (CL = 0x0f). */
++		tsk->regs.eax = 0x4f04;
++		tsk->regs.ecx = 0x000f;
++		tsk->regs.edx = 0x0000;
++		tsk->flags = TF_CALL;
++
++		if (vesafb_queue_task(tsk))
++			goto out;
++	
++		vesafb_wait_for_task(tsk);
++		
++		if ((tsk->regs.eax & 0xffff) != 0x004f) {
++			printk(KERN_WARNING "vesafb: VBE state buffer size "
++				"cannot be determined (eax: 0x%lx)\n",
++				tsk->regs.eax);
++			goto out;
++		}
++
++		par->vbe_state_size = 64 * (tsk->regs.ebx & 0xffff);
++		par->vbe_state = kzalloc(par->vbe_state_size, GFP_KERNEL);
++		if (!par->vbe_state) 
++			goto out;
++
++		vesafb_reset_task(tsk);
++		tsk->regs.eax = 0x4f04;
++		tsk->regs.ecx = 0x000f;
++		tsk->regs.edx = 0x0001;
++		tsk->flags = TF_CALL | TF_BUF_BX | TF_RETURN_BUF;
++		tsk->buf = (void*)(par->vbe_state);
++		tsk->buf_len = par->vbe_state_size;
++
++		if (vesafb_queue_task(tsk))
++			goto getstate_failed;
++		vesafb_wait_for_task(tsk);
++
++		if ((tsk->regs.eax & 0xffff) != 0x004f) {
++			printk(KERN_WARNING "vesafb: VBE get state call "
++				"failed (eax: 0x%lx)\n", tsk->regs.eax);
++			goto getstate_failed;
++		}
++	}
++out:
++	atomic_inc(&par->ref_count);
++	if (tsk)
++		kfree(tsk);
++	return 0;
++
++getstate_failed:
++	kfree(par->vbe_state);
++	par->vbe_state = NULL;
++	par->vbe_state_size = 0;
++	goto out;
++}
++
++static int vesafb_release(struct fb_info *info, int user)
++{
++	struct vesafb_task *tsk = NULL;
++	struct vesafb_par *par = info->par;
++	int cnt = atomic_read(&par->ref_count);
++
++	if (!cnt)
++		return -EINVAL;
++	
++	if (cnt == 1 && par->vbe_state && par->vbe_state_size) {
++		vesafb_create_task(tsk);
++		if (!tsk)
++			goto out;
++
++		tsk->regs.eax = 0x0003;
++		tsk->regs.ebx = 0x0000;
++		tsk->flags = TF_CALL;
++
++		if (vesafb_queue_task(tsk))
++			goto out;
++	
++		vesafb_wait_for_task(tsk);
++
++		vesafb_reset_task(tsk);
++		tsk->regs.eax = 0x4f04;
++		tsk->regs.ecx = 0x000f;
++		tsk->regs.edx = 0x0002;
++		tsk->buf = (void*)(par->vbe_state);
++		tsk->buf_len = par->vbe_state_size;
++		tsk->flags = TF_CALL | TF_BUF_BX;
++
++		if (vesafb_queue_task(tsk))
++			goto out;
++	
++		vesafb_wait_for_task(tsk);
++
++		if ((tsk->regs.eax & 0xffff) != 0x004f)
++			printk(KERN_WARNING "vesafb: VBE state restore call "
++				"failed (eax: 0x%lx)\n",
++				tsk->regs.eax);
++	}
++out:
++	atomic_dec(&par->ref_count);
++	if (tsk)
++		kfree(tsk);
++	return 0;
++}
++
++static int __init vesafb_probe(struct platform_device *device);
++
++static struct fb_ops vesafb_ops = {
++	.owner		= THIS_MODULE,
++	.fb_open	= vesafb_open,
++	.fb_release	= vesafb_release,
++	.fb_setcolreg	= vesafb_setcolreg,
++	.fb_setcmap	= vesafb_setcmap,
++	.fb_pan_display	= vesafb_pan_display,
++	.fb_blank       = vesafb_blank,
++	.fb_fillrect	= cfb_fillrect,
++	.fb_copyarea	= cfb_copyarea,
++	.fb_imageblit	= cfb_imageblit,
++	.fb_check_var	= vesafb_check_var,
++	.fb_set_par	= vesafb_set_par
++};
++
++static struct platform_driver vesafb_driver = {
++	.probe	= vesafb_probe,
++	.driver	= {
++		.name	= "vesafb",
++	},
++};
++
++static struct platform_device *vesafb_device;
++ 
++#ifndef MODULE
++int __init vesafb_setup(char *options)
++{
++	char *this_opt;
++
++	if (!options || !*options)
++		return 0;
++
++	DPRINTK("options %s\n",options);
++
++	while ((this_opt = strsep(&options, ",")) != NULL) {
++		if (!*this_opt) continue;
++
++		DPRINTK("this_opt: %s\n",this_opt);
++
++		if (! strcmp(this_opt, "redraw"))
++			ypan=0;
++		else if (! strcmp(this_opt, "ypan"))
++			ypan=1;
++		else if (! strcmp(this_opt, "ywrap"))
++			ypan=2;
++		else if (! strcmp(this_opt, "vgapal"))
++			pmi_setpal=0;
++		else if (! strcmp(this_opt, "pmipal"))
++			pmi_setpal=1;
++		else if (! strncmp(this_opt, "mtrr:", 5))
++			mtrr = simple_strtoul(this_opt+5, NULL, 0);
++		else if (! strcmp(this_opt, "nomtrr"))
++			mtrr=0;
++		else if (! strcmp(this_opt, "nocrtc"))
++			nocrtc=1;
++		else if (! strcmp(this_opt, "noedid"))
++			noedid=1;
++		else if (! strcmp(this_opt, "noblank"))
++			blank=0;
++		else if (! strcmp(this_opt, "gtf"))
++			gtf=1;
++		else if (! strncmp(this_opt, "vtotal:", 7))
++			vram_total = simple_strtoul(this_opt + 7, NULL, 0);
++		else if (! strncmp(this_opt, "vremap:", 7))
++			vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
++		else if (! strncmp(this_opt, "maxhf:", 6))
++			maxhf = simple_strtoul(this_opt + 6, NULL, 0);
++		else if (! strncmp(this_opt, "maxvf:", 6))
++			maxvf = simple_strtoul(this_opt + 6, NULL, 0);
++		else if (! strncmp(this_opt, "maxclk:", 7))
++			maxclk = simple_strtoul(this_opt + 7, NULL, 0);
++		else if (! strncmp(this_opt, "vbemode:", 8))
++			vbemode = simple_strtoul(this_opt + 8, NULL,0);
++		else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
++			DPRINTK("mode_option: %s\n",this_opt);
++			mode_option = this_opt;
++		} else {
++			printk(KERN_WARNING
++			       "vesafb: unrecognized option %s\n", this_opt);
++		}
++	}
++
++	return 0;
++}
++#endif /* !MODULE */
++
++static int vesafb_read_proc_modes(char *buf, char **start, off_t offset,
++			    	  int len, int *eof, void *private)
++{
++	int clen = 0, i;
++
++	for (i = 0; i < vbe_modes_cnt; i++) {
++		clen += sprintf(buf + clen, "%dx%d-%d\n", vbe_modes[i].x_res,
++				vbe_modes[i].y_res, vbe_modes[i].depth);
++	}
++	*start = buf + offset;
++
++	if (clen > offset) {
++		clen -= offset;
++	} else {
++		clen = 0;
++	}
++	return clen;
++}
++
++static int vesafb_read_proc_vbe_info(char *buf, char **start, off_t offset,
++			    	     int len, int *eof, void *private)
++{
++	int clen = 0;
++
++	clen += sprintf(buf + clen, "Version:    %d.%d\n",
++			((vbe_ib.vbe_version & 0xff00) >> 8),
++			vbe_ib.vbe_version & 0xff);
++	clen += sprintf(buf + clen, "Vendor:     %s\n",
++			(char*)vbe_ib.oem_vendor_name_ptr);
++	clen += sprintf(buf + clen, "Product:    %s\n",
++			(char*)vbe_ib.oem_product_name_ptr);
++	clen += sprintf(buf + clen, "OEM rev:    %s\n",
++			(char*)vbe_ib.oem_product_rev_ptr);
++	clen += sprintf(buf + clen, "OEM string: %s\n",
++			(char*)vbe_ib.oem_string_ptr);
++
++	*start = buf + offset;
++
++	if (clen > offset) {
++		clen -= offset;
++	} else {
++		clen = 0;
++	}
++	return clen;
++}
++
++static int __init inline vesafb_vbe_getinfo(struct vesafb_task *tsk)
++{
++	tsk->regs.eax = 0x4f00;
++	tsk->flags = TF_CALL | TF_GETVBEIB;
++	tsk->buf = &vbe_ib;
++	tsk->buf_len = sizeof(vbe_ib);
++	if (vesafb_queue_task (tsk))
++		return -EINVAL;
++	vesafb_wait_for_task(tsk);
++
++	if (vbe_ib.vbe_version < 0x0200) {
++		printk(KERN_ERR "vesafb: Sorry, pre-VBE 2.0 cards are "
++				"not supported.\n");
++		return -EINVAL;
++	}
++
++	if ((tsk->regs.eax & 0xffff) != 0x004f) {
++		printk(KERN_ERR "vesafb: Getting mode info block failed "
++				"(eax=0x%x)\n", (u32)tsk->regs.eax);
++		return -EINVAL;
++	}
++
++	printk(KERN_INFO "vesafb: %s, %s, %s (OEM: %s)\n",
++		(char*)vbe_ib.oem_vendor_name_ptr,
++		(char*)vbe_ib.oem_product_name_ptr,
++		(char*)vbe_ib.oem_product_rev_ptr,
++		(char*)vbe_ib.oem_string_ptr);
++
++	printk(KERN_INFO "vesafb: VBE version: %d.%d\n",
++			 ((vbe_ib.vbe_version & 0xff00) >> 8),
++			 vbe_ib.vbe_version & 0xff);
++	return 0;
++}
++
++static int __init inline vesafb_vbe_getmodes(struct vesafb_task *tsk)
++{
++	u16 *mode = 0;
++	int off = 0;
++
++	/* Count available modes. */
++	mode = (u16*)vbe_ib.mode_list_ptr;
++	while (*mode != 0xffff) {
++		vbe_modes_cnt++;
++		mode++;
++	}
++
++	vbe_modes = kmalloc(sizeof(struct vesafb_mode_ib)*
++			    vbe_modes_cnt, GFP_KERNEL);
++	if (!vbe_modes)
++		return -ENOMEM;
++
++	/* Get mode info for all available modes. */
++	mode = (u16*)vbe_ib.mode_list_ptr;
++
++	while (*mode != 0xffff) {
++		struct vesafb_mode_ib *mib;
++
++		vesafb_reset_task(tsk);
++		tsk->regs.eax = 0x4f01;
++		tsk->regs.ecx = (u32) *mode;
++		tsk->flags = TF_CALL | TF_RETURN_BUF | TF_BUF_DI;
++		tsk->buf = vbe_modes+off;
++		tsk->buf_len = sizeof(struct vesafb_mode_ib);
++		if (vesafb_queue_task(tsk))
++			return -EINVAL;
++		vesafb_wait_for_task(tsk);
++		mib = p_mode(tsk->buf);
++		mib->mode_id = *mode;
++
++		/* We only want modes that are supported with the currennt
++		 * hardware configuration (D0), color (D3), graphics (D4)
++		 * and that have support for the LFB (D7). */
++		if ((mib->mode_attr & 0x99) == 0x99 &&
++		    mib->bits_per_pixel >= 8) {
++			off++;
++		} else {
++			vbe_modes_cnt--;
++		}
++		mode++;
++		mib->depth = mib->red_len + mib->green_len + mib->blue_len;
++		/* Handle 8bpp modes and modes with broken color component
++		 * lengths. */
++		if (mib->depth == 0 ||
++		    (mib->depth == 24 && mib->bits_per_pixel == 32))
++			mib->depth = mib->bits_per_pixel;
++	}
++
++	return 0;
++}
++
++static int __init inline vesafb_vbe_getpmi(struct vesafb_task *tsk)
++{
++	int i;
++
++	vesafb_reset_task(tsk);
++	tsk->regs.eax = 0x4f0a;
++	tsk->regs.ebx = 0x0;
++	tsk->flags = TF_CALL;
++	if (vesafb_queue_task(tsk))
++		return -EINVAL;
++	vesafb_wait_for_task(tsk);
++
++	if ((tsk->regs.eax & 0xffff) != 0x004f || tsk->regs.es < 0xc000) {
++		pmi_setpal = ypan = 0;
++	} else {
++		pmi_base  = (u16*)phys_to_virt(((u32)tsk->regs.es << 4) +
++			     tsk->regs.edi);
++		pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
++		pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
++		printk(KERN_INFO "vesafb: protected mode interface info at "
++				 "%04x:%04x\n",
++				 (u16)tsk->regs.es, (u16)tsk->regs.edi);
++		printk(KERN_INFO "vesafb: pmi: set display start = %p, "
++				 "set palette = %p\n", pmi_start, pmi_pal);
++
++		if (pmi_base[3]) {
++			printk(KERN_INFO "vesafb: pmi: ports = ");
++			for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
++				printk("%x ",pmi_base[i]);
++			printk("\n");
++
++			/*
++			 * memory areas not supported (yet?)
++			 *
++			 * Rules are: we have to set up a descriptor for the
++			 * requested memory area and pass it in the ES register
++			 * to the BIOS function.
++			 */
++			if (pmi_base[i] != 0xffff) {
++				printk(KERN_INFO "vesafb: can't handle memory "
++						 "requests, pmi disabled\n");
++				ypan = pmi_setpal = 0;
++			}
++		}
++	}
++	return 0;
++}
++
++static int __init inline vesafb_vbe_getedid(struct vesafb_task *tsk,
++					    struct fb_info *info)
++{
++	int res = 0;
++
++	if (noedid || vbe_ib.vbe_version < 0x0300)
++		return -EINVAL;
++
++	vesafb_reset_task(tsk);
++	tsk->regs.eax = 0x4f15;
++	tsk->regs.ebx = 0;
++	tsk->regs.ecx = 0;
++	if (vesafb_queue_task(tsk))
++		return -EINVAL;
++	vesafb_wait_for_task(tsk);
++
++	if ((tsk->regs.eax & 0xffff) != 0x004f)
++		return -EINVAL;
++
++	if ((tsk->regs.ebx & 0x3) == 3) {
++		printk(KERN_INFO "vesafb: VBIOS/hardware supports both "
++				 "DDC1 and DDC2 transfers\n");
++	} else if ((tsk->regs.ebx & 0x3) == 2) {
++		printk(KERN_INFO "vesafb: VBIOS/hardware supports DDC2 "
++				 "transfers\n");
++	} else if ((tsk->regs.ebx & 0x3) == 1) {
++		printk(KERN_INFO "vesafb: VBIOS/hardware supports DDC1 "
++				 "transfers\n");
++	} else {
++		printk(KERN_INFO "vesafb: VBIOS/hardware doesn't support "
++				 "DDC transfers\n");
++		return -EINVAL;
++	}
++
++	vesafb_reset_task(tsk);
++	tsk->regs.eax = 0x4f15;
++	tsk->regs.ebx = 1;
++	tsk->regs.ecx = tsk->regs.edx = 0;
++	tsk->flags = TF_CALL | TF_RETURN_BUF | TF_BUF_DI;
++	tsk->buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
++	tsk->buf_len = EDID_LENGTH;
++
++	if (vesafb_queue_task(tsk)) {
++		res = -EINVAL;
++		goto out;
++	}
++	vesafb_wait_for_task(tsk);
++
++	if ((tsk->regs.eax & 0xffff) == 0x004f) {
++		fb_edid_to_monspecs(tsk->buf, &info->monspecs);
++		fb_videomode_to_modelist(info->monspecs.modedb,
++				info->monspecs.modedb_len, &info->modelist);
++		if (info->monspecs.vfmax && info->monspecs.hfmax) {
++			/* If the maximum pixel clock wasn't specified in
++			 * the EDID block, set it to 300 MHz. */
++			if (info->monspecs.dclkmax == 0)
++				info->monspecs.dclkmax = 300 * 1000000;
++			info->monspecs.gtf = 1;
++		} else {
++			res = -EINVAL;
++		}
++	}
++
++out:	kfree(tsk->buf);
++	return res;
++}
++
++static void __init inline vesafb_vbe_getmonspecs(struct vesafb_task *tsk,
++		                                 struct fb_info *info)
++{
++	struct fb_var_screeninfo var;
++	int i;
++	memset(&info->monspecs, 0, sizeof(struct fb_monspecs));
++
++	/* If we didn't get all necessary data from the EDID block,
++	 * mark it as incompatible with the GTF. */
++	if (vesafb_vbe_getedid(tsk, info))
++		info->monspecs.gtf = 0;
++
++	/* Kernel command line overrides. */
++	if (maxclk)
++		info->monspecs.dclkmax = maxclk * 1000000;
++	if (maxvf)
++		info->monspecs.vfmax = maxvf;
++	if (maxhf)
++		info->monspecs.hfmax = maxhf * 1000;
++
++	/* In case DDC transfers are not supported the user can provide
++	 * monitor limits manually. Lower limits are set to "safe" values. */
++	if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
++		info->monspecs.dclkmin = 0;
++		info->monspecs.vfmin = 60;
++		info->monspecs.hfmin = 29000;
++		info->monspecs.gtf = 1;
++	}
++
++	if (info->monspecs.gtf) {
++		printk(KERN_INFO
++		       	"vesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
++			"clk = %d MHz\n", info->monspecs.vfmax,
++			(int)(info->monspecs.hfmax / 1000),
++			(int)(info->monspecs.dclkmax / 1000000));
++		/* Add valid VESA video modes to our modelist. */
++		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
++			fb_videomode_to_var(&var, (struct fb_videomode *)
++					    &vesa_modes[i]);
++			if (!fb_validate_mode(&var, info))
++				fb_add_videomode((struct fb_videomode *)
++						 &vesa_modes[i],
++						 &info->modelist);
++		}
++	} else {
++		/* Add all VESA video modes to our modelist. */
++		fb_videomode_to_modelist((struct fb_videomode *)vesa_modes,
++				 	 VESA_MODEDB_SIZE, &info->modelist);
++		printk(KERN_INFO "vesafb: no monitor limits have been set\n");
++	}
++	return;
++}
++
++static int __init inline vesafb_vbe_init(struct fb_info *info)
++{
++	struct vesafb_task *tsk;
++	int res = 0;
++
++	vesafb_create_task(tsk);
++	if (!tsk)
++		return -EINVAL;
++	if ((res = vesafb_vbe_getinfo(tsk)) != 0)
++		goto out;
++	if ((res = vesafb_vbe_getmodes(tsk)) != 0)
++		goto out;
++	if (pmi_setpal || ypan)
++		vesafb_vbe_getpmi(tsk);
++
++	INIT_LIST_HEAD(&info->modelist);
++	vesafb_vbe_getmonspecs(tsk, info);
++
++out:	kfree(tsk);
++	return res;
++}
++
++static int __init decode_mode(u32 *xres, u32 *yres, u32 *bpp, u32 *refresh)
++{
++	int len = strlen(mode_option), i, err = 0;
++	u8 res_specified = 0, bpp_specified = 0, refresh_specified = 0,
++	   yres_specified = 0;
++
++	for (i = len-1; i >= 0; i--) {
++ 		switch (mode_option[i]) {
++		case '@':
++    			len = i;
++    			if (!refresh_specified && !bpp_specified &&
++			    !yres_specified) {
++				*refresh = simple_strtoul(&mode_option[i+1],
++							  NULL, 0);
++				refresh_specified = 1;
++			} else
++				goto out;
++		    	break;
++		case '-':
++			len = i;
++		    	if (!bpp_specified && !yres_specified) {
++			    	*bpp = simple_strtoul(&mode_option[i+1],
++						      NULL, 0);
++				bpp_specified = 1;
++		    	} else
++				goto out;
++		    	break;
++		case 'x':
++			if (!yres_specified) {
++				*yres = simple_strtoul(&mode_option[i+1],
++						       NULL, 0);
++				yres_specified = 1;
++		    	} else
++				goto out;
++		    	break;
++		case '0'...'9':
++			break;
++		default:
++			goto out;
++	    	}
++	}
++
++	if (i < 0 && yres_specified) {
++		*xres = simple_strtoul(mode_option, NULL, 0);
++	   	res_specified = 1;
++	}
++
++out:	if (!res_specified || !yres_specified) {
++		printk(KERN_ERR "vesafb: invalid resolution, "
++				"%s not specified\n",
++				(!res_specified) ? "width" : "height");
++		err = -EINVAL;
++	}
++
++	return err;
++}
++
++static int __init vesafb_init_set_mode(struct fb_info *info)
++{
++	struct fb_videomode *fbmode;
++	struct fb_videomode mode;
++	int i, modeid, refresh = 0;
++	u8 refresh_specified = 0;
++
++	if (!mode_option)
++		mode_option = CONFIG_FB_VESA_DEFAULT_MODE;
++
++	if (vbemode > 0) {
++		for (i = 0; i < vbe_modes_cnt; i++) {
++			if (vbe_modes[i].mode_id == vbemode) {
++				info->var.vmode = FB_VMODE_NONINTERLACED;
++				info->var.sync = FB_SYNC_VERT_HIGH_ACT;
++				vesafb_setup_var(&info->var, info,
++						 &vbe_modes[i]);
++				fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
++					    60, &info->var, info);
++				/* With pixclock set to 0, the default BIOS
++				 * timings will be used in set_par(). */
++				info->var.pixclock = 0;
++				modeid = i;
++				goto out;
++			}
++		}
++		printk(KERN_INFO "specified VBE mode %d not found\n",
++				 vbemode);
++		vbemode = 0;
++	}
++
++	/* Decode the mode specified on the kernel command line. We save
++	 * the depth into bits_per_pixel, which is wrong, but will work
++	 * anyway. */
++	if (decode_mode(&info->var.xres, &info->var.yres,
++			&info->var.bits_per_pixel, &refresh))
++		return -EINVAL;
++	if (refresh)
++		refresh_specified = 1;
++	else
++		refresh = 60;
++
++	/* Look for a matching VBE mode. We can live if an exact match
++	 * cannot be found. */
++	modeid = vesafb_find_vbe_mode(info->var.xres, info->var.yres,
++			              info->var.bits_per_pixel, 0);
++
++	if (modeid == -1) {
++		return -EINVAL;
++	} else {
++		info->var.vmode = FB_VMODE_NONINTERLACED;
++		info->var.sync = FB_SYNC_VERT_HIGH_ACT;
++		vesafb_setup_var(&info->var, info, &vbe_modes[modeid]);
++	}
++	if (vbe_ib.vbe_version < 0x0300) {
++		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
++			    &info->var, info);
++		goto out;
++	}
++	if (!gtf) {
++		struct fb_videomode tmode;
++
++		if (refresh_specified) {
++			fb_var_to_videomode(&tmode, &info->var);
++			tmode.refresh = refresh;
++			fbmode = fb_find_nearest_mode(&tmode, 
++						      &info->modelist);
++		} else
++			fbmode = fb_find_best_mode(&info->var, 
++						   &info->modelist);
++
++		if (fbmode->xres == info->var.xres &&
++		    fbmode->yres == info->var.yres &&
++		    !(fbmode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))
++		    && (!refresh_specified || 
++		    abs(refresh - fbmode->refresh) <= 5)) {
++			fb_videomode_to_var(&info->var, fbmode);
++			return modeid;
++		}
++	}
++	i = FB_MAXTIMINGS;
++	if (!info->monspecs.gtf)
++		i = FB_IGNOREMON | FB_VSYNCTIMINGS;
++	else if (refresh_specified)
++		i = FB_VSYNCTIMINGS;
++	if (!fb_get_mode(i, refresh, &info->var, info))
++		goto out;
++	if (info->monspecs.gtf &&
++	    !fb_get_mode(FB_MAXTIMINGS, 0, &info->var, info))
++		goto out;
++	/* Use default refresh rate */
++	printk(KERN_WARNING "vesafb: using default BIOS refresh rate\n");
++	info->var.pixclock = 0;
++
++out:
++	fb_var_to_videomode(&mode, &info->var);
++	fb_add_videomode(&mode, &info->modelist);
++	return modeid;
++}
++
++static int __init vesafb_probe(struct platform_device *dev)
++{
++	char entry[16];
++	struct fb_info *info;
++	struct vesafb_mode_ib *mode = NULL;
++	int err = 0, i, h;
++	unsigned int size_vmode;
++	unsigned int size_remap;
++	unsigned int size_total;
++
++	vesafb_info = info = framebuffer_alloc(sizeof(struct vesafb_par) +
++			                       sizeof(u32) * 256, &dev->dev);
++	if (!info)
++	 	return -ENOMEM;
++
++	if (vesafb_wait_for_thread()) {
++		printk(KERN_ERR "vesafb: vesafb thread not running\n");
++		framebuffer_release(info);
++		return -EINVAL;
++	}
++
++	if (vesafb_vbe_init(info)) {
++		printk(KERN_ERR "vesafb: vbe_init failed\n");
++		err = -EINVAL;
++		goto out;
++	}
++
++	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
++	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
++
++	info->pseudo_palette = ((u8*)info->par + sizeof(struct vesafb_par));
++	info->fbops = &vesafb_ops;
++	info->var = vesafb_defined;
++	info->fix = vesafb_fix;
++
++	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
++		err = -ENXIO;
++		goto out;
++	}
++
++	i = vesafb_init_set_mode(info);
++	if (i < 0) {
++		err = -EINVAL;
++		goto out_cmap;
++	} else
++		mode = &vbe_modes[i];
++
++	/* Disable blanking if the user requested so. */
++	if (!blank) {
++		info->fbops->fb_blank = NULL;
++	}
++
++	/* Find out how much IO memory is required for the mode with
++	 * the highest resolution. */
++	size_remap = 0;
++	for (i = 0; i < vbe_modes_cnt; i++) {
++		h = vbe_modes[i].bytes_per_scan_line * vbe_modes[i].y_res;
++		if (h > size_remap)
++			size_remap = h;
++	}
++	size_remap *= 2;
++
++	/*   size_vmode -- that is the amount of memory needed for the
++	 *                 used video mode, i.e. the minimum amount of
++	 *                 memory we need. */
++	if (mode != NULL) {
++		size_vmode = info->var.yres * mode->bytes_per_scan_line;
++	} else {
++		size_vmode = info->var.yres * info->var.xres *
++			     ((info->var.bits_per_pixel + 7) >> 3);
++	}
++
++	/*   size_total -- all video memory we have. Used for mtrr
++	 *                 entries, ressource allocation and bounds
++	 *                 checking. */
++	size_total = vbe_ib.total_memory * 65536;
++	if (vram_total)
++		size_total = vram_total * 1024 * 1024;
++	if (size_total < size_vmode)
++		size_total = size_vmode;
++	((struct vesafb_par*)(info->par))->mem_total = size_total;
++
++	/*   size_remap -- the amount of video memory we are going to
++	 *                 use for vesafb.  With modern cards it is no
++	 *                 option to simply use size_total as th
++	 *                 wastes plenty of kernel address space. */
++	if (vram_remap)
++		size_remap = vram_remap * 1024 * 1024;
++	if (size_remap < size_vmode)
++		size_remap = size_vmode;
++	if (size_remap > size_total)
++		size_remap = size_total;
++
++	info->fix.smem_len = size_remap;
++	info->fix.smem_start = mode->phys_base_ptr;
++
++	/* We have to set it here, because when setup_var() was called,
++	 * smem_len wasn't defined yet. */
++	info->var.yres_virtual = info->fix.smem_len /
++				 mode->bytes_per_scan_line;
++
++	if (ypan && info->var.yres_virtual > info->var.yres) {
++		printk(KERN_INFO "vesafb: scrolling: %s "
++		       "using protected mode interface, "
++		       "yres_virtual=%d\n",
++		       (ypan > 1) ? "ywrap" : "ypan",info->var.yres_virtual);
++	} else {
++		printk(KERN_INFO "vesafb: scrolling: redraw\n");
++		info->var.yres_virtual = info->var.yres;
++		ypan = 0;
++	}
++
++	info->flags = FBINFO_FLAG_DEFAULT |
++		(ypan) ? FBINFO_HWACCEL_YPAN : 0;
++
++	if (!ypan)
++		info->fbops->fb_pan_display = NULL;
++
++	if (!request_mem_region(info->fix.smem_start, size_total, "vesafb")) {
++		printk(KERN_WARNING "vesafb: cannot reserve video memory at "
++		       "0x%lx\n", info->fix.smem_start);
++		/* We cannot make this fatal. Sometimes this comes from magic
++		   spaces our resource handlers simply don't know about. */
++	}
++
++	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
++
++	if (!info->screen_base) {
++		printk(KERN_ERR
++		       "vesafb: abort, cannot ioremap video memory "
++		       "0x%x @ 0x%lx\n",
++		       info->fix.smem_len, info->fix.smem_start);
++		err = -EIO;
++		goto out_mem;
++ 	}
++
++	/* Request failure does not faze us, as vgacon probably has this
++	   region already (FIXME) */
++	request_region(0x3c0, 32, "vesafb");
++
++#ifdef CONFIG_MTRR
++	if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
++		int temp_size = size_total;
++		unsigned int type = 0;
++
++		switch (mtrr) {
++		case 1:
++			type = MTRR_TYPE_UNCACHABLE;
++			break;
++		case 2:
++			type = MTRR_TYPE_WRBACK;
++			break;
++		case 3:
++			type = MTRR_TYPE_WRCOMB;
++			break;
++		case 4:
++			type = MTRR_TYPE_WRTHROUGH;
++			break;
++		default:
++			type = 0;
++			break;
++		}
++
++		if (type) {
++			int rc;
++
++			/* Find the largest power-of-two */
++			while (temp_size & (temp_size - 1))
++				temp_size &= (temp_size - 1);
++
++			/* Try and find a power of two to add */
++			do {
++				rc = mtrr_add(info->fix.smem_start,
++					      temp_size, type, 1);
++				temp_size >>= 1;
++			} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
++  		}
++  	}
++#endif /* CONFIG_MTRR */
++
++	if (register_framebuffer(info) < 0) {
++		printk(KERN_ERR
++		       "vesafb: failed to register framebuffer device\n");
++		err = -EINVAL;
++		goto out_mem;
++	}
++
++  	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
++	       "using %dk, total %dk\n", info->fix.smem_start,
++	       info->screen_base, size_remap/1024, size_total/1024);
++	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
++	       info->fix.id);
++
++	sprintf(entry, "fb%d", info->node);
++	proc_mkdir(entry, 0);
++
++	sprintf(entry, "fb%d/modes", info->node);
++	create_proc_read_entry(entry, 0, 0, vesafb_read_proc_modes, NULL);
++
++	sprintf(entry, "fb%d/vbe_info", info->node);
++	create_proc_read_entry(entry, 0, 0, vesafb_read_proc_vbe_info, NULL);
++	return 0;
++
++out_mem:
++	release_mem_region(info->fix.smem_start, size_total);
++	if (!list_empty(&info->modelist))
++		fb_destroy_modelist(&info->modelist);
++	fb_destroy_modedb(info->monspecs.modedb);
++out_cmap:
++	fb_dealloc_cmap(&info->cmap);
++out:
++	framebuffer_release(info);
++	vesafb_info = NULL;
++	kfree(vbe_modes);
++	vbe_modes = NULL;
++	return err;
++}
++
++int __init vesafb_init(void)
++{
++	int ret;
++#ifndef MODULE
++	char *option = NULL;
++
++	if (fb_get_options("vesafb", &option))
++		return -ENODEV;
++	vesafb_setup(option);
++#endif
++	ret = platform_driver_register(&vesafb_driver);
++
++	if (!ret) {
++		vesafb_device = platform_device_alloc("vesafb", 0);
++
++		if (vesafb_device)
++			ret = platform_device_add(vesafb_device);
++		else
++			ret = -ENOMEM;
++
++		if (ret) {
++			platform_device_put(vesafb_device);
++			platform_driver_unregister(&vesafb_driver);
++		}
++	}
++	return ret;
++}
++
++module_init(vesafb_init);
++
++#ifdef MODULE
++void __exit vesafb_exit(void)
++{
++	char entry[16];
++
++	if (vesafb_info)
++		unregister_framebuffer(vesafb_info);
++
++	platform_device_unregister(vesafb_device);
++	platform_driver_unregister(&vesafb_driver);
++
++	if (vesafb_info) {
++		struct vesafb_par *par = (struct vesafb_par*)vesafb_info->par;
++
++		sprintf(entry, "fb%d/modes", vesafb_info->node);
++		remove_proc_entry(entry, NULL);
++
++		sprintf(entry, "fb%d/vbe_info", vesafb_info->node);
++		remove_proc_entry(entry, NULL);
++
++		sprintf(entry, "fb%d", vesafb_info->node);
++		remove_proc_entry(entry, NULL);
++
++		iounmap(vesafb_info->screen_base);
++		release_mem_region(vesafb_info->fix.smem_start,
++				   par->mem_total);
++		fb_dealloc_cmap(&vesafb_info->cmap);
++		if (!list_empty(&vesafb_info->modelist))
++			fb_destroy_modelist(&vesafb_info->modelist);
++		fb_destroy_modedb(vesafb_info->monspecs.modedb);
++		framebuffer_release(vesafb_info);
++	}
++
++	if (vbe_modes != NULL)
++		kfree(vbe_modes);
++}
++
++module_exit(vesafb_exit);
++
++static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
++{
++	return 0;
++}
++static inline int param_set_scroll(const char *val, struct kernel_param *kp)
++{
++	ypan = 0;
++
++	if (! strcmp(val, "redraw"))
++		ypan = 0;
++	else if (! strcmp(val, "ypan"))
++		ypan = 1;
++	else if (! strcmp(val, "ywrap"))
++		ypan = 2;
++
++	return 0;
++}
++
++#define param_check_scroll(name, p) __param_check(name, p, void);
++
++module_param_named(scroll, ypan, scroll, 0);
++MODULE_PARM_DESC(scroll,"Scrolling mode, set to 'redraw', 'ypan' or 'ywrap'");
++module_param_named(vgapal, pmi_setpal, invbool, 0);
++MODULE_PARM_DESC(vgapal,"bool: set palette using VGA registers");
++module_param_named(pmipal, pmi_setpal, bool, 0);
++MODULE_PARM_DESC(pmipal,"bool: set palette using PMI calls");
++module_param_named(nomtrr, mtrr, invbool, 0);
++MODULE_PARM_DESC(nomtrr,"bool: disable use of MTRR registers");
++module_param(blank, bool, 1);
++MODULE_PARM_DESC(blank,"bool: enable hardware blanking");
++module_param(nocrtc, bool, 0);
++MODULE_PARM_DESC(nocrtc,"bool: ignore CRTC timings when setting modes");
++module_param(noedid, bool, 0);
++MODULE_PARM_DESC(noedid,"bool: ignore EDID-provided monitor limits "
++		        "when setting modes");
++module_param(gtf, bool, 0);
++MODULE_PARM_DESC(gtf,"bool: force use of VESA GTF to calculate mode timings");
++module_param(vram_remap, uint, 0);
++MODULE_PARM_DESC(vram_remap,"Set amount of video memory to be used [MiB]");
++module_param(vram_total, uint, 0);
++MODULE_PARM_DESC(vram_total,"Set total amount of video memoery [MiB]");
++module_param(maxclk, ushort, 0);
++MODULE_PARM_DESC(maxclk,"Maximum pixelclock [MHz], overrides EDID data");
++module_param(maxhf, ushort, 0);
++MODULE_PARM_DESC(maxhf,"Maximum horizontal frequency [kHz], "
++		       "overrides EDID data");
++module_param(maxvf, ushort, 0);
++MODULE_PARM_DESC(maxvf,"Maximum vertical frequency [Hz], "
++		       "overrides EDID data");
++module_param_named(mode, mode_option, charp, 0);
++MODULE_PARM_DESC(mode, "Specify resolution as "
++		       "\"<xres>x<yres>[-<bpp>][@<refresh>]\"");
++module_param(vbemode, ushort, 0);
++MODULE_PARM_DESC(vbemode,"VBE mode number to set, overrides 'mode' setting");
++
++#endif /* MODULE */
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michal Januszewski");
++MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
++
+--- linux-2.6.17.orig/include/linux/sched.h
++++ linux-2.6.17/include/linux/sched.h
+@@ -1159,6 +1159,8 @@ extern void mmput(struct mm_struct *);
+ extern struct mm_struct *get_task_mm(struct task_struct *task);
+ /* Remove the current tasks stale references to the old mm_struct */
+ extern void mm_release(struct task_struct *, struct mm_struct *);
++/* Create a new mm for a kernel thread */
++extern int set_new_mm(void);
+ 
+ extern int  copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
+ extern void flush_thread(void);
+--- /dev/null
++++ linux-2.6.17/include/video/vesa.h
+@@ -0,0 +1,150 @@
++#if 0
++#define DPRINTK(fmt, args...)	printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , \
++						  ## args)
++#else
++#define DPRINTK(fmt, args...)
++#endif
++
++#define p_crtc(arg) ((struct vesafb_crtc_ib*)(arg))
++#define p_vbe(arg)  ((struct vesafb_vbe_ib*)(arg))
++#define p_mode(arg) ((struct vesafb_mode_ib*)(arg))
++
++struct vesafb_task {
++	u8 flags;
++	void *buf;
++	int buf_len;
++	struct vm86_regs regs;
++	struct list_head node;
++	struct completion done;
++};
++
++/* Vesafb task flags and masks */
++#define TF_CALL		0x00
++#define TF_EXIT		0x01
++#define TF_GETVBEIB	0x02
++#define TF_BUF_DI	0x04
++#define TF_BUF_BX	0x08
++#define TF_RETURN_BUF	0x10
++
++/* Macros and functions for manipulating vesafb tasks */
++#define vesafb_create_task(task)				\
++do { 								\
++	task = kmalloc(sizeof(struct vesafb_task), GFP_ATOMIC); \
++	if (task) 						\
++		memset(task, 0, sizeof(struct vesafb_task));	\
++	init_completion(&task->done);				\
++} while (0)
++
++#define vesafb_wait_for_task(task) 	wait_for_completion(&task->done);
++#define vesafb_reset_task(task)		init_completion(&task->done);
++int vesafb_queue_task(struct vesafb_task *task);
++
++/* Functions for controlling the vesafb thread */
++int vesafb_wait_for_thread(void);
++
++#define VBE_CAP_CAN_SWITCH_DAC	0x01
++#define VBE_CAP_VGACOMPAT	0x02
++
++/* This struct is 512 bytes long */
++struct vesafb_vbe_ib {
++	char vbe_signature[4];
++	u16  vbe_version;
++	u32  oem_string_ptr;
++	u32  capabilities;
++	u32  mode_list_ptr;
++	u16  total_memory;
++	u16  oem_software_rev;
++	u32  oem_vendor_name_ptr;
++	u32  oem_product_name_ptr;
++	u32  oem_product_rev_ptr;
++	u8   reserved[222];
++	char oem_data[256];
++} __attribute__ ((packed));
++
++struct vesafb_crtc_ib {
++	u16 horiz_total;
++	u16 horiz_start;
++	u16 horiz_end;
++	u16 vert_total;
++	u16 vert_start;
++	u16 vert_end;
++	u8  flags;
++	u32 pixel_clock;
++	u16 refresh_rate;
++	u8  reserved[40];
++} __attribute__ ((packed));
++
++#define VBE_MODE_VGACOMPAT	0x20
++
++struct vesafb_mode_ib {
++	/* for all VBE revisions */
++	u16 mode_attr;
++	u8  winA_attr;
++	u8  winB_attr;
++	u16 win_granularity;
++	u16 win_size;
++	u16 winA_seg;
++	u16 winB_seg;
++	u32 win_func_ptr;
++	u16 bytes_per_scan_line;
++
++	/* for VBE 1.2+ */
++	u16 x_res;
++	u16 y_res;
++	u8  x_char_size;
++	u8  y_char_size;
++	u8  planes;
++	u8  bits_per_pixel;
++	u8  banks;
++	u8  memory_model;
++	u8  bank_size;
++	u8  image_pages;
++	u8  reserved1;
++
++	/* Direct color fields for direct/6 and YUV/7 memory models. */
++	/* Offsets are bit positions of lsb in the mask. */
++	u8  red_len;
++	u8  red_off;
++	u8  green_len;
++	u8  green_off;
++	u8  blue_len;
++	u8  blue_off;
++	u8  rsvd_len;
++	u8  rsvd_off;
++	u8  direct_color_info;	/* direct color mode attributes */
++
++	/* for VBE 2.0+ */
++	u32 phys_base_ptr;
++	u8  reserved2[6];
++
++	/* for VBE 3.0+ */
++	u16 lin_bytes_per_scan_line;
++	u8  bnk_image_pages;
++	u8  lin_image_pages;
++	u8  lin_red_len;
++	u8  lin_red_off;
++	u8  lin_green_len;
++	u8  lin_green_off;
++	u8  lin_blue_len;
++	u8  lin_blue_off;
++	u8  lin_rsvd_len;
++	u8  lin_rsvd_off;
++	u32 max_pixel_clock;
++	u16 mode_id;
++	u8  depth;
++} __attribute__ ((packed));
++
++struct vesafb_pal_entry {
++	u_char blue, green, red, pad;
++} __attribute__ ((packed));
++
++struct vesafb_par {
++	u8 *vbe_state;
++	int vbe_state_size;
++	atomic_t ref_count;
++	
++	u32 mem_total;
++	int mode_idx;
++	struct vesafb_crtc_ib crtc;
++};
++
+--- linux-2.6.17.orig/kernel/fork.c
++++ linux-2.6.17/kernel/fork.c
+@@ -97,6 +97,7 @@ kmem_cache_t *fs_cachep;
+ 
+ /* SLAB cache for vm_area_struct structures */
+ kmem_cache_t *vm_area_cachep;
++EXPORT_SYMBOL_GPL(vm_area_cachep);
+ 
+ /* SLAB cache for mm_struct structures (tsk->mm) */
+ static kmem_cache_t *mm_cachep;
+@@ -383,6 +384,40 @@ void mmput(struct mm_struct *mm)
+ EXPORT_SYMBOL_GPL(mmput);
+ 
+ /**
++ * set_new_mm - allocate, init and activate a new mm for a kernel thread
++ */
++int set_new_mm(void)
++{
++	struct mm_struct *mm;
++	struct task_struct *tsk = current;
++	struct mm_struct *active_mm;
++
++	mm = mm_alloc();
++	if (!mm)
++		goto fail_nomem;
++	if (init_new_context(current,mm))
++		goto fail_nocontext;
++
++	task_lock(tsk);
++	tsk->flags |= PF_BORROWED_MM;	
++	active_mm = tsk->active_mm;
++	current->mm = mm;
++	current->active_mm = mm;
++	activate_mm(active_mm, mm);
++	task_unlock(current);
++
++	/* Drop the previous active_mm */
++	mmdrop(active_mm);
++	return 0;
++	
++fail_nocontext:
++	mmdrop(mm);
++fail_nomem:
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(set_new_mm);
++
++/**
+  * get_task_mm - acquire a reference to the task's mm
+  *
+  * Returns %NULL if the task has no mm.  Checks PF_BORROWED_MM (meaning
+--- linux-2.6.17.orig/mm/memory.c
++++ linux-2.6.17/mm/memory.c
+@@ -1162,6 +1162,7 @@ int zeromap_page_range(struct vm_area_st
+ 	} while (pgd++, addr = next, addr != end);
+ 	return err;
+ }
++EXPORT_SYMBOL_GPL(zeromap_page_range);
+ 
+ pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
+ {
+--- linux-2.6.17.orig/mm/mmap.c
++++ linux-2.6.17/mm/mmap.c
+@@ -1996,6 +1996,7 @@ int insert_vm_struct(struct mm_struct * 
+ 	vma_link(mm, vma, prev, rb_link, rb_parent);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(insert_vm_struct);
+ 
+ /*
+  * Copy the vma structure to a new location in the same mm,

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-reset-loop-r2.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-reset-loop-r2.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-reset-loop-r2.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,44 @@
+ sound/soc/codecs/wm9712.c |   28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+Index: linux-2.6.18/sound/soc/codecs/wm9712.c
+===================================================================
+--- linux-2.6.18.orig/sound/soc/codecs/wm9712.c	2006-12-05 23:25:33.000000000 +0000
++++ linux-2.6.18/sound/soc/codecs/wm9712.c	2006-12-05 23:27:20.000000000 +0000
+@@ -618,18 +618,26 @@ static int wm9712_dapm_event(struct snd_
+ 
+ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
+ {
+-	if (try_warm && soc_ac97_ops.warm_reset) {
+-		soc_ac97_ops.warm_reset(codec->ac97);
+-		if (!(ac97_read(codec, 0) & 0x8000))
+-			return 1;
+-	}
++	int retry = 3;
++ 
++	while (retry--)
++	{
++		if(try_warm && soc_ac97_ops.warm_reset) {
++			soc_ac97_ops.warm_reset(codec->ac97);
++			if(ac97_read(codec, 0) & 0x8000)
++				continue;
++			else
++				return 1;
++		}
+ 
+-	soc_ac97_ops.reset(codec->ac97);
+-	if (ac97_read(codec, 0) & 0x8000)
+-		goto err;
+-	return 0;
++		soc_ac97_ops.reset(codec->ac97);
++		if(ac97_read(codec, 0) & 0x8000)
++			continue;
++		else
++			return 0;
++
++	}
+ 
+-err:
+ 	printk(KERN_ERR "WM9712 AC97 reset failed\n");
+ 	return -EIO;
+ }

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-suspend-cold-res-r2.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-suspend-cold-res-r2.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm9712-suspend-cold-res-r2.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,16 @@
+ sound/soc/codecs/wm9712.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: linux-2.6.18/sound/soc/codecs/wm9712.c
+===================================================================
+--- linux-2.6.18.orig/sound/soc/codecs/wm9712.c	2006-12-05 23:19:53.000000000 +0000
++++ linux-2.6.18/sound/soc/codecs/wm9712.c	2006-12-05 23:22:04.000000000 +0000
+@@ -651,7 +651,7 @@ static int wm9712_soc_resume(struct plat
+ 	int i, ret;
+ 	u16 *cache = codec->reg_cache;
+ 
+-	ret = wm9712_reset(codec, 1);
++	ret = wm9712_reset(codec, 0);
+ 	if (ret < 0){
+ 		printk(KERN_ERR "could not reset AC97 codec\n");
+ 		return ret;

Added: trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm97xx-lcdnoise-r0.patch
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm97xx-lcdnoise-r0.patch	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-2.6.17/wm97xx-lcdnoise-r0.patch	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,208 @@
+Index: linux-tosa/drivers/input/touchscreen/wm9712.c
+===================================================================
+--- linux-tosa.orig/drivers/input/touchscreen/wm9712.c	2006-08-29 16:52:36.008543280 +0100
++++ linux-tosa/drivers/input/touchscreen/wm9712.c	2006-08-29 16:52:50.923275896 +0100
+@@ -1,7 +1,7 @@
+ /*
+  * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
+  *
+- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC.
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+  * Author: Liam Girdwood
+  *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
+  * Parts Copyright : Ian Molton <spyro at f2s.com>
+@@ -13,6 +13,12 @@
+  *  Free Software Foundation;  either version 2 of the  License, or (at your
+  *  option) any later version.
+  *
++ *  Revision history
++ *     4th Jul 2005  Initial version.
++ *    29th Aug 2006  Mike Arthur <mike at mikearthur.co.uk>
++ *                   Added fixes for Sharp SL-6000 (Tosa) LCD noise causing
++ *                   touchscreen interference.
++ *
+  */
+ 
+ #include <linux/module.h>
+@@ -28,6 +34,10 @@
+ #define WM9705_VERSION		"0.60"
+ #define DEFAULT_PRESSURE	0xb0c0
+ 
++#define CCNT(a)     asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
++#define CCNT_ON()   asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
++#define CCNT_OFF()  asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
++
+ /*
+  * Debug
+  */
+@@ -243,6 +253,36 @@
+ 	return wm->dig[2] & WM9712_PDEN;
+ }
+ 
++
++#ifdef CONFIG_MACH_TOSA
++/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait
++ * before sampling the Y axis of the touchscreen */
++static inline void wm9712_lcd_sync_on(struct wm97xx* wm, int adcsel) {
++    unsigned long timer1 = 0, timer2 = 0, wait_time = 0;
++    if (adcsel == WM97XX_ADCSEL_Y) {
++        wait_time = wm97xx_calc_lcd_waittime(wm);
++
++        CCNT_ON();
++
++        if (wait_time) {
++            /* wait for LCD rising edge */
++            wm_machinfo->wait_hsync();
++            /* get clock */
++            CCNT(timer1);
++            CCNT(timer2);
++
++            while ((timer2 - timer1) < wait_time) {
++                CCNT(timer2);
++            }
++        }
++    }
++}
++
++static inline void wm9712_lcd_sync_off(void) {
++    CCNT_OFF();
++}
++#endif
++
+ /*
+  * Read a sample from the WM9712 adc in polling mode.
+  */
+@@ -260,6 +300,9 @@
+ 	/* set up digitiser */
+ 	if (adcsel & 0x8000)
+ 		adcsel = ((adcsel & 0x7fff) + 3) << 12;
++    #ifdef CONFIG_MACH_TOSA
++    wm9712_lcd_sync_on(wm, adcsel);
++    #endif
+ 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+ 	
+ 	/* wait 3 AC97 time slots + delay for conversion */
+@@ -282,6 +325,10 @@
+ 	
+ 	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+ 	
++    #ifdef CONFIG_MACH_TOSA
++    wm9712_lcd_sync_off();
++    #endif
++
+ 	/* check we have correct sample */
+ 	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+ 		dbg ("adc wrong sample, read %x got %x", adcsel,
+@@ -303,11 +350,12 @@
+ static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
+ {
+ 	int rc;
+-	
+ 	if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
+ 		return rc;
++
+ 	if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
+ 		return rc;
++
+ 	if (pil && !five_wire) {
+ 		if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
+ 			return rc;
+Index: linux-tosa/drivers/input/touchscreen/wm97xx-core.c
+===================================================================
+--- linux-tosa.orig/drivers/input/touchscreen/wm97xx-core.c	2006-08-29 16:52:36.008543280 +0100
++++ linux-tosa/drivers/input/touchscreen/wm97xx-core.c	2006-08-29 16:52:50.924275744 +0100
+@@ -2,7 +2,7 @@
+  * wm97xx-core.c  --  Touch screen driver core for Wolfson WM9705, WM9712
+  *                           and WM9713 AC97 Codecs.
+  *
+- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC.
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+  * Author: Liam Girdwood
+  *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
+  * Parts Copyright : Ian Molton <spyro at f2s.com>
+@@ -67,6 +67,9 @@
+  *                   GPIOs) and 2.6 power management. 
+  *    29th Nov 2004  Added WM9713 support.
+  *     4th Jul 2005  Moved codec specific code out to seperate files.
++ *    29th Aug 2006  Mike Arthur <mike at mikearthur.co.uk>
++ *                   Added fixes for Sharp SL-6000 (Tosa) LCD noise causing
++ *                   touchscreen interference.
+  */  
+     
+ #include <linux/module.h>
+@@ -94,6 +97,7 @@
+ static DECLARE_MUTEX(gpio_sem);
+ static LIST_HEAD(wm97xx_misc_list);
+ static struct wm97xx* wm_codec = NULL;
++struct wm97xx_machinfo *wm_machinfo;
+ 
+ /*
+  * WM97xx - enable/disable AUX ADC sysfs 
+@@ -832,6 +836,23 @@
+ 		mdev->remove(wm_codec);
+ }
+ 
++#ifdef CONFIG_MACH_TOSA
++/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait
++ * before sampling the Y axis of the touchscreen */
++unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm) {
++    unsigned long hsync_time = wm_machinfo->get_hsync_time();
++    return hsync_time;
++}
++
++void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo) {
++    wm_machinfo = machinfo;
++}
++
++void wm97xx_unset_machinfo() {
++    wm_machinfo = NULL;
++}
++#endif
++
+ static struct device_driver wm97xx_driver = {
+ 	.name = 	"ac97", 
+ 	.bus = 		&ac97_bus_type, 
+@@ -861,6 +882,9 @@
+ EXPORT_SYMBOL_GPL(wm97xx_reg_write);
+ EXPORT_SYMBOL_GPL(wm97xx_register_misc_dev);
+ EXPORT_SYMBOL_GPL(wm97xx_unregister_misc_dev);
++EXPORT_SYMBOL_GPL(wm97xx_calc_lcd_waittime);
++EXPORT_SYMBOL_GPL(wm97xx_set_machinfo);
++EXPORT_SYMBOL_GPL(wm97xx_unset_machinfo);
+ 
+ module_init(wm97xx_init); 
+ module_exit(wm97xx_exit);
+Index: linux-tosa/include/linux/wm97xx.h
+===================================================================
+--- linux-tosa.orig/include/linux/wm97xx.h	2006-08-29 16:52:36.008543280 +0100
++++ linux-tosa/include/linux/wm97xx.h	2006-08-29 16:52:50.924275744 +0100
+@@ -207,6 +207,7 @@
+ 
+ struct wm97xx;
+ extern struct wm97xx_codec_drv wm97xx_codec;
++extern struct wm97xx_machinfo *wm_machinfo;
+ 
+ /*
+  * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
+@@ -253,6 +254,11 @@
+ 	struct list_head list;
+ };
+ 
++struct wm97xx_machinfo {
++    unsigned long (*get_hsync_time)(void);
++    void (*wait_hsync)(void);
++};
++
+ int wm97xx_register_misc_dev(struct wm97xx_misc_dev* mdev);
+ void wm97xx_unregister_misc_dev(struct wm97xx_misc_dev* mdev);
+ 
+@@ -281,4 +287,9 @@
+ int wm97xx_acc_startup(struct wm97xx* wm);
+ void wm97xx_acc_shutdown(struct wm97xx* wm);
+ 
++
++unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm);
++void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo);
++void wm97xx_unset_machinfo(void);
++
+ #endif

Added: trunk/oe/packages/linux-qemu/linux-rp-neo1973_2.6.17.bb
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp-neo1973_2.6.17.bb	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp-neo1973_2.6.17.bb	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,7 @@
+MACHINE = "qemuarm"
+
+require linux-rp_${PV}.bb
+
+FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/linux-rp-${PV}"
+
+SRC_URI += "file://versatile-change-fb-orientation.patch;patch=1"

Added: trunk/oe/packages/linux-qemu/linux-rp.inc
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp.inc	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp.inc	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,205 @@
+DESCRIPTION = "2.6 Linux Development Kernel for Zaurus devices and iPAQ hx2750."
+SECTION = "kernel"
+LICENSE = "GPL"
+
+inherit kernel
+
+RPROVIDES_kernel-image += "hostap-modules"
+
+DOSRC = "http://www.do13.de/openzaurus/patches"
+RPSRC = "http://www.rpsys.net/openzaurus/patches/archive"
+JLSRC = "http://www.cs.wisc.edu/~lenz/zaurus/files"
+BASRC = "http://www.orca.cx/zaurus/patches"
+CHSRC = "http://oz.drigon.com/patches"
+
+##############################################################
+# Compensate for sucky bootloader on all Sharp Zaurus models
+#
+FILES_kernel-image = ""
+ALLOW_EMPTY = "1"
+
+EXTRA_OEMAKE = "OPENZAURUS_RELEASE=-${DISTRO_VERSION}"
+COMPATIBLE_HOST = "(arm|i.86).*-linux"
+COMPATIBLE_MACHINE = '(collie|poodle|c7x0|akita|spitz|tosa|hx2000|qemuarm|qemux86)'
+KERNEL_IMAGETYPE_qemux86 = "bzImage"
+
+CMDLINE_CON = "console=ttyS0,115200n8 console=tty1 noinitrd"
+CMDLINE_ROOT = "root=/dev/mtdblock2 rootfstype=jffs2"
+CMDLINE_ROOT_spitz = "root=/dev/hda1 rootfstype=ext3 rootdelay=1 rw"
+CMDLINE_OTHER = "dyntick=enable"
+CMDLINE_DEBUG = '${@base_conditional("DISTRO_TYPE", "release", "quiet", "debug",d)}'
+
+##############################################################
+# Configure memory/ramdisk split for collie
+#
+export mem = '${@bb.data.getVar("COLLIE_MEMORY_SIZE",d,1) or "32"}'
+export rd  = '${@bb.data.getVar("COLLIE_RAMDISK_SIZE",d,1) or "32"}'
+
+CMDLINE_MEM_collie = "mem=${mem}M"
+CMDLINE_ROTATE_spitz = "fbcon=rotate:1"
+CMDLINE_ROTATE_akita = "fbcon=rotate:1"
+CMDLINE_ROTATE_collie = "fbcon=rotate:1"
+CMDLINE_ROTATE_poodle = "fbcon=rotate:1"
+CMDLINE = "${CMDLINE_CON} ${CMDLINE_ROOT} ${CMDLINE_MEM} ${CMDLINE_ROTATE} ${CMDLINE_OTHER} ${CMDLINE_DEBUG}"
+
+###############################################################
+# Enable or disable ELPP via local.conf - default is "no"
+#
+ENABLE_ELPP = '${@bb.data.getVar("OZ_KERNEL_ENABLE_ELPP",d,1) or "no"}'
+
+###############################################################
+# module configs specific to this kernel
+#
+module_autoload_ohci-hcd_tosa = "ohci-hcd"
+module_autoload_pxaficp_ir = "pxaficp_ir"
+module_autoload_snd-pcm-oss = "snd-pcm-oss"
+module_autoload_snd-soc-corgi_c7x0 = "snd-soc-corgi"
+module_autoload_snd-soc-spitz_akita = "snd-soc-spitz"
+module_autoload_snd-soc-spitz_spitz = "snd-soc-spitz"
+module_autoload_snd-soc-poodle_poodle = "snd-soc-poodle"
+
+do_configure() {
+	rm -f ${S}/.config
+
+	if [ "${MACHINE}" == "tosa" ]; then
+		gcc_version=`${KERNEL_CC} -dumpversion`		
+		if [ "${gcc_version}" == "4.0.1" ] || [ "${gcc_version}" == "4.0.2" ]; then
+			die "tosa kernel wont work with gcc 4.0.x"
+		fi
+	fi
+
+	if [ ! -e ${WORKDIR}/defconfig-${MACHINE} ]; then
+		die "No default configuration for ${MACHINE} available."
+	fi
+
+	if [ "${MACHINE}" == "collie" ]; then
+		mempos=`echo "obase=16; $mem * 1024 * 1024" | bc`
+		rdsize=`echo "$rd * 1024" | bc`
+		total=`expr $mem + $rd`
+		addr=`echo "obase=16; ibase=16; C0000000 + $mempos" | bc`
+	 	if [ "$rd" == "0" ]
+	 	then
+		    echo "No RAMDISK"
+			echo "# CONFIG_MTD_MTDRAM_SA1100 is not set" >> ${S}/.config
+		else
+		    echo "RAMDIR = $rdsize on $addr"
+			echo "CONFIG_MTD_MTDRAM_SA1100=y"           >> ${S}/.config
+			echo "CONFIG_MTDRAM_TOTAL_SIZE=$rdsize"     >> ${S}/.config
+			echo "CONFIG_MTDRAM_ERASE_SIZE=1"           >> ${S}/.config
+			echo "CONFIG_MTDRAM_ABS_POS=$addr"          >> ${S}/.config
+		fi
+	fi
+
+	echo "CONFIG_CMDLINE=\"${CMDLINE}\"" >> ${S}/.config
+
+	#if [ "${ENABLE_ELPP}" == "yes" ]; then
+        #        echo "# Enhanced Linux Progress Patch"  >> ${S}/.config
+        #        echo "CONFIG_FB_ELPP=y"                 >> ${S}/.config
+        #        echo "CONFIG_LOGO=y"                    >> ${S}/.config
+        #        echo "CONFIG_LOGO_LINUX_CLUT224=y"      >> ${S}/.config
+	#else
+	#	echo "# CONFIG_FB_ELPP is not set"	>> ${S}/.config
+	#fi
+
+	if [ "${TARGET_OS}" == "linux-gnueabi" -o  "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then
+		echo "CONFIG_AEABI=y"                   >> ${S}/.config
+		echo "CONFIG_OABI_COMPAT=y"             >> ${S}/.config
+	else 
+		echo "# CONFIG_AEABI is not set"        >> ${S}/.config
+		echo "# CONFIG_OABI_COMPAT is not set"  >> ${S}/.config
+	fi
+
+	if [ "${DISTRO}" == "openzaurus" -a "${MACHINE}" != "collie" ]; then
+		case ${MACHINE} in
+			c7x0 | akita | spitz )
+				echo "CONFIG_LOGO_OZ640_CLUT224=y"            >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ480_CLUT224 is not set" >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ240_CLUT224 is not set" >> ${S}/.config
+				;;
+			tosa )
+				echo "CONFIG_LOGO_OZ480_CLUT224=y"            >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ640_CLUT224 is not set" >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ240_CLUT224 is not set" >> ${S}/.config
+				;;
+			poodle | collie )
+				echo "CONFIG_LOGO_OZ240_CLUT224=y"            >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ640_CLUT224 is not set" >> ${S}/.config
+				echo "# CONFIG_LOGO_OZ480_CLUT224 is not set" >> ${S}/.config
+				;;
+		esac 
+		echo "CONFIG_LOGO=y"                          >> ${S}/.config
+		echo "# CONFIG_LOGO_LINUX_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OHAND_CLUT224 is not set" >> ${S}/.config
+	elif [ "${DISTRO}" == "poky" -a "${MACHINE}" != "collie" ]; then
+		echo "CONFIG_LOGO=y"                          >> ${S}/.config
+		echo "CONFIG_LOGO_OHAND_CLUT224=y"            >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ240_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ480_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ640_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_LINUX_CLUT224 is not set" >> ${S}/.config
+	else 
+		echo "# CONFIG_LOGO is not set"               >> ${S}/.config
+		echo "# CONFIG_LOGO_OHAND_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_LINUX_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ240_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ480_CLUT224 is not set" >> ${S}/.config
+		echo "# CONFIG_LOGO_OZ640_CLUT224 is not set" >> ${S}/.config
+	fi
+
+	sed -e '/CONFIG_AEABI/d' \
+	    -e '/CONFIG_OABI_COMPAT=/d' \
+	    -e '/CONFIG_CMDLINE=/d' \
+	    -e '/CONFIG_MTD_MTDRAM_SA1100=/d' \
+	    -e '/CONFIG_MTDRAM_TOTAL_SIZE=/d' \
+	    -e '/CONFIG_MTDRAM_ERASE_SIZE=/d' \
+	    -e '/CONFIG_MTDRAM_ABS_POS=/d' \
+	    -e '/CONFIG_LOGO=/d' \
+	    -e '/CONFIG_LOGO_LINUX_CLUT224=/d' \
+	    -e '/CONFIG_LOGO_OHAND_CLUT224=/d' \
+	    -e '/CONFIG_LOGO_OZ240_CLUT224=/d' \
+	    -e '/CONFIG_LOGO_OZ480_CLUT224=/d' \
+	    -e '/CONFIG_LOGO_OZ640_CLUT224=/d' \
+	    '${WORKDIR}/defconfig-${MACHINE}' >>'${S}/.config'
+
+	yes '' | oe_runmake oldconfig
+}
+
+# Check the kernel is below the 1264*1024 byte limit for the PXA Zaurii
+do_compile_append() {
+	case ${MACHINE} in
+		c7x0 | akita | poodle | spitz | tosa )
+			size=`ls -l arch/${ARCH}/boot/${KERNEL_IMAGETYPE} | awk '{ print $5}'`
+			if [ $size -ge 1294336 ]; then	
+				rm arch/${ARCH}/boot/${KERNEL_IMAGETYPE}
+				echo "Size is $size"
+				die "This kernel is too big for your PXA Zaurus and will destroy data if you flash it. Please reduce the size of the kernel by making more of it modular."
+			fi
+			;;
+		collie )
+			size=`ls -l arch/${ARCH}/boot/${KERNEL_IMAGETYPE} | awk '{ print $5}'`
+			if [ $size -ge 1048576 ]; then	
+				rm arch/${ARCH}/boot/${KERNEL_IMAGETYPE}
+				echo "Size is $size"
+				die "This kernel is too big for your Collie and will not be flashed. Please reduce the size of the kernel by making more of it modular."
+			fi
+			;;
+        	*)
+			;;
+	esac
+}
+
+do_deploy() {
+        install -d ${DEPLOY_DIR_IMAGE}
+        install -m 0644 arch/${ARCH}/boot/${KERNEL_IMAGETYPE} ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${PV}-${MACHINE}-${DATETIME}.bin
+	rm -f ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${MACHINE}.bin
+	ln -s ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${PV}-${MACHINE}-${DATETIME}.bin ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${MACHINE}.bin
+        tar -cvzf ${DEPLOY_DIR_IMAGE}/modules-${KERNEL_RELEASE}-${MACHINE}.tgz -C ${D} lib	
+}
+
+do_deploy[dirs] = "${S}"
+
+addtask deploy before do_package after do_install
+
+# wlan-ng stuff need compiled kernel sources
+do_rm_work() {
+}

Added: trunk/oe/packages/linux-qemu/linux-rp_2.6.17.bb
===================================================================
--- trunk/oe/packages/linux-qemu/linux-rp_2.6.17.bb	2007-02-09 16:36:55 UTC (rev 934)
+++ trunk/oe/packages/linux-qemu/linux-rp_2.6.17.bb	2007-02-10 00:18:29 UTC (rev 935)
@@ -0,0 +1,127 @@
+require linux-rp.inc
+
+PR = "r31"
+
+# Handy URLs
+# git://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git \
+# http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.bz2 \
+# http://www.kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.15-rc1.bz2;patch=1 \
+# http://www.kernel.org/pub/linux/kernel/v2.6/snapshots/patch-2.6.15-rc2-git1.bz2;patch=1 \
+# http://www.kernel.org/pub/linux/kernel/people/alan/linux-2.6/2.6.10/patch-2.6.10-ac8.gz;patch=1 \
+# http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.14-rc2/2.6.14-rc2-mm1/2.6.14-rc2-mm1.bz2;patch=1 \	   
+
+# Patches submitted upstream are towards top of this list 
+# Hacks should clearly named and at the bottom
+SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.17.tar.bz2 \
+           ${RPSRC}/poodle_partsize-r0.patch;patch=1;status=merged \
+           ${RPSRC}/jffs2_longfilename-r1.patch;patch=1;status=merged \
+           ${RPSRC}/locomo_led_default_trigger-r0.patch;patch=1;status=merged \
+           ${RPSRC}/zaurus_reboot-r3.patch;patch=1;status=merged \
+           ${RPSRC}/poodle_mmcsd_fix-r0.patch;patch=1;status=merged \
+           ${RPSRC}/poodle_ssp-r1.patch;patch=1;status=merged \
+           ${RPSRC}/sharpsl_pm-do-r2.patch;patch=1;status=merged \
+           ${RPSRC}/zlib_inflate-r3.patch;patch=1;status=merged \
+           ${RPSRC}/logo_rotate_fix-r1.patch;patch=1;status=merged \
+           ${RPSRC}/collie_frontlight-r6.patch;patch=1;status=merged \
+           ${RPSRC}/input_modalias_fix-r0.patch;patch=1;status=merged \
+           ${RPSRC}/spectrumcs_fix-r0.patch;patch=1 \
+           file://00-hostap.patch;patch=1;status=merged \
+           file://10-pcnet.patch;patch=1;status=merged \
+ 	   file://asoc-v0.12.4_2.6.17.patch;patch=1 \
+           ${RPSRC}/hx2750_base-r27.patch;patch=1 \
+           ${RPSRC}/hx2750_bl-r7.patch;patch=1 \
+           ${RPSRC}/hx2750_pcmcia-r2.patch;patch=1 \
+           ${RPSRC}/pxa_keys-r5.patch;patch=1 \
+           ${RPSRC}/tsc2101-r12.patch;patch=1 \
+           ${RPSRC}/hx2750_test1-r4.patch;patch=1 \
+           ${RPSRC}/pxa_timerfix-r0.patch;patch=1 \
+           ${RPSRC}/input_power-r5.patch;patch=1 \
+           ${RPSRC}/pxa25x_cpufreq-r0.patch;patch=1 \
+           ${RPSRC}/sharpsl_pm_fixes1-r0.patch;patch=1 \
+           ${RPSRC}/pm_changes-r1.patch;patch=1 \
+           ${RPSRC}/usb_pxa27x_udc-r0.patch;patch=1 \
+           ${RPSRC}/usb_add_epalloc-r1.patch;patch=1 \
+           ${DOSRC}/kexec-arm-r3.patch;patch=1 \
+           ${RPSRC}/locomo_kbd_tweak-r1.patch;patch=1 \
+           ${RPSRC}/poodle_pm-r3.patch;patch=1 \
+           ${RPSRC}/pxafb_changeres-r0.patch;patch=1 \
+           ${RPSRC}/poodle_audio-r7.patch;patch=1 \
+           ${RPSRC}/pxa27x_overlay-r2.patch;patch=1 \
+           ${RPSRC}/w100_extaccel-r0.patch;patch=1 \
+           file://serial-add-support-for-non-standard-xtals-to-16c950-driver.patch;patch=1 \
+           file://hrw-pcmcia-ids-r5.patch;patch=1 \
+           ${RPSRC}/logo_oh-r0.patch.bz2;patch=1;status=unmergable \
+           ${RPSRC}/logo_oz-r2.patch.bz2;patch=1;status=unmergable \
+           ${RPSRC}/pxa-linking-bug.patch;patch=1;status=unmergable \
+           file://add-oz-release-string.patch;patch=1;status=unmergable \
+           ${RPSRC}/mmcsd_large_cards-r0.patch;patch=1;status=hack \
+           ${RPSRC}/mmcsd_no_scr_check-r0.patch;patch=1;status=hack \
+           ${RPSRC}/integrator_rgb-r1.patch;patch=1;status=hack \
+           ${RPSRC}/pxa_cf_initorder_hack-r1.patch;patch=1;status=hack \
+           file://pxa-serial-hack.patch;patch=1;status=hack \
+           file://connectplus-remove-ide-HACK.patch;patch=1;status=hack \
+           file://orinoco-remove-all-which-are-in-hostap-HACK.patch;patch=1;status=unmergable-hack \
+           file://squashfs3.0-2.6.15.patch;patch=1;status=external \
+           file://vesafb-tng-1.0-rc2-git-20060629.patch;patch=1;status=external \
+           file://defconfig-c7x0 \
+           file://defconfig-hx2000 \
+           file://defconfig-collie \
+           file://defconfig-poodle \
+           file://defconfig-akita \
+           file://defconfig-spitz \
+           file://defconfig-qemuarm \
+           file://defconfig-qemux86 \
+           file://defconfig-tosa "
+
+# Add this to enable pm debug code (useful with a serial lead)
+#  ${RPSRC}/sharpsl_pm_debug-r0.patch;patch=1
+
+# Disabled until I find the reason this gives issues with cdc_subset
+#            ${RPSRC}/usb_rndis_tweaks-r0.patch;patch=1 \
+
+#           http://tglx.de/projects/armirq/2.6.17-rc3/patch-2.6.17-rc3-armirq4.patch;patch=1 \
+#           ${RPSRC}/../pxa27x_overlay-r0.patch;patch=1 \
+
+# Is anything out of this still needed? Parts were commited to mainline by rmk (drivers/mfd/)
+# (Pavel Machek's git tree has updated versions of this?)
+#  ${JLSRC}/zaurus-lcd-2.6.11.diff.gz;patch=1 
+
+# These patches are extracted from Pavel Machek's git tree
+# (diff against vanilla kernel)
+SRC_URI_append_collie = "\
+	   ${DOSRC}/collie/mtd-sharp-flash-hack-r0.patch;patch=1 \
+	   ${DOSRC}/collie/collie-r0.patch;patch=1 \
+	   ${DOSRC}/collie/locomolcd-backlight-r0.patch;patch=1 \
+	   ${DOSRC}/collie/ucb1x00-touch-audio-r0.patch;patch=1 \
+	   ${DOSRC}/collie/collie-mcp-r0.patch;patch=1 \
+	   ${DOSRC}/collie/sa1100-udc-r0.patch;patch=1 \
+#	   ${DOSRC}/collie/collie-pm-r1.patch;patch=1 \
+	   "
+
+SRC_URI_append_tosa = "\
+	   ${CHSRC}/usb-ohci-hooks-r1.patch;patch=1 \
+	   ${CHSRC}/tmio-core-r4.patch;patch=1 \
+	   ${DOSRC}/temp/tmio-tc6393-r6.patch;patch=1 \
+	   ${CHSRC}/tmio-nand-r5.patch;patch=1 \
+	   ${DOSRC}/temp/tmio-ohci-r4.patch;patch=1 \
+	   ${CHSRC}/tmio-fb-r6.patch;patch=1 \
+	   ${DOSRC}/tosa-keyboard-r17.patch;patch=1 \
+	   ${DOSRC}/tosa-pxaac97-r6.patch;patch=1 \
+	   ${DOSRC}/tosa-tmio-r6.patch;patch=1 \
+	   ${DOSRC}/tosa-power-r17.patch;patch=1 \
+	   ${DOSRC}/tosa-tmio-lcd-r8.patch;patch=1 \
+	   ${DOSRC}/tosa-bluetooth-r8.patch;patch=1 \
+	   ${DOSRC}/wm97xx-lg7-r0.patch;patch=1 \
+	   file://wm9712-suspend-cold-res-r2.patch;patch=1 \
+	   ${DOSRC}/sharpsl-pm-postresume-r0.patch;patch=1 \
+	   ${DOSRC}/wm97xx-dig-restore-r0.patch;patch=1 \
+	   ${DOSRC}/wm97xx-miscdevs-resume-r0.patch;patch=1 \
+	   file://wm9712-reset-loop-r2.patch;patch=1 \
+	   file://tosa-lcdnoise-r0.patch;patch=1 \
+	   file://wm97xx-lcdnoise-r0.patch;patch=1 "
+#	   ${DOSRC}/tosa-asoc-r1.patch;patch=1 "
+
+S = "${WORKDIR}/linux-2.6.17"
+
+# to get module dependencies working
+KERNEL_RELEASE = "2.6.17"





More information about the commitlog mailing list