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