r1875 - trunk/src/target/kernel/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Mon Apr 30 09:10:17 CEST 2007


Author: laforge
Date: 2007-04-30 09:09:50 +0200 (Mon, 30 Apr 2007)
New Revision: 1875

Removed:
   trunk/src/target/kernel/patches/2.6.17-s3c2410-spi-mode23.patch
   trunk/src/target/kernel/patches/2.6.20-s3c2410fb_uninitialized.patch
   trunk/src/target/kernel/patches/qt2410-biglcd.patch
   trunk/src/target/kernel/patches/s3c2410_nand-hwecc-backport.patch
   trunk/src/target/kernel/patches/sdhc-backport.patch
Modified:
   trunk/src/target/kernel/patches/asoc.patch
   trunk/src/target/kernel/patches/gta01-core.patch
   trunk/src/target/kernel/patches/gta01-pcf50606.patch
   trunk/src/target/kernel/patches/gta01-vibrator.patch
   trunk/src/target/kernel/patches/hxd8-core.patch
   trunk/src/target/kernel/patches/pm-debug_less_verbose.patch
   trunk/src/target/kernel/patches/qt2410-base.patch
   trunk/src/target/kernel/patches/qt2410-s3c_mci-pdata.patch
   trunk/src/target/kernel/patches/s3c2410-qt2410-buttons.patch
   trunk/src/target/kernel/patches/s3c2410_touchscreen.patch
   trunk/src/target/kernel/patches/s3c2410_udc-vbus_draw_pdata.patch
   trunk/src/target/kernel/patches/s3c2410_udc.patch
   trunk/src/target/kernel/patches/s3c_mci.patch
   trunk/src/target/kernel/patches/series
   trunk/src/target/kernel/patches/yaffs2-20070304.patch
Log:
update patches to apply against 2.6.21[.1]
*


Deleted: trunk/src/target/kernel/patches/2.6.17-s3c2410-spi-mode23.patch
===================================================================
--- trunk/src/target/kernel/patches/2.6.17-s3c2410-spi-mode23.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/2.6.17-s3c2410-spi-mode23.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,33 +0,0 @@
-diff --exclude patches --exclude .pc -Nru linux-2.6.17.7-fic1/drivers/spi/spi_s3c24xx_gpio.c linux-2.6.17.7-new/drivers/spi/spi_s3c24xx_gpio.c
---- linux-2.6.17.7-fic1/drivers/spi/spi_s3c24xx_gpio.c	2006-07-25 05:36:01.000000000 +0200
-+++ linux-2.6.17.7-new/drivers/spi/spi_s3c24xx_gpio.c	2006-10-28 16:53:36.000000000 +0200
-@@ -73,6 +73,19 @@
- 	return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
- }
- 
-+static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
-+				      unsigned nsecs, u32 word, u8 bits)
-+{
-+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
-+}
-+
-+static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
-+				      unsigned nsecs, u32 word, u8 bits)
-+{
-+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
-+}
-+
-+
- static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
- {
- 	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-@@ -108,6 +121,8 @@
- 
- 	sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
- 	sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
-+	sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
-+	sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
- 
- 	/* set state of spi pins */
- 	s3c2410_gpio_setpin(sp->info->pin_clk, 0);
-

Deleted: trunk/src/target/kernel/patches/2.6.20-s3c2410fb_uninitialized.patch
===================================================================
--- trunk/src/target/kernel/patches/2.6.20-s3c2410fb_uninitialized.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/2.6.20-s3c2410fb_uninitialized.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,18 +0,0 @@
-The current driver is not setting the dev field in the private data structure,
-which can lead to an OOPS if the driver tries to report an error.
-
-Signed-off-by: Ben Dooks <ben-linux at fluff.org>
-
---- linux-2.6.20/drivers/video/s3c2410fb.c	2007-02-04 18:44:54.000000000 +0000
-+++ linux-2.6.20-fbfix1/drivers/video/s3c2410fb.c	2007-02-15 22:42:51.000000000 +0000
-@@ -791,6 +791,8 @@ static int __init s3c2410fb_probe(struct
- 
- 	info = fbinfo->par;
- 	info->fb = fbinfo;
-+	info->dev = &pdev->dev;
-+
- 	platform_set_drvdata(pdev, fbinfo);
- 
- 	dprintk("devinit\n");
-
-

Modified: trunk/src/target/kernel/patches/asoc.patch
===================================================================
--- trunk/src/target/kernel/patches/asoc.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/asoc.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,2115 +1,3 @@
-Index: linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/DAI.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/DAI.txt
-@@ -0,0 +1,56 @@
-+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.
-Index: linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/clocking.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/clocking.txt
-@@ -0,0 +1,51 @@
-+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. In general
-+it's best to configure BCLK to the lowest possible speed (depending on your
-+rate, number of channels and wordsize) to save on power.
-+
-+It's also desireable to use the codec (if possible) to drive (or master) the
-+audio clocks as it's usually gives more accurate sample rates than the CPU.
-+
-+
-+
-Index: linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/codec.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/codec.txt
-@@ -0,0 +1,197 @@
-+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) Codec DAI and PCM configuration
-+ 2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
-+ 3) Mixers and audio controls
-+ 4) Codec audio operations
-+
-+Optionally, codec drivers can also provide:-
-+
-+ 5) DAPM description.
-+ 6) DAPM event handler.
-+ 7) 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 - Codec DAI and PCM configuration
-+-----------------------------------
-+Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
-+PCM's capablities and operations. This struct is exported so that it can be
-+registered with the core by your machine driver.
-+
-+e.g.
-+
-+struct snd_soc_codec_dai wm8731_dai = {
-+	.name = "WM8731",
-+	/* playback capabilities */
-+	.playback = {
-+		.stream_name = "Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8731_RATES,
-+		.formats = WM8731_FORMATS,},
-+	/* capture capabilities */
-+	.capture = {
-+		.stream_name = "Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8731_RATES,
-+		.formats = WM8731_FORMATS,},
-+	/* pcm operations - see section 4 below */
-+	.ops = {
-+		.prepare = wm8731_pcm_prepare,
-+		.hw_params = wm8731_hw_params,
-+		.shutdown = wm8731_shutdown,
-+	},
-+	/* DAI operations - see DAI.txt */
-+	.dai_ops = {
-+		.digital_mute = wm8731_mute,
-+		.set_sysclk = wm8731_set_dai_sysclk,
-+		.set_fmt = wm8731_set_dai_fmt,
-+	}
-+};
-+EXPORT_SYMBOL_GPL(wm8731_dai);
-+
-+
-+2 - 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;
-+
-+
-+3 - 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
-+
-+
-+4 - Codec Audio Operations
-+--------------------------
-+The codec driver also supports the following alsa operations:-
-+
-+/* 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 *);
-+};
-+
-+Please refer to the alsa driver PCM documentation for details.
-+http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
-+
-+
-+5 - 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.
-+
-+
-+6 - 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 */
-+
-+
-+7 - 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-asoc-pxa/Documentation/sound/alsa/soc/dapm.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/Documentation/sound/alsa/soc/machine.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/Documentation/sound/alsa/soc/machine.txt
-@@ -0,0 +1,113 @@
-+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,
-+	.ops = &corgi_ops,
-+};
-+
-+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,
-+};
-+
-+
-+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-asoc-pxa/Documentation/sound/alsa/soc/overview.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/Documentation/sound/alsa/soc/platform.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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)(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);
-+};
-+
-+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)(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;
-+};
-+
-+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-asoc-pxa/Documentation/sound/alsa/soc/pops_clicks.txt
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/include/sound/ac97_codec.h
-===================================================================
---- linux-2.6-asoc-pxa.orig/include/sound/ac97_codec.h
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/include/sound/soc-dapm.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/include/sound/soc.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/include/sound/soc.h
-@@ -0,0 +1,460 @@
-+/*
-+ * 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.13.3"
-+
-+/*
-+ * 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, xshift, xmask, xinvert,\
-+	 xhandler_get, xhandler_put) \
-+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-+	.info = snd_soc_info_volsw, \
-+	.get = xhandler_get, .put = xhandler_put, \
-+	.private_value = SOC_SINGLE_VALUE(xreg, xshift, 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		0	/* I2S mode */
-+#define SND_SOC_DAIFMT_RIGHT_J	1	/* Right justified mode */
-+#define SND_SOC_DAIFMT_LEFT_J	2	/* Left Justified mode */
-+#define SND_SOC_DAIFMT_DSP_A	3	/* L data msb after FRM or LRC */
-+#define SND_SOC_DAIFMT_DSP_B	4	/* L data msb during FRM or LRC */
-+#define SND_SOC_DAIFMT_AC97		5	/* AC97 */
-+
-+#define SND_SOC_DAIFMT_MSB 	SND_SOC_DAIFMT_LEFT_J
-+#define SND_SOC_DAIFMT_LSB	SND_SOC_DAIFMT_RIGHT_J
-+
-+/*
-+ * DAI Gating
-+ */
-+#define SND_SOC_DAIFMT_CONT			(0 << 4)	/* continuous clock */
-+#define SND_SOC_DAIFMT_GATED		(1 << 4)	/* clock is gated when not Tx/Rx */
-+
-+/*
-+ * DAI hardware signal inversions
-+ */
-+#define SND_SOC_DAIFMT_NB_NF		(0 << 8)	/* normal bit clock + frame */
-+#define SND_SOC_DAIFMT_NB_IF		(1 << 8)	/* normal bclk + inv frm */
-+#define SND_SOC_DAIFMT_IB_NF		(2 << 8)	/* invert bclk + nor frm */
-+#define SND_SOC_DAIFMT_IB_IF		(3 << 8)	/* 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	(0 << 12) /* codec clk & frm master */
-+#define SND_SOC_DAIFMT_CBS_CFM	(1 << 12) /* codec clk slave & frm master */
-+#define SND_SOC_DAIFMT_CBM_CFS	(2 << 12) /* codec clk master & frame slave */
-+#define SND_SOC_DAIFMT_CBS_CFS	(3 << 12) /* codec clk & frm slave */
-+
-+#define SND_SOC_DAIFMT_FORMAT_MASK		0x000f
-+#define SND_SOC_DAIFMT_CLOCK_MASK		0x00f0
-+#define SND_SOC_DAIFMT_INV_MASK			0x0f00
-+#define SND_SOC_DAIFMT_MASTER_MASK		0xf000
-+
-+
-+/*
-+ * Master Clock Directions
-+ */
-+#define SND_SOC_CLOCK_IN	0
-+#define SND_SOC_CLOCK_OUT	1
-+
-+/*
-+ * 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);
-+
-+/* 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;
-+	u64 formats;			/* SNDRV_PCM_FMTBIT_* */
-+	unsigned int rates;		/* SNDRV_PCM_RATE_* */
-+	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);
-+};
-+
-+/* ASoC codec DAI ops */
-+struct snd_soc_codec_ops {
-+	/* codec DAI clocking configuration */
-+	int (*set_sysclk)(struct snd_soc_codec_dai *codec_dai,
-+		int clk_id, unsigned int freq, int dir);
-+	int (*set_pll)(struct snd_soc_codec_dai *codec_dai,
-+		int pll_id, unsigned int freq_in, unsigned int freq_out);
-+	int (*set_clkdiv)(struct snd_soc_codec_dai *codec_dai,
-+		int div_id, int div);
-+
-+	/* CPU DAI format configuration */
-+	int (*set_fmt)(struct snd_soc_codec_dai *codec_dai,
-+		unsigned int fmt);
-+	int (*set_tdm_slot)(struct snd_soc_codec_dai *codec_dai,
-+		unsigned int mask, int slots);
-+	int (*set_tristate)(struct snd_soc_codec_dai *, int tristate);
-+
-+	/* digital mute */
-+	int (*digital_mute)(struct snd_soc_codec_dai *, int mute);
-+};
-+
-+/* ASoC cpu DAI ops */
-+struct snd_soc_cpu_ops {
-+	/* CPU DAI clocking configuration */
-+	int (*set_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
-+		int clk_id, unsigned int freq, int dir);
-+	int (*set_clkdiv)(struct snd_soc_cpu_dai *cpu_dai,
-+		int div_id, int div);
-+	int (*set_pll)(struct snd_soc_cpu_dai *cpu_dai,
-+		int pll_id, unsigned int freq_in, unsigned int freq_out);
-+
-+	/* CPU DAI format configuration */
-+	int (*set_fmt)(struct snd_soc_cpu_dai *cpu_dai,
-+		unsigned int fmt);
-+	int (*set_tdm_slot)(struct snd_soc_cpu_dai *cpu_dai,
-+		unsigned int mask, int slots);
-+	int (*set_tristate)(struct snd_soc_cpu_dai *, int tristate);
-+};
-+
-+/* 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;
-+
-+	/* DAI runtime info */
-+	struct snd_soc_codec *codec;
-+	unsigned int active;
-+	unsigned char pop_wait:1;
-+
-+	/* ops */
-+	struct snd_soc_ops ops;
-+	struct snd_soc_codec_ops dai_ops;
-+
-+	/* 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);
-+
-+	/* ops */
-+	struct snd_soc_ops ops;
-+	struct snd_soc_cpu_ops dai_ops;
-+
-+	/* DAI capabilities */
-+	struct snd_soc_pcm_stream capture;
-+	struct snd_soc_pcm_stream playback;
-+
-+	/* DAI runtime info */
-+	struct snd_pcm_runtime *runtime;
-+	unsigned char active:1;
-+	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;
-+	struct delayed_work delayed_work;
-+
-+	/* 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;
-+
-+	/* machine stream operations */
-+	struct snd_soc_ops *ops;
-+
-+	/* codec/machine specific init - e.g. add machine controls */
-+	int (*init)(struct snd_soc_codec *codec);
-+};
-+
-+/* 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);
-+
-+	/* 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;
-+	struct delayed_work delayed_work;
-+	void *codec_data;
-+};
-+
-+/* runtime channel data */
-+struct snd_soc_pcm_runtime {
-+	struct snd_soc_dai_link *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;
-+};
-+
-+#endif
-Index: linux-2.6-asoc-pxa/sound/Kconfig
-===================================================================
---- linux-2.6-asoc-pxa.orig/sound/Kconfig
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/sound/soc/Kconfig
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/sound/soc/Makefile
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/sound/soc/codecs/Kconfig
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/Kconfig
-@@ -0,0 +1,102 @@
-+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_WM8956
-+	tristate "SoC driver for the WM8956 codec"
-+	depends SND_SOC
-+	help
-+	  Say Y or M if you want to support the WM8956 codec.
-+
-+config SND_SOC_WM8960
-+	tristate "SoC driver for the WM8960 codec"
-+	depends SND_SOC
-+	help
-+	  Say Y or M if you want to support the WM8960 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-asoc-pxa/sound/soc/codecs/Makefile
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/Makefile
-@@ -0,0 +1,35 @@
-+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-wm8956-objs := wm8956.o
-+snd-soc-wm8960-objs := wm8960.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_WM8956)	+= snd-soc-wm8956.o
-+obj-$(CONFIG_SND_SOC_WM8960)	+= snd-soc-wm8960.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-asoc-pxa/sound/soc/codecs/ac97.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/ac97.c
-@@ -0,0 +1,156 @@
-+/*
-+ * 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.6"
-+
-+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);
-+}
-+
-+#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-+
-+static struct snd_soc_codec_dai ac97_dai = {
-+	.name = "AC97 HiFi",
-+	.playback = {
-+		.stream_name = "AC97 Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = STD_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.stream_name = "AC97 Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = STD_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.prepare = ac97_prepare,},
-+};
-+
-+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-asoc-pxa/sound/soc/codecs/ac97.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/sound/soc/codecs/ak4535.c
 ===================================================================
 --- /dev/null
@@ -3707,1955 +1595,6 @@
 +extern struct snd_soc_codec_device soc_codec_dev_uda1380;
 +
 +#endif /* _UDA1380_H */
-Index: linux-2.6-asoc-pxa/sound/soc/codecs/wm8731.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/wm8731.c
-@@ -0,0 +1,763 @@
-+/*
-+ * 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.13"
-+
-+/*
-+ * 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;
-+
-+/* codec private data */
-+struct wm8731_priv {
-+	unsigned int sysclk;
-+};
-+
-+/*
-+ * 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
-+};
-+
-+/*
-+ * 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},
-+	{12000000, 32000, 375, 0x6, 0x0, 0x1},
-+
-+	/* 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;
-+}
-+
-+static int wm8731_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_codec *codec = socdev->codec;
-+	struct wm8731_priv *wm8731 = codec->private_data;
-+	u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
-+	int i = get_coeff(wm8731->sysclk, params_rate(params));
-+	u16 srate = (coeff_div[i].sr << 2) |
-+		(coeff_div[i].bosr << 1) | coeff_div[i].usb;
-+
-+	wm8731_write(codec, WM8731_SRATE, srate);
-+
-+	/* bit size */
-+	switch (params_format(params)) {
-+	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;
-+	}
-+
-+	wm8731_write(codec, WM8731_IFACE, iface);
-+	return 0;
-+}
-+
-+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;
-+
-+	/* 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_dai *dai, int mute)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	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_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
-+		int clk_id, unsigned int freq, int dir)
-+{
-+	struct snd_soc_codec *codec = codec_dai->codec;
-+	struct wm8731_priv *wm8731 = codec->private_data;
-+
-+	switch (freq) {
-+	case 11289600:
-+	case 12000000:
-+	case 12288000:
-+	case 16934400:
-+	case 18432000:
-+		wm8731->sysclk = freq;
-+		return 0;
-+	}
-+	return -EINVAL;
-+}
-+
-+
-+static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
-+		unsigned int fmt)
-+{
-+	struct snd_soc_codec *codec = codec_dai->codec;
-+	u16 iface = 0;
-+
-+	/* set master/slave audio interface */
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+		iface |= 0x0040;
-+		break;
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	/* interface format */
-+	switch (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;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	/* clock inversion */
-+	switch (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;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	/* set iface */
-+	wm8731_write(codec, WM8731_IFACE, iface);
-+	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;
-+}
-+
-+#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_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
-+	SNDRV_PCM_FMTBIT_S24_LE)
-+
-+struct snd_soc_codec_dai wm8731_dai = {
-+	.name = "WM8731",
-+	.playback = {
-+		.stream_name = "Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8731_RATES,
-+		.formats = WM8731_FORMATS,},
-+	.capture = {
-+		.stream_name = "Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8731_RATES,
-+		.formats = WM8731_FORMATS,},
-+	.ops = {
-+		.prepare = wm8731_pcm_prepare,
-+		.hw_params = wm8731_hw_params,
-+		.shutdown = wm8731_shutdown,
-+	},
-+	.dai_ops = {
-+		.digital_mute = wm8731_mute,
-+		.set_sysclk = wm8731_set_dai_sysclk,
-+		.set_fmt = wm8731_set_dai_fmt,
-+	}
-+};
-+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) {
-+		printk(KERN_ERR "wm8731: failed to create pcms\n");
-+		goto pcm_err;
-+	}
-+
-+	/* 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) {
-+		printk(KERN_ERR "wm8731: failed to register card\n");
-+		goto card_err;
-+	}
-+
-+	return ret;
-+
-+card_err:
-+	snd_soc_free_pcms(socdev);
-+	snd_soc_dapm_free(socdev);
-+pcm_err:
-+	kfree(codec->reg_cache);
-+	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;
-+	struct wm8731_priv *wm8731;
-+	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;
-+
-+	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
-+	if (wm8731 == NULL) {
-+		kfree(codec);
-+		return -ENOMEM;
-+	}
-+
-+	codec->private_data = wm8731;
-+	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->private_data);
-+	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-asoc-pxa/sound/soc/codecs/wm8731.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/wm8731.h
-@@ -0,0 +1,44 @@
-+/*
-+ * 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
-+
-+#define WM8731_SYSCLK	0
-+#define WM8731_DAI		0
-+
-+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-asoc-pxa/sound/soc/codecs/wm8750.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/wm8750.c
-@@ -0,0 +1,1055 @@
-+/*
-+ * 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.12"
-+
-+/*
-+ * 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)
-+
-+/* codec private data */
-+struct wm8750_priv {
-+	unsigned int sysclk;
-+};
-+
-+/*
-+ * 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 */
-+};
-+
-+/*
-+ * 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;
-+}
-+
-+static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
-+		int clk_id, unsigned int freq, int dir)
-+{
-+	struct snd_soc_codec *codec = codec_dai->codec;
-+	struct wm8750_priv *wm8750 = codec->private_data;
-+
-+	switch (freq) {
-+	case 11289600:
-+	case 12000000:
-+	case 12288000:
-+	case 16934400:
-+	case 18432000:
-+		wm8750->sysclk = freq;
-+		return 0;
-+	}
-+	return -EINVAL;
-+}
-+
-+static int wm8750_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
-+		unsigned int fmt)
-+{
-+	struct snd_soc_codec *codec = codec_dai->codec;
-+	u16 iface = 0;
-+
-+	/* set master/slave audio interface */
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+		iface = 0x0040;
-+		break;
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	/* interface format */
-+	switch (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;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	/* clock inversion */
-+	switch (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;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	wm8750_write(codec, WM8750_IFACE, iface);
-+	return 0;
-+}
-+
-+static int wm8750_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_codec *codec = socdev->codec;
-+	struct wm8750_priv *wm8750 = codec->private_data;
-+	u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3;
-+	u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0;
-+	int coeff = get_coeff(wm8750->sysclk, params_rate(params));
-+
-+	/* bit size */
-+	switch (params_format(params)) {
-+	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;
-+	}
-+
-+	/* set iface & srate */
-+	wm8750_write(codec, WM8750_IFACE, iface);
-+	if (coeff >= 0)
-+		wm8750_write(codec, WM8750_SRATE, srate |
-+			(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
-+
-+	return 0;
-+}
-+
-+static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	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;
-+}
-+
-+#define WM8750_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 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-+
-+#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
-+	SNDRV_PCM_FMTBIT_S24_LE)
-+
-+struct snd_soc_codec_dai wm8750_dai = {
-+	.name = "WM8750",
-+	.playback = {
-+		.stream_name = "Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8750_RATES,
-+		.formats = WM8750_FORMATS,},
-+	.capture = {
-+		.stream_name = "Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM8750_RATES,
-+		.formats = WM8750_FORMATS,},
-+	.ops = {
-+		.hw_params = wm8750_pcm_hw_params,
-+	},
-+	.dai_ops = {
-+		.digital_mute = wm8750_mute,
-+		.set_fmt = wm8750_set_dai_fmt,
-+		.set_sysclk = wm8750_set_dai_sysclk,
-+	},
-+};
-+EXPORT_SYMBOL_GPL(wm8750_dai);
-+
-+static void wm8750_work(struct work_struct *work)
-+{
-+	struct snd_soc_codec *codec =
-+		container_of(work, struct snd_soc_codec, delayed_work.work);
-+	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;
-+		schedule_delayed_work(&codec->delayed_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) {
-+		printk(KERN_ERR "wm8750: failed to create pcms\n");
-+		goto pcm_err;
-+	}
-+
-+	/* charge output caps */
-+	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
-+	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
-+	schedule_delayed_work(&codec->delayed_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) {
-+		printk(KERN_ERR "wm8750: failed to register card\n");
-+		goto card_err;
-+	}
-+	return ret;
-+
-+card_err:
-+	snd_soc_free_pcms(socdev);
-+	snd_soc_dapm_free(socdev);
-+pcm_err:
-+	kfree(codec->reg_cache);
-+	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;
-+	struct wm8750_priv *wm8750;
-+	int ret = 0;
-+
-+	info("WM8750 Audio Codec %s", WM8750_VERSION);
-+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-+	if (codec == NULL)
-+		return -ENOMEM;
-+
-+	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
-+	if (wm8750 == NULL) {
-+		kfree(codec);
-+		return -ENOMEM;
-+	}
-+
-+	codec->private_data = wm8750;
-+	socdev->codec = codec;
-+	mutex_init(&codec->mutex);
-+	INIT_LIST_HEAD(&codec->dapm_widgets);
-+	INIT_LIST_HEAD(&codec->dapm_paths);
-+	wm8750_socdev = socdev;
-+	INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
-+
-+#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;
-+}
-+
-+/*
-+ * This function forces any delayed work to be queued and run.
-+ */
-+static int run_delayed_work(struct delayed_work *dwork)
-+{
-+	int ret;
-+
-+	/* cancel any work waiting to be queued. */
-+	ret = cancel_delayed_work(dwork);
-+
-+	/* if there was any work waiting then we run it now and
-+	 * wait for it's completion */
-+	if (ret) {
-+		schedule_delayed_work(dwork, 0);
-+		flush_scheduled_work();
-+	}
-+	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);
-+	run_delayed_work(&codec->delayed_work);
-+	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->private_data);
-+	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-asoc-pxa/sound/soc/codecs/wm8750.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/wm8750.h
-@@ -0,0 +1,67 @@
-+/*
-+ * 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
-+
-+#define WM8750_SYSCLK	0
-+
-+struct wm8750_setup_data {
-+	unsigned short i2c_address;
-+};
-+
-+extern struct snd_soc_codec_dai wm8750_dai;
-+extern struct snd_soc_codec_device soc_codec_dev_wm8750;
-+
-+#endif
 Index: linux-2.6-asoc-pxa/sound/soc/codecs/wm8753.c
 ===================================================================
 --- /dev/null
@@ -10264,801 +6203,6 @@
 +extern struct snd_soc_codec_device soc_codec_dev_wm8974;
 +
 +#endif
-Index: linux-2.6-asoc-pxa/sound/soc/codecs/wm9712.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/codecs/wm9712.c
-@@ -0,0 +1,771 @@
-+/*
-+ * 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);
-+
-+/*
-+ * 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);
-+}
-+
-+#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-+
-+struct snd_soc_codec_dai wm9712_dai[] = {
-+{
-+	.name = "AC97 HiFi",
-+	.playback = {
-+		.stream_name = "HiFi Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM9712_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.stream_name = "HiFi Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = WM9712_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.prepare = ac97_prepare,},
-+},
-+{
-+	.name = "AC97 Aux",
-+	.playback = {
-+		.stream_name = "Aux Playback",
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = WM9712_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.prepare = ac97_aux_prepare,},
-+}
-+};
-+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) {
-+		ret = -ENOMEM;
-+		goto cache_err;
-+	}
-+	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) {
-+		printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
-+		goto codec_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) {
-+		printk(KERN_ERR "wm9712: failed to register card\n");
-+		goto reset_err;
-+	}
-+
-+	return 0;
-+
-+reset_err:
-+	snd_soc_free_pcms(socdev);
-+
-+pcm_err:
-+	snd_soc_free_ac97_codec(codec);
-+
-+codec_err:
-+	kfree(codec->reg_cache);
-+
-+cache_err:
-+	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-asoc-pxa/sound/soc/codecs/wm9712.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/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-asoc-pxa/sound/soc/codecs/wm9713.c
 ===================================================================
 --- /dev/null
@@ -12340,586 +7484,6 @@
 +int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
 +
 +#endif
-Index: linux-2.6-asoc-pxa/sound/soc/pxa/Kconfig
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/Kconfig
-@@ -0,0 +1,143 @@
-+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 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).
-+
-+config SND_PXA2xx_SOC_MAGICIAN
-+	tristate "SoC Audio support for HTC Magician"
-+	depends on SND_PXA2xx_SOC
-+	select SND_PXA2xx_SOC_I2S
-+	select SND_PXA2xx_SOC_SSP
-+	help
-+	  Say Y if you want to add support for SoC audio on the
-+	  HTC Magician.
-+
-+config SND_PXA2xx_SOC_AMESOM_TLV320
-+	tristate "SoC SSP Audio support for AMESOM - TLV320AIC24k"
-+	depends on SND_PXA2xx_SOC && MACH_AMESOM
-+	select SND_PXA2xx_SOC_I2S
-+	select SND_PXA2xx_SOC_SSP
-+	help
-+	  Say Y if you want to add support for SoC audio on Amesom
-+	  with the tlv320.
-+
-+endmenu
-Index: linux-2.6-asoc-pxa/sound/soc/pxa/Makefile
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/Makefile
-@@ -0,0 +1,39 @@
-+# 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
-+snd-soc-magician-objs := magician.o
-+snd-soc-amesom-tlv320-objs := amesom_tlv320.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
-+obj-$(CONFIG_SND_PXA2xx_SOC_MAGICIAN) += snd-soc-magician.o
-+obj-$(CONFIG_SND_PXA2xx_SOC_AMESOM_TLV320) += snd-soc-amesom-tlv320.o
-Index: linux-2.6-asoc-pxa/sound/soc/pxa/corgi.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/corgi.c
-@@ -0,0 +1,383 @@
-+/*
-+ * 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"
-+#include "pxa2xx-i2s.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 int corgi_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+	unsigned int clk = 0;
-+	int ret = 0;
-+
-+	switch (params_rate(params)) {
-+	case 8000:
-+	case 16000:
-+	case 48000:
-+	case 96000:
-+		clk = 12288000;
-+		break;
-+	case 11025:
-+	case 22050:
-+	case 44100:
-+		clk = 11289600;
-+		break;
-+	}
-+
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set cpu DAI configuration */
-+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the codec system clock for DAC and ADC */
-+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the I2S system clock as input (unused) */
-+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+static struct snd_soc_ops corgi_ops = {
-+	.startup = corgi_startup,
-+	.hw_params = corgi_hw_params,
-+	.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;
-+}
-+
-+/* 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,
-+	.ops = &corgi_ops,
-+};
-+
-+/* corgi audio machine driver */
-+static struct snd_soc_machine snd_soc_machine_corgi = {
-+	.name = "Corgi",
-+	.dai_link = &corgi_dai,
-+	.num_links = 1,
-+};
-+
-+/* 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-asoc-pxa/sound/soc/pxa/mainstone.c
 ===================================================================
 --- /dev/null
@@ -15014,1538 +9578,6 @@
 +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-asoc-pxa/sound/soc/pxa/poodle.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/poodle.c
-@@ -0,0 +1,352 @@
-+/*
-+ * 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"
-+#include "pxa2xx-i2s.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 int poodle_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+	unsigned int clk = 0;
-+	int ret = 0;
-+
-+	switch (params_rate(params)) {
-+	case 8000:
-+	case 16000:
-+	case 48000:
-+	case 96000:
-+		clk = 12288000;
-+		break;
-+	case 11025:
-+	case 22050:
-+	case 44100:
-+		clk = 11289600;
-+		break;
-+	}
-+
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set cpu DAI configuration */
-+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the codec system clock for DAC and ADC */
-+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the I2S system clock as input (unused) */
-+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+static struct snd_soc_ops poodle_ops = {
-+	.startup = poodle_startup,
-+	.hw_params = poodle_hw_params,
-+	.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;
-+}
-+
-+/* 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,
-+	.ops = &poodle_ops,
-+};
-+
-+/* poodle audio machine driver */
-+static struct snd_soc_machine snd_soc_machine_poodle = {
-+	.name = "Poodle",
-+	.dai_link = &poodle_dai,
-+	.num_links = 1,
-+};
-+
-+/* 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-asoc-pxa/sound/soc/pxa/pxa2xx-ac97.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-ac97.c
-@@ -0,0 +1,431 @@
-+/*
-+ * 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"
-+#include "pxa2xx-ac97.h"
-+
-+static DEFINE_MUTEX(car_mutex);
-+static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
-+static volatile long gsr_bits;
-+
-+/*
-+ * 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, IRQF_DISABLED, "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;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
-+	else
-+		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;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
-+	else
-+		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;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+		return -ENODEV;
-+	else
-+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
-+
-+	return 0;
-+}
-+
-+#define PXA2XX_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)
-+
-+/*
-+ * 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,
-+		.rates = PXA2XX_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.stream_name = "AC97 Capture",
-+		.channels_min = 2,
-+		.channels_max = 2,
-+		.rates = PXA2XX_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.hw_params = pxa2xx_ac97_hw_params,},
-+},
-+{
-+	.name = "pxa2xx-ac97-aux",
-+	.id = 1,
-+	.type = SND_SOC_DAI_AC97,
-+	.playback = {
-+		.stream_name = "AC97 Aux Playback",
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = PXA2XX_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.stream_name = "AC97 Aux Capture",
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = PXA2XX_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.hw_params = pxa2xx_ac97_hw_aux_params,},
-+},
-+{
-+	.name = "pxa2xx-ac97-mic",
-+	.id = 2,
-+	.type = SND_SOC_DAI_AC97,
-+	.capture = {
-+		.stream_name = "AC97 Mic Capture",
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = PXA2XX_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.hw_params = pxa2xx_ac97_hw_mic_params,},
-+},
-+};
-+
-+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-asoc-pxa/sound/soc/pxa/pxa2xx-i2s.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-i2s.c
-@@ -0,0 +1,318 @@
-+/*
-+ * 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"
-+#include "pxa2xx-i2s.h"
-+
-+struct pxa_i2s_port {
-+	u32 sadiv;
-+	u32 sacr0;
-+	u32 sacr1;
-+	u32 saimr;
-+	int master;
-+	u32 fmt;
-+};
-+static struct pxa_i2s_port pxa_i2s;
-+
-+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;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+	if (!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_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
-+		unsigned int fmt)
-+{
-+	/* interface format */
-+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+	case SND_SOC_DAIFMT_I2S:
-+		pxa_i2s.fmt = 0;
-+		break;
-+	case SND_SOC_DAIFMT_LEFT_J:
-+		pxa_i2s.fmt = SACR1_AMSL;
-+		break;
-+	}
-+
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		pxa_i2s.master = 1;
-+		break;
-+	case SND_SOC_DAIFMT_CBM_CFS:
-+		pxa_i2s.master = 0;
-+		break;
-+	default:
-+		break;
-+	}
-+	return 0;
-+}
-+
-+static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
-+		int clk_id, unsigned int freq, int dir)
-+{
-+	if (clk_id != PXA2XX_I2S_SYSCLK)
-+		return -ENODEV;
-+
-+	if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT)
-+		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
-+
-+	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;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+
-+	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)
-+		cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
-+	else
-+		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);
-+		SACR1 |= pxa_i2s.fmt;
-+	}
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+		SAIMR |= SAIMR_TFS;
-+	else
-+		SAIMR |= SAIMR_RFS;
-+
-+	switch (params_rate(params)) {
-+	case 8000:
-+		SADIV = 0x48;
-+		break;
-+	case 11025:
-+		SADIV = 0x34;
-+		break;
-+	case 16000:
-+		SADIV = 0x24;
-+		break;
-+	case 22050:
-+		SADIV = 0x1a;
-+		break;
-+	case 44100:
-+		SADIV = 0xd;
-+		break;
-+	case 48000:
-+		SADIV = 0xc;
-+		break;
-+	case 96000: /* not in manual and possibly slightly inaccurate */
-+		SADIV = 0x6;
-+		break;
-+	}
-+
-+	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
-+
-+#define PXA2XX_I2S_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 | SNDRV_PCM_RATE_96000)
-+
-+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,
-+	.playback = {
-+		.channels_min = 2,
-+		.channels_max = 2,
-+		.rates = PXA2XX_I2S_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.channels_min = 2,
-+		.channels_max = 2,
-+		.rates = PXA2XX_I2S_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.startup = pxa2xx_i2s_startup,
-+		.shutdown = pxa2xx_i2s_shutdown,
-+		.trigger = pxa2xx_i2s_trigger,
-+		.hw_params = pxa2xx_i2s_hw_params,},
-+	.dai_ops = {
-+		.set_fmt = pxa2xx_i2s_set_dai_fmt,
-+		.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
-+	},
-+};
-+
-+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-asoc-pxa/sound/soc/pxa/pxa2xx-pcm.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-pcm.c
-@@ -0,0 +1,372 @@
-+/*
-+ * 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->dai->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;
-+
-+	/* return if this is a bufferless transfer e.g.
-+	 * codec <--> BT codec or GSM modem -- lg FIXME */
-+	 if (!dma)
-+	 	return 0;
-+
-+	/* 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;
-+
-+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-+	if (ret < 0)
-+		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-asoc-pxa/sound/soc/pxa/pxa2xx-pcm.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-pcm.h
-@@ -0,0 +1,34 @@
-+/*
-+ * 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;
-+};
-+
-+/* platform data */
-+extern struct snd_soc_platform pxa2xx_soc_platform;
-+
-+#endif
 Index: linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-ssp.c
 ===================================================================
 --- /dev/null
@@ -17217,3678 +10249,6 @@
 +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-asoc-pxa/sound/soc/pxa/spitz.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/spitz.c
-@@ -0,0 +1,394 @@
-+/*
-+ * 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"
-+#include "pxa2xx-i2s.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 int spitz_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+	unsigned int clk = 0;
-+	int ret = 0;
-+
-+	switch (params_rate(params)) {
-+	case 8000:
-+	case 16000:
-+	case 48000:
-+	case 96000:
-+		clk = 12288000;
-+		break;
-+	case 11025:
-+	case 22050:
-+	case 44100:
-+		clk = 11289600;
-+		break;
-+	}
-+
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set cpu DAI configuration */
-+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the codec system clock for DAC and ADC */
-+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, clk,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set the I2S system clock as input (unused) */
-+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+static struct snd_soc_ops spitz_ops = {
-+	.startup = spitz_startup,
-+	.hw_params = spitz_hw_params,
-+};
-+
-+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;
-+}
-+
-+/* 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,
-+	.ops = &spitz_ops,
-+};
-+
-+/* spitz audio machine driver */
-+static struct snd_soc_machine snd_soc_machine_spitz = {
-+	.name = "Spitz",
-+	.dai_link = &spitz_dai,
-+	.num_links = 1,
-+};
-+
-+/* 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-asoc-pxa/sound/soc/pxa/tosa.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/tosa.c
-@@ -0,0 +1,289 @@
-+/*
-+ * 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"
-+#include "pxa2xx-ac97.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,
-+	.ops = &tosa_ops,
-+},
-+{
-+	.name = "AC97 Aux",
-+	.stream_name = "AC97 Aux",
-+	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-+	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
-+	.ops = &tosa_ops,
-+},
-+};
-+
-+static struct snd_soc_machine tosa = {
-+	.name = "Tosa",
-+	.dai_link = tosa_dai,
-+	.num_links = ARRAY_SIZE(tosa_dai),
-+};
-+
-+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-asoc-pxa/sound/soc/soc-dapm.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/soc-dapm.c
-@@ -0,0 +1,1329 @@
-+/*
-+ * 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).
-+ */
-+static 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) {
-+					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 */
-+static 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;
-+}
-+
-+/* test and update the power status of a mixer widget */
-+static 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;
-+}
-+
-+/* 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 */
-+static 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;
-+
-+	if (stream == NULL)
-+		return 0;
-+
-+	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-asoc-pxa/sound/soc/soc-core.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/soc-core.c
-@@ -0,0 +1,1587 @@
-+/*
-+ * soc-core.c  --  ALSA SoC Audio Layer
-+ *
-+ * Copyright 2005 Wolfson Microelectronics PLC.
-+ * Copyright 2005 Openedhand Ltd.
-+ *
-+ * Author: Liam Girdwood
-+ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *         with code, comments and ideas from :-
-+ *         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
-+ *    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 0
-+#if SOC_DEBUG
-+#define dbg(format, arg...) printk(format, ## arg)
-+#else
-+#define dbg(format, arg...)
-+#endif
-+
-+static DEFINE_MUTEX(pcm_mutex);
-+static DEFINE_MUTEX(io_mutex);
-+static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
-+
-+/*
-+ * 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)");
-+
-+/*
-+ * This function forces any delayed work to be queued and run.
-+ */
-+static int run_delayed_work(struct delayed_work *dwork)
-+{
-+	int ret;
-+
-+	/* cancel any work waiting to be queued. */
-+	ret = cancel_delayed_work(dwork);
-+
-+	/* if there was any work waiting then we run it now and
-+	 * wait for it's completion */
-+	if (ret) {
-+		schedule_delayed_work(dwork, 0);
-+		flush_scheduled_work();
-+	}
-+	return ret;
-+}
-+
-+#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;
-+}
-+
-+/*
-+ * 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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	int ret = 0;
-+
-+	mutex_lock(&pcm_mutex);
-+
-+	/* startup the audio subsystem */
-+	if (cpu_dai->ops.startup) {
-+		ret = cpu_dai->ops.startup(substream);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: can't open interface %s\n",
-+				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 (codec_dai->ops.startup) {
-+		ret = codec_dai->ops.startup(substream);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: can't open codec %s\n",
-+				codec_dai->name);
-+			goto codec_dai_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;
-+		}
-+	}
-+
-+	/* Check that the codec and cpu DAI's are compatible */
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+		runtime->hw.rate_min =
-+			max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min);
-+		runtime->hw.rate_max =
-+			min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max);
-+		runtime->hw.channels_min =
-+			max(codec_dai->playback.channels_min,
-+				cpu_dai->playback.channels_min);
-+		runtime->hw.channels_max =
-+			min(codec_dai->playback.channels_max,
-+				cpu_dai->playback.channels_max);
-+		runtime->hw.formats =
-+			codec_dai->playback.formats & cpu_dai->playback.formats;
-+		runtime->hw.rates =
-+			codec_dai->playback.rates & cpu_dai->playback.rates;
-+	} else {
-+		runtime->hw.rate_min =
-+			max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min);
-+		runtime->hw.rate_max =
-+			min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max);
-+		runtime->hw.channels_min =
-+			max(codec_dai->capture.channels_min,
-+				cpu_dai->capture.channels_min);
-+		runtime->hw.channels_max =
-+			min(codec_dai->capture.channels_max,
-+				cpu_dai->capture.channels_max);
-+		runtime->hw.formats =
-+			codec_dai->capture.formats & cpu_dai->capture.formats;
-+		runtime->hw.rates =
-+			codec_dai->capture.rates & cpu_dai->capture.rates;
-+	}
-+
-+	snd_pcm_limit_hw_rates(runtime);
-+	if (!runtime->hw.rates) {
-+		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
-+			codec_dai->name, cpu_dai->name);
-+		goto machine_err;
-+	}
-+	if (!runtime->hw.formats) {
-+		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
-+			codec_dai->name, cpu_dai->name);
-+		goto machine_err;
-+	}
-+	if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
-+		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
-+			codec_dai->name, cpu_dai->name);
-+		goto machine_err;
-+	}
-+
-+	dbg("asoc: %s <-> %s info:\n",codec_dai->name, 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)
-+		cpu_dai->playback.active = codec_dai->playback.active = 1;
-+	else
-+		cpu_dai->capture.active = codec_dai->capture.active = 1;
-+	cpu_dai->active = codec_dai->active = 1;
-+	cpu_dai->runtime = runtime;
-+	socdev->codec->active++;
-+	mutex_unlock(&pcm_mutex);
-+	return 0;
-+
-+machine_err:
-+	if (machine->ops && machine->ops->shutdown)
-+		machine->ops->shutdown(substream);
-+
-+codec_dai_err:
-+	if (platform->pcm_ops->close)
-+		platform->pcm_ops->close(substream);
-+
-+platform_err:
-+	if (cpu_dai->ops.shutdown)
-+		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(struct work_struct *work)
-+{
-+	struct snd_soc_device *socdev =
-+		container_of(work, struct snd_soc_device, delayed_work.work);
-+	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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	struct snd_soc_codec *codec = socdev->codec;
-+
-+	mutex_lock(&pcm_mutex);
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+		cpu_dai->playback.active = codec_dai->playback.active = 0;
-+	else
-+		cpu_dai->capture.active = codec_dai->capture.active = 0;
-+
-+	if (codec_dai->playback.active == 0 &&
-+		codec_dai->capture.active == 0) {
-+		cpu_dai->active = codec_dai->active = 0;
-+	}
-+	codec->active--;
-+
-+	if (cpu_dai->ops.shutdown)
-+		cpu_dai->ops.shutdown(substream);
-+
-+	if (codec_dai->ops.shutdown)
-+		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);
-+	cpu_dai->runtime = NULL;
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+		/* start delayed pop wq here for playback streams */
-+		codec_dai->pop_wait = 1;
-+		schedule_delayed_work(&socdev->delayed_work,
-+			msecs_to_jiffies(pmdown_time));
-+	} else {
-+		/* capture streams can be powered down now */
-+		snd_soc_dapm_stream_event(codec,
-+			codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_STOP);
-+
-+		if (codec->active == 0 && 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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	struct snd_soc_codec *codec = socdev->codec;
-+	int ret = 0;
-+
-+	mutex_lock(&pcm_mutex);
-+
-+	if (machine->ops && machine->ops->prepare) {
-+		ret = machine->ops->prepare(substream);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: machine prepare error\n");
-+			goto out;
-+		}
-+	}
-+
-+	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 (codec_dai->ops.prepare) {
-+		ret = codec_dai->ops.prepare(substream);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: codec DAI prepare error\n");
-+			goto out;
-+		}
-+	}
-+
-+	if (cpu_dai->ops.prepare) {
-+		ret = cpu_dai->ops.prepare(substream);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
-+			goto out;
-+		}
-+	}
-+
-+	/* we only want to start a DAPM playback stream if we are not waiting
-+	 * on an existing one stopping */
-+	if (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(socdev->codec,
-+					codec_dai->capture.stream_name,
-+					SND_SOC_DAPM_STREAM_START);
-+		else {
-+			codec_dai->pop_wait = 0;
-+			cancel_delayed_work(&socdev->delayed_work);
-+			if (codec_dai->dai_ops.digital_mute)
-+				codec_dai->dai_ops.digital_mute(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,
-+					codec_dai->playback.stream_name,
-+					SND_SOC_DAPM_STREAM_START);
-+			else
-+				snd_soc_dapm_stream_event(codec,
-+					codec_dai->capture.stream_name,
-+					SND_SOC_DAPM_STREAM_START);
-+
-+			if (codec->dapm_event)
-+				codec->dapm_event(codec, SNDRV_CTL_POWER_D0);
-+			if (codec_dai->dai_ops.digital_mute)
-+				codec_dai->dai_ops.digital_mute(codec_dai, 0);
-+
-+		} else {
-+			/* codec already powered - power on widgets */
-+			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+				snd_soc_dapm_stream_event(codec,
-+					codec_dai->playback.stream_name,
-+					SND_SOC_DAPM_STREAM_START);
-+			else
-+				snd_soc_dapm_stream_event(codec,
-+					codec_dai->capture.stream_name,
-+					SND_SOC_DAPM_STREAM_START);
-+			if (codec_dai->dai_ops.digital_mute)
-+				codec_dai->dai_ops.digital_mute(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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	int ret = 0;
-+
-+	mutex_lock(&pcm_mutex);
-+
-+	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 out;
-+		}
-+	}
-+
-+	if (codec_dai->ops.hw_params) {
-+		ret = codec_dai->ops.hw_params(substream, params);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
-+				codec_dai->name);
-+			goto codec_err;
-+		}
-+	}
-+
-+	if (cpu_dai->ops.hw_params) {
-+		ret = cpu_dai->ops.hw_params(substream, params);
-+		if (ret < 0) {
-+			printk(KERN_ERR "asoc: can't set interface %s hw params\n",
-+				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;
-+		}
-+	}
-+
-+out:
-+	mutex_unlock(&pcm_mutex);
-+	return ret;
-+
-+platform_err:
-+	if (cpu_dai->ops.hw_free)
-+		cpu_dai->ops.hw_free(substream);
-+
-+interface_err:
-+	if (codec_dai->ops.hw_free)
-+		codec_dai->ops.hw_free(substream);
-+
-+codec_err:
-+	if(machine->ops && machine->ops->hw_free)
-+		machine->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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	struct snd_soc_codec *codec = socdev->codec;
-+
-+	mutex_lock(&pcm_mutex);
-+
-+	/* apply codec digital mute */
-+	if (!codec->active && codec_dai->dai_ops.digital_mute)
-+		codec_dai->dai_ops.digital_mute(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 (codec_dai->ops.hw_free)
-+		codec_dai->ops.hw_free(substream);
-+
-+	if (cpu_dai->ops.hw_free)
-+		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_dai_link *machine = rtd->dai;
-+	struct snd_soc_platform *platform = socdev->platform;
-+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
-+	int ret;
-+
-+	if (codec_dai->ops.trigger) {
-+		ret = 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 (cpu_dai->ops.trigger) {
-+		ret = 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->dai_ops.digital_mute && dai->playback.active)
-+			dai->dai_ops.digital_mute(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 */
-+	run_delayed_work(&socdev->delayed_work);
-+	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->dai_ops.digital_mute && dai->playback.active)
-+			dai->dai_ops.digital_mute(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 */
-+	INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
-+	return 0;
-+
-+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;
-+
-+	run_delayed_work(&socdev->delayed_work);
-+
-+	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->dai = dai_link;
-+	rtd->socdev = socdev;
-+	codec_dai->codec = socdev->codec;
-+
-+	/* 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_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-asoc-pxa/sound/soc/at91/Kconfig
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/Kconfig
-@@ -0,0 +1,32 @@
-+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 WM8731-based Endrelia ETI-B1 boards"
-+	depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
-+	select SND_AT91_SOC_I2S
-+	select SND_SOC_WM8731
-+	help
-+	  Say Y if you want to add support for SoC audio on WM8731-based
-+	  Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
-+
-+config SND_AT91_SOC_ETI_SLAVE
-+	bool "Run codec in slave Mode on Endrelia boards"
-+	depends on SND_AT91_SOC_ETI_B1_WM8731
-+	default n
-+	help
-+	  Say Y if you want to run with the AT91 SSC generating the BCLK
-+	  and LRC signals on Endrelia boards.
-+
-+endmenu
-Index: linux-2.6-asoc-pxa/sound/soc/at91/Makefile
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/Makefile
-@@ -0,0 +1,11 @@
-+# AT91 Platform Support
-+snd-soc-at91-objs := at91-pcm.o
-+snd-soc-at91-i2s-objs := at91-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-asoc-pxa/sound/soc/imx/imx-ssi.c
 ===================================================================
 --- /dev/null
@@ -21544,19 +10904,6 @@
 +snd-soc-mx21ads-wm8731-objs := mx21ads_wm8731.o
 +obj-$(CONFIG_SND_SOC_MX21ADS_WM8731) += snd-soc-mx21ads-wm8731.o
 +
-Index: linux-2.6-asoc-pxa/sound/Makefile
-===================================================================
---- linux-2.6-asoc-pxa.orig/sound/Makefile
-+++ linux-2.6-asoc-pxa/sound/Makefile
-@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o
- obj-$(CONFIG_SOUND_PRIME) += sound_firmware.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/
- obj-$(CONFIG_SND_AOA) += aoa/
- 
- # This one must be compilable even if sound is configured out
 Index: linux-2.6-asoc-pxa/sound/soc/codecs/wm8711.c
 ===================================================================
 --- /dev/null
@@ -23373,386 +12720,6 @@
 +extern struct snd_soc_codec_device soc_codec_dev_wm8980;
 +
 +#endif
-Index: linux-2.6-asoc-pxa/sound/soc/at91/eti_b1_wm8731.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/eti_b1_wm8731.c
-@@ -0,0 +1,375 @@
-+/*
-+ * eti_b1_wm8731  --  SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#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/hardware.h>
-+#include <asm/arch/at91_pio.h>
-+#include <asm/arch/gpio.h>
-+
-+#include "../codecs/wm8731.h"
-+#include "at91-pcm.h"
-+#include "at91-i2s.h"
-+
-+#if 0
-+#define	DBG(x...)	printk(KERN_INFO "eti_b1_wm8731: " x)
-+#else
-+#define	DBG(x...)
-+#endif
-+
-+#define AT91_PIO_TF1	(1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
-+#define AT91_PIO_TK1	(1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
-+#define AT91_PIO_TD1	(1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
-+#define AT91_PIO_RD1	(1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
-+#define AT91_PIO_RK1	(1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
-+#define AT91_PIO_RF1	(1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
-+
-+static struct clk *pck1_clk;
-+static struct clk *pllb_clk;
-+
-+
-+static int eti_b1_startup(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+	int ret;
-+
-+	/* cpu clock is the AT91 master clock sent to the SSC */
-+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
-+		60000000, SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* codec system clock is supplied by PCK1, set to 12MHz */
-+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK,
-+		12000000, SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* Start PCK1 clock. */
-+	clk_enable(pck1_clk);
-+	DBG("pck1 started\n");
-+
-+	return 0;
-+}
-+
-+static void eti_b1_shutdown(struct snd_pcm_substream *substream)
-+{
-+	/* Stop PCK1 clock. */
-+	clk_disable(pck1_clk);
-+	DBG("pck1 stopped\n");
-+}
-+
-+static int eti_b1_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
-+	int ret;
-+
-+#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-+	unsigned int rate;
-+	int cmr_div, period;
-+
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set cpu DAI configuration */
-+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0)
-+		return ret;
-+
-+	/*
-+	 * The SSC clock dividers depend on the sample rate.  The CMR.DIV
-+	 * field divides the system master clock MCK to drive the SSC TK
-+	 * signal which provides the codec BCLK.  The TCMR.PERIOD and
-+	 * RCMR.PERIOD fields further divide the BCLK signal to drive
-+	 * the SSC TF and RF signals which provide the codec DACLRC and
-+	 * ADCLRC clocks.
-+	 *
-+	 * The dividers were determined through trial and error, where a
-+	 * CMR.DIV value is chosen such that the resulting BCLK value is
-+	 * divisible, or almost divisible, by (2 * sample rate), and then
-+	 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
-+	 */
-+	rate = params_rate(params);
-+
-+	switch (rate) {
-+	case 8000:
-+		cmr_div = 25;	/* BCLK = 60MHz/(2*25) = 1.2MHz */
-+		period = 74;	/* LRC = BCLK/(2*(74+1)) = 8000Hz */
-+		break;
-+	case 32000:
-+		cmr_div = 7;	/* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
-+		period = 66;	/* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
-+		break;
-+	case 48000:
-+		cmr_div = 13;	/* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
-+		period = 23;	/* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
-+		break;
-+	default:
-+		printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
-+		return -EINVAL;
-+	}
-+
-+	/* set the MCK divider for BCLK */
-+	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
-+	if (ret < 0)
-+		return ret;
-+
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+		/* set the BCLK divider for DACLRC */
-+		ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
-+						AT91SSC_TCMR_PERIOD, period);
-+	} else {
-+		/* set the BCLK divider for ADCLRC */
-+		ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
-+						AT91SSC_RCMR_PERIOD, period);
-+	}
-+	if (ret < 0)
-+		return ret;
-+
-+#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-+	/*
-+	 * Codec in Master Mode.
-+	 */
-+
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set cpu DAI configuration */
-+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-+	if (ret < 0)
-+		return ret;
-+
-+#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-+
-+	return 0;
-+}
-+
-+static struct snd_soc_ops eti_b1_ops = {
-+	.startup = eti_b1_startup,
-+	.hw_params = eti_b1_hw_params,
-+	.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;
-+}
-+
-+static struct snd_soc_dai_link eti_b1_dai = {
-+	.name = "WM8731",
-+	.stream_name = "WM8731",
-+	.cpu_dai = &at91_i2s_dai[1],
-+	.codec_dai = &wm8731_dai,
-+	.init = eti_b1_wm8731_init,
-+	.ops = &eti_b1_ops,
-+};
-+
-+static struct snd_soc_machine snd_soc_machine_eti_b1 = {
-+	.name = "ETI_B1",
-+	.dai_link = &eti_b1_dai,
-+	.num_links = 1,
-+};
-+
-+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 = &at91_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;
-+	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-+
-+	if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
-+		DBG("SSC1 memory region is busy\n");
-+		return -EBUSY;
-+	}
-+
-+	ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
-+	if (!ssc->base) {
-+		DBG("SSC1 memory ioremap failed\n");
-+		ret = -ENOMEM;
-+		goto fail_release_mem;
-+	}
-+
-+	ssc->pid = AT91RM9200_ID_SSC1;
-+
-+	eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
-+	if (!eti_b1_snd_device) {
-+		DBG("platform device allocation failed\n");
-+		ret = -ENOMEM;
-+		goto fail_io_unmap;
-+	}
-+
-+	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) {
-+		DBG("platform device add failed\n");
-+		platform_device_put(eti_b1_snd_device);
-+		goto fail_io_unmap;
-+	}
-+
-+ 	ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
-+			| AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_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);
-+
-+#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-+	printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
-+#else
-+	printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
-+#endif
-+	return ret;
-+
-+fail_io_unmap:
-+	iounmap(ssc->base);
-+fail_release_mem:
-+	release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-+	return ret;
-+}
-+
-+static void __exit eti_b1_exit(void)
-+{
-+	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-+
-+	clk_put(pck1_clk);
-+	clk_put(pllb_clk);
-+
-+	platform_device_unregister(eti_b1_snd_device);
-+
-+	iounmap(ssc->base);
-+	release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-+}
-+
-+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-asoc-pxa/sound/soc/codecs/wm8510.c
 ===================================================================
 --- /dev/null
@@ -24953,19 +13920,6 @@
 +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-asoc-pxa/include/linux/i2c-id.h
-===================================================================
---- linux-2.6-asoc-pxa.orig/include/linux/i2c-id.h
-+++ linux-2.6-asoc-pxa/include/linux/i2c-id.h
-@@ -115,6 +115,8 @@
- #define I2C_DRIVERID_KS0127	86	/* Samsung ks0127 video decoder */
- #define I2C_DRIVERID_TLV320AIC23B 87	/* TI TLV320AIC23B audio codec  */
- #define I2C_DRIVERID_ISL1208	88	/* Intersil ISL1208 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              */
 Index: linux-2.6-asoc-pxa/sound/soc/codecs/wm8976.c
 ===================================================================
 --- /dev/null
@@ -29589,1245 +18543,6 @@
 +module_init(template_init);
 +module_exit(template_exit);
 +
-Index: linux-2.6-asoc-pxa/sound/soc/at91/at91-i2s.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/at91-i2s.c
-@@ -0,0 +1,720 @@
-+/*
-+ * at91-i2s.c  --  ALSA SoC I2S Audio Layer Platform driver
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#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/hardware.h>
-+#include <asm/arch/at91_pmc.h>
-+#include <asm/arch/at91_ssc.h>
-+#include <asm/arch/at91_pdc.h>
-+
-+#include "at91-pcm.h"
-+#include "at91-i2s.h"
-+
-+#if 0
-+#define	DBG(x...)	printk(KERN_DEBUG "at91-i2s:" x)
-+#else
-+#define	DBG(x...)
-+#endif
-+
-+#if defined(CONFIG_ARCH_AT91SAM9260)
-+#define NUM_SSC_DEVICES		1
-+#else
-+#define NUM_SSC_DEVICES		3
-+#endif
-+
-+
-+/*
-+ * SSC PDC registers required by the PCM DMA engine.
-+ */
-+static struct at91_pdc_regs pdc_tx_reg = {
-+	.xpr		= AT91_PDC_TPR,
-+	.xcr		= AT91_PDC_TCR,
-+	.xnpr		= AT91_PDC_TNPR,
-+	.xncr		= AT91_PDC_TNCR,
-+};
-+
-+static struct at91_pdc_regs pdc_rx_reg = {
-+	.xpr		= AT91_PDC_RPR,
-+	.xcr		= AT91_PDC_RCR,
-+	.xnpr		= AT91_PDC_RNPR,
-+	.xncr		= AT91_PDC_RNCR,
-+};
-+
-+/*
-+ * SSC & PDC status bits for transmit and receive.
-+ */
-+static struct at91_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 at91_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,
-+};
-+
-+
-+/*
-+ * DMA parameters.
-+ */
-+static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
-+	{{
-+	.name		= "SSC0/I2S PCM Stereo out",
-+	.pdc		= &pdc_tx_reg,
-+	.mask		= &ssc_tx_mask,
-+	},
-+	{
-+	.name		= "SSC0/I2S PCM Stereo in",
-+	.pdc		= &pdc_rx_reg,
-+	.mask		= &ssc_rx_mask,
-+	}},
-+#if NUM_SSC_DEVICES == 3
-+	{{
-+	.name		= "SSC1/I2S PCM Stereo out",
-+	.pdc		= &pdc_tx_reg,
-+	.mask		= &ssc_tx_mask,
-+	},
-+	{
-+	.name		= "SSC1/I2S PCM Stereo in",
-+	.pdc		= &pdc_rx_reg,
-+	.mask		= &ssc_rx_mask,
-+	}},
-+	{{
-+	.name		= "SSC2/I2S PCM Stereo out",
-+	.pdc		= &pdc_tx_reg,
-+	.mask		= &ssc_tx_mask,
-+	},
-+	{
-+	.name		= "SSC1/I2S PCM Stereo in",
-+	.pdc		= &pdc_rx_reg,
-+	.mask		= &ssc_rx_mask,
-+	}},
-+#endif
-+};
-+
-+struct at91_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 at91_ssc_info {
-+	char		*name;
-+	struct at91_ssc_periph ssc;
-+	spinlock_t 	lock;		/* lock for dir_mask */
-+	unsigned short	dir_mask;	/* 0=unused, 1=playback, 2=capture */
-+	unsigned short	initialized;	/* 1=SSC has been initialized */
-+	unsigned short	daifmt;
-+	unsigned short	cmr_div;
-+	unsigned short	tcmr_period;
-+	unsigned short	rcmr_period;
-+	struct at91_pcm_dma_params *dma_params[2];
-+	struct at91_ssc_state ssc_state;
-+
-+} ssc_info[NUM_SSC_DEVICES] = {
-+	{
-+	.name		= "ssc0",
-+	.lock		= SPIN_LOCK_UNLOCKED,
-+	.dir_mask	= 0,
-+	.initialized	= 0,
-+	},
-+#if NUM_SSC_DEVICES == 3
-+	{
-+	.name		= "ssc1",
-+	.lock		= SPIN_LOCK_UNLOCKED,
-+	.dir_mask	= 0,
-+	.initialized	= 0,
-+	},
-+	{
-+	.name		= "ssc2",
-+	.lock		= SPIN_LOCK_UNLOCKED,
-+	.dir_mask	= 0,
-+	.initialized	= 0,
-+	},
-+#endif
-+};
-+
-+static unsigned int at91_i2s_sysclk;
-+
-+/*
-+ * SSC interrupt handler.  Passes PDC interrupts to the DMA
-+ * interrupt handler in the PCM driver.
-+ */
-+static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
-+{
-+	struct at91_ssc_info *ssc_p = dev_id;
-+	struct at91_pcm_dma_params *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;
-+}
-+
-+/*
-+ * Startup.  Only that one substream allowed in each direction.
-+ */
-+static int at91_i2s_startup(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->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;
-+}
-+
-+/*
-+ * Shutdown.  Clear DMA parameters and shutdown the SSC if there
-+ * are no other substreams open.
-+ */
-+static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
-+	struct at91_pcm_dma_params *dma_params;
-+	int dir, dir_mask;
-+
-+	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-+	dma_params = ssc_p->dma_params[dir];
-+
-+	if (dma_params != NULL) {
-+		at91_ssc_write(dma_params->ssc_base + AT91_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->ssc_base = NULL;
-+		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->ssc.pid);
-+		at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
-+
-+		if (ssc_p->initialized) {
-+			free_irq(ssc_p->ssc.pid, ssc_p);
-+			ssc_p->initialized = 0;
-+		}
-+
-+		/* Reset the SSC */
-+		at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-+
-+		/* Clear the SSC dividers */
-+		ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
-+	}
-+	spin_unlock_irq(&ssc_p->lock);
-+}
-+
-+/*
-+ * Record the SSC system clock rate.
-+ */
-+static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
-+		int clk_id, unsigned int freq, int dir)
-+{
-+	/*
-+	 * The only clock supplied to the SSC is the AT91 master clock,
-+	 * which is only used if the SSC is generating BCLK and/or
-+	 * LRC clocks.
-+	 */
-+	switch (clk_id) {
-+	case AT91_SYSCLK_MCK:
-+		at91_i2s_sysclk = freq;
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * Record the DAI format for use in hw_params().
-+ */
-+static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
-+		unsigned int fmt)
-+{
-+	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-+
-+	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
-+		return -EINVAL;
-+
-+	ssc_p->daifmt = fmt;
-+	return 0;
-+}
-+
-+/*
-+ * Record SSC clock dividers for use in hw_params().
-+ */
-+static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
-+	int div_id, int div)
-+{
-+	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-+
-+	switch (div_id) {
-+	case AT91SSC_CMR_DIV:
-+		/*
-+		 * The same master clock divider is used for both
-+		 * transmit and receive, so if a value has already
-+		 * been set, it must match this value.
-+		 */
-+		if (ssc_p->cmr_div == 0)
-+			ssc_p->cmr_div = div;
-+		else
-+			if (div != ssc_p->cmr_div)
-+				return -EBUSY;
-+		break;
-+
-+	case AT91SSC_TCMR_PERIOD:
-+		ssc_p->tcmr_period = div;
-+		break;
-+
-+	case AT91SSC_RCMR_PERIOD:
-+		ssc_p->rcmr_period = div;
-+		break;
-+
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * Configure the SSC.
-+ */
-+static int at91_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->dai->cpu_dai->id;
-+	struct at91_ssc_info *ssc_p = &ssc_info[id];
-+	struct at91_pcm_dma_params *dma_params;
-+	int dir, channels, bits;
-+	u32 tfmr, rfmr, tcmr, rcmr;
-+	int start_event;
-+	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->ssc_base = ssc_p->ssc.base;
-+	dma_params->substream = substream;
-+
-+	ssc_p->dma_params[dir] = dma_params;
-+
-+	/*
-+	 * The cpu_dai->dma_data field is only used to communicate the
-+	 * appropriate DMA parameters to the pcm driver hw_params()
-+	 * function.  It should not be used for other purposes
-+	 * as it is common to all substreams.
-+	 */
-+	rtd->dai->cpu_dai->dma_data = dma_params;
-+
-+	channels = params_channels(params);
-+
-+	/*
-+	 * The SSC only supports up to 16-bit samples in I2S format, due
-+	 * to the size of the Frame Mode Register FSLEN field.  Also, I2S
-+	 * implies signed data.
-+	 */
-+	bits = 16;
-+	dma_params->pdc_xfer_size = 2;
-+
-+	/*
-+	 * Compute SSC register settings.
-+	 */
-+	switch (ssc_p->daifmt) {
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		/*
-+		 * SSC provides BCLK and LRC clocks.
-+		 *
-+		 * The SSC transmit and receive clocks are generated from the
-+		 * MCK divider, and the BCLK signal is output on the SSC TK line.
-+		 */
-+		rcmr =	  (( ssc_p->rcmr_period		<< 24) & AT91_SSC_PERIOD)
-+			| (( 1				<< 16) & AT91_SSC_STTDLY)
-+			| (( AT91_SSC_START_FALLING_RF	     ) & AT91_SSC_START)
-+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
-+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
-+			| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
-+
-+		rfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
-+			| (( 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_LOOP)
-+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
-+
-+		tcmr =	  (( ssc_p->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);
-+
-+		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);
-+		break;
-+
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+
-+		/*
-+		 * CODEC supplies BCLK and LRC clocks.
-+		 *
-+		 * The SSC transmit clock is obtained from the BCLK signal on
-+		 * on the TK line, and the SSC receive clock is generated from the
-+		 * transmit clock.
-+		 *
-+		 * For single channel data, one sample is transferred on the falling
-+		 * edge of the LRC clock.  For two channel data, one sample is
-+		 * transferred on both edges of the LRC clock.
-+		 */
-+		start_event = channels == 1
-+				? AT91_SSC_START_FALLING_RF
-+				: AT91_SSC_START_EDGE_RF;
-+
-+		rcmr =	  (( 0				<< 24) & AT91_SSC_PERIOD)
-+			| (( 1				<< 16) & AT91_SSC_STTDLY)
-+			| (( start_event		     ) & AT91_SSC_START)
-+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
-+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
-+			| (( AT91_SSC_CKS_CLOCK		     ) & AT91_SSC_CKS);
-+
-+		rfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
-+			| (( AT91_SSC_FSOS_NONE		     ) & AT91_SSC_FSOS)
-+			| (( 0				<< 16) & AT91_SSC_FSLEN)
-+			| (( 0				<<  8) & AT91_SSC_DATNB)
-+			| (( 1				<<  7) & AT91_SSC_MSBF)
-+			| (( 0				<<  5) & AT91_SSC_LOOP)
-+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
-+
-+		tcmr =	  (( 0				<< 24) & AT91_SSC_PERIOD)
-+			| (( 1				<< 16) & AT91_SSC_STTDLY)
-+			| (( start_event		     ) & AT91_SSC_START)
-+			| (( AT91_SSC_CKI_FALLING	     ) & AT91_SSC_CKI)
-+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
-+			| (( AT91_SSC_CKS_PIN		     ) & AT91_SSC_CKS);
-+
-+		tfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
-+			| (( 0				<< 23) & AT91_SSC_FSDEN)
-+			| (( AT91_SSC_FSOS_NONE		     ) & AT91_SSC_FSOS)
-+			| (( 0				<< 16) & AT91_SSC_FSLEN)
-+			| (( 0				<<  8) & AT91_SSC_DATNB)
-+			| (( 1				<<  7) & AT91_SSC_MSBF)
-+			| (( 0				<<  5) & AT91_SSC_DATDEF)
-+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
-+		break;
-+
-+	case SND_SOC_DAIFMT_CBS_CFM:
-+	case SND_SOC_DAIFMT_CBM_CFS:
-+	default:
-+		printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n",
-+			ssc_p->daifmt);
-+		return -EINVAL;
-+		break;
-+	}
-+	DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
-+
-+	if (!ssc_p->initialized) {
-+
-+		/* Enable PMC peripheral clock for this SSC */
-+		DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
-+		at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
-+
-+		/* Reset the SSC and its PDC registers */
-+		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);
-+
-+		if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
-+					0, ssc_p->name, ssc_p)) < 0) {
-+			printk(KERN_WARNING "at91-i2s: request_irq failure\n");
-+
-+			DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
-+			at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
-+			return ret;
-+		}
-+
-+		ssc_p->initialized = 1;
-+	}
-+
-+	/* set SSC clock mode register */
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
-+
-+	/* set receive clock mode and format */
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
-+
-+	/* set transmit clock mode and format */
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
-+
-+	DBG("hw_params: SSC initialized\n");
-+	return 0;
-+}
-+
-+
-+static int at91_i2s_prepare(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
-+	struct at91_pcm_dma_params *dma_params;
-+	int dir;
-+
-+	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-+	dma_params = ssc_p->dma_params[dir];
-+
-+	at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
-+			dma_params->mask->ssc_enable);
-+
-+	DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
-+		at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
-+	return 0;
-+}
-+
-+
-+#ifdef CONFIG_PM
-+static int at91_i2s_suspend(struct platform_device *pdev,
-+	struct snd_soc_cpu_dai *cpu_dai)
-+{
-+	struct at91_ssc_info *ssc_p;
-+
-+	if(!cpu_dai->active)
-+		return 0;
-+
-+	ssc_p = &ssc_info[cpu_dai->id];
-+
-+	/* Save the status register before disabling transmit and receive. */
-+	ssc_p->ssc_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->ssc_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->ssc_state.ssc_imr);
-+
-+	ssc_p->ssc_state.ssc_cmr  = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
-+	ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
-+	ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
-+	ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
-+	ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
-+
-+	return 0;
-+}
-+
-+static int at91_i2s_resume(struct platform_device *pdev,
-+	struct snd_soc_cpu_dai *cpu_dai)
-+{
-+	struct at91_ssc_info *ssc_p;
-+
-+	if(!cpu_dai->active)
-+		return 0;
-+
-+	ssc_p = &ssc_info[cpu_dai->id];
-+
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR,  ssc_p->ssc_state.ssc_cmr);
-+
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER,  ssc_p->ssc_state.ssc_imr);
-+
-+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
-+		((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
-+		((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
-+
-+	return 0;
-+}
-+
-+#else
-+#define at91_i2s_suspend	NULL
-+#define at91_i2s_resume		NULL
-+#endif
-+
-+#define AT91_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)
-+
-+struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = {
-+	{	.name = "at91_ssc0/i2s",
-+		.id = 0,
-+		.type = SND_SOC_DAI_I2S,
-+		.suspend = at91_i2s_suspend,
-+		.resume = at91_i2s_resume,
-+		.playback = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.capture = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.ops = {
-+			.startup = at91_i2s_startup,
-+			.shutdown = at91_i2s_shutdown,
-+			.prepare = at91_i2s_prepare,
-+			.hw_params = at91_i2s_hw_params,},
-+		.dai_ops = {
-+			.set_sysclk = at91_i2s_set_dai_sysclk,
-+			.set_fmt = at91_i2s_set_dai_fmt,
-+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
-+		.private_data = &ssc_info[0].ssc,
-+	},
-+#if NUM_SSC_DEVICES == 3
-+	{	.name = "at91_ssc1/i2s",
-+		.id = 1,
-+		.type = SND_SOC_DAI_I2S,
-+		.suspend = at91_i2s_suspend,
-+		.resume = at91_i2s_resume,
-+		.playback = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.capture = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.ops = {
-+			.startup = at91_i2s_startup,
-+			.shutdown = at91_i2s_shutdown,
-+			.prepare = at91_i2s_prepare,
-+			.hw_params = at91_i2s_hw_params,},
-+		.dai_ops = {
-+			.set_sysclk = at91_i2s_set_dai_sysclk,
-+			.set_fmt = at91_i2s_set_dai_fmt,
-+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
-+		.private_data = &ssc_info[1].ssc,
-+	},
-+	{	.name = "at91_ssc2/i2s",
-+		.id = 2,
-+		.type = SND_SOC_DAI_I2S,
-+		.suspend = at91_i2s_suspend,
-+		.resume = at91_i2s_resume,
-+		.playback = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.capture = {
-+			.channels_min = 1,
-+			.channels_max = 2,
-+			.rates = AT91_I2S_RATES,
-+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+		.ops = {
-+			.startup = at91_i2s_startup,
-+			.shutdown = at91_i2s_shutdown,
-+			.prepare = at91_i2s_prepare,
-+			.hw_params = at91_i2s_hw_params,},
-+		.dai_ops = {
-+			.set_sysclk = at91_i2s_set_dai_sysclk,
-+			.set_fmt = at91_i2s_set_dai_fmt,
-+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
-+		.private_data = &ssc_info[2].ssc,
-+	},
-+#endif
-+};
-+
-+EXPORT_SYMBOL_GPL(at91_i2s_dai);
-+
-+/* Module information */
-+MODULE_AUTHOR("Frank Mandarino, fmandarino at endrelia.com, www.endrelia.com");
-+MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
-+MODULE_LICENSE("GPL");
-Index: linux-2.6-asoc-pxa/sound/soc/at91/at91-pcm.c
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/at91-pcm.c
-@@ -0,0 +1,432 @@
-+/*
-+ * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
-+ *
-+ * 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/hardware.h>
-+#include <asm/arch/at91_ssc.h>
-+#include <asm/arch/at91_pdc.h>
-+
-+#include "at91-pcm.h"
-+
-+#if 0
-+#define	DBG(x...)	printk(KERN_INFO "at91-pcm: " x)
-+#else
-+#define	DBG(x...)
-+#endif
-+
-+static const struct snd_pcm_hardware at91_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 at91_runtime_data {
-+	struct at91_pcm_dma_params *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 at91_pcm_dma_irq(u32 ssc_sr,
-+	struct snd_pcm_substream *substream)
-+{
-+	struct at91_runtime_data *prtd = substream->runtime->private_data;
-+	struct at91_pcm_dma_params *params = prtd->params;
-+	static int count = 0;
-+
-+	count++;
-+
-+	if (ssc_sr & params->mask->ssc_endbuf) {
-+
-+		printk(KERN_WARNING
-+			"at91-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->ssc_base + AT91_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->ssc_base + params->pdc->xpr, prtd->period_ptr);
-+		at91_ssc_write(params->ssc_base + params->pdc->xcr,
-+				prtd->period_size / params->pdc_xfer_size);
-+
-+		at91_ssc_write(params->ssc_base + AT91_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->ssc_base + params->pdc->xnpr, prtd->period_ptr);
-+		at91_ssc_write(params->ssc_base + params->pdc->xncr,
-+				prtd->period_size / params->pdc_xfer_size);
-+	}
-+
-+	snd_pcm_period_elapsed(substream);
-+}
-+
-+static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct at91_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->dai->cpu_dai->dma_data;
-+	prtd->params->dma_intr_handler = at91_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 at91_pcm_hw_free(struct snd_pcm_substream *substream)
-+{
-+	struct at91_runtime_data *prtd = substream->runtime->private_data;
-+	struct at91_pcm_dma_params *params = prtd->params;
-+
-+	if (params != NULL) {
-+		at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
-+		prtd->params->dma_intr_handler = NULL;
-+	}
-+
-+	return 0;
-+}
-+
-+static int at91_pcm_prepare(struct snd_pcm_substream *substream)
-+{
-+	struct at91_runtime_data *prtd = substream->runtime->private_data;
-+	struct at91_pcm_dma_params *params = prtd->params;
-+
-+	at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
-+			params->mask->ssc_endx | params->mask->ssc_endbuf);
-+
-+	at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
-+	return 0;
-+}
-+
-+static int at91_pcm_trigger(struct snd_pcm_substream *substream,
-+	int cmd)
-+{
-+	struct at91_runtime_data *prtd = substream->runtime->private_data;
-+	struct at91_pcm_dma_params *params = prtd->params;
-+	int ret = 0;
-+
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		prtd->period_ptr = prtd->dma_buffer;
-+
-+		at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
-+		at91_ssc_write(params->ssc_base + params->pdc->xcr,
-+				prtd->period_size / params->pdc_xfer_size);
-+
-+		prtd->period_ptr += prtd->period_size;
-+		at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
-+		at91_ssc_write(params->ssc_base + 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->ssc_base + params->pdc->xpr),
-+			at91_ssc_read(params->ssc_base + params->pdc->xcr),
-+			at91_ssc_read(params->ssc_base + params->pdc->xnpr),
-+			at91_ssc_read(params->ssc_base + params->pdc->xncr));
-+
-+		at91_ssc_write(params->ssc_base + AT91_SSC_IER,
-+			params->mask->ssc_endx | params->mask->ssc_endbuf);
-+
-+		at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
-+
-+		DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc_base + AT91_SSC_SR),
-+					at91_ssc_read(params->ssc_base + AT91_SSC_IER));
-+		break;
-+
-+	case SNDRV_PCM_TRIGGER_STOP:
-+	case SNDRV_PCM_TRIGGER_SUSPEND:
-+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+		at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
-+		break;
-+
-+	case SNDRV_PCM_TRIGGER_RESUME:
-+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+		at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
-+		break;
-+
-+	default:
-+		ret = -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+
-+static snd_pcm_uframes_t at91_pcm_pointer(
-+	struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct at91_runtime_data *prtd = runtime->private_data;
-+	struct at91_pcm_dma_params *params = prtd->params;
-+	dma_addr_t ptr;
-+	snd_pcm_uframes_t x;
-+
-+	ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
-+	x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-+
-+	if (x == runtime->buffer_size)
-+		x = 0;
-+	return x;
-+}
-+
-+static int at91_pcm_open(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct at91_runtime_data *prtd;
-+	int ret = 0;
-+
-+	snd_soc_set_runtime_hwparams(substream, &at91_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 at91_runtime_data), GFP_KERNEL);
-+	if (prtd == NULL) {
-+		ret = -ENOMEM;
-+		goto out;
-+	}
-+	runtime->private_data = prtd;
-+
-+ out:
-+	return ret;
-+}
-+
-+static int at91_pcm_close(struct snd_pcm_substream *substream)
-+{
-+	struct at91_runtime_data *prtd = substream->runtime->private_data;
-+
-+	kfree(prtd);
-+	return 0;
-+}
-+
-+static int at91_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 at91_pcm_ops = {
-+	.open		= at91_pcm_open,
-+	.close		= at91_pcm_close,
-+	.ioctl		= snd_pcm_lib_ioctl,
-+	.hw_params	= at91_pcm_hw_params,
-+	.hw_free	= at91_pcm_hw_free,
-+	.prepare	= at91_pcm_prepare,
-+	.trigger	= at91_pcm_trigger,
-+	.pointer	= at91_pcm_pointer,
-+	.mmap		= at91_pcm_mmap,
-+};
-+
-+static int at91_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 = at91_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 at91_pcm_dmamask = 0xffffffff;
-+
-+static int at91_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 = &at91_pcm_dmamask;
-+	if (!card->dev->coherent_dma_mask)
-+		card->dev->coherent_dma_mask = 0xffffffff;
-+
-+	if (dai->playback.channels_min) {
-+		ret = at91_pcm_preallocate_dma_buffer(pcm,
-+			SNDRV_PCM_STREAM_PLAYBACK);
-+		if (ret)
-+			goto out;
-+	}
-+
-+	if (dai->capture.channels_min) {
-+		ret = at91_pcm_preallocate_dma_buffer(pcm,
-+			SNDRV_PCM_STREAM_CAPTURE);
-+		if (ret)
-+			goto out;
-+	}
-+ out:
-+	return ret;
-+}
-+
-+static void at91_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;
-+	}
-+}
-+
-+#ifdef CONFIG_PM
-+static int at91_pcm_suspend(struct platform_device *pdev,
-+	struct snd_soc_cpu_dai *dai)
-+{
-+	struct snd_pcm_runtime *runtime = dai->runtime;
-+	struct at91_runtime_data *prtd;
-+	struct at91_pcm_dma_params *params;
-+
-+	if (!runtime)
-+		return 0;
-+
-+	prtd = runtime->private_data;
-+	params = prtd->params;
-+
-+	/* disable the PDC and save the PDC registers */
-+
-+	at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
-+
-+	prtd->pdc_xpr_save  = at91_ssc_read(params->ssc_base + params->pdc->xpr);
-+	prtd->pdc_xcr_save  = at91_ssc_read(params->ssc_base + params->pdc->xcr);
-+	prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
-+	prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
-+
-+	return 0;
-+}
-+
-+static int at91_pcm_resume(struct platform_device *pdev,
-+	struct snd_soc_cpu_dai *dai)
-+{
-+	struct snd_pcm_runtime *runtime = dai->runtime;
-+	struct at91_runtime_data *prtd;
-+	struct at91_pcm_dma_params *params;
-+
-+	if (!runtime)
-+		return 0;
-+
-+	prtd = runtime->private_data;
-+	params = prtd->params;
-+
-+	/* restore the PDC registers and enable the PDC */
-+	at91_ssc_write(params->ssc_base + params->pdc->xpr,  prtd->pdc_xpr_save);
-+	at91_ssc_write(params->ssc_base + params->pdc->xcr,  prtd->pdc_xcr_save);
-+	at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
-+	at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
-+
-+	at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
-+	return 0;
-+}
-+#else
-+#define at91_pcm_suspend	NULL
-+#define at91_pcm_resume		NULL
-+#endif
-+
-+struct snd_soc_platform at91_soc_platform = {
-+	.name		= "at91-audio",
-+	.pcm_ops 	= &at91_pcm_ops,
-+	.pcm_new	= at91_pcm_new,
-+	.pcm_free	= at91_pcm_free_dma_buffers,
-+	.suspend	= at91_pcm_suspend,
-+	.resume		= at91_pcm_resume,
-+};
-+
-+EXPORT_SYMBOL_GPL(at91_soc_platform);
-+
-+MODULE_AUTHOR("Frank Mandarino <fmandarino at endrelia.com>");
-+MODULE_DESCRIPTION("Atmel AT91 PCM module");
-+MODULE_LICENSE("GPL");
-Index: linux-2.6-asoc-pxa/sound/soc/at91/at91-pcm.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/at91-pcm.h
-@@ -0,0 +1,72 @@
-+/*
-+ * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _AT91_PCM_H
-+#define _AT91_PCM_H
-+
-+#include <asm/arch/hardware.h>
-+
-+struct at91_ssc_periph {
-+	void __iomem	*base;
-+	u32		pid;
-+};
-+
-+/*
-+ * Registers and status bits that are required by the PCM driver.
-+ */
-+struct at91_pdc_regs {
-+	unsigned int	xpr;		/* PDC recv/trans pointer */
-+	unsigned int	xcr;		/* PDC recv/trans counter */
-+	unsigned int	xnpr;		/* PDC next recv/trans pointer */
-+	unsigned int	xncr;		/* PDC next recv/trans counter */
-+	unsigned int	ptcr;		/* PDC transfer control */
-+};
-+
-+struct at91_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.
-+ */
-+struct at91_pcm_dma_params {
-+	char *name;			/* stream identifier */
-+	int pdc_xfer_size;		/* PDC counter increment in bytes */
-+	void __iomem *ssc_base;		/* SSC base address */
-+	struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
-+	struct at91_ssc_mask *mask;/* SSC & PDC status bits */
-+	struct snd_pcm_substream *substream;
-+	void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
-+};
-+
-+extern struct snd_soc_platform at91_soc_platform;
-+
-+#define at91_ssc_read(a)	((unsigned long) __raw_readl(a))
-+#define at91_ssc_write(a,v)	__raw_writel((v),(a))
-+
-+#endif /* _AT91_PCM_H */
 Index: linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-ssp.h
 ===================================================================
 --- /dev/null
@@ -30876,58 +18591,6 @@
 +extern struct snd_soc_cpu_dai pxa_ssp_dai[3];
 +
 +#endif
-Index: linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-ac97.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-ac97.h
-@@ -0,0 +1,22 @@
-+/*
-+ * linux/sound/arm/pxa2xx-ac97.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 _PXA2XX_AC97_H
-+#define _PXA2XX_AC97_H
-+
-+/* pxa2xx DAI ID's */
-+#define PXA2XX_DAI_AC97_HIFI	0
-+#define PXA2XX_DAI_AC97_AUX		1
-+#define PXA2XX_DAI_AC97_MIC		2
-+
-+extern struct snd_soc_cpu_dai pxa_ac97_dai[3];
-+
-+/* platform data */
-+extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
-+
-+#endif
-Index: linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-i2s.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/pxa/pxa2xx-i2s.h
-@@ -0,0 +1,20 @@
-+/*
-+ * linux/sound/arm/pxa2xx-i2s.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 _PXA2XX_I2S_H
-+#define _PXA2XX_I2S_H
-+
-+/* pxa2xx DAI ID's */
-+#define PXA2XX_DAI_I2S			0
-+
-+/* I2S clock */
-+#define PXA2XX_I2S_SYSCLK		0
-+
-+extern struct snd_soc_cpu_dai pxa_i2s_dai;
-+
-+#endif
 Index: linux-2.6-asoc-pxa/sound/soc/s3c24xx/Kconfig
 ===================================================================
 --- /dev/null
@@ -34415,38 +22078,6 @@
 +extern struct snd_soc_cpu_dai imx_ssi_pcm_dai[2];
 +
 +#endif
-Index: linux-2.6-asoc-pxa/sound/soc/at91/at91-i2s.h
-===================================================================
---- /dev/null
-+++ linux-2.6-asoc-pxa/sound/soc/at91/at91-i2s.h
-@@ -0,0 +1,27 @@
-+/*
-+ * at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC
-+ *
-+ * Author:	Frank Mandarino <fmandarino at endrelia.com>
-+ *		Endrelia Technologies Inc.
-+ * Created:	Jan 9, 2007
-+ *
-+ * 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 _AT91_I2S_H
-+#define _AT91_I2S_H
-+
-+/* I2S system clock ids */
-+#define AT91_SYSCLK_MCK		0 /* SSC uses AT91 MCK as system clock */
-+
-+/* I2S divider ids */
-+#define AT91SSC_CMR_DIV		0 /* MCK divider for BCLK */
-+#define AT91SSC_TCMR_PERIOD	1 /* BCLK divider for transmit FS */
-+#define AT91SSC_RCMR_PERIOD	2 /* BCLK divider for receive FS */
-+
-+extern struct snd_soc_cpu_dai at91_i2s_dai[];
-+
-+#endif /* _AT91_I2S_H */
-+
 Index: linux-2.6-asoc-pxa/sound/soc/imx/mx31ads_wm8753.c
 ===================================================================
 --- /dev/null

Modified: trunk/src/target/kernel/patches/gta01-core.patch
===================================================================
--- trunk/src/target/kernel/patches/gta01-core.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/gta01-core.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,11 +1,11 @@
 This patch adds support for the FIC GTA01 machine type to the ARM port of
 the linux kernel.
 
-Index: linux-2.6.20.7-moko/arch/arm/mach-s3c2410/Kconfig
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2410/Kconfig
 ===================================================================
---- linux-2.6.20.7-moko.orig/arch/arm/mach-s3c2410/Kconfig
-+++ linux-2.6.20.7-moko/arch/arm/mach-s3c2410/Kconfig
-@@ -86,6 +86,14 @@
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2410/Kconfig
++++ linux-2.6.21-moko/arch/arm/mach-s3c2410/Kconfig
+@@ -109,5 +109,12 @@
  	help
  	   Say Y here if you are using the Armzone QT2410
  
@@ -16,26 +16,22 @@
 +	help
 +	   Say Y here if you are using the FIC Neo1973 GSM Phone
 +
-+
- config ARCH_S3C2440
- 	bool "SMDK2440"
- 	select CPU_S3C2440
-Index: linux-2.6.20.7-moko/arch/arm/mach-s3c2410/Makefile
+ endmenu
+ 
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2410/Makefile
 ===================================================================
---- linux-2.6.20.7-moko.orig/arch/arm/mach-s3c2410/Makefile
-+++ linux-2.6.20.7-moko/arch/arm/mach-s3c2410/Makefile
-@@ -89,5 +89,6 @@
- obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
- obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2410/Makefile
++++ linux-2.6.21-moko/arch/arm/mach-s3c2410/Makefile
+@@ -29,3 +29,4 @@
+ obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
+ obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
  obj-$(CONFIG_MACH_QT2410)	+= mach-qt2410.o
 +obj-$(CONFIG_MACH_GTA01)	+= mach-gta01.o
- 
- obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
-Index: linux-2.6.20.7-moko/arch/arm/mach-s3c2410/mach-gta01.c
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-gta01.c
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.7-moko/arch/arm/mach-s3c2410/mach-gta01.c
-@@ -0,0 +1,741 @@
++++ linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-gta01.c
+@@ -0,0 +1,740 @@
 +/*
 + * linux/arch/arm/mach-s3c2410/mach-gta01.c
 + *
@@ -105,11 +101,10 @@
 +
 +#include <asm/arch/gta01.h>
 +
-+#include "devs.h"
-+#include "cpu.h"
++#include <asm/plat-s3c24xx/devs.h>
++#include <asm/plat-s3c24xx/cpu.h>
++#include <asm/plat-s3c24xx/pm.h>
 +
-+#include "pm.h"
-+
 +static struct map_desc gta01_iodesc[] __initdata = {
 +	{
 +		.virtual	= 0xe0000000,
@@ -766,7 +761,7 @@
 +	s3c2410_pm_init();
 +}
 +
-+MACHINE_START(GTA01, "GTA01")
++MACHINE_START(NEO1973_GTA01, "GTA01")
 +	.phys_io	= S3C2410_PA_UART,
 +	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 +	.boot_params	= S3C2410_SDRAM_PA + 0x100,
@@ -777,10 +772,10 @@
 +MACHINE_END
 +
 +
-Index: linux-2.6.20.7-moko/include/asm-arm/arch-s3c2410/gta01.h
+Index: linux-2.6.21-moko/include/asm-arm/arch-s3c2410/gta01.h
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.7-moko/include/asm-arm/arch-s3c2410/gta01.h
++++ linux-2.6.21-moko/include/asm-arm/arch-s3c2410/gta01.h
 @@ -0,0 +1,69 @@
 +#ifndef _GTA01_H
 +#define _GTA01_H

Modified: trunk/src/target/kernel/patches/gta01-pcf50606.patch
===================================================================
--- trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,10 +1,10 @@
 This is the PCF50606 power management unit driver for FIC GTA01
 
-Index: linux-2.6.20.7-moko/drivers/i2c/chips/pcf50606.c
+Index: linux-2.6.21-moko/drivers/i2c/chips/pcf50606.c
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.7-moko/drivers/i2c/chips/pcf50606.c
-@@ -0,0 +1,1923 @@
++++ linux-2.6.21-moko/drivers/i2c/chips/pcf50606.c
+@@ -0,0 +1,1925 @@
 +/* Philips PCF50606 Power Management Unit (PMU) driver
 + *
 + * (C) 2006 by OpenMoko, Inc.
@@ -55,8 +55,8 @@
 +#include <linux/sched.h>
 +#include <linux/platform_device.h>
 +#include <linux/pcf50606.h>
++#include <linux/apm-emulation.h>
 +
-+#include <asm/apm.h>
 +#include <asm/mach-types.h>
 +#include <asm/arch/gta01.h>
 +
@@ -1478,23 +1478,20 @@
 +static int pcf50606bl_set_intensity(struct backlight_device *bd)
 +{
 +	struct pcf50606_data *pcf = class_get_devdata(&bd->class_dev);
-+	int intensity = bd->props->brightness;
++	int intensity = bd->props.brightness;
 +
-+	if (bd->props->power != FB_BLANK_UNBLANK)
++	if (bd->props.power != FB_BLANK_UNBLANK)
 +		intensity = 0;
-+	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
++	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 +		intensity = 0;
 +
 +	return reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
 +				(intensity << PCF50606_PWMC1_DC_SHIFT));
 +}
 +
-+static struct backlight_properties pcf50606bl_prop = {
-+	.owner		= THIS_MODULE,
++static struct backlight_ops pcf50606bl_ops = {
 +	.get_brightness	= pcf50606bl_get_intensity,
 +	.update_status	= pcf50606bl_set_intensity,
-+	.max_brightness	= 16,
-+	.brightness	= 0,
 +};
 +
 +/***********************************************************************
@@ -1671,9 +1668,14 @@
 +		data->backlight = backlight_device_register("pcf50606-bl",
 +							    &new_client->dev,
 +							    data,
-+							    &pcf50606bl_prop);
++							    &pcf50606bl_ops);
 +		if (!data->backlight)
 +			goto exit_misc;
++		/* FIXME: are we sure we want default == off? */
++		data->backlight->props.max_brightness = 16;
++		data->backlight->props.power = FB_BLANK_UNBLANK;
++		data->backlight->props.brightness = 0;
++		backlight_update_status(data->backlight);
 +	}
 +
 +	data->input_dev = input_allocate_device();
@@ -1695,7 +1697,7 @@
 +	apm_get_power_status = pcf50606_get_power_status;
 +
 +#ifdef CONFIG_MACH_GTA01
-+	if (machine_is_gta01()) {
++	if (machine_is_neo1973_gta01()) {
 +		gta01_pm_gps_dev.dev.parent = &new_client->dev;
 +		switch (system_rev) {
 +		case GTA01Bv2_SYSTEM_REV:
@@ -1928,10 +1930,10 @@
 +
 +module_init(pcf50606_init);
 +module_exit(pcf50606_exit);
-Index: linux-2.6.20.7-moko/drivers/i2c/chips/pcf50606.h
+Index: linux-2.6.21-moko/drivers/i2c/chips/pcf50606.h
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.7-moko/drivers/i2c/chips/pcf50606.h
++++ linux-2.6.21-moko/drivers/i2c/chips/pcf50606.h
 @@ -0,0 +1,302 @@
 +#ifndef _PCF50606_H
 +#define _PCF50606_H
@@ -2235,10 +2237,10 @@
 +
 +#endif /* _PCF50606_H */
 +
-Index: linux-2.6.20.7-moko/drivers/i2c/chips/Kconfig
+Index: linux-2.6.21-moko/drivers/i2c/chips/Kconfig
 ===================================================================
---- linux-2.6.20.7-moko.orig/drivers/i2c/chips/Kconfig
-+++ linux-2.6.20.7-moko/drivers/i2c/chips/Kconfig
+--- linux-2.6.21-moko.orig/drivers/i2c/chips/Kconfig
++++ linux-2.6.21-moko/drivers/i2c/chips/Kconfig
 @@ -36,6 +36,17 @@
  	  This driver can also be built as a module.  If so, the module
  	  will be called eeprom.
@@ -2257,10 +2259,10 @@
  config SENSORS_PCF8574
  	tristate "Philips PCF8574 and PCF8574A"
  	depends on I2C && EXPERIMENTAL
-Index: linux-2.6.20.7-moko/drivers/i2c/chips/Makefile
+Index: linux-2.6.21-moko/drivers/i2c/chips/Makefile
 ===================================================================
---- linux-2.6.20.7-moko.orig/drivers/i2c/chips/Makefile
-+++ linux-2.6.20.7-moko/drivers/i2c/chips/Makefile
+--- linux-2.6.21-moko.orig/drivers/i2c/chips/Makefile
++++ linux-2.6.21-moko/drivers/i2c/chips/Makefile
 @@ -8,6 +8,7 @@
  obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
  obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
@@ -2269,10 +2271,10 @@
  obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
  obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
  obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
-Index: linux-2.6.20.7-moko/include/linux/i2c-id.h
+Index: linux-2.6.21-moko/include/linux/i2c-id.h
 ===================================================================
---- linux-2.6.20.7-moko.orig/include/linux/i2c-id.h
-+++ linux-2.6.20.7-moko/include/linux/i2c-id.h
+--- linux-2.6.21-moko.orig/include/linux/i2c-id.h
++++ linux-2.6.21-moko/include/linux/i2c-id.h
 @@ -159,6 +159,7 @@
  #define I2C_DRIVERID_FSCHER 1046
  #define I2C_DRIVERID_W83L785TS 1047
@@ -2281,10 +2283,10 @@
  
  /*
   * ---- Adapter types ----------------------------------------------------
-Index: linux-2.6.20.7-moko/include/linux/pcf50606.h
+Index: linux-2.6.21-moko/include/linux/pcf50606.h
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.7-moko/include/linux/pcf50606.h
++++ linux-2.6.21-moko/include/linux/pcf50606.h
 @@ -0,0 +1,101 @@
 +#ifndef _LINUX_PCF50606_H
 +#define _LINUX_PCF50606_H

Modified: trunk/src/target/kernel/patches/gta01-vibrator.patch
===================================================================
--- trunk/src/target/kernel/patches/gta01-vibrator.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/gta01-vibrator.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -2,10 +2,10 @@
 uses the existing LED class driver framework, since there's a lot of
 similarity between the LED and the vibrator function.
 
-Index: linux-2.6.20.4-moko/drivers/leds/leds-gta01.c
+Index: linux-2.6.21-moko/drivers/leds/leds-gta01.c
 ===================================================================
 --- /dev/null
-+++ linux-2.6.20.4-moko/drivers/leds/leds-gta01.c
++++ linux-2.6.21-moko/drivers/leds/leds-gta01.c
 @@ -0,0 +1,133 @@
 +/*
 + * LED driver for the FIC GTA01 (Neo1973) GSM Phone Vibrator
@@ -80,7 +80,7 @@
 +	struct gta01_vib_priv *vp;
 +	struct resource *r;
 +
-+	if (!machine_is_gta01())
++	if (!machine_is_neo1973_gta01())
 +		return -EIO;
 +
 +	r = platform_get_resource(pdev, 0, 0);
@@ -140,13 +140,13 @@
 +MODULE_AUTHOR("Harald Welte <laforge at openmoko.org>");
 +MODULE_DESCRIPTION("FIC GTA01 Vibrator driver");
 +MODULE_LICENSE("GPL");
-Index: linux-2.6.20.4-moko/drivers/leds/Kconfig
+Index: linux-2.6.21-moko/drivers/leds/Kconfig
 ===================================================================
---- linux-2.6.20.4-moko.orig/drivers/leds/Kconfig
-+++ linux-2.6.20.4-moko/drivers/leds/Kconfig
-@@ -82,6 +82,12 @@
+--- linux-2.6.21-moko.orig/drivers/leds/Kconfig
++++ linux-2.6.21-moko/drivers/leds/Kconfig
+@@ -94,6 +94,12 @@
  	help
- 	  This option enables support for the PCEngines WRAP programmable LEDs.
+ 	  This option enables support for the front LED on Cobalt Server
  
 +config LEDS_GTA01
 +	tristate "LED Support for the FIC Neo1973 Vibrator"
@@ -157,14 +157,14 @@
  comment "LED Triggers"
  
  config LEDS_TRIGGERS
-Index: linux-2.6.20.4-moko/drivers/leds/Makefile
+Index: linux-2.6.21-moko/drivers/leds/Makefile
 ===================================================================
---- linux-2.6.20.4-moko.orig/drivers/leds/Makefile
-+++ linux-2.6.20.4-moko/drivers/leds/Makefile
-@@ -14,6 +14,7 @@
- obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
- obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
+--- linux-2.6.21-moko.orig/drivers/leds/Makefile
++++ linux-2.6.21-moko/drivers/leds/Makefile
+@@ -16,6 +16,7 @@
  obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
+ obj-$(CONFIG_LEDS_H1940)		+= leds-h1940.o
+ obj-$(CONFIG_LEDS_COBALT)		+= leds-cobalt.o
 +obj-$(CONFIG_LEDS_GTA01)		+= leds-gta01.o
  
  # LED Triggers

Modified: trunk/src/target/kernel/patches/hxd8-core.patch
===================================================================
--- trunk/src/target/kernel/patches/hxd8-core.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/hxd8-core.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,11 +1,11 @@
 This patch adds another machine, the FIC HXD8
-Index: linux-2.6.20.4/arch/arm/mach-s3c2410/Kconfig
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2440/Kconfig
 ===================================================================
---- linux-2.6.20.4.orig/arch/arm/mach-s3c2410/Kconfig	2007-03-30 21:33:04.000000000 +0200
-+++ linux-2.6.20.4/arch/arm/mach-s3c2410/Kconfig	2007-03-30 21:33:04.000000000 +0200
-@@ -94,6 +94,12 @@
- 	help
- 	   Say Y here if you are using the FIC Neo1973 GSM Phone
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2440/Kconfig
++++ linux-2.6.21-moko/arch/arm/mach-s3c2440/Kconfig
+@@ -66,6 +66,12 @@
+ 	default y if ARCH_S3C2440
+ 	select CPU_S3C2440
  
 +config MACH_HXD8
 +	bool "FIC HXD8"
@@ -14,25 +14,23 @@
 +	help
 +	   Say Y here if you are using the FIC Neo1973 GSM Phone
  
- config ARCH_S3C2440
- 	bool "SMDK2440"
-Index: linux-2.6.20.4/arch/arm/mach-s3c2410/Makefile
+ endmenu
+ 
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2440/Makefile
 ===================================================================
---- linux-2.6.20.4.orig/arch/arm/mach-s3c2410/Makefile	2007-03-30 21:32:42.000000000 +0200
-+++ linux-2.6.20.4/arch/arm/mach-s3c2410/Makefile	2007-03-30 21:33:04.000000000 +0200
-@@ -90,5 +90,6 @@
- obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
- obj-$(CONFIG_MACH_QT2410)	+= mach-qt2410.o
- obj-$(CONFIG_MACH_GTA01)	+= mach-gta01.o
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2440/Makefile
++++ linux-2.6.21-moko/arch/arm/mach-s3c2440/Makefile
+@@ -21,3 +21,4 @@
+ obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
+ obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
+ obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
 +obj-$(CONFIG_MACH_HXD8)		+= mach-hxd8.o
- 
- obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
-Index: linux-2.6.20.4/arch/arm/mach-s3c2410/mach-hxd8.c
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2440/mach-hxd8.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.4/arch/arm/mach-s3c2410/mach-hxd8.c	2007-03-30 22:39:28.000000000 +0200
+--- /dev/null
++++ linux-2.6.21-moko/arch/arm/mach-s3c2440/mach-hxd8.c
 @@ -0,0 +1,428 @@
-+/* linux/arch/arm/mach-s3c2410/mach-hxd8.c
++/* linux/arch/arm/mach-s3c2440/mach-hxd8.c
 + *
 + * S3C2440 Machine Support for the FIC HXD8
 + *
@@ -99,15 +97,15 @@
 +#include <asm/arch/spi-gpio.h>
 +#include <asm/arch/usb-control.h>
 +
-+#include <asm/arch/hxd8.h>
++#include <asm/arch-s3c2440/hxd8.h>
 +#include <asm/arch/gta01.h>
 +
 +//#include "s3c2410.h"
 +//#include "s3c2440.h"
 +//#include "clock.h"
-+#include "devs.h"
-+#include "cpu.h"
-+#include "pm.h"
++#include <asm/plat-s3c24xx/devs.h>
++#include <asm/plat-s3c24xx/cpu.h>
++#include <asm/plat-s3c24xx/pm.h>
 +
 +static struct map_desc hxd8_iodesc[] __initdata = {
 +	/* ISA IO Space map (memory space selected by A24) */
@@ -460,10 +458,10 @@
 +	.init_machine	= hxd8_machine_init,
 +	.timer		= &s3c24xx_timer,
 +MACHINE_END
-Index: linux-2.6.20.4/include/asm-arm/arch-s3c2410/hxd8.h
+Index: linux-2.6.21-moko/include/asm-arm/arch-s3c2440/hxd8.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.4/include/asm-arm/arch-s3c2410/hxd8.h	2007-03-30 21:33:04.000000000 +0200
+--- /dev/null
++++ linux-2.6.21-moko/include/asm-arm/arch-s3c2440/hxd8.h
 @@ -0,0 +1,16 @@
 +#ifndef _HXD8_H
 +#define _HXD8_H

Modified: trunk/src/target/kernel/patches/pm-debug_less_verbose.patch
===================================================================
--- trunk/src/target/kernel/patches/pm-debug_less_verbose.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/pm-debug_less_verbose.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,15 +1,16 @@
-Index: linux-2.6.20/drivers/base/power/main.c
+Index: linux-2.6.21-moko/drivers/base/power/main.c
 ===================================================================
---- linux-2.6.20.orig/drivers/base/power/main.c	2007-02-15 19:56:34.000000000 +0100
-+++ linux-2.6.20/drivers/base/power/main.c	2007-02-15 19:56:43.000000000 +0100
-@@ -53,8 +53,8 @@
+--- linux-2.6.21-moko.orig/drivers/base/power/main.c
++++ linux-2.6.21-moko/drivers/base/power/main.c
+@@ -53,9 +53,9 @@
  {
  	int error;
  
 -	pr_debug("PM: Adding info for %s:%s\n",
--		 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
-+	//pr_debug("PM: Adding info for %s:%s\n",
-+	//	 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
++	/*pr_debug("PM: Adding info for %s:%s\n",
+ 		 dev->bus ? dev->bus->name : "No Bus",
+-		 kobject_name(&dev->kobj));
++		 kobject_name(&dev->kobj)); */
  	down(&dpm_list_sem);
  	list_add_tail(&dev->power.entry, &dpm_active);
  	device_pm_set_parent(dev, dev->parent);

Modified: trunk/src/target/kernel/patches/qt2410-base.patch
===================================================================
--- trunk/src/target/kernel/patches/qt2410-base.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/qt2410-base.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,37 +1,7 @@
-Index: linux-2.6.20.1/arch/arm/mach-s3c2410/Kconfig
+Index: linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c.old
 ===================================================================
---- linux-2.6.20.1.orig/arch/arm/mach-s3c2410/Kconfig	2007-02-20 21:32:44.000000000 +0100
-+++ linux-2.6.20.1/arch/arm/mach-s3c2410/Kconfig	2007-02-21 16:28:00.000000000 +0100
-@@ -80,6 +80,12 @@
- 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
-            <http://www.fsforth.de>
- 
-+config MACH_QT2410
-+	bool "QT2410"
-+	select CPU_S3C2410
-+	help
-+	   Say Y here if you are using the Armzone QT2410
-+
- config ARCH_S3C2440
- 	bool "SMDK2440"
- 	select CPU_S3C2440
-Index: linux-2.6.20.1/arch/arm/mach-s3c2410/Makefile
-===================================================================
---- linux-2.6.20.1.orig/arch/arm/mach-s3c2410/Makefile	2007-02-20 21:32:44.000000000 +0100
-+++ linux-2.6.20.1/arch/arm/mach-s3c2410/Makefile	2007-02-21 16:28:00.000000000 +0100
-@@ -88,5 +88,6 @@
- obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
- obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
- obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
-+obj-$(CONFIG_MACH_QT2410)	+= mach-qt2410.o
- 
--obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
-\ No newline at end of file
-+obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
-Index: linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c
-===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-21 16:28:56.000000000 +0100
++++ linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c.old	2007-02-21 16:28:56.000000000 +0100
 @@ -0,0 +1,356 @@
 +/*
 + *

Deleted: trunk/src/target/kernel/patches/qt2410-biglcd.patch
===================================================================
--- trunk/src/target/kernel/patches/qt2410-biglcd.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/qt2410-biglcd.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,180 +0,0 @@
-Index: linux-2.6.20/arch/arm/mach-s3c2410/mach-qt2410.c
-===================================================================
---- linux-2.6.20.orig/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-17 00:41:38.000000000 +0100
-+++ linux-2.6.20/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-17 00:43:47.000000000 +0100
-@@ -96,6 +96,135 @@
- 
- /* LCD driver info */
- 
-+/* Configuration for 640x480 SHARP LQ080V3DG01 */
-+static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
-+	.type	=  S3C2410_LCDCON1_TFT,
-+	.regs	= {
-+
-+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
-+				  S3C2410_LCDCON1_TFT |
-+				  S3C2410_LCDCON1_CLKVAL(0x01),	/* HCLK/4 */
-+
-+		.lcdcon2	= S3C2410_LCDCON2_VBPD(18) |	/* 19 */
-+				  S3C2410_LCDCON2_LINEVAL(479) |
-+				  S3C2410_LCDCON2_VFPD(10) |	/* 11 */
-+				  S3C2410_LCDCON2_VSPW(14),	/* 15 */
-+
-+		.lcdcon3	= S3C2410_LCDCON3_HBPD(43) |	/* 44 */
-+				  S3C2410_LCDCON3_HOZVAL(639) |	/* 640 */
-+				  S3C2410_LCDCON3_HFPD(115),	/* 116 */
-+
-+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
-+				  S3C2410_LCDCON4_HSPW(95),	/* 96 */
-+
-+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
-+				  S3C2410_LCDCON5_INVVLINE |
-+				  S3C2410_LCDCON5_INVVFRAME |
-+				  S3C2410_LCDCON5_PWREN |
-+				  S3C2410_LCDCON5_HWSWP,
-+	},
-+
-+#if 0
-+	/* currently setup by downloader */
-+	.gpccon		= 0xaa940659,
-+	.gpccon_mask	= 0xffffffff,
-+	.gpcup		= 0x0000ffff,
-+	.gpcup_mask	= 0xffffffff,
-+	.gpdcon		= 0xaa84aaa0,
-+	.gpdcon_mask	= 0xffffffff,
-+	.gpdup		= 0x0000faff,
-+	.gpdup_mask	= 0xffffffff,
-+#endif
-+
-+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
-+
-+	.width		= 640,
-+	.height		= 480,
-+
-+	.xres		= {
-+		.min	= 640,
-+		.max	= 640,
-+		.defval	= 640,
-+	},
-+
-+	.yres		= {
-+		.min	= 480,
-+		.max	= 480,
-+		.defval = 480,
-+	},
-+
-+	.bpp		= {
-+		.min	= 16,
-+		.max	= 16,
-+		.defval = 16,
-+	},
-+};
-+
-+/* Configuration for 480x640 toppoly TD028TTEC1 */
-+static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
-+	.type	= S3C2410_LCDCON1_TFT,
-+	.regs	= {
-+
-+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
-+				  S3C2410_LCDCON1_TFT |
-+				  S3C2410_LCDCON1_CLKVAL(0x01),	/* HCLK/4 */
-+
-+		.lcdcon2	= S3C2410_LCDCON2_VBPD(1) |	/* 2 */
-+				  S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
-+				  S3C2410_LCDCON2_VFPD(3) |	/* 4 */
-+				  S3C2410_LCDCON2_VSPW(1),	/* 2 */
-+
-+		.lcdcon3	= S3C2410_LCDCON3_HBPD(7) |	/* 8 */
-+				  S3C2410_LCDCON3_HOZVAL(479) |	/* 479 */
-+				  S3C2410_LCDCON3_HFPD(23),	/* 24 */
-+
-+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
-+				  S3C2410_LCDCON4_HSPW(7),	/* 8 */
-+
-+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
-+				  S3C2410_LCDCON5_INVVLINE |
-+				  S3C2410_LCDCON5_INVVFRAME |
-+				  S3C2410_LCDCON5_PWREN |
-+				  S3C2410_LCDCON5_HWSWP,
-+	},
-+
-+#if 0
-+	/* currently setup by downloader */
-+	.gpccon		= 0xaa940659,
-+	.gpccon_mask	= 0xffffffff,
-+	.gpcup		= 0x0000ffff,
-+	.gpcup_mask	= 0xffffffff,
-+	.gpdcon		= 0xaa84aaa0,
-+	.gpdcon_mask	= 0xffffffff,
-+	.gpdup		= 0x0000faff,
-+	.gpdup_mask	= 0xffffffff,
-+#endif
-+
-+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
-+
-+	.width		= 480,
-+	.height		= 640,
-+
-+	.xres		= {
-+		.min	= 480,
-+		.max	= 480,
-+		.defval	= 480,
-+	},
-+
-+	.yres		= {
-+		.min	= 640,
-+		.max	= 640,
-+		.defval = 640,
-+	},
-+
-+	.bpp		= {
-+		.min	= 16,
-+		.max	= 16,
-+		.defval = 16,
-+	},
-+};
-+
-+/* Config for 240x320 LCD */
- static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
- 	.type = S3C2410_LCDCON1_TFT,
- 	.regs	= {
-@@ -337,6 +466,17 @@
- 	.oversampling_shift = 2,
- };
- 
-+static char tft_type = 's';
-+
-+int __init tft_setup(char *str)
-+{
-+	tft_type = str[0];
-+	return 1;
-+}
-+
-+__setup("tft=", tft_setup);
-+
-+
- static void __init qt2410_map_io(void)
- {
- 	s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
-@@ -360,7 +500,20 @@
- 	s3c2410_gpio_setpin(S3C2410_GPF7, 1);
- 
- 	s3c_device_nand.dev.platform_data = &qt2410_nand_info;
--	s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
-+
-+	switch (tft_type) {
-+	case 'p': /* production */
-+		s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
-+		break;
-+	case 'b': /* big */
-+		s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
-+		break;
-+	case 's': /* small */
-+	default:
-+		s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
-+		break;
-+	}
-+
- 	s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
- 	set_s3c2410ts_info(&qt2410_ts_cfg);
- 

Modified: trunk/src/target/kernel/patches/qt2410-s3c_mci-pdata.patch
===================================================================
--- trunk/src/target/kernel/patches/qt2410-s3c_mci-pdata.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/qt2410-s3c_mci-pdata.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -5,14 +5,6 @@
 ===================================================================
 --- linux-2.6.20.orig/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-15 17:07:38.000000000 +0100
 +++ linux-2.6.20/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-15 17:08:16.000000000 +0100
-@@ -31,6 +31,7 @@
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/serial_core.h>
-+#include <linux/mmc/protocol.h>
- #include <linux/spi/spi.h>
- #include <linux/spi/spi_bitbang.h>
- 
 @@ -56,6 +57,7 @@
  #include <asm/arch/ts.h>
  #include <asm/arch/spi.h>

Modified: trunk/src/target/kernel/patches/s3c2410-qt2410-buttons.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c2410-qt2410-buttons.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c2410-qt2410-buttons.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,8 +1,8 @@
-Index: linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-qt2410.c
 ===================================================================
---- linux-2.6.20.1.orig/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-21 17:23:47.000000000 +0100
-+++ linux-2.6.20.1/arch/arm/mach-s3c2410/mach-qt2410.c	2007-02-21 17:26:52.000000000 +0100
-@@ -457,6 +457,24 @@
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2410/mach-qt2410.c
++++ linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-qt2410.c
+@@ -408,6 +408,24 @@
  	.ocr_avail 	= MMC_VDD_32_33,
  };
  
@@ -27,19 +27,11 @@
  static void __init qt2410_map_io(void)
  {
  	s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
-@@ -502,6 +520,7 @@
- 	spi_register_board_info(qt2410_spi_board_info,
- 				ARRAY_SIZE(qt2410_spi_board_info));
- 	platform_device_register(&s3c_device_spi_lcm);
-+	platform_device_register(&qt2410_button_dev);
- 
- 	s3c2410_pm_init();
- }
-Index: linux-2.6.20.1/drivers/input/keyboard/Kconfig
+Index: linux-2.6.21-moko/drivers/input/keyboard/Kconfig
 ===================================================================
---- linux-2.6.20.1.orig/drivers/input/keyboard/Kconfig	2007-02-21 17:22:08.000000000 +0100
-+++ linux-2.6.20.1/drivers/input/keyboard/Kconfig	2007-02-21 17:22:39.000000000 +0100
-@@ -225,5 +225,10 @@
+--- linux-2.6.21-moko.orig/drivers/input/keyboard/Kconfig
++++ linux-2.6.21-moko/drivers/input/keyboard/Kconfig
+@@ -240,5 +240,10 @@
  	  To compile this driver as a module, choose M here: the
  	  module will be called gta01kbd.
  
@@ -50,10 +42,10 @@
 +
  
  endif
-Index: linux-2.6.20.1/drivers/input/keyboard/Makefile
+Index: linux-2.6.21-moko/drivers/input/keyboard/Makefile
 ===================================================================
---- linux-2.6.20.1.orig/drivers/input/keyboard/Makefile	2007-02-21 17:22:06.000000000 +0100
-+++ linux-2.6.20.1/drivers/input/keyboard/Makefile	2007-02-21 17:22:53.000000000 +0100
+--- linux-2.6.21-moko.orig/drivers/input/keyboard/Makefile
++++ linux-2.6.21-moko/drivers/input/keyboard/Makefile
 @@ -14,6 +14,7 @@
  obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
  obj-$(CONFIG_KEYBOARD_CORGI)		+= corgikbd.o
@@ -62,10 +54,10 @@
  obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
  obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
  obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
-Index: linux-2.6.20.1/drivers/input/keyboard/qt2410kbd.c
+Index: linux-2.6.21-moko/drivers/input/keyboard/qt2410kbd.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/drivers/input/keyboard/qt2410kbd.c	2007-02-21 17:25:50.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/drivers/input/keyboard/qt2410kbd.c
 @@ -0,0 +1,218 @@
 +/*
 + * Keyboard driver for Armzone QT2410 

Deleted: trunk/src/target/kernel/patches/s3c2410_nand-hwecc-backport.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c2410_nand-hwecc-backport.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c2410_nand-hwecc-backport.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,130 +0,0 @@
-From: Ben Dooks <ben-linux at fluff.org>
-Date: Fri, 2 Feb 2007 16:59:33 +0000 (+0000)
-Subject: [MTD] [NAND] S3C2410: Hardware ECC correction code
-X-Git-Tag: v2.6.21-rc1^0~66^2~13
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a2593247d747954cd12c32da8c5a3aecb9cd19a3
-
-[MTD] [NAND] S3C2410: Hardware ECC correction code
-
-Add support for correcting errors detected by the
-hardware ECC.
-
-Signed-off-by: Ben Dooks <ben-linux at fluff.org>
-Signed-off-by: David Woodhouse <dwmw2 at infradead.org>
----
-
-diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
-index 9326a56..143a7f0 100644
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -126,10 +126,6 @@ config MTD_NAND_S3C2410_HWECC
- 	  incorrect ECC generation, and if using these, the default of
- 	  software ECC is preferable.
- 
--	  If you lay down a device with the hardware ECC, then you will
--	  currently not be able to switch to software, as there is no
--	  implementation for ECC method used by the S3C2410
--
- config MTD_NAND_NDFC
- 	tristate "NDFC NanD Flash Controller"
- 	depends on MTD_NAND && 44x
-diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
-index 8b32035..e8e0301 100644
---- a/drivers/mtd/nand/s3c2410.c
-+++ b/drivers/mtd/nand/s3c2410.c
-@@ -337,17 +337,69 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
- static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
- 				     u_char *read_ecc, u_char *calc_ecc)
- {
--	pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
-+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-+	unsigned int diff0, diff1, diff2;
-+	unsigned int bit, byte;
- 
--	pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
--		 read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
-+	pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
- 
--	if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
--		return 0;
-+	diff0 = read_ecc[0] ^ calc_ecc[0];
-+	diff1 = read_ecc[1] ^ calc_ecc[1];
-+	diff2 = read_ecc[2] ^ calc_ecc[2];
-+
-+	pr_debug("%s: rd %02x%02x%02x calc %02x%02x%02x diff %02x%02x%02x\n",
-+		 __func__,
-+		 read_ecc[0], read_ecc[1], read_ecc[2],
-+		 calc_ecc[0], calc_ecc[1], calc_ecc[2],
-+		 diff0, diff1, diff2);
-+
-+	if (diff0 == 0 && diff1 == 0 && diff2 == 0)
-+		return 0;		/* ECC is ok */
-+
-+	/* Can we correct this ECC (ie, one row and column change).
-+	 * Note, this is similar to the 256 error code on smartmedia */
-+
-+	if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
-+	    ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
-+	    ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
-+		/* calculate the bit position of the error */
-+
-+		bit  = (diff2 >> 2) & 1;
-+		bit |= (diff2 >> 3) & 2;
-+		bit |= (diff2 >> 4) & 4;
-+
-+		/* calculate the byte position of the error */
-+
-+		byte  = (diff1 << 1) & 0x80;
-+		byte |= (diff1 << 2) & 0x40;
-+		byte |= (diff1 << 3) & 0x20;
-+		byte |= (diff1 << 4) & 0x10;
- 
--	/* we curently have no method for correcting the error */
-+		byte |= (diff0 >> 3) & 0x08;
-+		byte |= (diff0 >> 2) & 0x04;
-+		byte |= (diff0 >> 1) & 0x02;
-+		byte |= (diff0 >> 0) & 0x01;
- 
--	return -1;
-+		byte |= (diff2 << 8) & 0x100;
-+
-+		dev_dbg(info->device, "correcting error bit %d, byte %d\n",
-+			bit, byte);
-+
-+		dat[byte] ^= (1 << bit);
-+		return 1;
-+	}
-+
-+	/* if there is only one bit difference in the ECC, then
-+	 * one of only a row or column parity has changed, which
-+	 * means the error is most probably in the ECC itself */
-+
-+	diff0 |= (diff1 << 8);
-+	diff0 |= (diff2 << 16);
-+
-+	if ((diff0 & ~(1<<fls(diff0))) == 0)
-+		return 1;
-+
-+	return 0;
- }
- 
- /* ECC functions
-@@ -383,7 +435,8 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
- 	ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
- 	ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
- 
--	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
-+	pr_debug("%s: returning ecc %02x%02x%02x\n", __func__,
-+		 ecc_code[0], ecc_code[1], ecc_code[2]);
- 
- 	return 0;
- }
-@@ -397,7 +450,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
- 	ecc_code[1] = ecc >> 8;
- 	ecc_code[2] = ecc >> 16;
- 
--	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
-+	pr_debug("%s: returning ecc %06x\n", __func__, ecc);
- 
- 	return 0;
- }

Modified: trunk/src/target/kernel/patches/s3c2410_touchscreen.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c2410_touchscreen.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c2410_touchscreen.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,16 +1,16 @@
-diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
-index e55a6a9..9a2a67b 100644
---- a/arch/arm/mach-s3c2410/devs.c
-+++ b/arch/arm/mach-s3c2410/devs.c
-@@ -29,6 +29,7 @@ #include <asm/irq.h>
+Index: linux-2.6.21-moko/arch/arm/plat-s3c24xx/devs.c
+===================================================================
+--- linux-2.6.21-moko.orig/arch/arm/plat-s3c24xx/devs.c
++++ linux-2.6.21-moko/arch/arm/plat-s3c24xx/devs.c
+@@ -30,6 +30,7 @@
  
  #include <asm/arch/regs-serial.h>
  #include <asm/arch/udc.h>
 +#include <asm/arch/ts.h>
  
- #include "devs.h"
- #include "cpu.h"
-@@ -205,6 +206,23 @@ struct platform_device s3c_device_nand =
+ #include <asm/plat-s3c24xx/devs.h>
+ #include <asm/plat-s3c24xx/cpu.h>
+@@ -206,6 +207,23 @@
  
  EXPORT_SYMBOL(s3c_device_nand);
  
@@ -34,11 +34,11 @@
  /* USB Device (Gadget)*/
  
  static struct resource s3c_usbgadget_resource[] = {
-diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
-index 14fb0ba..0fc63cf 100644
---- a/arch/arm/mach-s3c2410/devs.h
-+++ b/arch/arm/mach-s3c2410/devs.h
-@@ -41,6 +41,7 @@ extern struct platform_device s3c_device
+Index: linux-2.6.21-moko/include/asm-arm/plat-s3c24xx/devs.h
+===================================================================
+--- linux-2.6.21-moko.orig/include/asm-arm/plat-s3c24xx/devs.h
++++ linux-2.6.21-moko/include/asm-arm/plat-s3c24xx/devs.h
+@@ -41,6 +41,7 @@
  extern struct platform_device s3c_device_timer3;
  
  extern struct platform_device s3c_device_usbgadget;
@@ -46,19 +46,19 @@
  
  /* s3c2440 specific devices */
  
-diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
-index f539535..f65b7ce 100644
---- a/arch/arm/mach-s3c2410/mach-h1940.c
-+++ b/arch/arm/mach-s3c2410/mach-h1940.c
-@@ -39,6 +39,7 @@ #include <asm/arch/h1940.h>
+Index: linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-h1940.c
+===================================================================
+--- linux-2.6.21-moko.orig/arch/arm/mach-s3c2410/mach-h1940.c
++++ linux-2.6.21-moko/arch/arm/mach-s3c2410/mach-h1940.c
+@@ -38,6 +38,7 @@
  #include <asm/arch/h1940-latch.h>
  #include <asm/arch/fb.h>
  #include <asm/arch/udc.h>
 +#include <asm/arch/ts.h>
  
- #include <linux/serial_core.h>
- 
-@@ -132,6 +133,11 @@ static struct s3c2410_udc_mach_info h194
+ #include <asm/plat-s3c24xx/clock.h>
+ #include <asm/plat-s3c24xx/devs.h>
+@@ -129,6 +130,11 @@
  };
  
  
@@ -70,15 +70,15 @@
  
  /**
   * Set lcd on or off
-@@ -183,6 +189,7 @@ static struct platform_device *h1940_dev
+@@ -185,6 +191,7 @@
  	&s3c_device_i2c,
  	&s3c_device_iis,
  	&s3c_device_usbgadget,
 +	&s3c_device_ts,
+ 	&s3c_device_leds,
  };
  
- static struct s3c24xx_board h1940_board __initdata = {
-@@ -213,6 +220,7 @@ static void __init h1940_init(void)
+@@ -218,6 +225,7 @@
  	u32 tmp;
  
  	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
@@ -86,11 +86,11 @@
   	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
  
  	/* Turn off suspend on both USB ports, and switch the
-diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
-index 6b46c9b..91f5f4f 100644
---- a/drivers/input/touchscreen/Kconfig
-+++ b/drivers/input/touchscreen/Kconfig
-@@ -49,6 +49,24 @@ config TOUCHSCREEN_CORGI
+Index: linux-2.6.21-moko/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.21-moko.orig/drivers/input/touchscreen/Kconfig
++++ linux-2.6.21-moko/drivers/input/touchscreen/Kconfig
+@@ -54,6 +54,24 @@
  	  To compile this driver as a module, choose M here: the
  	  module will be called corgi_ts.
  
@@ -115,20 +115,19 @@
  config TOUCHSCREEN_GUNZE
  	tristate "Gunze AHL-51S touchscreen"
  	select SERIO
-diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
-index 30e6e22..8cbaac5 100644
---- a/drivers/input/touchscreen/Makefile
-+++ b/drivers/input/touchscreen/Makefile
-@@ -16,3 +16,4 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= pe
+Index: linux-2.6.21-moko/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.21-moko.orig/drivers/input/touchscreen/Makefile
++++ linux-2.6.21-moko/drivers/input/touchscreen/Makefile
+@@ -16,3 +16,4 @@
  obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
  obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
  obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
 +obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
-diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
-new file mode 100644
-index 0000000..0dea2ef
+Index: linux-2.6.21-moko/drivers/input/touchscreen/s3c2410_ts.c
+===================================================================
 --- /dev/null
-+++ b/drivers/input/touchscreen/s3c2410_ts.c
++++ linux-2.6.21-moko/drivers/input/touchscreen/s3c2410_ts.c
 @@ -0,0 +1,401 @@
 +/*
 + * This program is free software; you can redistribute it and/or modify
@@ -531,24 +530,10 @@
 +        c-basic-offset: 8
 +    End:
 +*/
-diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
-index 3196a28..c7f2319 100644
---- a/include/asm-arm/arch-s3c2410/regs-adc.h
-+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
-@@ -41,7 +41,7 @@ #define S3C2410_ADCTSC_XM_SEN		(1<<5)
- #define S3C2410_ADCTSC_XP_SEN		(1<<4)
- #define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
- #define S3C2410_ADCTSC_AUTO_PST		(1<<2)
--#define S3C2410_ADCTSC_XY_PST		(0x3<<0)
-+#define S3C2410_ADCTSC_XY_PST(x)	(((x)&0x3)<<0)
- 
- /* ADCDAT0 Bits */
- #define S3C2410_ADCDAT0_UPDOWN		(1<<15)
-diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.h
-new file mode 100644
-index 0000000..8566f25
+Index: linux-2.6.21-moko/include/asm-arm/arch-s3c2410/ts.h
+===================================================================
 --- /dev/null
-+++ b/include/asm-arm/arch-s3c2410/ts.h
++++ linux-2.6.21-moko/include/asm-arm/arch-s3c2410/ts.h
 @@ -0,0 +1,28 @@
 +/* linux/include/asm/arch-s3c2410/ts.h
 + *

Modified: trunk/src/target/kernel/patches/s3c2410_udc-vbus_draw_pdata.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c2410_udc-vbus_draw_pdata.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c2410_udc-vbus_draw_pdata.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -2,22 +2,22 @@
 which gets called when the amount of power we can draw from Vbus
 has changed.
 
-Index: linux-2.6.20/drivers/usb/gadget/s3c2410_udc.c
+Index: linux-2.6.21-moko/drivers/usb/gadget/s3c2410_udc.c
 ===================================================================
---- linux-2.6.20.orig/drivers/usb/gadget/s3c2410_udc.c	2007-02-15 14:55:45.000000000 +0100
-+++ linux-2.6.20/drivers/usb/gadget/s3c2410_udc.c	2007-02-15 15:00:11.000000000 +0100
+--- linux-2.6.21-moko.orig/drivers/usb/gadget/s3c2410_udc.c
++++ linux-2.6.21-moko/drivers/usb/gadget/s3c2410_udc.c
 @@ -1404,12 +1404,23 @@
  	return IRQ_HANDLED;
  }
  
-+static void s3c2410_vbus_draw(struct usb_gadget *_gadget, int ma)
++static int s3c2410_vbus_draw(struct usb_gadget *_gadget, int ma)
 +{
 +	struct s3c2410_udc  *udc;
 +
 +	dprintk(DEBUG_NORMAL, "s3c2410_vbus_draw()\n");
 +
 +	if (udc_info && udc_info->vbus_draw)
-+		udc_info->vbus_draw(ma);
++		return udc_info->vbus_draw(ma);
 +}
 +
  static const struct usb_gadget_ops s3c2410_ops = {
@@ -30,23 +30,16 @@
  };
  
  /*------------------------- gadget driver handling---------------------------*/
-Index: linux-2.6.20/include/asm-arm/arch-s3c2410/udc.h
+Index: linux-2.6.21-moko/include/asm/arch-s3c2410/udc.h
 ===================================================================
---- linux-2.6.20.orig/include/asm-arm/arch-s3c2410/udc.h	2007-02-15 14:54:49.000000000 +0100
-+++ linux-2.6.20/include/asm-arm/arch-s3c2410/udc.h	2007-02-15 15:00:50.000000000 +0100
-@@ -12,6 +12,7 @@
-  *	14-Mar-2005	RTP	Created file
-  *	02-Aug-2005	RTP	File rename
-  *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
-+ *	18-Jan-2007	HMW	Add per-platform vbus_draw function
- */
+--- linux-2.6.21-moko.orig/include/asm/arch-s3c2410/udc.h
++++ linux-2.6.21-moko/include/asm/arch-s3c2410/udc.h
+@@ -26,7 +26,7 @@
  
- #ifndef __ASM_ARM_ARCH_UDC_H
-@@ -25,6 +26,7 @@
- 
  struct s3c2410_udc_mach_info {
  	void	(*udc_command)(enum s3c2410_udc_cmd_e);
-+ 	void	(*vbus_draw)(unsigned int ma);
+- 	void	(*vbus_draw)(unsigned int ma);
++ 	int	(*vbus_draw)(unsigned int ma);
  	unsigned int vbus_pin;
  	unsigned char vbus_pin_inverted;
  };

Modified: trunk/src/target/kernel/patches/s3c2410_udc.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c2410_udc.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c2410_udc.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,127 +1,3 @@
-Index: linux-2.6.20/arch/arm/mach-s3c2410/devs.c
-===================================================================
---- linux-2.6.20.orig/arch/arm/mach-s3c2410/devs.c	2007-02-04 19:44:54.000000000 +0100
-+++ linux-2.6.20/arch/arm/mach-s3c2410/devs.c	2007-02-15 14:54:49.000000000 +0100
-@@ -29,6 +29,7 @@
- #include <asm/irq.h>
- 
- #include <asm/arch/regs-serial.h>
-+#include <asm/arch/udc.h>
- 
- #include "devs.h"
- #include "cpu.h"
-@@ -230,6 +231,20 @@
- 
- EXPORT_SYMBOL(s3c_device_usbgadget);
- 
-+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
-+{
-+	struct s3c2410_udc_mach_info *npd;
-+
-+	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
-+	if (npd) {
-+		memcpy(npd, pd, sizeof(*npd));
-+		s3c_device_usbgadget.dev.platform_data = npd;
-+	} else {
-+		printk(KERN_ERR "no memory for udc platform data\n");
-+	}
-+}
-+
-+
- /* Watchdog */
- 
- static struct resource s3c_wdt_resource[] = {
-Index: linux-2.6.20/arch/arm/mach-s3c2410/mach-h1940.c
-===================================================================
---- linux-2.6.20.orig/arch/arm/mach-s3c2410/mach-h1940.c	2007-02-04 19:44:54.000000000 +0100
-+++ linux-2.6.20/arch/arm/mach-s3c2410/mach-h1940.c	2007-02-15 14:54:49.000000000 +0100
-@@ -33,10 +33,13 @@
- 
- #include <asm/arch/regs-serial.h>
- #include <asm/arch/regs-lcd.h>
-+#include <asm/arch/regs-gpio.h>
-+#include <asm/arch/regs-clock.h>
- 
- #include <asm/arch/h1940.h>
- #include <asm/arch/h1940-latch.h>
- #include <asm/arch/fb.h>
-+#include <asm/arch/udc.h>
- 
- #include "clock.h"
- #include "devs.h"
-@@ -102,6 +105,32 @@
- 
- EXPORT_SYMBOL_GPL(h1940_latch_control);
- 
-+static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-+{
-+	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
-+
-+	switch (cmd)
-+	{
-+		case S3C2410_UDC_P_ENABLE :
-+			h1940_latch_control(0, H1940_LATCH_USB_DP);
-+			break;
-+		case S3C2410_UDC_P_DISABLE :
-+			h1940_latch_control(H1940_LATCH_USB_DP, 0);
-+			break;
-+		case S3C2410_UDC_P_RESET :
-+			break;
-+		default:
-+			break;
-+	}
-+}
-+
-+static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
-+	.udc_command		= h1940_udc_pullup,
-+	.vbus_pin		= S3C2410_GPG5,
-+	.vbus_pin_inverted	= 1,
-+};
-+
-+
- 
- /**
-  * Set lcd on or off
-@@ -152,6 +181,7 @@
- 	&s3c_device_wdt,
- 	&s3c_device_i2c,
- 	&s3c_device_iis,
-+	&s3c_device_usbgadget,
- };
- 
- static struct s3c24xx_board h1940_board __initdata = {
-@@ -179,7 +209,23 @@
- 
- static void __init h1940_init(void)
- {
-+	u32 tmp;
-+
- 	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
-+ 	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
-+
-+	/* Turn off suspend on both USB ports, and switch the
-+	 * selectable USB port to USB device mode. */
-+
-+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
-+			      S3C2410_MISCCR_USBSUSPND0 |
-+			      S3C2410_MISCCR_USBSUSPND1, 0x0);
-+
-+	tmp = (
-+		 0x78 << S3C2410_PLLCON_MDIVSHIFT)
-+	      | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
-+	      | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
-+	writel(tmp, S3C2410_UPLLCON);
- }
- 
- MACHINE_START(H1940, "IPAQ-H1940")
-@@ -189,6 +235,6 @@
- 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
- 	.map_io		= h1940_map_io,
- 	.init_irq	= h1940_init_irq,
--	.init_machine   = h1940_init,
-+	.init_machine	= h1940_init,
- 	.timer		= &s3c24xx_timer,
- MACHINE_END
 Index: linux-2.6.20/arch/arm/mach-s3c2410/s3c2410.c
 ===================================================================
 --- linux-2.6.20.orig/arch/arm/mach-s3c2410/s3c2410.c	2007-02-04 19:44:54.000000000 +0100
@@ -2271,42 +2147,4 @@
 +#endif
 +
 +
-Index: linux-2.6.20/include/asm-arm/arch-s3c2410/udc.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20/include/asm-arm/arch-s3c2410/udc.h	2007-02-15 14:54:49.000000000 +0100
-@@ -0,0 +1,34 @@
-+/* linux/include/asm/arch-s3c2410/udc.h
-+ *
-+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard at rtp-net.org>
-+ *
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ *  Changelog:
-+ *	14-Mar-2005	RTP	Created file
-+ *	02-Aug-2005	RTP	File rename
-+ *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
-+*/
-+
-+#ifndef __ASM_ARM_ARCH_UDC_H
-+#define __ASM_ARM_ARCH_UDC_H
-+
-+enum s3c2410_udc_cmd_e {
-+	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
-+	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
-+	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
-+};
-+
-+struct s3c2410_udc_mach_info {
-+	void	(*udc_command)(enum s3c2410_udc_cmd_e);
-+	unsigned int vbus_pin;
-+	unsigned char vbus_pin_inverted;
-+};
-+
-+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
-+
-+#endif /* __ASM_ARM_ARCH_UDC_H */
+

Modified: trunk/src/target/kernel/patches/s3c_mci.patch
===================================================================
--- trunk/src/target/kernel/patches/s3c_mci.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/s3c_mci.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,9 +1,9 @@
 This is the latest S3C MMC/SD driver by Thomas Kleffel
 
-Index: linux-2.6.20.1/drivers/mmc/Kconfig
+Index: linux-2.6.21-moko/drivers/mmc/Kconfig
 ===================================================================
---- linux-2.6.20.1.orig/drivers/mmc/Kconfig	2007-02-26 00:46:48.000000000 +0100
-+++ linux-2.6.20.1/drivers/mmc/Kconfig	2007-02-26 00:46:55.000000000 +0100
+--- linux-2.6.21-moko.orig/drivers/mmc/Kconfig
++++ linux-2.6.21-moko/drivers/mmc/Kconfig
 @@ -125,4 +125,16 @@
            To compile this driver as a module, choose M here: the
  	  module will be called tifm_sd.
@@ -21,10 +21,10 @@
 +
 +
  endmenu
-Index: linux-2.6.20.1/drivers/mmc/mmc_debug.c
+Index: linux-2.6.21-moko/drivers/mmc/mmc_debug.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/drivers/mmc/mmc_debug.c	2007-02-26 00:46:55.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/drivers/mmc/mmc_debug.c
 @@ -0,0 +1,59 @@
 +/*
 + *  linux/drivers/mmc/mmc_debug.c
@@ -85,10 +85,10 @@
 +	}
 +}
 +EXPORT_SYMBOL(mmc_err2str);
-Index: linux-2.6.20.1/drivers/mmc/mmc_debug.h
+Index: linux-2.6.21-moko/drivers/mmc/mmc_debug.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/drivers/mmc/mmc_debug.h	2007-02-26 00:46:55.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/drivers/mmc/mmc_debug.h
 @@ -0,0 +1,7 @@
 +#ifndef MMC_DEBUG_H
 +#define MMC_DEBUG_H
@@ -97,10 +97,10 @@
 +char *mmc_err2str(int err);
 +
 +#endif /* MMC_DEBUG_H */
-Index: linux-2.6.20.1/drivers/mmc/s3cmci.c
+Index: linux-2.6.21-moko/drivers/mmc/s3cmci.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/drivers/mmc/s3cmci.c	2007-03-02 12:55:44.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/drivers/mmc/s3cmci.c
 @@ -0,0 +1,1339 @@
 +/*
 + *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
@@ -1293,8 +1293,8 @@
 +	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
 +	mmc->f_max 	= host->clk_rate / host->clk_div;
 +
-+	mmc->max_sectors	= 4095;
-+	mmc->max_seg_size	= mmc->max_sectors << 9;
++	mmc->max_req_size	= 4095 * 512;
++	mmc->max_seg_size	= mmc->max_req_size;
 +
 +	mmc->max_phys_segs	= 128;
 +	mmc->max_hw_segs	= 128;
@@ -1441,10 +1441,10 @@
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Thomas Kleffel <tk at maintech.de>");
 +
-Index: linux-2.6.20.1/drivers/mmc/s3cmci.h
+Index: linux-2.6.21-moko/drivers/mmc/s3cmci.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/drivers/mmc/s3cmci.h	2007-03-02 12:55:41.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/drivers/mmc/s3cmci.h
 @@ -0,0 +1,71 @@
 +/*
 + *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
@@ -1517,10 +1517,10 @@
 +	unsigned int		ccnt, dcnt;
 +	struct tasklet_struct	pio_tasklet;
 +};
-Index: linux-2.6.20.1/include/asm-arm/arch-s3c2410/regs-sdi.h
+Index: linux-2.6.21-moko/include/asm-arm/arch-s3c2410/regs-sdi.h
 ===================================================================
---- linux-2.6.20.1.orig/include/asm-arm/arch-s3c2410/regs-sdi.h	2007-02-26 00:46:48.000000000 +0100
-+++ linux-2.6.20.1/include/asm-arm/arch-s3c2410/regs-sdi.h	2007-02-26 00:46:55.000000000 +0100
+--- linux-2.6.21-moko.orig/include/asm-arm/arch-s3c2410/regs-sdi.h
++++ linux-2.6.21-moko/include/asm-arm/arch-s3c2410/regs-sdi.h
 @@ -28,9 +28,15 @@
  #define S3C2410_SDIDCNT               (0x30)
  #define S3C2410_SDIDSTA               (0x34)
@@ -1588,11 +1588,11 @@
  #define S3C2410_SDIFSTA_RFLAST         (1<<9)
  #define S3C2410_SDIFSTA_RFFULL         (1<<8)
  #define S3C2410_SDIFSTA_RFHALF         (1<<7)
-Index: linux-2.6.20.1/include/linux/mmc/mmc.h
+Index: linux-2.6.21-moko/include/linux/mmc/mmc.h
 ===================================================================
---- linux-2.6.20.1.orig/include/linux/mmc/mmc.h	2007-02-26 00:46:48.000000000 +0100
-+++ linux-2.6.20.1/include/linux/mmc/mmc.h	2007-02-26 00:46:55.000000000 +0100
-@@ -54,12 +54,15 @@
+--- linux-2.6.21-moko.orig/include/linux/mmc/mmc.h
++++ linux-2.6.21-moko/include/linux/mmc/mmc.h
+@@ -55,12 +55,15 @@
  	unsigned int		retries;	/* max number of retries */
  	unsigned int		error;		/* command error */
  
@@ -1614,10 +1614,10 @@
  
  	struct mmc_data		*data;		/* data segment associated with cmd */
  	struct mmc_request	*mrq;		/* associated request */
-Index: linux-2.6.20.1/drivers/mmc/Makefile
+Index: linux-2.6.21-moko/drivers/mmc/Makefile
 ===================================================================
---- linux-2.6.20.1.orig/drivers/mmc/Makefile	2007-03-02 10:18:32.000000000 +0100
-+++ linux-2.6.20.1/drivers/mmc/Makefile	2007-03-02 10:18:14.000000000 +0100
+--- linux-2.6.21-moko.orig/drivers/mmc/Makefile
++++ linux-2.6.21-moko/drivers/mmc/Makefile
 @@ -24,10 +24,12 @@
  obj-$(CONFIG_MMC_OMAP)		+= omap.o
  obj-$(CONFIG_MMC_AT91)		+= at91_mci.o

Deleted: trunk/src/target/kernel/patches/sdhc-backport.patch
===================================================================
--- trunk/src/target/kernel/patches/sdhc-backport.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/sdhc-backport.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,323 +0,0 @@
-From: Philip Langdale <philipl at overt.org>
-Date: Thu, 4 Jan 2007 14:57:32 +0000 (-0800)
-Subject: mmc: Add support for SDHC cards
-X-Git-Tag: v2.6.21-rc1^0~274^2~627^2~26
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=fba68bd2dab1ac99af3c5a963ec9581cfa9f1725
-
-mmc: Add support for SDHC cards
-
-Thanks to the generous donation of an SDHC card by John Gilmore, and
-the surprisingly enlightened decision by the SD Card Association to
-publish useful specs, I've been able to bash out support for SDHC. The
-changes are not too profound:
-
-i) Add a card flag indicating the card uses block level addressing and
-check it in the block driver. As we never took advantage of byte-level
-addressing, this simply involves skipping the block -> byte
-translation when sending commands.
-
-ii) The layout of the CSD is changed - a set of fields are discarded
-to make space for a larger C_SIZE. We did not reference any of the
-discarded fields except those related to the C_SIZE.
-
-iii) Read and write timeouts are fixed values and not calculated from
-CSD values.
-
-iv) Before invoking SEND_APP_OP_COND, we must invoke the new
-SEND_IF_COND to inform the card we support SDHC.
-
-Signed-off-by: Philipl Langdale <philipl at overt.org>
-Signed-off-by: Pierre Ossman <drzeus at drzeus.cx>
----
-
-diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
-index 105f419..b48c277 100644
---- a/drivers/mmc/mmc.c
-+++ b/drivers/mmc/mmc.c
-@@ -289,7 +289,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
- 		else
- 			limit_us = 100000;
- 
--		if (timeout_us > limit_us) {
-+		/*
-+		 * SDHC cards always use these fixed values.
-+		 */
-+		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
- 			data->timeout_ns = limit_us * 1000;
- 			data->timeout_clks = 0;
- 		}
-@@ -372,7 +375,7 @@ static inline void mmc_set_ios(struct mmc_host *host)
- 		 mmc_hostname(host), ios->clock, ios->bus_mode,
- 		 ios->power_mode, ios->chip_select, ios->vdd,
- 		 ios->bus_width);
--	
-+
- 	host->ops->set_ios(host, ios);
- }
- 
-@@ -588,34 +591,65 @@ static void mmc_decode_csd(struct mmc_card *card)
- 
- 	if (mmc_card_sd(card)) {
- 		csd_struct = UNSTUFF_BITS(resp, 126, 2);
--		if (csd_struct != 0) {
-+
-+		switch (csd_struct) {
-+		case 0:
-+			m = UNSTUFF_BITS(resp, 115, 4);
-+			e = UNSTUFF_BITS(resp, 112, 3);
-+			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-+			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-+
-+			m = UNSTUFF_BITS(resp, 99, 4);
-+			e = UNSTUFF_BITS(resp, 96, 3);
-+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-+
-+			e = UNSTUFF_BITS(resp, 47, 3);
-+			m = UNSTUFF_BITS(resp, 62, 12);
-+			csd->capacity	  = (1 + m) << (e + 2);
-+
-+			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-+			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-+			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-+			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-+			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-+			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-+			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-+			break;
-+		case 1:
-+			/*
-+			 * This is a block-addressed SDHC card. Most
-+			 * interesting fields are unused and have fixed
-+			 * values. To avoid getting tripped by buggy cards,
-+			 * we assume those fixed values ourselves.
-+			 */
-+			mmc_card_set_blockaddr(card);
-+
-+			csd->tacc_ns	 = 0; /* Unused */
-+			csd->tacc_clks	 = 0; /* Unused */
-+
-+			m = UNSTUFF_BITS(resp, 99, 4);
-+			e = UNSTUFF_BITS(resp, 96, 3);
-+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-+
-+			m = UNSTUFF_BITS(resp, 48, 22);
-+			csd->capacity     = (1 + m) << 10;
-+
-+			csd->read_blkbits = 9;
-+			csd->read_partial = 0;
-+			csd->write_misalign = 0;
-+			csd->read_misalign = 0;
-+			csd->r2w_factor = 4; /* Unused */
-+			csd->write_blkbits = 9;
-+			csd->write_partial = 0;
-+			break;
-+		default:
- 			printk("%s: unrecognised CSD structure version %d\n",
- 				mmc_hostname(card->host), csd_struct);
- 			mmc_card_set_bad(card);
- 			return;
- 		}
--
--		m = UNSTUFF_BITS(resp, 115, 4);
--		e = UNSTUFF_BITS(resp, 112, 3);
--		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
--		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
--
--		m = UNSTUFF_BITS(resp, 99, 4);
--		e = UNSTUFF_BITS(resp, 96, 3);
--		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
--		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
--
--		e = UNSTUFF_BITS(resp, 47, 3);
--		m = UNSTUFF_BITS(resp, 62, 12);
--		csd->capacity	  = (1 + m) << (e + 2);
--
--		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
--		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
--		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
--		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
--		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
--		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
--		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
- 	} else {
- 		/*
- 		 * We only understand CSD structure v1.1 and v1.2.
-@@ -848,6 +882,41 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
- 	return err;
- }
- 
-+static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
-+{
-+	struct mmc_command cmd;
-+	int err, sd2;
-+	static const u8 test_pattern = 0xAA;
-+
-+	/*
-+	* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
-+	* before SD_APP_OP_COND. This command will harmlessly fail for
-+	* SD 1.0 cards.
-+	*/
-+	cmd.opcode = SD_SEND_IF_COND;
-+	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
-+	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
-+
-+	err = mmc_wait_for_cmd(host, &cmd, 0);
-+	if (err == MMC_ERR_NONE) {
-+		if ((cmd.resp[0] & 0xFF) == test_pattern) {
-+			sd2 = 1;
-+		} else {
-+			sd2 = 0;
-+			err = MMC_ERR_FAILED;
-+		}
-+	} else {
-+		/*
-+		 * Treat errors as SD 1.0 card.
-+		 */
-+		sd2 = 0;
-+		err = MMC_ERR_NONE;
-+	}
-+	if (rsd2)
-+		*rsd2 = sd2;
-+	return err;
-+}
-+
- /*
-  * Discover cards by requesting their CID.  If this command
-  * times out, it is not an error; there are no further cards
-@@ -1334,6 +1403,10 @@ static void mmc_setup(struct mmc_host *host)
- 		mmc_power_up(host);
- 		mmc_idle_cards(host);
- 
-+		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
-+		if (err != MMC_ERR_NONE) {
-+			return;
-+		}
- 		err = mmc_send_app_op_cond(host, 0, &ocr);
- 
- 		/*
-@@ -1386,10 +1459,21 @@ static void mmc_setup(struct mmc_host *host)
- 	 * all get the idea that they should be ready for CMD2.
- 	 * (My SanDisk card seems to need this.)
- 	 */
--	if (host->mode == MMC_MODE_SD)
--		mmc_send_app_op_cond(host, host->ocr, NULL);
--	else
-+	if (host->mode == MMC_MODE_SD) {
-+		int err, sd2;
-+		err = mmc_send_if_cond(host, host->ocr, &sd2);
-+		if (err == MMC_ERR_NONE) {
-+			/*
-+			* If SD_SEND_IF_COND indicates an SD 2.0
-+			* compliant card and we should set bit 30
-+			* of the ocr to indicate that we can handle
-+			* block-addressed SDHC cards.
-+			*/
-+			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
-+		}
-+	} else {
- 		mmc_send_op_cond(host, host->ocr, NULL);
-+	}
- 
- 	mmc_discover_cards(host);
- 
-diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
-index 8771357..5a4eaca 100644
---- a/drivers/mmc/mmc_block.c
-+++ b/drivers/mmc/mmc_block.c
-@@ -237,7 +237,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
- 		brq.mrq.cmd = &brq.cmd;
- 		brq.mrq.data = &brq.data;
- 
--		brq.cmd.arg = req->sector << 9;
-+		brq.cmd.arg = req->sector;
-+		if (!mmc_card_blockaddr(card))
-+			brq.cmd.arg <<= 9;
- 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
- 		brq.data.blksz = 1 << md->block_bits;
- 		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
-@@ -494,6 +496,10 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
- 	struct mmc_command cmd;
- 	int err;
- 
-+	/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
-+	if (mmc_card_blockaddr(card))
-+		return 0;
-+
- 	mmc_card_claim_host(card);
- 	cmd.opcode = MMC_SET_BLOCKLEN;
- 	cmd.arg = 1 << md->block_bits;
-diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
-index d0e6a54..e45712a 100644
---- a/include/linux/mmc/card.h
-+++ b/include/linux/mmc/card.h
-@@ -71,6 +71,7 @@ struct mmc_card {
- #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
- #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
- #define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
-+#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
- 	u32			raw_cid[4];	/* raw card CID */
- 	u32			raw_csd[4];	/* raw card CSD */
- 	u32			raw_scr[2];	/* raw card SCR */
-@@ -87,6 +88,7 @@ struct mmc_card {
- #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
- #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
- #define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-+#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
- 
- #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
- #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
-@@ -94,6 +96,7 @@ struct mmc_card {
- #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
- #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
- #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-+#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
- 
- #define mmc_card_name(c)	((c)->cid.prod_name)
- #define mmc_card_id(c)		((c)->dev.bus_id)
-diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
-index bcf2490..cdc54be 100644
---- a/include/linux/mmc/mmc.h
-+++ b/include/linux/mmc/mmc.h
-@@ -43,6 +43,7 @@ struct mmc_command {
- #define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
- #define MMC_RSP_R3	(MMC_RSP_PRESENT)
- #define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-+#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
- 
- #define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
- 
-diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
-index 2dce60c..c90b676 100644
---- a/include/linux/mmc/protocol.h
-+++ b/include/linux/mmc/protocol.h
-@@ -79,9 +79,12 @@
- #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
- 
- /* SD commands                           type  argument     response */
--  /* class 8 */
-+  /* class 0 */
- /* This is basically the same command as for MMC with some quirks. */
- #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
-+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
-+
-+  /* class 10 */
- #define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
- 
-   /* Application commands */
-@@ -115,6 +118,14 @@
-  */
- 
- /*
-+ * SD_SEND_IF_COND argument format:
-+ *
-+ *	[31:12] Reserved (0)
-+ *	[11:8] Host Voltage Supply Flags
-+ *	[7:0] Check Pattern (0xAA)
-+ */
-+
-+/*
-   MMC status in R1
-   Type
-   	e : error bit

Modified: trunk/src/target/kernel/patches/series
===================================================================
--- trunk/src/target/kernel/patches/series	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/series	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,15 +1,11 @@
 asoc.patch
 asoc-asm_hardware_h.patch
 asoc-platform-hw_init-pcm_emulation-fix.patch
-sdhc-backport.patch
-s3c2410_nand-hwecc-backport.patch
 yaffs2-20070304.patch
 i2c-permit_invalid_addrs.patch
 pm-debug_less_verbose.patch
 g_ether-highpower.patch
 g_ether-vendor_product.patch
-2.6.20-s3c2410fb_uninitialized.patch
-2.6.17-s3c2410-spi-mode23.patch
 s3c2410_serial-nodebug.patch
 s3c2410_udc.patch
 s3c2410_touchscreen.patch
@@ -23,7 +19,6 @@
 s3c_mci_platform.patch
 qt2410-base.patch
 qt2410-cs8900.patch
-qt2410-biglcd.patch
 qt2410-s3c_mci-pdata.patch
 gta01-pcf50606.patch
 gta01-core.patch

Modified: trunk/src/target/kernel/patches/yaffs2-20070304.patch
===================================================================
--- trunk/src/target/kernel/patches/yaffs2-20070304.patch	2007-04-30 04:30:57 UTC (rev 1874)
+++ trunk/src/target/kernel/patches/yaffs2-20070304.patch	2007-04-30 07:09:50 UTC (rev 1875)
@@ -1,22 +1,21 @@
-Index: linux-2.6.20.1/fs/Kconfig
+Index: linux-2.6.21-moko/fs/Kconfig
 ===================================================================
---- linux-2.6.20.1.orig/fs/Kconfig	2007-02-04 19:44:54.000000000 +0100
-+++ linux-2.6.20.1/fs/Kconfig	2007-03-04 16:08:19.000000000 +0100
-@@ -1196,6 +1196,10 @@
+--- linux-2.6.21-moko.orig/fs/Kconfig
++++ linux-2.6.21-moko/fs/Kconfig
+@@ -1189,6 +1189,9 @@
  	  To compile the EFS file system support as a module, choose M here: the
  	  module will be called efs.
  
-+
 +# Patched by YAFFS
 +source "fs/yaffs2/Kconfig"
 +
- config JFFS_FS
- 	tristate "Journalling Flash File System (JFFS) support"
- 	depends on MTD && BLOCK && BROKEN
-Index: linux-2.6.20.1/fs/yaffs2/Kconfig
+ config JFFS2_FS
+ 	tristate "Journalling Flash File System v2 (JFFS2) support"
+ 	select CRC32
+Index: linux-2.6.21-moko/fs/yaffs2/Kconfig
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/Kconfig	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/Kconfig
 @@ -0,0 +1,159 @@
 +#
 +# YAFFS file system configurations
@@ -177,10 +176,10 @@
 +	  but makes look-ups faster.
 +
 +	  If unsure, say Y.
-Index: linux-2.6.20.1/fs/yaffs2/Makefile
+Index: linux-2.6.21-moko/fs/yaffs2/Makefile
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/Makefile	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/Makefile
 @@ -0,0 +1,10 @@
 +#
 +# Makefile for the linux YAFFS filesystem routines.
@@ -192,10 +191,10 @@
 +yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
 +yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
 +yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
-Index: linux-2.6.20.1/fs/yaffs2/devextras.h
+Index: linux-2.6.21-moko/fs/yaffs2/devextras.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/devextras.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/devextras.h
 @@ -0,0 +1,264 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -461,10 +460,10 @@
 +#endif
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/moduleconfig.h
+Index: linux-2.6.21-moko/fs/yaffs2/moduleconfig.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/moduleconfig.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/moduleconfig.h
 @@ -0,0 +1,51 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -517,10 +516,10 @@
 +#endif /* YAFFS_OUT_OF_TREE */
 +
 +#endif /* __YAFFS_CONFIG_H__ */
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_checkptrw.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_checkptrw.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_checkptrw.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_checkptrw.c
 @@ -0,0 +1,384 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -906,10 +905,10 @@
 +
 +
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_checkptrw.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_checkptrw.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_checkptrw.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_checkptrw.h
 @@ -0,0 +1,33 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -944,10 +943,10 @@
 +
 +#endif
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_ecc.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_ecc.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_ecc.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_ecc.c
 @@ -0,0 +1,331 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -1280,10 +1279,10 @@
 +
 +}
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_ecc.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_ecc.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_ecc.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_ecc.h
 @@ -0,0 +1,44 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -1329,10 +1328,10 @@
 +			  yaffs_ECCOther * read_ecc,
 +			  const yaffs_ECCOther * test_ecc);
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_fs.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_fs.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_fs.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_fs.c
 @@ -0,0 +1,2136 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -3470,10 +3469,10 @@
 +MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
 +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006");
 +MODULE_LICENSE("GPL");
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_guts.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_guts.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_guts.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_guts.c
 @@ -0,0 +1,6674 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -10149,10 +10148,10 @@
 +
 +	    return YAFFS_OK;
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_guts.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_guts.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_guts.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_guts.h
 @@ -0,0 +1,889 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11043,10 +11042,10 @@
 +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_mtdif.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_mtdif.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif.c
 @@ -0,0 +1,241 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -11289,10 +11288,10 @@
 +	return YAFFS_OK;
 +}
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_mtdif.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_mtdif.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif.h
 @@ -0,0 +1,27 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11321,10 +11320,10 @@
 +int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber);
 +int nandmtd_InitialiseNAND(yaffs_Device * dev);
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_mtdif2.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif2.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_mtdif2.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif2.c
 @@ -0,0 +1,232 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -11558,10 +11557,10 @@
 +		return YAFFS_FAIL;
 +}
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_mtdif2.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif2.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_mtdif2.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_mtdif2.h
 @@ -0,0 +1,29 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11592,10 +11591,10 @@
 +			    yaffs_BlockState * state, int *sequenceNumber);
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_nand.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_nand.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_nand.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_nand.c
 @@ -0,0 +1,134 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -11731,10 +11730,10 @@
 +
 +
 + 
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_nand.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_nand.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_nand.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_nand.h
 @@ -0,0 +1,44 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11780,10 +11779,10 @@
 +
 +#endif
 +
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_nandemul2k.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_nandemul2k.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_nandemul2k.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_nandemul2k.h
 @@ -0,0 +1,39 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11824,10 +11823,10 @@
 +int nandemul2k_GetNumberOfBlocks(void);
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_packedtags1.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags1.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_packedtags1.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags1.c
 @@ -0,0 +1,52 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -11881,10 +11880,10 @@
 +
 +	}
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_packedtags1.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags1.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_packedtags1.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags1.h
 @@ -0,0 +1,37 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -11923,10 +11922,10 @@
 +void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t);
 +void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt);
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_packedtags2.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags2.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_packedtags2.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags2.c
 @@ -0,0 +1,182 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -12110,10 +12109,10 @@
 +	yaffs_DumpTags2(t);
 +
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_packedtags2.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags2.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_packedtags2.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_packedtags2.h
 @@ -0,0 +1,38 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -12153,10 +12152,10 @@
 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_qsort.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_qsort.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_qsort.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_qsort.c
 @@ -0,0 +1,156 @@
 +/*
 + * Copyright (c) 1992, 1993
@@ -12314,10 +12313,10 @@
 +	}
 +/*		qsort(pn - r, r / es, es, cmp);*/
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_qsort.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_qsort.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_qsort.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_qsort.h
 @@ -0,0 +1,23 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -12342,10 +12341,10 @@
 +                   int (*cmp)(const void *, const void *));
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_tagscompat.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_tagscompat.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_tagscompat.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_tagscompat.c
 @@ -0,0 +1,530 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -12877,10 +12876,10 @@
 +
 +	return YAFFS_OK;
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_tagscompat.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_tagscompat.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_tagscompat.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_tagscompat.h
 @@ -0,0 +1,36 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -12918,10 +12917,10 @@
 +					  state, int *sequenceNumber);
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_tagsvalidity.c
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_tagsvalidity.c
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_tagsvalidity.c	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_tagsvalidity.c
 @@ -0,0 +1,28 @@
 +/*
 + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
@@ -12951,10 +12950,10 @@
 +		tags->validMarker1 == 0x55555555);
 +
 +}
-Index: linux-2.6.20.1/fs/yaffs2/yaffs_tagsvalidity.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffs_tagsvalidity.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffs_tagsvalidity.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffs_tagsvalidity.h
 @@ -0,0 +1,24 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -12980,10 +12979,10 @@
 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
 +int yaffs_ValidateTags(yaffs_ExtendedTags * tags);
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yaffsinterface.h
+Index: linux-2.6.21-moko/fs/yaffs2/yaffsinterface.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yaffsinterface.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yaffsinterface.h
 @@ -0,0 +1,21 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -13006,10 +13005,10 @@
 +int yaffs_Initialise(unsigned nBlocks);
 +
 +#endif
-Index: linux-2.6.20.1/fs/yaffs2/yportenv.h
+Index: linux-2.6.21-moko/fs/yaffs2/yportenv.h
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.1/fs/yaffs2/yportenv.h	2007-03-04 16:08:19.000000000 +0100
+--- /dev/null
++++ linux-2.6.21-moko/fs/yaffs2/yportenv.h
 @@ -0,0 +1,162 @@
 +/*
 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
@@ -13173,11 +13172,11 @@
 +#endif
 +
 +#endif
-Index: linux-2.6.20.1/fs/Makefile
+Index: linux-2.6.21-moko/fs/Makefile
 ===================================================================
---- linux-2.6.20.1.orig/fs/Makefile	2007-03-04 16:08:24.000000000 +0100
-+++ linux-2.6.20.1/fs/Makefile	2007-03-04 16:09:34.000000000 +0100
-@@ -115,3 +115,4 @@
+--- linux-2.6.21-moko.orig/fs/Makefile
++++ linux-2.6.21-moko/fs/Makefile
+@@ -114,3 +114,4 @@
  obj-$(CONFIG_DEBUG_FS)		+= debugfs/
  obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
  obj-$(CONFIG_GFS2_FS)           += gfs2/





More information about the commitlog mailing list