r3047 - branches/src/target/kernel/2.6.23.x/patches

shoragan at sita.openmoko.org shoragan at sita.openmoko.org
Wed Sep 26 18:16:04 CEST 2007


Author: shoragan
Date: 2007-09-26 18:16:04 +0200 (Wed, 26 Sep 2007)
New Revision: 3047

Removed:
   branches/src/target/kernel/2.6.23.x/patches/alsa-2.6.23-rc1-commit.diff
   branches/src/target/kernel/2.6.23.x/patches/s3c2410_udc_from_upstream.patch
Modified:
   branches/src/target/kernel/2.6.23.x/patches/series
Log:
Drop patches which have been merged

Deleted: branches/src/target/kernel/2.6.23.x/patches/alsa-2.6.23-rc1-commit.diff
===================================================================
--- branches/src/target/kernel/2.6.23.x/patches/alsa-2.6.23-rc1-commit.diff	2007-09-26 16:12:59 UTC (rev 3046)
+++ branches/src/target/kernel/2.6.23.x/patches/alsa-2.6.23-rc1-commit.diff	2007-09-26 16:16:04 UTC (rev 3047)
@@ -1,10960 +0,0 @@
---- linux-2.6.22.1.orig/CREDITS
-+++ linux-2.6.22.1/CREDITS
-@@ -2212,13 +2212,13 @@
- S: Denmark
- 
- N: Claudio S. Matsuoka
--E: claudio at conectiva.com
--E: claudio at helllabs.org
-+E: cmatsuoka at gmail.com
-+E: claudio at mandriva.com
- W: http://helllabs.org/~claudio
--D: V4L, OV511 driver hacks
-+D: V4L, OV511 and HDA-codec hacks
- S: Conectiva S.A.
--S: R. Tocantins 89
--S: 80050-430  Curitiba PR
-+S: Souza Naves 1250
-+S: 80050-040  Curitiba PR
- S: Brazil
- 
- N: Heinz Mauelshagen
---- linux-2.6.22.1.orig/Documentation/sound/alsa/ALSA-Configuration.txt
-+++ linux-2.6.22.1/Documentation/sound/alsa/ALSA-Configuration.txt
-@@ -467,7 +467,12 @@
-     above explicitly.
- 
-     The power-management is supported.
--    
-+
-+  Module snd-cs5530
-+  _________________
-+
-+    Module for Cyrix/NatSemi Geode 5530 chip. 
-+  
-   Module snd-cs5535audio
-   ----------------------
- 
-@@ -759,6 +764,7 @@
- 
-     model	- force the model name
-     position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
-+    probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
-     single_cmd  - Use single immediate commands to communicate with
- 		codecs (for debugging only)
-     enable_msi	- Enable Message Signaled Interrupt (MSI) (default = off)
-@@ -803,6 +809,8 @@
- 	  hp-3013	HP machines (3013-variant)
- 	  fujitsu	Fujitsu S7020
- 	  acer		Acer TravelMate
-+	  will		Will laptops (PB V7900)
-+	  replacer	Replacer 672V
- 	  basic		fixed pin assignment (old default model)
- 	  auto		auto-config reading BIOS (default)
- 
-@@ -811,16 +819,31 @@
- 	  hp-bpc	HP xw4400/6400/8400/9400 laptops
- 	  hp-bpc-d7000	HP BPC D7000
- 	  benq		Benq ED8
-+	  benq-t31	Benq T31
- 	  hippo		Hippo (ATI) with jack detection, Sony UX-90s
- 	  hippo_1	Hippo (Benq) with jack detection
-+	  sony-assamd	Sony ASSAMD
- 	  basic		fixed pin assignment w/o SPDIF
- 	  auto		auto-config reading BIOS (default)
- 
-+	ALC268
-+	  3stack	3-stack model
-+	  auto		auto-config reading BIOS (default)
-+
-+	ALC662
-+	  3stack-dig	3-stack (2-channel) with SPDIF
-+	  3stack-6ch	 3-stack (6-channel)
-+	  3stack-6ch-dig 3-stack (6-channel) with SPDIF
-+	  6stack-dig	 6-stack with SPDIF
-+	  lenovo-101e	 Lenovo laptop
-+	  auto		auto-config reading BIOS (default)
-+
- 	ALC882/885
- 	  3stack-dig	3-jack with SPDIF I/O
- 	  6stack-dig	6-jack digital with SPDIF I/O
- 	  arima		Arima W820Di1
- 	  macpro	MacPro support
-+	  imac24	iMac 24'' with jack detection
- 	  w2jc		ASUS W2JC
- 	  auto		auto-config reading BIOS (default)
- 
-@@ -832,9 +855,15 @@
- 	  6stack-dig-demo  6-jack digital for Intel demo board
- 	  acer		Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
- 	  medion	Medion Laptops
-+	  medion-md2	Medion MD2
- 	  targa-dig	Targa/MSI
- 	  targa-2ch-dig	Targs/MSI with 2-channel
- 	  laptop-eapd   3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
-+	  lenovo-101e	Lenovo 101E
-+	  lenovo-nb0763	Lenovo NB0763
-+	  lenovo-ms7195-dig Lenovo MS7195
-+	  6stack-hp	HP machines with 6stack (Nettle boards)
-+	  3stack-hp	HP machines with 3stack (Lucknow, Samba boards)
- 	  auto		auto-config reading BIOS (default)
- 
- 	ALC861/660
-@@ -853,7 +882,9 @@
- 	  3stack-dig	3-jack with SPDIF OUT
- 	  6stack-dig	6-jack with SPDIF OUT
- 	  3stack-660	3-jack (for ALC660VD)
-+	  3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
- 	  lenovo	Lenovo 3000 C200
-+	  dallas	Dallas laptops
- 	  auto		auto-config reading BIOS (default)
- 
- 	CMI9880
-@@ -864,12 +895,26 @@
- 	  allout	5-jack in back, 2-jack in front, SPDIF out
- 	  auto		auto-config reading BIOS (default)
- 
-+	AD1882
-+	  3stack	3-stack mode (default)
-+	  6stack	6-stack mode
-+
-+	AD1884
-+	  N/A
-+
- 	AD1981
- 	  basic		3-jack (default)
- 	  hp		HP nx6320
- 	  thinkpad	Lenovo Thinkpad T60/X60/Z60
- 	  toshiba	Toshiba U205
- 
-+	AD1983
-+	  N/A
-+
-+	AD1984
-+	  basic		default configuration
-+	  thinkpad	Lenovo Thinkpad T61/X61
-+
- 	AD1986A
- 	  6stack	6-jack, separate surrounds (default)
- 	  3stack	3-stack, shared surrounds
-@@ -907,11 +952,18 @@
- 	  ref		Reference board
- 	  3stack	D945 3stack
- 	  5stack	D945 5stack + SPDIF
--	  macmini	Intel Mac Mini
--	  macbook	Intel Mac Book
--	  macbook-pro-v1 Intel Mac Book Pro 1st generation
--	  macbook-pro	Intel Mac Book Pro 2nd generation
--	  imac-intel	Intel iMac
-+	  dell		Dell XPS M1210
-+	  intel-mac-v1	Intel Mac Type 1
-+	  intel-mac-v2	Intel Mac Type 2
-+	  intel-mac-v3	Intel Mac Type 3
-+	  intel-mac-v4	Intel Mac Type 4
-+	  intel-mac-v5	Intel Mac Type 5
-+	  macmini	Intel Mac Mini (equivalent with type 3)
-+	  macbook	Intel Mac Book (eq. type 5)
-+	  macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
-+	  macbook-pro	Intel Mac Book Pro 2nd generation (eq. type 3)
-+	  imac-intel	Intel iMac (eq. type 2)
-+	  imac-intel-20	Intel iMac (newer version) (eq. type 3)
- 
- 	STAC9202/9250/9251
- 	  ref		Reference board, base config
-@@ -956,6 +1008,17 @@
-     from the irq.  Remember this is a last resort, and should be
-     avoided as much as possible...
-     
-+    MORE NOTES ON "azx_get_response timeout" PROBLEMS:
-+    On some hardwares, you may need to add a proper probe_mask option
-+    to avoid the "azx_get_response timeout" problem above, instead.
-+    This occurs when the access to non-existing or non-working codec slot
-+    (likely a modem one) causes a stall of the communication via HD-audio
-+    bus.  You can see which codec slots are probed by enabling
-+    CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec
-+    proc files.  Then limit the slots to probe by probe_mask option.
-+    For example, probe_mask=1 means to probe only the first slot, and
-+    probe_mask=4 means only the third slot.
-+
-     The power-management is supported.
- 
-   Module snd-hdsp
---- linux-2.6.22.1.orig/Documentation/sound/alsa/Audiophile-Usb.txt
-+++ linux-2.6.22.1/Documentation/sound/alsa/Audiophile-Usb.txt
-@@ -1,4 +1,4 @@
--	Guide to using M-Audio Audiophile USB with ALSA and Jack	v1.3
-+	Guide to using M-Audio Audiophile USB with ALSA and Jack	v1.5
- 	========================================================
- 
- 	    Thibault Le Meur <Thibault.LeMeur at supelec.fr>
-@@ -6,8 +6,19 @@
- This document is a guide to using the M-Audio Audiophile USB (tm) device with 
- ALSA and JACK.
- 
-+History
-+=======
-+* v1.4 - Thibault Le Meur (2007-07-11)
-+ - Added Low Endianness nature of 16bits-modes
-+   found by Hakan Lennestal <Hakan.Lennestal at brfsodrahamn.se>
-+ - Modifying document structure
-+* v1.5 - Thibault Le Meur (2007-07-12)
-+ - Added AC3/DTS passthru info
-+
-+
- 1 - Audiophile USB Specs and correct usage
- ==========================================
-+
- This part is a reminder of important facts about the functions and limitations 
- of the device.
- 
-@@ -25,18 +36,18 @@
- The internal DAC/ADC has the following characteristics:
- * sample depth of 16 or 24 bits
- * sample rate from 8kHz to 96kHz
--* Two ports can't use different sample depths at the same time. Moreover, the 
--Audiophile USB documentation gives the following Warning: "Please exit any 
--audio application running before switching between bit depths"
-+* Two interfaces can't use different sample depths at the same time.
-+Moreover, the Audiophile USB documentation gives the following Warning:
-+"Please exit any audio application running before switching between bit depths"
- 
- Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be 
- activated at the same time depending on the audio mode selected:
-- * 16-bit/48kHz ==> 4 channels in/4 channels out
-+ * 16-bit/48kHz ==> 4 channels in + 4 channels out
-    - Ai+Ao+Di+Do
-- * 24-bit/48kHz ==> 4 channels in/2 channels out, 
--                    or 2 channels in/4 channels out
-+ * 24-bit/48kHz ==> 4 channels in + 2 channels out, 
-+                    or 2 channels in + 4 channels out
-    - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do
-- * 24-bit/96kHz ==> 2 channels in, or 2 channels out (half duplex only)
-+ * 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only)
-    - Ai or Ao or Di or Do
- 
- Important facts about the Digital interface:
-@@ -52,44 +63,56 @@
- synchronization error (for instance sound played at an odd sample rate)
- 
- 
--2 - Audiophile USB support in ALSA
--==================================
-+2 - Audiophile USB MIDI support in ALSA
-+=======================================
- 
--2.1 - MIDI ports
------------------
--The Audiophile USB MIDI ports will be automatically supported once the 
-+The Audiophile USB MIDI ports will be automatically supported once the
- following modules have been loaded:
-  * snd-usb-audio
-  * snd-seq-midi
- 
- No additional setting is required.
- 
--2.2 - Audio ports
-------------------
-+
-+3 - Audiophile USB Audio support in ALSA
-+========================================
- 
- Audio functions of the Audiophile USB device are handled by the snd-usb-audio 
- module. This module can work in a default mode (without any device-specific 
- parameter), or in an "advanced" mode with the device-specific parameter called 
- "device_setup".
- 
--2.2.1 - Default Alsa driver mode
--
--The default behavior of the snd-usb-audio driver is to parse the device 
--capabilities at startup and enable all functions inside the device (including 
--all ports at any supported sample rates and sample depths). This approach 
--has the advantage to let the driver easily switch from sample rates/depths 
--automatically according to the need of the application claiming the device.
-+3.1 - Default Alsa driver mode
-+------------------------------
- 
--In this case the Audiophile ports are mapped to alsa pcm devices in the 
--following way (I suppose the device's index is 1):
-+The default behavior of the snd-usb-audio driver is to list the device 
-+capabilities at startup and activate the required mode when required 
-+by the applications: for instance if the user is recording in a 
-+24bit-depth-mode and immediately after wants to switch to a 16bit-depth mode,
-+the snd-usb-audio module will reconfigure the device on the fly.
-+
-+This approach has the advantage to let the driver automatically switch from sample 
-+rates/depths automatically according to the user's needs. However, those who 
-+are using the device under windows know that this is not how the device is meant to
-+work: under windows applications must be closed before using the m-audio control
-+panel to switch the device working mode. Thus as we'll see in next section, this 
-+Default Alsa driver mode can lead to device misconfigurations.
-+
-+Let's get back to the Default Alsa driver mode for now.  In this case the 
-+Audiophile interfaces are mapped to alsa pcm devices in the following 
-+way (I suppose the device's index is 1):
-  * hw:1,0 is Ao in playback and Di in capture
-  * hw:1,1 is Do in playback and Ai in capture
-  * hw:1,2 is Do in AC3/DTS passthrough mode
- 
--You must note as well that the device uses Big Endian byte encoding so that 
--supported audio format are S16_BE  for 16-bit depth modes and S24_3BE for 
--24-bits depth mode. One exception is the hw:1,2 port which is Little Endian 
--compliant and thus uses S16_LE.
-+In this mode, the device uses Big Endian byte-encoding so that 
-+supported audio format are S16_BE for 16-bit depth modes and S24_3BE for 
-+24-bits depth mode.
-+
-+One exception is the hw:1,2 port which was reported to be Little Endian 
-+compliant (supposedly supporting S16_LE) but processes in fact only S16_BE streams.
-+This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface 
-+is reported to be big endian in this default driver mode.
- 
- Examples:
-  * playing a S24_3BE encoded raw file to the Ao port
-@@ -98,22 +121,26 @@
-    % arecord -D hw:1,1 -c2  -t raw -r48000 -fS24_3BE test.raw
-  * playing a S16_BE encoded raw file to the Do port
-    % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
-+ * playing an ac3 sample file to the Do port
-+   % aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
- 
--If you're happy with the default Alsa driver setup and don't experience any 
-+If you're happy with the default Alsa driver mode and don't experience any 
- issue with this mode, then you can skip the following chapter.
- 
--2.2.2 - Advanced module setup
-+3.2 - Advanced module setup
-+---------------------------
- 
- Due to the hardware constraints described above, the device initialization made 
- by the Alsa driver in default mode may result in a corrupted state of the 
- device. For instance, a particularly annoying issue is that the sound captured 
--from the Ai port sounds distorted (as if boosted with an excessive high volume 
--gain).
-+from the Ai interface sounds distorted (as if boosted with an excessive high
-+volume gain).
- 
- For people having this problem, the snd-usb-audio module has a new module 
--parameter called "device_setup".
-+parameter called "device_setup" (this parameter was introduced in kernel
-+release 2.6.17)
- 
--2.2.2.1 - Initializing the working mode of the Audiophile USB
-+3.2.1 - Initializing the working mode of the Audiophile USB
- 
- As far as the Audiophile USB device is concerned, this value let the user 
- specify:
-@@ -121,33 +148,57 @@
-  * the sample rate
-  * whether the Di port is used or not 
- 
--Here is a list of supported device_setup values for this device:
-- * device_setup=0x00 (or omitted)
--   - Alsa driver default mode
--   - maintains backward compatibility with setups that do not use this 
--     parameter by not introducing any change
--   - results sometimes in corrupted sound as described earlier
-+When initialized with "device_setup=0x00", the snd-usb-audio module has
-+the same behaviour as when the parameter is omitted (see paragraph "Default 
-+Alsa driver mode" above)
-+
-+Others modes are described in the following subsections.
-+
-+3.2.1.1 - 16-bit modes
-+
-+The two supported modes are:
-+
-  * device_setup=0x01
-    - 16bits 48kHz mode with Di disabled
-    - Ai,Ao,Do can be used at the same time
-    - hw:1,0 is not available in capture mode
-    - hw:1,2 is not available
-+
-  * device_setup=0x11
-    - 16bits 48kHz mode with Di enabled
-    - Ai,Ao,Di,Do can be used at the same time
-    - hw:1,0 is available in capture mode
-    - hw:1,2 is not available
-+
-+In this modes the device operates only at 16bits-modes. Before kernel 2.6.23,
-+the devices where reported to be Big-Endian when in fact they were Little-Endian
-+so that playing a file was a matter of using:
-+   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw
-+where "test_S16_LE.raw" was in fact a little-endian sample file.
-+
-+Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in
-+these modes) a fix has been committed (expected in kernel 2.6.23) and
-+Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as
-+using:
-+   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw
-+
-+3.2.1.2 - 24-bit modes
-+
-+The three supported modes are:
-+
-  * device_setup=0x09
-    - 24bits 48kHz mode with Di disabled
-    - Ai,Ao,Do can be used at the same time
-    - hw:1,0 is not available in capture mode
-    - hw:1,2 is not available
-+
-  * device_setup=0x19
-    - 24bits 48kHz mode with Di enabled
-    - 3 ports from {Ai,Ao,Di,Do} can be used at the same time
-    - hw:1,0 is available in capture mode and an active digital source must be 
-      connected to Di
-    - hw:1,2 is not available
-+
-  * device_setup=0x0D or 0x10
-    - 24bits 96kHz mode
-    - Di is enabled by default for this mode but does not need to be connected 
-@@ -155,34 +206,64 @@
-    - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time
-    - hw:1,0 is available in captured mode
-    - hw:1,2 is not available
-+
-+In these modes the device is only Big-Endian compliant (see "Default Alsa driver 
-+mode" above for an aplay command example)
-+
-+3.2.1.3 - AC3 w/ DTS passthru mode
-+
-+Thanks to Hakan Lennestal, I now have a report saying that this mode works.
-+
-  * device_setup=0x03
-    - 16bits 48kHz mode with only the Do port enabled 
--   - AC3 with DTS passthru (not tested)
-+   - AC3 with DTS passthru
-    - Caution with this setup the Do port is mapped to the pcm device hw:1,0
- 
--2.2.2.2 - Setting and switching configurations with the device_setup parameter
-+The command line used to playback the AC3/DTS encoded .wav-files in this mode:
-+   % aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw
-+
-+3.2.2 - How to use the device_setup parameter
-+----------------------------------------------
- 
- The parameter can be given:
-+
-  * By manually probing the device (as root):
-    # modprobe -r snd-usb-audio
-    # modprobe snd-usb-audio index=1 device_setup=0x09
-+
-  * Or while configuring the modules options in your modules configuration file
-    - For Fedora distributions, edit the /etc/modprobe.conf file:
-        alias snd-card-1 snd-usb-audio
-        options snd-usb-audio index=1 device_setup=0x09
- 
--IMPORTANT NOTE WHEN SWITCHING CONFIGURATION:
---------------------------------------------
-- * You may need to _first_ initialize the module with the correct device_setup 
--   parameter and _only_after_ turn on the Audiophile USB device
-- * This is especially true when switching the sample depth:
-+CAUTION when initializaing the device
-+-------------------------------------
-+
-+ * Correct initialization on the device requires that device_setup is given to
-+   the module BEFORE the device is turned on. So, if you use the "manual probing"
-+   method described above, take care to power-on the device AFTER this initialization.
-+
-+ * Failing to respect this will lead in a misconfiguration of the device. In this case
-+   turn off the device, unproble the snd-usb-audio module, then probe it again with 
-+   correct device_setup parameter and then (and only then) turn on the device again.
-+
-+ * If you've correctly initialized the device in a valid mode and then want to switch
-+   to  another mode (possibly with another sample-depth), please use also the following 
-+   procedure:
-    - first turn off the device
-    - de-register the snd-usb-audio module (modprobe -r)
-    - change the device_setup parameter by changing the device_setup
-      option in /etc/modprobe.conf 
-    - turn on the device
-+ * A workaround for this last issue has been applied to kernel 2.6.23, but it may not
-+   be enough to ensure the 'stability' of the device initialization.
- 
--2.2.2.3 - Audiophile USB's device_setup structure
-+3.2.3 - Technical details for hackers
-+-------------------------------------
-+This section is for hackers, wanting to understand details about the device
-+internals and how Alsa supports it.
-+
-+3.2.3.1 - Audiophile USB's device_setup structure
- 
- If you want to understand the device_setup magic numbers for the Audiophile 
- USB, you need some very basic understanding of binary computation. However, 
-@@ -228,12 +309,12 @@
-    - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll
-      only be able to use one at the same time
- 
--2.2.3 -  USB implementation details for this device
-+3.2.3.2 -  USB implementation details for this device
- 
- You may safely skip this section if you're not interested in driver 
--development.
-+hacking.
- 
--This section describes some internal aspects of the device and summarize the 
-+This section describes some internal aspects of the device and summarizes the 
- data I got by usb-snooping the windows and Linux drivers.
- 
- The M-Audio Audiophile USB has 7 USB Interfaces:
-@@ -293,43 +374,45 @@
- "audiophile_skip_setting_quirk" in order to prevent AltSettings not 
- corresponding to device_setup from being registered in the driver.
- 
--3 - Audiophile USB and Jack support
-+4 - Audiophile USB and Jack support
- ===================================
- 
- This section deals with support of the Audiophile USB device in Jack.
--The main issue regarding this support is that the device is Big Endian 
--compliant.
- 
--3.1 - Using the plug alsa plugin
----------------------------------
-+There are 2 main potential issues when using Jackd with the device:
-+* support for Big-Endian devices in 24-bit modes
-+* support for 4-in / 4-out channels
-+
-+4.1 - Direct support in Jackd
-+-----------------------------
-+
-+Jack supports big endian devices only in recent versions (thanks to
-+Andreas Steinmetz for his first big-endian patch). I can't remember 
-+extacly when this support was released into jackd, let's just say that 
-+with jackd version 0.103.0 it's almost ok (just a small bug is affecting 
-+16bits Big-Endian devices, but since you've read  carefully the above 
-+paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices 
-+are now Little Endians ;-) ).
- 
--Jack doesn't directly support big endian devices. Thus, one way to have support 
--for this device with Alsa is to use the Alsa "plug" converter.
-+You can run jackd with the following command for playback with Ao and
-+record with Ai:
-+  % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
-+
-+4.2 - Using Alsa plughw
-+-----------------------
-+If you don't have a recent Jackd installed, you can downgrade to using
-+the Alsa "plug" converter.
- 
- For instance here is one way to run Jack with 2 playback channels on Ao and 2 
- capture channels from Ai:
-   % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
- 
--
- However you may see the following warning message:
- "You appear to be using the ALSA software "plug" layer, probably a result of 
- using the "default" ALSA device. This is less efficient than it could be. 
- Consider using a hardware device instead rather than using the plug layer."
- 
--3.2 - Patching alsa to use direct pcm device
----------------------------------------------
--A patch for Jack by Andreas Steinmetz adds support for Big Endian devices. 
--However it has not been included in the CVS tree.
--
--You can find it at the following URL:
--http://sourceforge.net/tracker/index.php?func=detail&aid=1289682&group_id=39687&
--atid=425939
--
--After having applied the patch you can run jackd with the following command 
--line:
--  % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
--
--3.2 - Getting 2 input and/or output interfaces in Jack
-+4.3 - Getting 2 input and/or output interfaces in Jack
- ------------------------------------------------------
- 
- As you can see, starting the Jack server this way will only enable 1 stereo
-@@ -339,6 +422,7 @@
- * Jack can only open one capture device and one playback device at a time
- * The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
-   (and optionally hw:1,2)
-+
- If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
- combine the Alsa devices into one logical "complex" device.
- 
-@@ -348,13 +432,11 @@
- the Audiophile USB.
- 
- Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
--* patching Jack with the previously mentioned "Big Endian" patch
--* patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page)
--* patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
-+* Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page)
-+* (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
- * define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
-   file 
- * start jackd with this device
- 
--I had no success in testing this for now, but this may be due to my OS
--configuration. If you have any success with this kind of setup, please
--drop me an email.
-+I had no success in testing this for now, if you have any success with this kind 
-+of setup, please drop me an email.
---- linux-2.6.22.1.orig/Documentation/sound/alsa/OSS-Emulation.txt
-+++ linux-2.6.22.1/Documentation/sound/alsa/OSS-Emulation.txt
-@@ -278,6 +278,21 @@
- image.
- 
- 
-+Duplex Streams
-+==============
-+
-+Note that when attempting to use a single device file for playback and
-+capture, the OSS API provides no way to set the format, sample rate or
-+number of channels different in each direction.  Thus
-+	io_handle = open("device", O_RDWR)
-+will only function correctly if the values are the same in each direction.
-+
-+To use different values in the two directions, use both
-+	input_handle = open("device", O_RDONLY)
-+	output_handle = open("device", O_WRONLY)
-+and set the values for the corresponding handle.
-+
-+
- Unsupported Features
- ====================
- 
---- linux-2.6.22.1.orig/include/linux/i2c-id.h
-+++ linux-2.6.22.1/include/linux/i2c-id.h
-@@ -115,9 +115,10 @@
- #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_WM8753		91	/* Wolfson WM8753 audio codec */
-+#define I2C_DRIVERID_WM8731	89	/* Wolfson WM8731 audio codec */
-+#define I2C_DRIVERID_WM8750	90	/* Wolfson WM8750 audio codec */
-+#define I2C_DRIVERID_WM8753	91	/* Wolfson WM8753 audio codec */
-+#define I2C_DRIVERID_LM4857 	92 	/* LM4857 Audio Amplifier */
- 
- #define I2C_DRIVERID_I2CDEV	900
- #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
---- linux-2.6.22.1.orig/include/sound/ak4xxx-adda.h
-+++ linux-2.6.22.1/include/sound/ak4xxx-adda.h
-@@ -43,6 +43,7 @@
- struct snd_akm4xxx_dac_channel {
- 	char *name;		/* mixer volume name */
- 	unsigned int num_channels;
-+	char *switch_name;		/* mixer switch*/
- };
- 
- /* ADC labels and channels */
---- linux-2.6.22.1.orig/include/sound/cs46xx.h
-+++ linux-2.6.22.1/include/sound/cs46xx.h
-@@ -1723,6 +1723,10 @@
- 	struct snd_cs46xx_pcm *playback_pcm;
- 	unsigned int play_ctl;
- #endif
-+
-+#ifdef CONFIG_PM
-+	u32 *saved_regs;
-+#endif
- };
- 
- int snd_cs46xx_create(struct snd_card *card,
---- linux-2.6.22.1.orig/include/sound/cs46xx_dsp_spos.h
-+++ linux-2.6.22.1/include/sound/cs46xx_dsp_spos.h
-@@ -107,6 +107,7 @@
- 	char scb_name[DSP_MAX_SCB_NAME];
- 	u32 address;
- 	int index;
-+	u32 *data;
- 
- 	struct dsp_scb_descriptor * sub_list_ptr;
- 	struct dsp_scb_descriptor * next_scb_ptr;
-@@ -127,6 +128,7 @@
- 	int size;
- 	u32 address;
- 	int index;
-+	u32 *data;
- };
- 
- struct dsp_pcm_channel_descriptor {
---- linux-2.6.22.1.orig/include/sound/emu10k1.h
-+++ linux-2.6.22.1/include/sound/emu10k1.h
-@@ -1120,6 +1120,16 @@
- /************************************************************************************************/
- /* EMU1010m HANA Destinations									*/
- /************************************************************************************************/
-+/* 32-bit destinations of signal in the Hana FPGA. Destinations are either
-+ * physical outputs of Hana, or outputs going to Alice2 (audigy) for capture
-+ * - 16 x EMU_DST_ALICE2_EMU32_X.
-+ */
-+/* EMU32 = 32-bit serial channel between Alice2 (audigy) and Hana (FPGA) */
-+/* EMU_DST_ALICE2_EMU32_X - data channels from Hana to Alice2 used for capture.
-+ * Which data is fed into a EMU_DST_ALICE2_EMU32_X channel in Hana depends on
-+ * setup of mixer control for each destination - see emumixer.c -
-+ * snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[]
-+ */
- #define EMU_DST_ALICE2_EMU32_0	0x000f	/* 16 EMU32 channels to Alice2 +0 to +0xf */
- #define EMU_DST_ALICE2_EMU32_1	0x0000	/* 16 EMU32 channels to Alice2 +0 to +0xf */
- #define EMU_DST_ALICE2_EMU32_2	0x0001	/* 16 EMU32 channels to Alice2 +0 to +0xf */
-@@ -1199,6 +1209,12 @@
- /************************************************************************************************/
- /* EMU1010m HANA Sources									*/
- /************************************************************************************************/
-+/* 32-bit sources of signal in the Hana FPGA. The sources are routed to
-+ * destinations using mixer control for each destination - see emumixer.c
-+ * Sources are either physical inputs of FPGA,
-+ * or outputs from Alice (audigy) - 16 x EMU_SRC_ALICE_EMU32A +
-+ * 16 x EMU_SRC_ALICE_EMU32B
-+ */
- #define EMU_SRC_SILENCE		0x0000	/* Silence */
- #define EMU_SRC_DOCK_MIC_A1	0x0100	/* Audio Dock Mic A, 1st or 48kHz only */
- #define EMU_SRC_DOCK_MIC_A2	0x0101	/* Audio Dock Mic A, 2nd or 96kHz */
---- linux-2.6.22.1.orig/include/sound/sb.h
-+++ linux-2.6.22.1/include/sound/sb.h
-@@ -38,6 +38,7 @@
- 	SB_HW_ALS100,		/* Avance Logic ALS100 chip */
- 	SB_HW_ALS4000,		/* Avance Logic ALS4000 chip */
- 	SB_HW_DT019X,		/* Diamond Tech. DT-019X / Avance Logic ALS-007 */
-+	SB_HW_CS5530,		/* Cyrix/NatSemi 5530 VSA1 */
- };
- 
- #define SB_OPEN_PCM			0x01
---- linux-2.6.22.1.orig/include/sound/version.h
-+++ linux-2.6.22.1/include/sound/version.h
-@@ -1,3 +1,3 @@
- /* include/version.h.  Generated by alsa/ksync script.  */
- #define CONFIG_SND_VERSION "1.0.14"
--#define CONFIG_SND_DATE " (Thu May 31 09:03:25 2007 UTC)"
-+#define CONFIG_SND_DATE " (Fri Jul 20 09:12:58 2007 UTC)"
---- linux-2.6.22.1.orig/include/sound/wavefront_fx.h
-+++ /dev/null
-@@ -1,9 +0,0 @@
--#ifndef __SOUND_WAVEFRONT_FX_H
--#define __SOUND_WAVEFRONT_FX_H
--
--extern int  snd_wavefront_fx_detect (snd_wavefront_t *);
--extern void snd_wavefront_fx_ioctl  (snd_synth_t *sdev, 
--				     unsigned int cmd, 
--				     unsigned long arg);
--
--#endif  __SOUND_WAVEFRONT_FX_H
---- linux-2.6.22.1.orig/sound/Kconfig
-+++ linux-2.6.22.1/sound/Kconfig
-@@ -65,6 +65,8 @@
- 
- source "sound/mips/Kconfig"
- 
-+source "sound/sh/Kconfig"
-+
- # the following will depend on the order of config.
- # here assuming USB is defined before ALSA
- source "sound/usb/Kconfig"
---- linux-2.6.22.1.orig/sound/Makefile
-+++ linux-2.6.22.1/sound/Makefile
-@@ -5,7 +5,7 @@
- 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/ soc/
-+obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
- obj-$(CONFIG_SND_AOA) += aoa/
- 
- # This one must be compilable even if sound is configured out
---- linux-2.6.22.1.orig/sound/aoa/codecs/snd-aoa-codec-onyx.c
-+++ linux-2.6.22.1/sound/aoa/codecs/snd-aoa-codec-onyx.c
-@@ -661,7 +661,7 @@
- 		.tag = 2,
- 	},
- #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
--Once alsa gets supports for this kind of thing we can add it...
-+	/* Once alsa gets supports for this kind of thing we can add it... */
- 	{
- 		/* digital compressed output */
- 		.formats =  SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
-@@ -713,7 +713,7 @@
- 	if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
- 		/* mute and lock analog output */
- 		onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
--		if (onyx_write_register(onyx
-+		if (onyx_write_register(onyx,
- 					ONYX_REG_DAC_CONTROL,
- 					v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
- 			goto out_unlock;
---- linux-2.6.22.1.orig/sound/core/pcm_native.c
-+++ linux-2.6.22.1/sound/core/pcm_native.c
-@@ -1487,7 +1487,7 @@
- 
- 	snd_pcm_stream_lock_irq(substream);
- 	/* resume pause */
--	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
-+	if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED)
- 		snd_pcm_pause(substream, 0);
- 
- 	/* pre-start/stop - all running streams are changed to DRAINING state */
---- linux-2.6.22.1.orig/sound/core/seq/seq_instr.c
-+++ linux-2.6.22.1/sound/core/seq/seq_instr.c
-@@ -109,7 +109,7 @@
- 			spin_lock_irqsave(&list->lock, flags);
- 			while (instr->use) {
- 				spin_unlock_irqrestore(&list->lock, flags);
--				schedule_timeout_interruptible(1);
-+				schedule_timeout(1);
- 				spin_lock_irqsave(&list->lock, flags);
- 			}				
- 			spin_unlock_irqrestore(&list->lock, flags);
-@@ -199,7 +199,7 @@
- 			instr = flist;
- 			flist = instr->next;
- 			while (instr->use)
--				schedule_timeout_interruptible(1);
-+				schedule_timeout(1);
- 			if (snd_seq_instr_free(instr, atomic)<0)
- 				snd_printk(KERN_WARNING "instrument free problem\n");
- 			instr = next;
-@@ -555,7 +555,7 @@
- 					   SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
- 		while (instr->use) {
- 			spin_unlock_irqrestore(&list->lock, flags);
--			schedule_timeout_interruptible(1);
-+			schedule_timeout(1);
- 			spin_lock_irqsave(&list->lock, flags);
- 		}				
- 		spin_unlock_irqrestore(&list->lock, flags);
---- linux-2.6.22.1.orig/sound/core/timer.c
-+++ linux-2.6.22.1/sound/core/timer.c
-@@ -1549,9 +1549,11 @@
- 	int err = 0;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	t = tu->timeri->timer;
--	snd_assert(t != NULL, return -ENXIO);
-+	if (!t)
-+		return -EBADFD;
- 
- 	info = kzalloc(sizeof(*info), GFP_KERNEL);
- 	if (! info)
-@@ -1579,9 +1581,11 @@
- 	int err;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	t = tu->timeri->timer;
--	snd_assert(t != NULL, return -ENXIO);
-+	if (!t)
-+		return -EBADFD;
- 	if (copy_from_user(&params, _params, sizeof(params)))
- 		return -EFAULT;
- 	if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
-@@ -1675,7 +1679,8 @@
- 	struct snd_timer_status status;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	memset(&status, 0, sizeof(status));
- 	status.tstamp = tu->tstamp;
- 	status.resolution = snd_timer_resolution(tu->timeri);
-@@ -1695,7 +1700,8 @@
- 	struct snd_timer_user *tu;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	snd_timer_stop(tu->timeri);
- 	tu->timeri->lost = 0;
- 	tu->last_resolution = 0;
-@@ -1708,7 +1714,8 @@
- 	struct snd_timer_user *tu;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
- }
- 
-@@ -1718,7 +1725,8 @@
- 	struct snd_timer_user *tu;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	tu->timeri->lost = 0;
- 	return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
- }
-@@ -1729,7 +1737,8 @@
- 	struct snd_timer_user *tu;
- 
- 	tu = file->private_data;
--	snd_assert(tu->timeri != NULL, return -ENXIO);
-+	if (!tu->timeri)
-+		return -EBADFD;
- 	return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
- }
- 
---- linux-2.6.22.1.orig/sound/drivers/dummy.c
-+++ linux-2.6.22.1/sound/drivers/dummy.c
-@@ -659,7 +659,7 @@
- 	},
- };
- 
--static void __init_or_module snd_dummy_unregister_all(void)
-+static void snd_dummy_unregister_all(void)
- {
- 	int i;
- 
---- linux-2.6.22.1.orig/sound/drivers/mpu401/mpu401.c
-+++ linux-2.6.22.1/sound/drivers/mpu401/mpu401.c
-@@ -228,7 +228,7 @@
- static struct pnp_driver snd_mpu401_pnp_driver;
- #endif
- 
--static void __init_or_module snd_mpu401_unregister_all(void)
-+static void snd_mpu401_unregister_all(void)
- {
- 	int i;
- 
---- linux-2.6.22.1.orig/sound/drivers/portman2x4.c
-+++ linux-2.6.22.1/sound/drivers/portman2x4.c
-@@ -833,7 +833,7 @@
- /*********************************************************************
-  * module init stuff
-  *********************************************************************/
--static void __init_or_module snd_portman_unregister_all(void)
-+static void snd_portman_unregister_all(void)
- {
- 	int i;
- 
---- linux-2.6.22.1.orig/sound/drivers/serial-u16550.c
-+++ linux-2.6.22.1/sound/drivers/serial-u16550.c
-@@ -998,7 +998,7 @@
- 	},
- };
- 
--static void __init_or_module snd_serial_unregister_all(void)
-+static void snd_serial_unregister_all(void)
- {
- 	int i;
- 
---- linux-2.6.22.1.orig/sound/drivers/virmidi.c
-+++ linux-2.6.22.1/sound/drivers/virmidi.c
-@@ -145,7 +145,7 @@
- 	},
- };
- 
--static void __init_or_module snd_virmidi_unregister_all(void)
-+static void snd_virmidi_unregister_all(void)
- {
- 	int i;
- 
---- linux-2.6.22.1.orig/sound/i2c/other/ak4xxx-adda.c
-+++ linux-2.6.22.1/sound/i2c/other/ak4xxx-adda.c
-@@ -481,8 +481,8 @@
- 	int addr = AK_GET_ADDR(kcontrol->private_value);
- 	int shift = AK_GET_SHIFT(kcontrol->private_value);
- 	int invert = AK_GET_INVERT(kcontrol->private_value);
--	unsigned char val = snd_akm4xxx_get(ak, chip, addr);
--
-+	/* we observe the (1<<shift) bit only */
-+	unsigned char val = snd_akm4xxx_get(ak, chip, addr) & (1<<shift);
- 	if (invert)
- 		val = ! val;
- 	ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0;
-@@ -585,6 +585,26 @@
- 
- 	mixer_ch = 0;
- 	for (idx = 0; idx < ak->num_dacs; ) {
-+		/* mute control for Revolution 7.1 - AK4381 */
-+		if (ak->type == SND_AK4381 
-+				&&  ak->dac_info[mixer_ch].switch_name) {
-+			memset(&knew, 0, sizeof(knew));
-+			knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-+			knew.count = 1;
-+			knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
-+			knew.name = ak->dac_info[mixer_ch].switch_name;
-+			knew.info = ak4xxx_switch_info;
-+			knew.get = ak4xxx_switch_get;
-+			knew.put = ak4xxx_switch_put;
-+			knew.access = 0;
-+			/* register 1, bit 0 (SMUTE): 0 = normal operation,
-+			   1 = mute */
-+			knew.private_value =
-+				AK_COMPOSE(idx/2, 1, 0, 0) | AK_INVERT;
-+			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
-+			if (err < 0)
-+				return err;
-+		}
- 		memset(&knew, 0, sizeof(knew));
- 		if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) {
- 			knew.name = "DAC Volume";
---- linux-2.6.22.1.orig/sound/isa/Kconfig
-+++ linux-2.6.22.1/sound/isa/Kconfig
-@@ -1,8 +1,5 @@
- # ALSA ISA drivers
- 
--menu "ISA devices"
--	depends on SND!=n && ISA && ISA_DMA_API
--
- config SND_AD1848_LIB
-         tristate
-         select SND_PCM
-@@ -11,6 +8,22 @@
-         tristate
-         select SND_PCM
- 
-+config SND_SB_COMMON
-+        tristate
-+
-+config SND_SB8_DSP
-+        tristate
-+        select SND_PCM
-+        select SND_SB_COMMON
-+
-+config SND_SB16_DSP
-+        tristate
-+        select SND_PCM
-+        select SND_SB_COMMON
-+
-+menu "ISA devices"
-+	depends on SND!=n && ISA && ISA_DMA_API
-+
- config SND_ADLIB
- 	tristate "AdLib FM card"
- 	depends on SND
-@@ -55,7 +68,7 @@
- 	select ISAPNP
- 	select SND_OPL3_LIB
- 	select SND_MPU401_UART
--	select SND_PCM
-+	select SND_SB16_DSP
- 	help
- 	  Say Y here to include support for soundcards based on Avance
- 	  Logic ALS100, ALS110, ALS120 and ALS200 chips.
-@@ -81,6 +94,7 @@
- 	tristate "C-Media CMI8330"
- 	depends on SND
- 	select SND_AD1848_LIB
-+	select SND_SB16_DSP
- 	help
- 	  Say Y here to include support for soundcards based on the
- 	  C-Media CMI8330 chip.
-@@ -132,7 +146,7 @@
- 	select ISAPNP
- 	select SND_OPL3_LIB
- 	select SND_MPU401_UART
--	select SND_PCM
-+	select SND_SB16_DSP
- 	help
- 	  Say Y here to include support for soundcards based on the
- 	  Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
-@@ -145,7 +159,7 @@
- 	depends on SND && PNP && ISA
- 	select ISAPNP
- 	select SND_MPU401_UART
--	select SND_PCM
-+	select SND_SB8_DSP
- 	help
- 	  Say Y here to include support for ESS AudioDrive ES968 chips.
- 
-@@ -321,7 +335,7 @@
- 	depends on SND
- 	select SND_OPL3_LIB
- 	select SND_RAWMIDI
--	select SND_PCM
-+	select SND_SB8_DSP
- 	help
- 	  Say Y here to include support for Creative Sound Blaster 1.0/
- 	  2.0/Pro (8-bit) or 100% compatible soundcards.
-@@ -334,7 +348,7 @@
- 	depends on SND
- 	select SND_OPL3_LIB
- 	select SND_MPU401_UART
--	select SND_PCM
-+	select SND_SB16_DSP
- 	help
- 	  Say Y here to include support for Sound Blaster 16 soundcards
- 	  (including the Plug and Play version).
-@@ -347,7 +361,7 @@
- 	depends on SND
- 	select SND_OPL3_LIB
- 	select SND_MPU401_UART
--	select SND_PCM
-+	select SND_SB16_DSP
- 	help
- 	  Say Y here to include support for Sound Blaster AWE soundcards
- 	  (including the Plug and Play version).
---- linux-2.6.22.1.orig/sound/isa/ad1848/ad1848_lib.c
-+++ linux-2.6.22.1/sound/isa/ad1848/ad1848_lib.c
-@@ -245,7 +245,7 @@
- 			snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n");
- 			return;
- 		}
--		time = schedule_timeout_interruptible(time);
-+		time = schedule_timeout(time);
- 		spin_lock_irqsave(&chip->reg_lock, flags);
- 	}
- #if 0
-@@ -258,7 +258,7 @@
- 			snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
- 			return;
- 		}
--		time = schedule_timeout_interruptible(time);
-+		time = schedule_timeout(time);
- 		spin_lock_irqsave(&chip->reg_lock, flags);
- 	}
- 	spin_unlock_irqrestore(&chip->reg_lock, flags);
---- linux-2.6.22.1.orig/sound/isa/opl3sa2.c
-+++ linux-2.6.22.1/sound/isa/opl3sa2.c
-@@ -164,6 +164,8 @@
- 	{ .id = "YMH0801", .devs = { { "YMH0021" } } },
- 	/* NeoMagic MagicWave 3DX */
- 	{ .id = "NMX2200", .devs = { { "YMH2210" } } },
-+	/* NeoMagic MagicWave 3D */
-+	{ .id = "NMX2200", .devs = { { "NMX2210" } } },
- 	/* --- */
- 	{ .id = "" }	/* end */
- };
---- linux-2.6.22.1.orig/sound/isa/opti9xx/opti92x-ad1848.c
-+++ linux-2.6.22.1/sound/isa/opti9xx/opti92x-ad1848.c
-@@ -1927,10 +1927,12 @@
- static int __devinit snd_opti9xx_isa_match(struct device *devptr,
- 					   unsigned int dev)
- {
-+#ifdef CONFIG_PNP
- 	if (snd_opti9xx_pnp_is_probed)
- 		return 0;
- 	if (isapnp)
- 		return 0;
-+#endif
- 	return 1;
- }
- 
-@@ -2096,6 +2098,7 @@
- 	pnp_register_card_driver(&opti9xx_pnpc_driver);
- 	if (snd_opti9xx_pnp_is_probed)
- 		return 0;
-+	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
- #endif
- 	return isa_register_driver(&snd_opti9xx_driver, 1);
- }
---- linux-2.6.22.1.orig/sound/isa/sb/Makefile
-+++ linux-2.6.22.1/sound/isa/sb/Makefile
-@@ -22,14 +22,13 @@
- sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
- 
- # Toplevel Module Dependency
--obj-$(CONFIG_SND_ALS100) += snd-sb16-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_CMI8330) += snd-sb16-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_DT019X) += snd-sb16-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o
--obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o
-+obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o
-+obj-$(CONFIG_SND_SB16_DSP) += snd-sb16-dsp.o
-+obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o
-+obj-$(CONFIG_SND_SB8) += snd-sb8.o
-+obj-$(CONFIG_SND_SB16) += snd-sb16.o
-+obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o
-+obj-$(CONFIG_SND_ES968) += snd-es968.o
- ifeq ($(CONFIG_SND_SB16_CSP),y)
-   obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
-   obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
---- linux-2.6.22.1.orig/sound/isa/sb/sb16_main.c
-+++ linux-2.6.22.1/sound/isa/sb/sb16_main.c
-@@ -563,6 +563,11 @@
-       __open_ok:
- 	if (chip->hardware == SB_HW_ALS100)
- 		runtime->hw.rate_max = 48000;
-+	if (chip->hardware == SB_HW_CS5530) {
-+		runtime->hw.buffer_bytes_max = 32 * 1024;
-+		runtime->hw.periods_min = 2;
-+		runtime->hw.rate_min = 44100;
-+	}
- 	if (chip->mode & SB_RATE_LOCK)
- 		runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
- 	chip->playback_substream = substream;
-@@ -633,6 +638,11 @@
-       __open_ok:
- 	if (chip->hardware == SB_HW_ALS100)
- 		runtime->hw.rate_max = 48000;
-+	if (chip->hardware == SB_HW_CS5530) {
-+		runtime->hw.buffer_bytes_max = 32 * 1024;
-+		runtime->hw.periods_min = 2;
-+		runtime->hw.rate_min = 44100;
-+	}
- 	if (chip->mode & SB_RATE_LOCK)
- 		runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
- 	chip->capture_substream = substream;
---- linux-2.6.22.1.orig/sound/isa/sb/sb_common.c
-+++ linux-2.6.22.1/sound/isa/sb/sb_common.c
-@@ -128,7 +128,7 @@
- 	minor = version & 0xff;
- 	snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n",
- 		    chip->port, major, minor);
--	
-+
- 	switch (chip->hardware) {
- 	case SB_HW_AUTO:
- 		switch (major) {
-@@ -168,6 +168,9 @@
- 	case SB_HW_DT019X:
- 		str = "(DT019X/ALS007)";
- 		break;
-+	case SB_HW_CS5530:
-+		str = "16 (CS5530)";
-+		break;
- 	default:
- 		return -ENODEV;
- 	}
---- linux-2.6.22.1.orig/sound/isa/sb/sb_mixer.c
-+++ linux-2.6.22.1/sound/isa/sb/sb_mixer.c
-@@ -821,6 +821,7 @@
- 		break;
- 	case SB_HW_16:
- 	case SB_HW_ALS100:
-+	case SB_HW_CS5530:
- 		if ((err = snd_sbmixer_init(chip,
- 					    snd_sb16_controls,
- 					    ARRAY_SIZE(snd_sb16_controls),
-@@ -950,6 +951,7 @@
- 		break;
- 	case SB_HW_16:
- 	case SB_HW_ALS100:
-+	case SB_HW_CS5530:
- 		save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
- 		break;
- 	case SB_HW_ALS4000:
-@@ -975,6 +977,7 @@
- 		break;
- 	case SB_HW_16:
- 	case SB_HW_ALS100:
-+	case SB_HW_CS5530:
- 		restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
- 		break;
- 	case SB_HW_ALS4000:
---- linux-2.6.22.1.orig/sound/isa/sscape.c
-+++ linux-2.6.22.1/sound/isa/sscape.c
-@@ -382,7 +382,7 @@
- 		unsigned long flags;
- 		unsigned char x;
- 
--		schedule_timeout_interruptible(1);
-+		schedule_timeout(1);
- 
- 		spin_lock_irqsave(&s->lock, flags);
- 		x = inb(HOST_DATA_IO(s->io_base));
-@@ -409,7 +409,7 @@
- 		unsigned long flags;
- 		unsigned char x;
- 
--		schedule_timeout_interruptible(1);
-+		schedule_timeout(1);
- 
- 		spin_lock_irqsave(&s->lock, flags);
- 		x = inb(HOST_DATA_IO(s->io_base));
---- linux-2.6.22.1.orig/sound/isa/wavefront/wavefront_synth.c
-+++ linux-2.6.22.1/sound/isa/wavefront/wavefront_synth.c
-@@ -1780,7 +1780,7 @@
- 	outb (val,port);
- 	spin_unlock_irq(&dev->irq_lock);
- 	while (1) {
--		if ((timeout = schedule_timeout_interruptible(timeout)) == 0)
-+		if ((timeout = schedule_timeout(timeout)) == 0)
- 			return;
- 		if (dev->irq_ok)
- 			return;
---- linux-2.6.22.1.orig/sound/pci/Kconfig
-+++ linux-2.6.22.1/sound/pci/Kconfig
-@@ -33,6 +33,7 @@
- 	select SND_OPL3_LIB
- 	select SND_MPU401_UART
- 	select SND_PCM
-+	select SND_SB_COMMON
- 	help
- 	  Say Y here to include support for soundcards based on Avance Logic
- 	  ALS4000 chips.
-@@ -215,6 +216,16 @@
- 
- 	  This works better than the old code, so say Y.
- 
-+config SND_CS5530
-+	tristate "CS5530 Audio"
-+	depends on SND && ISA_DMA_API
-+	select SND_SB16_DSP
-+	help
-+	  Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
-+
-+	  To compile this driver as a module, choose M here: the module
-+	  will be called snd-cs5530.
-+
- config SND_CS5535AUDIO
- 	tristate "CS5535/CS5536 Audio"
- 	depends on SND && X86 && !X86_64
---- linux-2.6.22.1.orig/sound/pci/Makefile
-+++ linux-2.6.22.1/sound/pci/Makefile
-@@ -12,6 +12,7 @@
- snd-bt87x-objs := bt87x.o
- snd-cmipci-objs := cmipci.o
- snd-cs4281-objs := cs4281.o
-+snd-cs5530-objs := cs5530.o
- snd-ens1370-objs := ens1370.o
- snd-ens1371-objs := ens1371.o
- snd-es1938-objs := es1938.o
-@@ -36,6 +37,7 @@
- obj-$(CONFIG_SND_BT87X) += snd-bt87x.o
- obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o
- obj-$(CONFIG_SND_CS4281) += snd-cs4281.o
-+obj-$(CONFIG_SND_CS5530) += snd-cs5530.o
- obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o
- obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o
- obj-$(CONFIG_SND_ES1938) += snd-es1938.o
---- linux-2.6.22.1.orig/sound/pci/ali5451/ali5451.c
-+++ linux-2.6.22.1/sound/pci/ali5451/ali5451.c
-@@ -239,7 +239,7 @@
- 
- 
- struct snd_ali {
--	unsigned long	irq;
-+	int		irq;
- 	unsigned long	port;
- 	unsigned char	revision;
- 
-@@ -731,8 +731,7 @@
- 		return;
- 	}
- 
--	count = 0;
--	while (count++ <= 50000) {
-+	for (count = 0; count <= 50000; count++) {
- 		snd_ali_delay(codec, 6);
- 		bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
- 		R2 = bval & 0x1F;
-@@ -2343,7 +2342,7 @@
- 	strcpy(card->driver, "ALI5451");
- 	strcpy(card->shortname, "ALI 5451");
- 	
--	sprintf(card->longname, "%s at 0x%lx, irq %li",
-+	sprintf(card->longname, "%s at 0x%lx, irq %i",
- 		card->shortname, codec->port, codec->irq);
- 
- 	snd_ali_printk("register card.\n");
---- linux-2.6.22.1.orig/sound/pci/als300.c
-+++ linux-2.6.22.1/sound/pci/als300.c
-@@ -88,8 +88,8 @@
- #define PLAYBACK_BLOCK_COUNTER	0x9A
- #define RECORD_BLOCK_COUNTER	0x9B
- 
--#define DEBUG_CALLS	1
--#define DEBUG_PLAY_REC	1
-+#define DEBUG_CALLS	0
-+#define DEBUG_PLAY_REC	0
- 
- #if DEBUG_CALLS
- #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
-@@ -733,7 +733,8 @@
- 
- 	snd_als300_init(chip);
- 
--	if (snd_als300_ac97(chip) < 0) {
-+	err = snd_als300_ac97(chip);
-+	if (err < 0) {
- 		snd_printk(KERN_WARNING "Could not create ac97\n");
- 		snd_als300_free(chip);
- 		return err;
---- linux-2.6.22.1.orig/sound/pci/ca0106/ca0106_main.c
-+++ linux-2.6.22.1/sound/pci/ca0106/ca0106_main.c
-@@ -168,6 +168,25 @@
- #include "ca0106.h"
- 
- static struct snd_ca0106_details ca0106_chip_details[] = {
-+	 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
-+	 /* It is really just a normal SB Live 24bit. */
-+	 /*
-+ 	  * CTRL:CA0111-WTLF
-+	  * ADC: WM8775SEDS
-+	  * DAC: CS4382-KQZ
-+	  */
-+	 /* Tested:
-+	  * Playback on front, rear, center/lfe speakers
-+	  * Capture from Mic in.
-+	  * Not-Tested:
-+	  * Capture from Line in.
-+	  * Playback to digital out.
-+	  */
-+	 { .serial = 0x10121102,
-+	   .name   = "X-Fi Extreme Audio [SB0790]",
-+	   .gpio_type = 1,
-+	   .i2c_adc = 1 } ,
-+	 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
- 	 /* AudigyLS[SB0310] */
- 	 { .serial = 0x10021102,
- 	   .name   = "AudigyLS [SB0310]",
---- linux-2.6.22.1.orig/sound/pci/cs46xx/cs46xx_lib.c
-+++ linux-2.6.22.1/sound/pci/cs46xx/cs46xx_lib.c
-@@ -2897,6 +2897,10 @@
- 	}
- #endif
- 	
-+#ifdef CONFIG_PM
-+	kfree(chip->saved_regs);
-+#endif
-+
- 	pci_disable_device(chip->pci);
- 	kfree(chip);
- 	return 0;
-@@ -3140,6 +3144,23 @@
- /*
-  *  start and load DSP 
-  */
-+
-+static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
-+{
-+	unsigned int tmp;
-+
-+	snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
-+        
-+	tmp = snd_cs46xx_peek(chip, BA1_PFIE);
-+	tmp &= ~0x0000f03f;
-+	snd_cs46xx_poke(chip, BA1_PFIE, tmp);	/* playback interrupt enable */
-+
-+	tmp = snd_cs46xx_peek(chip, BA1_CIE);
-+	tmp &= ~0x0000003f;
-+	tmp |=  0x00000001;
-+	snd_cs46xx_poke(chip, BA1_CIE, tmp);	/* capture interrupt enable */
-+}
-+
- int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
- {	
- 	unsigned int tmp;
-@@ -3214,19 +3235,7 @@
- 
- 	snd_cs46xx_proc_start(chip);
- 
--	/*
--	 *  Enable interrupts on the part.
--	 */
--	snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
--        
--	tmp = snd_cs46xx_peek(chip, BA1_PFIE);
--	tmp &= ~0x0000f03f;
--	snd_cs46xx_poke(chip, BA1_PFIE, tmp);	/* playback interrupt enable */
--
--	tmp = snd_cs46xx_peek(chip, BA1_CIE);
--	tmp &= ~0x0000003f;
--	tmp |=  0x00000001;
--	snd_cs46xx_poke(chip, BA1_CIE, tmp);	/* capture interrupt enable */
-+	cs46xx_enable_stream_irqs(chip);
- 	
- #ifndef CONFIG_SND_CS46XX_NEW_DSP
- 	/* set the attenuation to 0dB */ 
-@@ -3665,11 +3674,19 @@
-  * APM support
-  */
- #ifdef CONFIG_PM
-+static unsigned int saved_regs[] = {
-+	BA0_ACOSV,
-+	BA0_ASER_FADDR,
-+	BA0_ASER_MASTER,
-+	BA1_PVOL,
-+	BA1_CVOL,
-+};
-+
- int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
- {
- 	struct snd_card *card = pci_get_drvdata(pci);
- 	struct snd_cs46xx *chip = card->private_data;
--	int amp_saved;
-+	int i, amp_saved;
- 
- 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- 	chip->in_suspend = 1;
-@@ -3680,6 +3697,10 @@
- 	snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
- 	snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
- 
-+	/* save some registers */
-+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
-+		chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]);
-+
- 	amp_saved = chip->amplifier;
- 	/* turn off amp */
- 	chip->amplifier_ctrl(chip, -chip->amplifier);
-@@ -3698,7 +3719,7 @@
- {
- 	struct snd_card *card = pci_get_drvdata(pci);
- 	struct snd_cs46xx *chip = card->private_data;
--	int amp_saved;
-+	int i, amp_saved;
- 
- 	pci_set_power_state(pci, PCI_D0);
- 	pci_restore_state(pci);
-@@ -3716,6 +3737,16 @@
- 
- 	snd_cs46xx_chip_init(chip);
- 
-+	snd_cs46xx_reset(chip);
-+#ifdef CONFIG_SND_CS46XX_NEW_DSP
-+	cs46xx_dsp_resume(chip);
-+	/* restore some registers */
-+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
-+		snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]);
-+#else
-+	snd_cs46xx_download_image(chip);
-+#endif
-+
- #if 0
- 	snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 
- 			       chip->ac97_general_purpose);
-@@ -3730,6 +3761,13 @@
- 	snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
- 	snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
- 
-+	/* reset playback/capture */
-+	snd_cs46xx_set_play_sample_rate(chip, 8000);
-+	snd_cs46xx_set_capture_sample_rate(chip, 8000);
-+	snd_cs46xx_proc_start(chip);
-+
-+	cs46xx_enable_stream_irqs(chip);
-+
- 	if (amp_saved)
- 		chip->amplifier_ctrl(chip, 1); /* turn amp on */
- 	else
-@@ -3896,6 +3934,15 @@
- 	
- 	snd_cs46xx_proc_init(card, chip);
- 
-+#ifdef CONFIG_PM
-+	chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) *
-+				   ARRAY_SIZE(saved_regs), GFP_KERNEL);
-+	if (!chip->saved_regs) {
-+		snd_cs46xx_free(chip);
-+		return -ENOMEM;
-+	}
-+#endif
-+
- 	chip->active_ctrl(chip, -1); /* disable CLKRUN */
- 
- 	snd_card_set_dev(card, &pci->dev);
---- linux-2.6.22.1.orig/sound/pci/cs46xx/cs46xx_lib.h
-+++ linux-2.6.22.1/sound/pci/cs46xx/cs46xx_lib.h
-@@ -86,6 +86,9 @@
- struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip);
- void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip);
- int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module);
-+#ifdef CONFIG_PM
-+int cs46xx_dsp_resume(struct snd_cs46xx * chip);
-+#endif
- struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name,
- 						   int symbol_type);
- #ifdef CONFIG_PROC_FS
---- linux-2.6.22.1.orig/sound/pci/cs46xx/dsp_spos.c
-+++ linux-2.6.22.1/sound/pci/cs46xx/dsp_spos.c
-@@ -306,13 +306,59 @@
- 	mutex_unlock(&chip->spos_mutex);
- }
- 
-+static int dsp_load_parameter(struct snd_cs46xx *chip,
-+			      struct dsp_segment_desc *parameter)
-+{
-+	u32 doffset, dsize;
-+
-+	if (!parameter) {
-+		snd_printdd("dsp_spos: module got no parameter segment\n");
-+		return 0;
-+	}
-+
-+	doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
-+	dsize   = parameter->size * 4;
-+
-+	snd_printdd("dsp_spos: "
-+		    "downloading parameter data to chip (%08x-%08x)\n",
-+		    doffset,doffset + dsize);
-+	if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
-+		snd_printk(KERN_ERR "dsp_spos: "
-+			   "failed to download parameter data to DSP\n");
-+		return -EINVAL;
-+	}
-+	return 0;
-+}
-+
-+static int dsp_load_sample(struct snd_cs46xx *chip,
-+			   struct dsp_segment_desc *sample)
-+{
-+	u32 doffset, dsize;
-+
-+	if (!sample) {
-+		snd_printdd("dsp_spos: module got no sample segment\n");
-+		return 0;
-+	}
-+
-+	doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
-+	dsize   =  sample->size * 4;
-+
-+	snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
-+		    doffset,doffset + dsize);
-+
-+	if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
-+		snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
-+		return -EINVAL;
-+	}
-+	return 0;
-+}
-+
- int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
- {
- 	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
- 	struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
--	struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
--	struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
- 	u32 doffset, dsize;
-+	int err;
- 
- 	if (ins->nmodules == DSP_MAX_MODULES - 1) {
- 		snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
-@@ -326,49 +372,20 @@
- 		snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
- 	}
-   
--	if (parameter == NULL) {
--		snd_printdd("dsp_spos: module got no parameter segment\n");
--	} else {
--		if (ins->nmodules > 0) {
--			snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
--		}
--
--		doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
--		dsize   = parameter->size * 4;
--
--		snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
--			    doffset,doffset + dsize);
--
--		if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
--			snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
--			return -EINVAL;
--		}
--	}
-+	err = dsp_load_parameter(chip, get_segment_desc(module,
-+							SEGTYPE_SP_PARAMETER));
-+	if (err < 0)
-+		return err;
- 
- 	if (ins->nmodules == 0) {
- 		snd_printdd("dsp_spos: clearing sample area\n");
- 		snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
- 	}
- 
--	if (sample == NULL) {
--		snd_printdd("dsp_spos: module got no sample segment\n");
--	} else {
--		if (ins->nmodules > 0) {
--			snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
--		}
--
--		doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
--		dsize   =  sample->size * 4;
--
--		snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
--			    doffset,doffset + dsize);
--
--		if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
--			snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
--			return -EINVAL;
--		}
--	}
--
-+	err = dsp_load_sample(chip, get_segment_desc(module,
-+						     SEGTYPE_SP_SAMPLE));
-+	if (err < 0)
-+		return err;
- 
- 	if (ins->nmodules == 0) {
- 		snd_printdd("dsp_spos: clearing code area\n");
-@@ -986,7 +1003,10 @@
- 		return NULL;
- 	}
- 
--	strcpy(ins->tasks[ins->ntask].task_name,name);
-+	if (name)
-+		strcpy(ins->tasks[ins->ntask].task_name, name);
-+	else
-+		strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
- 	ins->tasks[ins->ntask].address = dest;
- 	ins->tasks[ins->ntask].size = size;
- 
-@@ -995,7 +1015,8 @@
- 	desc = (ins->tasks + ins->ntask);
- 	ins->ntask++;
- 
--	add_symbol (chip,name,dest,SYMBOL_PARAMETER);
-+	if (name)
-+		add_symbol (chip,name,dest,SYMBOL_PARAMETER);
- 	return desc;
- }
- 
-@@ -1006,6 +1027,7 @@
- 
- 	desc = _map_scb (chip,name,dest);
- 	if (desc) {
-+		desc->data = scb_data;
- 		_dsp_create_scb(chip,scb_data,dest);
- 	} else {
- 		snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
-@@ -1023,6 +1045,7 @@
- 
- 	desc = _map_task_tree (chip,name,dest,size);
- 	if (desc) {
-+		desc->data = task_data;
- 		_dsp_create_task_tree(chip,task_data,dest,size);
- 	} else {
- 		snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
-@@ -1320,8 +1343,10 @@
- 			0x0000ffff
- 		};
-     
--		/* dirty hack ... */
--		_dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2);
-+		if (!cs46xx_dsp_create_task_tree(chip, NULL,
-+						 (u32 *)&mix2_ostream_spb,
-+						 WRITE_BACK_SPB, 2))
-+			goto _fail_end;
- 	}
- 
- 	/* input sample converter */
-@@ -1622,7 +1647,6 @@
- 	return 0;
- }
- 
--
- static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
- {
- 	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
-@@ -1894,3 +1918,61 @@
- 
- 	return 0;
- }
-+
-+#ifdef CONFIG_PM
-+int cs46xx_dsp_resume(struct snd_cs46xx * chip)
-+{
-+	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
-+	int i, err;
-+
-+	/* clear parameter, sample and code areas */
-+	snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET,
-+			     DSP_PARAMETER_BYTE_SIZE);
-+	snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET,
-+			     DSP_SAMPLE_BYTE_SIZE);
-+	snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
-+
-+	for (i = 0; i < ins->nmodules; i++) {
-+		struct dsp_module_desc *module = &ins->modules[i];
-+		struct dsp_segment_desc *seg;
-+		u32 doffset, dsize;
-+
-+		seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER);
-+		err = dsp_load_parameter(chip, seg);
-+		if (err < 0)
-+			return err;
-+
-+		seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE);
-+		err = dsp_load_sample(chip, seg);
-+		if (err < 0)
-+			return err;
-+
-+		seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM);
-+		if (!seg)
-+			continue;
-+
-+		doffset = seg->offset * 4 + module->load_address * 4
-+			+ DSP_CODE_BYTE_OFFSET;
-+		dsize   = seg->size * 4;
-+		err = snd_cs46xx_download(chip,
-+					  ins->code.data + module->load_address,
-+					  doffset, dsize);
-+		if (err < 0)
-+			return err;
-+	}
-+
-+	for (i = 0; i < ins->ntask; i++) {
-+		struct dsp_task_descriptor *t = &ins->tasks[i];
-+		_dsp_create_task_tree(chip, t->data, t->address, t->size);
-+	}
-+
-+	for (i = 0; i < ins->nscb; i++) {
-+		struct dsp_scb_descriptor *s = &ins->scbs[i];
-+		if (s->deleted)
-+			continue;
-+		_dsp_create_scb(chip, s->data, s->address);
-+	}
-+
-+	return 0;
-+}
-+#endif
---- /dev/null
-+++ linux-2.6.22.1/sound/pci/cs5530.c
-@@ -0,0 +1,306 @@
-+/*
-+ * cs5530.c - Initialisation code for Cyrix/NatSemi VSA1 softaudio
-+ *
-+ * 	(C) Copyright 2007 Ash Willis <ashwillis at programmer.net>
-+ *	(C) Copyright 2003 Red Hat Inc <alan at redhat.com>
-+ *
-+ * This driver was ported (shamelessly ripped ;) from oss/kahlua.c but I did
-+ * mess with it a bit. The chip seems to have to have trouble with full duplex
-+ * mode. If we're recording in 8bit 8000kHz, say, and we then attempt to
-+ * simultaneously play back audio at 16bit 44100kHz, the device actually plays
-+ * back in the same format in which it is capturing. By forcing the chip to
-+ * always play/capture in 16/44100, we can let alsa-lib convert the samples and
-+ * that way we can hack up some full duplex audio. 
-+ * 
-+ * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems.
-+ * The older version (VSA1) provides fairly good soundblaster emulation
-+ * although there are a couple of bugs: large DMA buffers break record,
-+ * and the MPU event handling seems suspect. VSA2 allows the native driver
-+ * to control the AC97 audio engine directly and requires a different driver.
-+ *
-+ * Thanks to National Semiconductor for providing the needed information
-+ * on the XpressAudio(tm) internals.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * TO DO:
-+ *	Investigate whether we can portably support Cognac (5520) in the
-+ *	same manner.
-+ */
-+
-+#include <sound/driver.h>
-+#include <linux/delay.h>
-+#include <linux/moduleparam.h>
-+#include <linux/pci.h>
-+#include <sound/core.h>
-+#include <sound/sb.h>
-+#include <sound/initval.h>
-+
-+MODULE_AUTHOR("Ash Willis");
-+MODULE_DESCRIPTION("CS5530 Audio");
-+MODULE_LICENSE("GPL");
-+
-+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-+
-+struct snd_cs5530 {
-+	struct snd_card *card;
-+	struct pci_dev *pci;
-+	struct snd_sb *sb;
-+	unsigned long pci_base;
-+};
-+
-+static struct pci_device_id snd_cs5530_ids[] = {
-+	{PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID,
-+							PCI_ANY_ID, 0, 0},
-+	{0,}
-+};
-+
-+MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
-+
-+static int snd_cs5530_free(struct snd_cs5530 *chip)
-+{
-+	pci_release_regions(chip->pci);
-+	pci_disable_device(chip->pci);
-+	kfree(chip);
-+	return 0;
-+}
-+
-+static int snd_cs5530_dev_free(struct snd_device *device)
-+{
-+	struct snd_cs5530 *chip = device->device_data;
-+	return snd_cs5530_free(chip);
-+}
-+
-+static void __devexit snd_cs5530_remove(struct pci_dev *pci)
-+{
-+	snd_card_free(pci_get_drvdata(pci));
-+	pci_set_drvdata(pci, NULL);
-+}
-+
-+static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
-+{
-+	outb(reg, io + 4);
-+	udelay(20);
-+	reg = inb(io + 5);
-+	udelay(20);
-+	return reg;
-+}
-+
-+static int __devinit snd_cs5530_create(struct snd_card *card,
-+				       struct pci_dev *pci,
-+				       struct snd_cs5530 **rchip)
-+{
-+	struct snd_cs5530 *chip;
-+	unsigned long sb_base;
-+	u8 irq, dma8, dma16 = 0;
-+	u16 map;
-+	void __iomem *mem;
-+	int err;
-+
-+	static struct snd_device_ops ops = {
-+		.dev_free = snd_cs5530_dev_free,
-+	};
-+	*rchip = NULL;
-+
-+	err = pci_enable_device(pci);
-+ 	if (err < 0)
-+		return err;
-+
-+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-+	if (chip == NULL) {
-+		pci_disable_device(pci);
-+		return -ENOMEM;
-+	}
-+
-+	chip->card = card;
-+	chip->pci = pci;
-+
-+	err = pci_request_regions(pci, "CS5530");
-+	if (err < 0) {
-+		kfree(chip); 
-+		pci_disable_device(pci);
-+		return err;
-+	}
-+	chip->pci_base = pci_resource_start(pci, 0);
-+
-+	mem = ioremap_nocache(chip->pci_base, pci_resource_len(pci, 0));
-+	if (mem == NULL) {
-+		kfree(chip);
-+		pci_disable_device(pci);
-+		return -EBUSY;
-+	}
-+
-+	map = readw(mem + 0x18);
-+	iounmap(mem);
-+
-+	/* Map bits
-+		0:1	* 0x20 + 0x200 = sb base
-+		2	sb enable
-+		3	adlib enable
-+		5	MPU enable 0x330
-+		6	MPU enable 0x300
-+
-+	   The other bits may be used internally so must be masked */
-+
-+	sb_base = 0x220 + 0x20 * (map & 3);
-+
-+	if (map & (1<<2))
-+		printk(KERN_INFO "CS5530: XpressAudio at 0x%lx\n", sb_base);
-+	else {
-+		printk(KERN_ERR "Could not find XpressAudio!\n");
-+		snd_cs5530_free(chip);
-+		return -ENODEV;
-+	}
-+
-+	if (map & (1<<5))
-+		printk(KERN_INFO "CS5530: MPU at 0x300\n");
-+	else if (map & (1<<6))
-+		printk(KERN_INFO "CS5530: MPU at 0x330\n");
-+
-+	irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F;
-+	dma8 = snd_cs5530_mixer_read(sb_base, 0x81);
-+
-+	if (dma8 & 0x20)
-+		dma16 = 5;
-+	else if (dma8 & 0x40)
-+		dma16 = 6;
-+	else if (dma8 & 0x80)
-+		dma16 = 7;
-+	else {
-+		printk(KERN_ERR "CS5530: No 16bit DMA enabled\n");
-+		snd_cs5530_free(chip);
-+		return -ENODEV;
-+	}
-+
-+	if (dma8 & 0x01)
-+		dma8 = 0;
-+	else if (dma8 & 02)
-+		dma8 = 1;
-+	else if (dma8 & 0x08)
-+		dma8 = 3;
-+	else {
-+		printk(KERN_ERR "CS5530: No 8bit DMA enabled\n");
-+		snd_cs5530_free(chip);
-+		return -ENODEV;
-+	}
-+
-+	if (irq & 1)
-+		irq = 9;
-+	else if (irq & 2)
-+		irq = 5;
-+	else if (irq & 4)
-+		irq = 7;
-+	else if (irq & 8)
-+		irq = 10;
-+	else {
-+		printk(KERN_ERR "CS5530: SoundBlaster IRQ not set\n");
-+		snd_cs5530_free(chip);
-+		return -ENODEV;
-+	}
-+
-+	printk(KERN_INFO "CS5530: IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, 
-+									dma16);
-+
-+	err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8,
-+						dma16, SB_HW_CS5530, &chip->sb);
-+	if (err < 0) {
-+		printk(KERN_ERR "CS5530: Could not create SoundBlaster\n");
-+		snd_cs5530_free(chip);
-+		return err;
-+	}
-+
-+	err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm);
-+	if (err < 0) {
-+		printk(KERN_ERR "CS5530: Could not create PCM\n");
-+		snd_cs5530_free(chip);
-+		return err;
-+	}
-+
-+	err = snd_sbmixer_new(chip->sb);
-+	if (err < 0) {
-+		printk(KERN_ERR "CS5530: Could not create Mixer\n");
-+		snd_cs5530_free(chip);
-+		return err;
-+	}
-+
-+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-+	if (err < 0) {
-+		snd_cs5530_free(chip);
-+		return err;
-+	}
-+
-+	snd_card_set_dev(card, &pci->dev);
-+	*rchip = chip;
-+	return 0;
-+}
-+
-+static int __devinit snd_cs5530_probe(struct pci_dev *pci,
-+					const struct pci_device_id *pci_id)
-+{
-+	static int dev;
-+	struct snd_card *card;
-+	struct snd_cs5530 *chip = NULL;
-+	int err;
-+
-+	if (dev >= SNDRV_CARDS)
-+		return -ENODEV;
-+	if (!enable[dev]) {
-+		dev++;
-+		return -ENOENT;
-+	}
-+
-+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-+
-+	if (card == NULL)
-+		return -ENOMEM;
-+
-+	err = snd_cs5530_create(card, pci, &chip);
-+	if (err < 0) {
-+		snd_card_free(card);
-+		return err;
-+	}
-+
-+	strcpy(card->driver, "CS5530");
-+	strcpy(card->shortname, "CS5530 Audio");
-+	sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
-+
-+	err = snd_card_register(card);
-+	if (err < 0) {
-+		snd_card_free(card);
-+		return err;
-+	}
-+	pci_set_drvdata(pci, card);
-+	dev++;
-+	return 0;
-+}
-+
-+static struct pci_driver driver = {
-+	.name = "CS5530_Audio",
-+	.id_table = snd_cs5530_ids,
-+	.probe = snd_cs5530_probe,
-+	.remove = __devexit_p(snd_cs5530_remove),
-+};
-+
-+static int __init alsa_card_cs5530_init(void)
-+{
-+	return pci_register_driver(&driver);
-+}
-+
-+static void __exit alsa_card_cs5530_exit(void)
-+{
-+	pci_unregister_driver(&driver);
-+}
-+
-+module_init(alsa_card_cs5530_init)
-+module_exit(alsa_card_cs5530_exit)
-+
---- linux-2.6.22.1.orig/sound/pci/emu10k1/emu10k1_main.c
-+++ linux-2.6.22.1/sound/pci/emu10k1/emu10k1_main.c
-@@ -51,9 +51,15 @@
- 
- #define HANA_FILENAME "emu/hana.fw"
- #define DOCK_FILENAME "emu/audio_dock.fw"
-+#define EMU1010B_FILENAME "emu/emu1010b.fw"
-+#define MICRO_DOCK_FILENAME "emu/micro_dock.fw"
-+#define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw"
- 
- MODULE_FIRMWARE(HANA_FILENAME);
- MODULE_FIRMWARE(DOCK_FILENAME);
-+MODULE_FIRMWARE(EMU1010B_FILENAME);
-+MODULE_FIRMWARE(MICRO_DOCK_FILENAME);
-+MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME);
- 
- 
- /*************************************************************************
-@@ -660,10 +666,12 @@
- 		return err;
- 	}
- 	snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
-+#if 0
- 	if (fw_entry->size != 0x133a4) {
- 		snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename);
- 		return -EINVAL;
- 	}
-+#endif
- 
- 	/* The FPGA is a Xilinx Spartan IIE XC2S50E */
- 	/* GPIO7 -> FPGA PGMN
-@@ -694,6 +702,37 @@
- 	return 0;
- }
- 
-+/*
-+ * EMU-1010 - details found out from this driver, official MS Win drivers,
-+ * testing the card:
-+ *
-+ * Audigy2 (aka Alice2):
-+ * ---------------------
-+ * 	* communication over PCI
-+ * 	* conversion of 32-bit data coming over EMU32 links from HANA FPGA
-+ *	  to 2 x 16-bit, using internal DSP instructions
-+ * 	* slave mode, clock supplied by HANA
-+ * 	* linked to HANA using:
-+ * 		32 x 32-bit serial EMU32 output channels
-+ * 		16 x EMU32 input channels
-+ * 		(?) x I2S I/O channels (?)
-+ *
-+ * FPGA (aka HANA):
-+ * ---------------
-+ * 	* provides all (?) physical inputs and outputs of the card
-+ * 		(ADC, DAC, SPDIF I/O, ADAT I/O, etc.)
-+ * 	* provides clock signal for the card and Alice2
-+ * 	* two crystals - for 44.1kHz and 48kHz multiples
-+ * 	* provides internal routing of signal sources to signal destinations
-+ * 	* inputs/outputs to Alice2 - see above
-+ *
-+ * Current status of the driver:
-+ * ----------------------------
-+ * 	* only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz)
-+ * 	* PCM device nb. 2:
-+ *		16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops
-+ * 		16 x 32-bit capture - snd_emu10k1_capture_efx_ops
-+ */
- static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
- {
- 	unsigned int i;
-@@ -727,7 +766,7 @@
- 	/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
- 	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- 	snd_printdd("reg1=0x%x\n",reg);
--	if (reg == 0x55) {
-+	if ((reg & 0x3f) == 0x15) {
- 		/* FPGA netlist already present so clear it */
- 		/* Return to programming mode */
- 
-@@ -735,19 +774,32 @@
- 	}
- 	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- 	snd_printdd("reg2=0x%x\n",reg);
--	if (reg == 0x55) {
-+	if ((reg & 0x3f) == 0x15) {
- 		/* FPGA failed to return to programming mode */
-+		snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n");
- 		return -ENODEV;
- 	}
- 	snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
--	if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) {
--		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME);
--		return err;
-+	if (emu->card_capabilities->emu1010 == 1) {
-+		if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) {
-+			snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME);
-+			return err;
-+		}
-+	} else if (emu->card_capabilities->emu1010 == 2) {
-+		if ((err = snd_emu1010_load_firmware(emu, EMU1010B_FILENAME)) != 0) {
-+			snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010B_FILENAME);
-+			return err;
-+		}
-+	} else if (emu->card_capabilities->emu1010 == 3) {
-+		if ((err = snd_emu1010_load_firmware(emu, EMU1010_NOTEBOOK_FILENAME)) != 0) {
-+			snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010_NOTEBOOK_FILENAME);
-+			return err;
-+		}
- 	}
- 
- 	/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- 	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
--	if (reg != 0x55) {
-+	if ((reg & 0x3f) != 0x15) {
- 		/* FPGA failed to be programmed */
- 		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
- 		return -ENODEV;
-@@ -850,6 +902,27 @@
- 		EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1);
- 	snd_emu1010_fpga_link_dst_src_write(emu,
- 		EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1);
-+	/* Pavel Hofman - setting defaults for 8 more capture channels
-+	 * Defaults only, users will set their own values anyways, let's
-+	 * just copy/paste.
-+	 */
-+	
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1);
-+	snd_emu1010_fpga_link_dst_src_write(emu,
-+		EMU_DST_ALICE2_EMU32_F, EMU_SRC_DOCK_ADC2_RIGHT1);
- #endif
- #if 0
- 	/* Original */
-@@ -943,16 +1016,27 @@
- 		/* Return to Audio Dock programming mode */
- 		snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
- 		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
--		if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
--			return err;
-+		if (emu->card_capabilities->emu1010 == 1) {
-+			if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
-+				return err;
-+			}
-+		} else if (emu->card_capabilities->emu1010 == 2) {
-+			if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
-+				return err;
-+			}
-+		} else if (emu->card_capabilities->emu1010 == 3) {
-+			if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
-+				return err;
-+			}
- 		}
-+
- 		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0 );
- 		snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
- 		snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
- 		/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- 		snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- 		snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
--		if (reg != 0x55) {
-+		if ((reg & 0x3f) != 0x15) {
- 			/* FPGA failed to be programmed */
- 			snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
- 			return 0;
-@@ -1227,9 +1311,15 @@
- 	 .emu10k2_chip = 1,
- 	 .ca0108_chip = 1,
- 	 .ca_cardbus_chip = 1,
--	 .spi_dac = 1,
--	 .i2c_adc = 1,
--	 .spk71 = 1} ,
-+	 .spk71 = 1 ,
-+	 .emu1010 = 3} ,
-+	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102,
-+	 .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]", 
-+	 .id = "EMU1010",
-+	 .emu10k2_chip = 1,
-+	 .ca0108_chip = 1,
-+	 .spk71 = 1 ,
-+	 .emu1010 = 2} ,
- 	{.vendor = 0x1102, .device = 0x0008, 
- 	 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
- 	 .id = "Audigy2",
-@@ -1665,12 +1755,13 @@
- 	emu->fx8010.extout_mask = extout_mask;
- 	emu->enable_ir = enable_ir;
- 
-+	if (emu->card_capabilities->ca_cardbus_chip) {
-+		if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
-+			goto error;
-+	}
- 	if (emu->card_capabilities->ecard) {
- 		if ((err = snd_emu10k1_ecard_init(emu)) < 0)
- 			goto error;
--	} else if (emu->card_capabilities->ca_cardbus_chip) {
--		if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
--			goto error;
-  	} else if (emu->card_capabilities->emu1010) {
-  		if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
-  			snd_emu10k1_free(emu);
-@@ -1816,10 +1907,10 @@
- 
- void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
- {
-+	if (emu->card_capabilities->ca_cardbus_chip)
-+		snd_emu10k1_cardbus_init(emu);
- 	if (emu->card_capabilities->ecard)
- 		snd_emu10k1_ecard_init(emu);
--	else if (emu->card_capabilities->ca_cardbus_chip)
--		snd_emu10k1_cardbus_init(emu);
- 	else if (emu->card_capabilities->emu1010)
-  		snd_emu10k1_emu1010_init(emu);
- 	else
---- linux-2.6.22.1.orig/sound/pci/emu10k1/emufx.c
-+++ linux-2.6.22.1/sound/pci/emu10k1/emufx.c
-@@ -1123,6 +1123,11 @@
- 	ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
- }
- 
-+/*
-+ * Used for emu1010 - conversion from 32-bit capture inputs from HANA
-+ * to 2 x 16-bit registers in audigy - their values are read via DMA.
-+ * Conversion is performed by Audigy DSP instructions of FX8010.
-+ */
- static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
- 				struct snd_emu10k1_fx8010_code *icode,
- 				u32 *ptr, int tmp, int bit_shifter16,
-@@ -1193,7 +1198,11 @@
- 	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
- 
- #if 1
--	/* PCM front Playback Volume (independent from stereo mix) */
-+	/* PCM front Playback Volume (independent from stereo mix)
-+	 * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31)
-+	 * where gpr contains attenuation from corresponding mixer control
-+	 * (snd_emu10k1_init_stereo_control)
-+	 */
- 	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
- 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
- 	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
-@@ -1549,7 +1558,7 @@
- 
- 	if (emu->card_capabilities->emu1010) {
- 		snd_printk("EMU inputs on\n");
--		/* Capture 8 channels of S32_LE sound */
-+		/* Capture 16 (originally 8) channels of S32_LE sound */
- 		
- 		/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
- 		/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
-@@ -1560,6 +1569,11 @@
- 		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
- 		/* Right ADC in 1 of 2 */
- 		gpr_map[gpr++] = 0x00000000;
-+		/* Delaying by one sample: instead of copying the input
-+		 * value A_P16VIN to output A_FXBUS2 as in the first channel,
-+		 * we use an auxiliary register, delaying the value by one
-+		 * sample
-+		 */
- 		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
- 		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
- 		gpr_map[gpr++] = 0x00000000;
-@@ -1583,6 +1597,66 @@
- 		gpr_map[gpr++] = 0x00000000;
- 		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
- 		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
-+		/* Pavel Hofman - we still have voices, A_FXBUS2s, and
-+		 * A_P16VINs available -
-+		 * let's add 8 more capture channels - total of 16
-+		 */
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x10));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x12));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x14));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x16));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x18));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x1a));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x1c));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
-+		     A_C_00000000, A_C_00000000);
-+		gpr_map[gpr++] = 0x00000000;
-+		snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
-+							  bit_shifter16,
-+							  A_GPR(gpr - 1),
-+							  A_FXBUS2(0x1e));
-+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
-+		     A_C_00000000, A_C_00000000);
- 
- #if 0
- 		for (z = 4; z < 8; z++) {
---- linux-2.6.22.1.orig/sound/pci/emu10k1/emumixer.c
-+++ linux-2.6.22.1/sound/pci/emu10k1/emumixer.c
-@@ -77,6 +77,10 @@
- 	return 0;
- }
- 
-+/*
-+ * Items labels in enum mixer controls assigning source data to
-+ * each destination
-+ */
- static char *emu1010_src_texts[] = { 
- 	"Silence",
- 	"Dock Mic A",
-@@ -133,6 +137,9 @@
- 	"DSP 31",
- };
- 
-+/*
-+ * List of data sources available for each destination
-+ */
- static unsigned int emu1010_src_regs[] = {
- 	EMU_SRC_SILENCE,/* 0 */
- 	EMU_SRC_DOCK_MIC_A1, /* 1 */
-@@ -189,6 +196,10 @@
- 	EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
- };
- 
-+/*
-+ * Data destinations - physical EMU outputs.
-+ * Each destination has an enum mixer control to choose a data source
-+ */
- static unsigned int emu1010_output_dst[] = {
- 	EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
- 	EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
-@@ -216,6 +227,11 @@
- 	EMU_DST_HANA_ADAT+7, /* 23 */
- };
- 
-+/*
-+ * Data destinations - HANA outputs going to Alice2 (audigy) for
-+ *   capture (EMU32 + I2S links)
-+ * Each destination has an enum mixer control to choose a data source
-+ */
- static unsigned int emu1010_input_dst[] = {
- 	EMU_DST_ALICE2_EMU32_0,
- 	EMU_DST_ALICE2_EMU32_1,
---- linux-2.6.22.1.orig/sound/pci/emu10k1/emupcm.c
-+++ linux-2.6.22.1/sound/pci/emu10k1/emupcm.c
-@@ -1233,24 +1233,26 @@
- 	runtime->hw.rate_min = runtime->hw.rate_max = 48000;
- 	spin_lock_irq(&emu->reg_lock);
- 	if (emu->card_capabilities->emu1010) {
--		/* TODO 
-+		/*  Nb. of channels has been increased to 16 */
-+		/* TODO
- 		 * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
- 		 * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
- 		 * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
- 		 * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
- 		 * rate_min = 44100,
- 		 * rate_max = 192000,
--		 * channels_min = 8,
--		 * channels_max = 8,
-+		 * channels_min = 16,
-+		 * channels_max = 16,
- 		 * Need to add mixer control to fix sample rate
- 		 *                 
--		 * There are 16 mono channels of 16bits each.
-+		 * There are 32 mono channels of 16bits each.
- 		 * 24bit Audio uses 2x channels over 16bit
- 		 * 96kHz uses 2x channels over 48kHz
- 		 * 192kHz uses 4x channels over 48kHz
--		 * So, for 48kHz 24bit, one has 8 channels
--		 * for 96kHz 24bit, one has 4 channels
--		 * for 192kHz 24bit, one has 2 channels
-+		 * So, for 48kHz 24bit, one has 16 channels
-+		 * for 96kHz 24bit, one has 8 channels
-+		 * for 192kHz 24bit, one has 4 channels
-+		 *
- 		 */
- #if 1
- 		switch (emu->emu1010.internal_clock) {
-@@ -1258,13 +1260,15 @@
- 			/* For 44.1kHz */
- 			runtime->hw.rates = SNDRV_PCM_RATE_44100;
- 			runtime->hw.rate_min = runtime->hw.rate_max = 44100;
--			runtime->hw.channels_min = runtime->hw.channels_max = 8;
-+			runtime->hw.channels_min =
-+				runtime->hw.channels_max = 16;
- 			break;
- 		case 1:
- 			/* For 48kHz */
- 			runtime->hw.rates = SNDRV_PCM_RATE_48000;
- 			runtime->hw.rate_min = runtime->hw.rate_max = 48000;
--			runtime->hw.channels_min = runtime->hw.channels_max = 8;
-+			runtime->hw.channels_min =
-+				runtime->hw.channels_max = 16;
- 			break;
- 		};
- #endif
-@@ -1282,7 +1286,7 @@
- #endif
- 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
- 		/* efx_voices_mask[0] is expected to be zero
-- 		 * efx_voices_mask[1] is expected to have 16bits set
-+ 		 * efx_voices_mask[1] is expected to have 32bits set
- 		 */
- 	} else {
- 		runtime->hw.channels_min = runtime->hw.channels_max = 0;
-@@ -1787,11 +1791,24 @@
- 	/* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
- 	if (emu->audigy) {
- 		emu->efx_voices_mask[0] = 0;
--		emu->efx_voices_mask[1] = 0xffff;
-+		if (emu->card_capabilities->emu1010)
-+			/* Pavel Hofman - 32 voices will be used for
-+			 * capture (write mode) -
-+			 * each bit = corresponding voice
-+			 */
-+			emu->efx_voices_mask[1] = 0xffffffff;
-+		else
-+			emu->efx_voices_mask[1] = 0xffff;
- 	} else {
- 		emu->efx_voices_mask[0] = 0xffff0000;
- 		emu->efx_voices_mask[1] = 0;
- 	}
-+	/* For emu1010, the control has to set 32 upper bits (voices)
-+	 * out of the 64 bits (voices) to true for the 16-channels capture
-+	 * to work correctly. Correct A_FXWC2 initial value (0xffffffff)
-+	 * is already defined but the snd_emu10k1_pcm_efx_voices_mask
-+	 * control can override this register's value.
-+	 */
- 	kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu);
- 	if (!kctl)
- 		return -ENOMEM;
---- linux-2.6.22.1.orig/sound/pci/ens1370.c
-+++ linux-2.6.22.1/sound/pci/ens1370.c
-@@ -1607,8 +1607,8 @@
- 	unsigned char rev;		/* revision */
- };
- 
--static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq,
--					 struct es1371_quirk *list)
-+static int es1371_quirk_lookup(struct ensoniq *ensoniq,
-+				struct es1371_quirk *list)
- {
- 	while (list->vid != (unsigned short)PCI_ANY_ID) {
- 		if (ensoniq->pci->vendor == list->vid &&
---- linux-2.6.22.1.orig/sound/pci/hda/hda_intel.c
-+++ linux-2.6.22.1/sound/pci/hda/hda_intel.c
-@@ -341,6 +341,9 @@
- 	unsigned int single_cmd :1;
- 	unsigned int polling_mode :1;
- 	unsigned int msi :1;
-+
-+	/* for debugging */
-+	unsigned int last_cmd;	/* last issued command (to sync) */
- };
- 
- /* driver types */
-@@ -466,18 +469,10 @@
- }
- 
- /* send a command */
--static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
--			     unsigned int verb, unsigned int para)
-+static int azx_corb_send_cmd(struct hda_codec *codec, u32 val)
- {
- 	struct azx *chip = codec->bus->private_data;
- 	unsigned int wp;
--	u32 val;
--
--	val = (u32)(codec->addr & 0x0f) << 28;
--	val |= (u32)direct << 27;
--	val |= (u32)nid << 20;
--	val |= verb << 8;
--	val |= para;
- 
- 	/* add command to corb */
- 	wp = azx_readb(chip, CORBWP);
-@@ -538,12 +533,12 @@
- 		}
- 		if (! chip->rirb.cmds)
- 			return chip->rirb.res; /* the last value */
--		schedule_timeout_interruptible(1);
-+		schedule_timeout(1);
- 	} while (time_after_eq(timeout, jiffies));
- 
- 	if (chip->msi) {
- 		snd_printk(KERN_WARNING "hda_intel: No response from codec, "
--			   "disabling MSI...\n");
-+			   "disabling MSI: last cmd=0x%08x\n", chip->last_cmd);
- 		free_irq(chip->irq, chip);
- 		chip->irq = -1;
- 		pci_disable_msi(chip->pci);
-@@ -555,13 +550,15 @@
- 
- 	if (!chip->polling_mode) {
- 		snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
--			   "switching to polling mode...\n");
-+			   "switching to polling mode: last cmd=0x%08x\n",
-+			   chip->last_cmd);
- 		chip->polling_mode = 1;
- 		goto again;
- 	}
- 
- 	snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
--		   "switching to single_cmd mode...\n");
-+		   "switching to single_cmd mode: last cmd=0x%08x\n",
-+		   chip->last_cmd);
- 	chip->rirb.rp = azx_readb(chip, RIRBWP);
- 	chip->rirb.cmds = 0;
- 	/* switch to single_cmd mode */
-@@ -581,20 +578,11 @@
-  */
- 
- /* send a command */
--static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid,
--			       int direct, unsigned int verb,
--			       unsigned int para)
-+static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
- {
- 	struct azx *chip = codec->bus->private_data;
--	u32 val;
- 	int timeout = 50;
- 
--	val = (u32)(codec->addr & 0x0f) << 28;
--	val |= (u32)direct << 27;
--	val |= (u32)nid << 20;
--	val |= verb << 8;
--	val |= para;
--
- 	while (timeout--) {
- 		/* check ICB busy bit */
- 		if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) {
-@@ -639,10 +627,19 @@
- 			unsigned int para)
- {
- 	struct azx *chip = codec->bus->private_data;
-+	u32 val;
-+
-+	val = (u32)(codec->addr & 0x0f) << 28;
-+	val |= (u32)direct << 27;
-+	val |= (u32)nid << 20;
-+	val |= verb << 8;
-+	val |= para;
-+	chip->last_cmd = val;
-+
- 	if (chip->single_cmd)
--		return azx_single_send_cmd(codec, nid, direct, verb, para);
-+		return azx_single_send_cmd(codec, val);
- 	else
--		return azx_corb_send_cmd(codec, nid, direct, verb, para);
-+		return azx_corb_send_cmd(codec, val);
- }
- 
- /* get a response */
-@@ -1788,6 +1785,12 @@
- 	{ 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
- 	{ 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
- 	{ 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
-+	{ 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-+	{ 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-+	{ 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-+	{ 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-+	{ 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-+	{ 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
- 	{ 0, }
- };
- MODULE_DEVICE_TABLE(pci, azx_ids);
---- linux-2.6.22.1.orig/sound/pci/hda/hda_proc.c
-+++ linux-2.6.22.1/sound/pci/hda/hda_proc.c
-@@ -250,6 +250,12 @@
- 	snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
- 	snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
- 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
-+
-+	if (codec->mfg)
-+		snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
-+	else
-+		snd_iprintf(buffer, "No Modem Function Group found\n");
-+
- 	if (! codec->afg)
- 		return;
- 	snd_iprintf(buffer, "Default PCM:\n");
---- linux-2.6.22.1.orig/sound/pci/hda/patch_analog.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_analog.c
-@@ -1,7 +1,8 @@
- /*
-- * HD audio interface patch for AD1981HD, AD1983, AD1986A, AD1988
-+ * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
-+ *   AD1986A, AD1988
-  *
-- * Copyright (c) 2005 Takashi Iwai <tiwai at suse.de>
-+ * Copyright (c) 2005-2007 Takashi Iwai <tiwai at suse.de>
-  *
-  *  This driver is free software; you can redistribute it and/or modify
-  *  it under the terms of the GNU General Public License as published by
-@@ -61,7 +62,7 @@
- 	int num_channel_mode;
- 
- 	/* PCM information */
--	struct hda_pcm pcm_rec[2];	/* used in alc_build_pcms() */
-+	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
- 
- 	struct mutex amp_mutex;	/* PCM volume/mute control mutex */
- 	unsigned int spdif_route;
-@@ -2775,11 +2776,634 @@
- 
- 
- /*
-+ * AD1884 / AD1984
-+ *
-+ * port-B - front line/mic-in
-+ * port-E - aux in/out
-+ * port-F - aux in/out
-+ * port-C - rear line/mic-in
-+ * port-D - rear line/hp-out
-+ * port-A - front line/hp-out
-+ *
-+ * AD1984 = AD1884 + two digital mic-ins
-+ *
-+ * FIXME:
-+ * For simplicity, we share the single DAC for both HP and line-outs
-+ * right now.  The inidividual playbacks could be easily implemented,
-+ * but no build-up framework is given, so far.
-+ */
-+
-+static hda_nid_t ad1884_dac_nids[1] = {
-+	0x04,
-+};
-+
-+static hda_nid_t ad1884_adc_nids[2] = {
-+	0x08, 0x09,
-+};
-+
-+static hda_nid_t ad1884_capsrc_nids[2] = {
-+	0x0c, 0x0d,
-+};
-+
-+#define AD1884_SPDIF_OUT	0x02
-+
-+static struct hda_input_mux ad1884_capture_source = {
-+	.num_items = 4,
-+	.items = {
-+		{ "Front Mic", 0x0 },
-+		{ "Mic", 0x1 },
-+		{ "CD", 0x2 },
-+		{ "Mix", 0x3 },
-+	},
-+};
-+
-+static struct snd_kcontrol_new ad1884_base_mixers[] = {
-+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-+	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
-+	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
-+	/*
-+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
-+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-+	*/
-+	HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* The multiple "Capture Source" controls confuse alsamixer
-+		 * So call somewhat different..
-+		 * FIXME: the controls appear in the "playback" view!
-+		 */
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = ad198x_mux_enum_info,
-+		.get = ad198x_mux_enum_get,
-+		.put = ad198x_mux_enum_put,
-+	},
-+	/* SPDIF controls */
-+	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-+		/* identical with ad1983 */
-+		.info = ad1983_spdif_route_info,
-+		.get = ad1983_spdif_route_get,
-+		.put = ad1983_spdif_route_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
-+	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
-+			     HDA_INPUT),
-+	HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
-+			   HDA_INPUT),
-+	{ } /* end */
-+};
-+
-+/*
-+ * initialization verbs
-+ */
-+static struct hda_verb ad1884_init_verbs[] = {
-+	/* DACs; mute as default */
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	/* Port-A (HP) mixer */
-+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Port-A pin */
-+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* HP selector - select DAC2 */
-+	{0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
-+	/* Port-D (Line-out) mixer */
-+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Port-D pin */
-+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Mono-out mixer */
-+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Mono-out pin */
-+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Mono selector */
-+	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-+	/* Port-B (front mic) pin */
-+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Port-C (rear mic) pin */
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Analog mixer; mute as default */
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-+	/* Analog Mix output amp */
-+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-+	/* SPDIF output selector */
-+	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
-+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-+	{ } /* end */
-+};
-+
-+static int patch_ad1884(struct hda_codec *codec)
-+{
-+	struct ad198x_spec *spec;
-+
-+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-+	if (spec == NULL)
-+		return -ENOMEM;
-+
-+	mutex_init(&spec->amp_mutex);
-+	codec->spec = spec;
-+
-+	spec->multiout.max_channels = 2;
-+	spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
-+	spec->multiout.dac_nids = ad1884_dac_nids;
-+	spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
-+	spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
-+	spec->adc_nids = ad1884_adc_nids;
-+	spec->capsrc_nids = ad1884_capsrc_nids;
-+	spec->input_mux = &ad1884_capture_source;
-+	spec->num_mixers = 1;
-+	spec->mixers[0] = ad1884_base_mixers;
-+	spec->num_init_verbs = 1;
-+	spec->init_verbs[0] = ad1884_init_verbs;
-+	spec->spdif_route = 0;
-+
-+	codec->patch_ops = ad198x_patch_ops;
-+
-+	return 0;
-+}
-+
-+/*
-+ * Lenovo Thinkpad T61/X61
-+ */
-+static struct hda_input_mux ad1984_thinkpad_capture_source = {
-+	.num_items = 3,
-+	.items = {
-+		{ "Mic", 0x0 },
-+		{ "Internal Mic", 0x1 },
-+		{ "Mix", 0x3 },
-+	},
-+};
-+
-+static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
-+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-+	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
-+	HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
-+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* The multiple "Capture Source" controls confuse alsamixer
-+		 * So call somewhat different..
-+		 * FIXME: the controls appear in the "playback" view!
-+		 */
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = ad198x_mux_enum_info,
-+		.get = ad198x_mux_enum_get,
-+		.put = ad198x_mux_enum_put,
-+	},
-+	{ } /* end */
-+};
-+
-+/* additional verbs */
-+static struct hda_verb ad1984_thinkpad_init_verbs[] = {
-+	/* Port-E (docking station mic) pin */
-+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* docking mic boost */
-+	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Analog mixer - docking mic; mute as default */
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-+	/* enable EAPD bit */
-+	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-+	{ } /* end */
-+};
-+
-+/* Digial MIC ADC NID 0x05 + 0x06 */
-+static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
-+				   struct hda_codec *codec,
-+				   unsigned int stream_tag,
-+				   unsigned int format,
-+				   struct snd_pcm_substream *substream)
-+{
-+	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-+				   stream_tag, 0, format);
-+	return 0;
-+}
-+
-+static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
-+				   struct hda_codec *codec,
-+				   struct snd_pcm_substream *substream)
-+{
-+	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-+				   0, 0, 0);
-+	return 0;
-+}
-+
-+static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
-+	.substreams = 2,
-+	.channels_min = 2,
-+	.channels_max = 2,
-+	.nid = 0x05,
-+	.ops = {
-+		.prepare = ad1984_pcm_dmic_prepare,
-+		.cleanup = ad1984_pcm_dmic_cleanup
-+	},
-+};
-+
-+static int ad1984_build_pcms(struct hda_codec *codec)
-+{
-+	struct ad198x_spec *spec = codec->spec;
-+	struct hda_pcm *info;
-+	int err;
-+
-+	err = ad198x_build_pcms(codec);
-+	if (err < 0)
-+		return err;
-+
-+	info = spec->pcm_rec + codec->num_pcms;
-+	codec->num_pcms++;
-+	info->name = "AD1984 Digital Mic";
-+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
-+	return 0;
-+}
-+
-+/* models */
-+enum {
-+	AD1984_BASIC,
-+	AD1984_THINKPAD,
-+	AD1984_MODELS
-+};
-+
-+static const char *ad1984_models[AD1984_MODELS] = {
-+	[AD1984_BASIC]		= "basic",
-+	[AD1984_THINKPAD]	= "thinkpad",
-+};
-+
-+static struct snd_pci_quirk ad1984_cfg_tbl[] = {
-+	/* Lenovo Thinkpad T61/X61 */
-+	SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
-+	{}
-+};
-+
-+static int patch_ad1984(struct hda_codec *codec)
-+{
-+	struct ad198x_spec *spec;
-+	int board_config, err;
-+
-+	err = patch_ad1884(codec);
-+	if (err < 0)
-+		return err;
-+	spec = codec->spec;
-+	board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
-+						  ad1984_models, ad1984_cfg_tbl);
-+	switch (board_config) {
-+	case AD1984_BASIC:
-+		/* additional digital mics */
-+		spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
-+		codec->patch_ops.build_pcms = ad1984_build_pcms;
-+		break;
-+	case AD1984_THINKPAD:
-+		spec->multiout.dig_out_nid = 0;
-+		spec->input_mux = &ad1984_thinkpad_capture_source;
-+		spec->mixers[0] = ad1984_thinkpad_mixers;
-+		spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
-+		break;
-+	}
-+	return 0;
-+}
-+
-+
-+/*
-+ * AD1882
-+ *
-+ * port-A - front hp-out
-+ * port-B - front mic-in
-+ * port-C - rear line-in, shared surr-out (3stack)
-+ * port-D - rear line-out
-+ * port-E - rear mic-in, shared clfe-out (3stack)
-+ * port-F - rear surr-out (6stack)
-+ * port-G - rear clfe-out (6stack)
-+ */
-+
-+static hda_nid_t ad1882_dac_nids[3] = {
-+	0x04, 0x03, 0x05
-+};
-+
-+static hda_nid_t ad1882_adc_nids[2] = {
-+	0x08, 0x09,
-+};
-+
-+static hda_nid_t ad1882_capsrc_nids[2] = {
-+	0x0c, 0x0d,
-+};
-+
-+#define AD1882_SPDIF_OUT	0x02
-+
-+/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
-+static struct hda_input_mux ad1882_capture_source = {
-+	.num_items = 5,
-+	.items = {
-+		{ "Front Mic", 0x1 },
-+		{ "Mic", 0x4 },
-+		{ "Line", 0x2 },
-+		{ "CD", 0x3 },
-+		{ "Mix", 0x7 },
-+	},
-+};
-+
-+static struct snd_kcontrol_new ad1882_base_mixers[] = {
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
-+	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
-+	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
-+	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
-+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* The multiple "Capture Source" controls confuse alsamixer
-+		 * So call somewhat different..
-+		 * FIXME: the controls appear in the "playback" view!
-+		 */
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = ad198x_mux_enum_info,
-+		.get = ad198x_mux_enum_get,
-+		.put = ad198x_mux_enum_put,
-+	},
-+	/* SPDIF controls */
-+	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-+		/* identical with ad1983 */
-+		.info = ad1983_spdif_route_info,
-+		.get = ad1983_spdif_route_get,
-+		.put = ad1983_spdif_route_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
-+	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		.name = "Channel Mode",
-+		.info = ad198x_ch_mode_info,
-+		.get = ad198x_ch_mode_get,
-+		.put = ad198x_ch_mode_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
-+	HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
-+	{ } /* end */
-+};
-+
-+static struct hda_verb ad1882_ch2_init[] = {
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	{ } /* end */
-+};
-+
-+static struct hda_verb ad1882_ch4_init[] = {
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	{ } /* end */
-+};
-+
-+static struct hda_verb ad1882_ch6_init[] = {
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{ } /* end */
-+};
-+
-+static struct hda_channel_mode ad1882_modes[3] = {
-+	{ 2, ad1882_ch2_init },
-+	{ 4, ad1882_ch4_init },
-+	{ 6, ad1882_ch6_init },
-+};
-+
-+/*
-+ * initialization verbs
-+ */
-+static struct hda_verb ad1882_init_verbs[] = {
-+	/* DACs; mute as default */
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	/* Port-A (HP) mixer */
-+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Port-A pin */
-+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* HP selector - select DAC2 */
-+	{0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
-+	/* Port-D (Line-out) mixer */
-+	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Port-D pin */
-+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Mono-out mixer */
-+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	/* Mono-out pin */
-+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Port-B (front mic) pin */
-+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-+	/* Port-C (line-in) pin */
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-+	/* Port-C mixer - mute as input */
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	/* Port-E (mic-in) pin */
-+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-+	/* Port-E mixer - mute as input */
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	/* Port-F (surround) */
-+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Port-G (CLFE) */
-+	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	/* Analog mixer; mute as default */
-+	/* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-+	/* Analog Mix output amp */
-+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-+	/* SPDIF output selector */
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-+	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
-+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-+	{ } /* end */
-+};
-+
-+/* models */
-+enum {
-+	AD1882_3STACK,
-+	AD1882_6STACK,
-+	AD1882_MODELS
-+};
-+
-+static const char *ad1882_models[AD1986A_MODELS] = {
-+	[AD1882_3STACK]		= "3stack",
-+	[AD1882_6STACK]		= "6stack",
-+};
-+
-+
-+static int patch_ad1882(struct hda_codec *codec)
-+{
-+	struct ad198x_spec *spec;
-+	int board_config;
-+
-+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-+	if (spec == NULL)
-+		return -ENOMEM;
-+
-+	mutex_init(&spec->amp_mutex);
-+	codec->spec = spec;
-+
-+	spec->multiout.max_channels = 6;
-+	spec->multiout.num_dacs = 3;
-+	spec->multiout.dac_nids = ad1882_dac_nids;
-+	spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
-+	spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
-+	spec->adc_nids = ad1882_adc_nids;
-+	spec->capsrc_nids = ad1882_capsrc_nids;
-+	spec->input_mux = &ad1882_capture_source;
-+	spec->num_mixers = 1;
-+	spec->mixers[0] = ad1882_base_mixers;
-+	spec->num_init_verbs = 1;
-+	spec->init_verbs[0] = ad1882_init_verbs;
-+	spec->spdif_route = 0;
-+
-+	codec->patch_ops = ad198x_patch_ops;
-+
-+	/* override some parameters */
-+	board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
-+						  ad1882_models, NULL);
-+	switch (board_config) {
-+	default:
-+	case AD1882_3STACK:
-+		spec->num_mixers = 2;
-+		spec->mixers[1] = ad1882_3stack_mixers;
-+		spec->channel_mode = ad1882_modes;
-+		spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
-+		spec->need_dac_fix = 1;
-+		spec->multiout.max_channels = 2;
-+		spec->multiout.num_dacs = 1;
-+		break;
-+	case AD1882_6STACK:
-+		spec->num_mixers = 2;
-+		spec->mixers[1] = ad1882_6stack_mixers;
-+		break;
-+	}
-+	return 0;
-+}
-+
-+
-+/*
-  * patch entries
-  */
- struct hda_codec_preset snd_hda_preset_analog[] = {
-+	{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
-+	{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
- 	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
- 	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
-+	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
- 	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
- 	{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
- 	{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
---- linux-2.6.22.1.orig/sound/pci/hda/patch_atihdmi.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_atihdmi.c
-@@ -172,6 +172,7 @@
-  */
- struct hda_codec_preset snd_hda_preset_atihdmi[] = {
- 	{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
-+	{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
- 	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
- 	{ .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi },
- 	{} /* terminator */
---- linux-2.6.22.1.orig/sound/pci/hda/patch_conexant.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_conexant.c
-@@ -801,7 +801,9 @@
- 	SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP),
- 	SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP),
- 	SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP),
-+	SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP),
- 	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU),
-+	SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP),
- 	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP),
- 	{}
- };
---- linux-2.6.22.1.orig/sound/pci/hda/patch_realtek.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_realtek.c
-@@ -94,10 +94,18 @@
- 	ALC262_HP_BPC_D7000_WF,
- 	ALC262_BENQ_ED8,
- 	ALC262_SONY_ASSAMD,
-+	ALC262_BENQ_T31,
- 	ALC262_AUTO,
- 	ALC262_MODEL_LAST /* last tag */
- };
- 
-+/* ALC268 models */
-+enum {
-+	ALC268_3ST,
-+	ALC268_AUTO,
-+	ALC268_MODEL_LAST /* last tag */
-+};
-+
- /* ALC861 models */
- enum {
- 	ALC861_3ST,
-@@ -115,6 +123,7 @@
- /* ALC861-VD models */
- enum {
- 	ALC660VD_3ST,
-+	ALC660VD_3ST_DIG,
- 	ALC861VD_3ST,
- 	ALC861VD_3ST_DIG,
- 	ALC861VD_6ST_DIG,
-@@ -144,6 +153,7 @@
- 	ALC882_TARGA,
- 	ALC882_ASUS_A7J,
- 	ALC885_MACPRO,
-+	ALC885_IMAC24,
- 	ALC882_AUTO,
- 	ALC882_MODEL_LAST,
- };
-@@ -163,6 +173,8 @@
- 	ALC883_LENOVO_101E_2ch,
- 	ALC883_LENOVO_NB0763,
- 	ALC888_LENOVO_MS7195_DIG,		
-+	ALC888_6ST_HP,
-+	ALC888_3ST_HP,
- 	ALC883_AUTO,
- 	ALC883_MODEL_LAST,
- };
-@@ -713,6 +725,38 @@
- }
- 
- /*
-+ * Fix-up pin default configurations
-+ */
-+
-+struct alc_pincfg {
-+	hda_nid_t nid;
-+	u32 val;
-+};
-+
-+static void alc_fix_pincfg(struct hda_codec *codec,
-+			   const struct snd_pci_quirk *quirk,
-+			   const struct alc_pincfg **pinfix)
-+{
-+	const struct alc_pincfg *cfg;
-+
-+	quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
-+	if (!quirk)
-+		return;
-+
-+	cfg = pinfix[quirk->value];
-+	for (; cfg->nid; cfg++) {
-+		int i;
-+		u32 val = cfg->val;
-+		for (i = 0; i < 4; i++) {
-+			snd_hda_codec_write(codec, cfg->nid, 0,
-+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
-+				    val & 0xff);
-+			val >>= 8;
-+		}
-+	}
-+}
-+
-+/*
-  * ALC880 3-stack model
-  *
-  * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
-@@ -1878,31 +1922,53 @@
-  * Pin assignment:
-  *   Speaker-out: 0x14
-  *   Mic-In: 0x18
-- *   Built-in Mic-In: 0x19 (?)
-- *   HP-Out: 0x1b
-+ *   Built-in Mic-In: 0x19
-+ *   Line-In: 0x1b
-+ *   HP-Out: 0x1a
-  *   SPDIF-Out: 0x1e
-  */
- 
--/* seems analog CD is not working */
- static struct hda_input_mux alc880_lg_lw_capture_source = {
--	.num_items = 2,
-+	.num_items = 3,
- 	.items = {
- 		{ "Mic", 0x0 },
- 		{ "Internal Mic", 0x1 },
-+		{ "Line In", 0x2 },
- 	},
- };
- 
-+#define alc880_lg_lw_modes alc880_threestack_modes
-+
- static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
--	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
--	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- 	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- 	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		.name = "Channel Mode",
-+		.info = alc_ch_mode_info,
-+		.get = alc_ch_mode_get,
-+		.put = alc_ch_mode_put,
-+	},
- 	{ } /* end */
- };
- 
- static struct hda_verb alc880_lg_lw_init_verbs[] = {
-+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-+
- 	/* set capture source to mic-in */
- 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- 	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-@@ -1912,7 +1978,6 @@
- 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- 	/* HP-out */
--	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
- 	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- 	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- 	/* mic-in to input */
-@@ -2856,11 +2921,11 @@
- 		.mixers = { alc880_lg_lw_mixer },
- 		.init_verbs = { alc880_volume_init_verbs,
- 				alc880_lg_lw_init_verbs },
--		.num_dacs = 1,
-+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
- 		.dac_nids = alc880_dac_nids,
- 		.dig_out_nid = ALC880_DIGOUT_NID,
--		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
--		.channel_mode = alc880_2_jack_modes,
-+		.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
-+		.channel_mode = alc880_lg_lw_modes,
- 		.input_mux = &alc880_lg_lw_capture_source,
- 		.unsol_event = alc880_lg_lw_unsol_event,
- 		.init_hook = alc880_lg_lw_automute,
-@@ -5054,6 +5119,60 @@
- 	{ }
- };
- 
-+/* iMac 24 mixer. */
-+static struct snd_kcontrol_new alc885_imac24_mixer[] = {
-+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
-+	{ } /* end */
-+};
-+
-+/* iMac 24 init verbs. */
-+static struct hda_verb alc885_imac24_init_verbs[] = {
-+	/* Internal speakers: output 0 (0x0c) */
-+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-+	/* Internal speakers: output 0 (0x0c) */
-+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-+	/* Headphone: output 0 (0x0c) */
-+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-+	/* Front Mic: input vref at 80% */
-+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{ }
-+};
-+
-+/* Toggle speaker-output according to the hp-jack state */
-+static void alc885_imac24_automute(struct hda_codec *codec)
-+{
-+ 	unsigned int present;
-+
-+ 	present = snd_hda_codec_read(codec, 0x14, 0,
-+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-+	snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0,
-+				 0x80, present ? 0x80 : 0);
-+	snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0,
-+				 0x80, present ? 0x80 : 0);
-+	snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
-+				 0x80, present ? 0x80 : 0);
-+	snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
-+				 0x80, present ? 0x80 : 0);
-+}
-+
-+/* Processes unsolicited events. */
-+static void alc885_imac24_unsol_event(struct hda_codec *codec,
-+				      unsigned int res)
-+{
-+	/* Headphone insertion or removal. */
-+	if ((res >> 26) == ALC880_HP_EVENT)
-+		alc885_imac24_automute(codec);
-+}
-+
- static struct hda_verb alc882_targa_verbs[] = {
- 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-@@ -5274,6 +5393,7 @@
- 	[ALC882_ARIMA]		= "arima",
- 	[ALC882_W2JC]		= "w2jc",
- 	[ALC885_MACPRO]		= "macpro",
-+	[ALC885_IMAC24]		= "imac24",
- 	[ALC882_AUTO]		= "auto",
- };
- 
-@@ -5284,6 +5404,7 @@
- 	SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
- 	SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
- 	SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
-+	SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
- 	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
- 	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
- 	{}
-@@ -5345,6 +5466,19 @@
- 		.channel_mode = alc882_ch_modes,
- 		.input_mux = &alc882_capture_source,
- 	},
-+	[ALC885_IMAC24] = {
-+		.mixers = { alc885_imac24_mixer },
-+		.init_verbs = { alc885_imac24_init_verbs },
-+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-+		.dac_nids = alc882_dac_nids,
-+		.dig_out_nid = ALC882_DIGOUT_NID,
-+		.dig_in_nid = ALC882_DIGIN_NID,
-+		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
-+		.channel_mode = alc882_ch_modes,
-+		.input_mux = &alc882_capture_source,
-+		.unsol_event = alc885_imac24_unsol_event,
-+		.init_hook = alc885_imac24_automute,
-+	},
- 	[ALC882_TARGA] = {
- 		.mixers = { alc882_targa_mixer, alc882_chmode_mixer,
- 			    alc882_capture_mixer },
-@@ -5379,6 +5513,29 @@
- 
- 
- /*
-+ * Pin config fixes
-+ */
-+enum { 
-+	PINFIX_ABIT_AW9D_MAX
-+};
-+
-+static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
-+	{ 0x15, 0x01080104 }, /* side */
-+	{ 0x16, 0x01011012 }, /* rear */
-+	{ 0x17, 0x01016011 }, /* clfe */
-+	{ }
-+};
-+
-+static const struct alc_pincfg *alc882_pin_fixes[] = {
-+	[PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix,
-+};
-+
-+static struct snd_pci_quirk alc882_pinfix_tbl[] = {
-+	SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
-+	{}
-+};
-+
-+/*
-  * BIOS auto configuration
-  */
- static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
-@@ -5494,6 +5651,9 @@
- 		case 0x106b0c00: /* Mac Pro */
- 			board_config = ALC885_MACPRO;
- 			break;
-+		case 0x106b1000: /* iMac 24 */
-+			board_config = ALC885_IMAC24;
-+			break;
- 		default:
- 			printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
- 		       			 "trying auto-probe from BIOS...\n");
-@@ -5501,6 +5661,8 @@
- 		}
- 	}
- 
-+	alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes);
-+
- 	if (board_config == ALC882_AUTO) {
- 		/* automatic parse from the BIOS config */
- 		err = alc882_parse_auto_config(codec);
-@@ -5518,7 +5680,7 @@
- 	if (board_config != ALC882_AUTO)
- 		setup_preset(spec, &alc882_presets[board_config]);
- 
--	if (board_config == ALC885_MACPRO) {
-+	if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) {
- 		alc882_gpio_mute(codec, 0, 0);
- 		alc882_gpio_mute(codec, 1, 0);
- 	}
-@@ -5995,6 +6157,84 @@
- 	{ } /* end */
- };	
- 
-+static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = alc883_mux_enum_info,
-+		.get = alc883_mux_enum_get,
-+		.put = alc883_mux_enum_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = alc883_mux_enum_info,
-+		.get = alc883_mux_enum_get,
-+		.put = alc883_mux_enum_put,
-+	},
-+	{ } /* end */
-+};
-+
- static struct snd_kcontrol_new alc883_chmode_mixer[] = {
- 	{
- 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-@@ -6126,6 +6366,42 @@
- 	{ } /* end */
- };
- 
-+static struct hda_verb alc888_6st_hp_verbs[] = {
-+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},	/* Rear : output 2 (0x0e) */
-+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* CLFE : output 1 (0x0d) */
-+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},	/* Side : output 3 (0x0f) */
-+	{ }
-+};
-+
-+static struct hda_verb alc888_3st_hp_verbs[] = {
-+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
-+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
-+	{ }
-+};
-+
-+static struct hda_verb alc888_3st_hp_2ch_init[] = {
-+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-+	{ }
-+};
-+
-+static struct hda_verb alc888_3st_hp_6ch_init[] = {
-+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-+	{ }
-+};
-+
-+static struct hda_channel_mode alc888_3st_hp_modes[2] = {
-+	{ 2, alc888_3st_hp_2ch_init },
-+	{ 6, alc888_3st_hp_6ch_init },
-+};
-+
- /* toggle front-jack and RCA according to the hp-jack state */
- static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
- {
-@@ -6368,11 +6644,14 @@
- 	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
- 	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
- 	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
-+	[ALC888_6ST_HP]		= "6stack-hp",
-+	[ALC888_3ST_HP]		= "3stack-hp",
- 	[ALC883_AUTO]		= "auto",
- };
- 
- static struct snd_pci_quirk alc883_cfg_tbl[] = {
- 	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
-+	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
- 	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
- 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
- 	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
-@@ -6381,6 +6660,8 @@
- 	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
- 	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
- 	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
-+	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
-+	SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
- 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
- 	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
- 	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
-@@ -6400,6 +6681,9 @@
- 	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
- 	SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
- 	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
-+	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),
-+	SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
-+	SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
- 	SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
- 	{}
- };
-@@ -6584,6 +6868,31 @@
- 		.unsol_event = alc883_lenovo_ms7195_unsol_event,
- 		.init_hook = alc888_lenovo_ms7195_front_automute,
- 	},	
-+	[ALC888_6ST_HP] = {
-+		.mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
-+		.init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },
-+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-+		.dac_nids = alc883_dac_nids,
-+		.dig_out_nid = ALC883_DIGOUT_NID,
-+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-+		.adc_nids = alc883_adc_nids,
-+		.dig_in_nid = ALC883_DIGIN_NID,
-+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-+		.channel_mode = alc883_sixstack_modes,
-+		.input_mux = &alc883_capture_source,
-+	},
-+	[ALC888_3ST_HP] = {
-+		.mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
-+		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
-+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-+		.dac_nids = alc883_dac_nids,
-+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-+		.adc_nids = alc883_adc_nids,
-+		.num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
-+		.channel_mode = alc888_3st_hp_modes,
-+		.need_dac_fix = 1,
-+		.input_mux = &alc883_capture_source,
-+	},
- };
- 
- 
-@@ -6857,7 +7166,16 @@
- 	{ } /* end */
- };
- 
--
-+static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-+	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-+	{ } /* end */
-+};
- 
- #define alc262_capture_mixer		alc882_capture_mixer
- #define alc262_capture_alt_mixer	alc882_capture_alt_mixer
-@@ -7189,6 +7507,15 @@
- 	{}
- };
- 
-+static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
-+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-+
-+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-+	{0x20, AC_VERB_SET_PROC_COEF,  0x3050},
-+	{}
-+};
-+
- /* add playback controls from the parsed DAC table */
- static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
- 					     const struct auto_pin_cfg *cfg)
-@@ -7584,7 +7911,8 @@
- 	[ALC262_HP_BPC]		= "hp-bpc",
- 	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
- 	[ALC262_BENQ_ED8]	= "benq",
--	[ALC262_BENQ_ED8]	= "sony-assamd",
-+	[ALC262_BENQ_T31]	= "benq-t31",
-+	[ALC262_SONY_ASSAMD]	= "sony-assamd",
- 	[ALC262_AUTO]		= "auto",
- };
- 
-@@ -7592,8 +7920,12 @@
- 	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
- 	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
- 	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
-+	SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),
-+	SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC),
- 	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
-+	SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC),
- 	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
-+	SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),
- 	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
- 	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
- 	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
-@@ -7606,6 +7938,7 @@
- 	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
- 	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
- 	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
-+	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
- 	SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
- 	SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
- 	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
-@@ -7710,6 +8043,17 @@
- 		.channel_mode = alc262_modes,
- 		.input_mux = &alc262_capture_source,
- 		.unsol_event = alc262_hippo_unsol_event,
-+	},
-+	[ALC262_BENQ_T31] = {
-+		.mixers = { alc262_benq_t31_mixer },
-+		.init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs },
-+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-+		.dac_nids = alc262_dac_nids,
-+		.hp_nid = 0x03,
-+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-+		.channel_mode = alc262_modes,
-+		.input_mux = &alc262_capture_source,
-+		.unsol_event = alc262_hippo_unsol_event,
- 	},	
- };
- 
-@@ -7800,31 +8144,540 @@
- }
- 
- /*
-- *  ALC861 channel source setting (2/6 channel selection for 3-stack)
-+ *  ALC268 channel source setting (2 channel)
-  */
-+#define ALC268_DIGOUT_NID	ALC880_DIGOUT_NID
-+#define alc268_modes		alc260_modes
-+	
-+static hda_nid_t alc268_dac_nids[2] = {
-+	/* front, hp */
-+	0x02, 0x03
-+};
- 
--/*
-- * set the path ways for 2 channel output
-- * need to set the codec line out and mic 1 pin widgets to inputs
-- */
--static struct hda_verb alc861_threestack_ch2_init[] = {
--	/* set pin widget 1Ah (line in) for input */
--	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
--	/* set pin widget 18h (mic1/2) for input, for mic also enable
--	 * the vref
--	 */
--	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-+static hda_nid_t alc268_adc_nids[2] = {
-+	/* ADC0-1 */
-+	0x08, 0x07
-+};
- 
--	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
--#if 0
--	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
--	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
--#endif
--	{ } /* end */
-+static hda_nid_t alc268_adc_nids_alt[1] = {
-+	/* ADC0 */
-+	0x08
- };
--/*
-- * 6ch mode
-- * need to set the codec line out and mic 1 pin widgets to outputs
-+
-+static struct snd_kcontrol_new alc268_base_mixer[] = {
-+	/* output mixer control */
-+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-+	{ }
-+};
-+
-+/*
-+ * generic initialization of ADC, input mixers and output mixers
-+ */
-+static struct hda_verb alc268_base_init_verbs[] = {
-+	/* Unmute DAC0-1 and set vol = 0 */
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+
-+	/*
-+	 * Set up output mixers (0x0c - 0x0e)
-+	 */
-+	/* set vol=0 to output mixers */
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
-+
-+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+
-+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+
-+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-+
-+	/* FIXME: use matrix-type input source selection */
-+	/* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */
-+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-+	/* Input mixer2 */
-+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-+
-+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-+	{ }
-+};
-+
-+/*
-+ * generic initialization of ADC, input mixers and output mixers
-+ */
-+static struct hda_verb alc268_volume_init_verbs[] = {
-+	/* set output DAC */
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+
-+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-+
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-+
-+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+
-+	/* set PCBEEP vol = 0 */
-+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
-+
-+	{ }
-+};
-+
-+#define alc268_mux_enum_info alc_mux_enum_info
-+#define alc268_mux_enum_get alc_mux_enum_get
-+
-+static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
-+			       struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-+	struct alc_spec *spec = codec->spec;
-+	const struct hda_input_mux *imux = spec->input_mux;
-+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-+	static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
-+	hda_nid_t nid = capture_mixers[adc_idx];
-+	unsigned int *cur_val = &spec->cur_mux[adc_idx];
-+	unsigned int i, idx;
-+
-+	idx = ucontrol->value.enumerated.item[0];
-+	if (idx >= imux->num_items)
-+		idx = imux->num_items - 1;
-+	if (*cur_val == idx && !codec->in_resume)
-+		return 0;
-+	for (i = 0; i < imux->num_items; i++) {
-+		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
-+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-+				    v | (imux->items[i].index << 8));
-+                snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
-+				    idx );
-+	}
-+	*cur_val = idx;
-+	return 1;
-+}
-+
-+static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
-+	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* The multiple "Capture Source" controls confuse alsamixer
-+		 * So call somewhat different..
-+		 * FIXME: the controls appear in the "playback" view!
-+		 */
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 1,
-+		.info = alc268_mux_enum_info,
-+		.get = alc268_mux_enum_get,
-+		.put = alc268_mux_enum_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct snd_kcontrol_new alc268_capture_mixer[] = {
-+	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
-+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
-+	{
-+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+		/* The multiple "Capture Source" controls confuse alsamixer
-+		 * So call somewhat different..
-+		 * FIXME: the controls appear in the "playback" view!
-+		 */
-+		/* .name = "Capture Source", */
-+		.name = "Input Source",
-+		.count = 2,
-+		.info = alc268_mux_enum_info,
-+		.get = alc268_mux_enum_get,
-+		.put = alc268_mux_enum_put,
-+	},
-+	{ } /* end */
-+};
-+
-+static struct hda_input_mux alc268_capture_source = {
-+	.num_items = 4,
-+	.items = {
-+		{ "Mic", 0x0 },
-+		{ "Front Mic", 0x1 },
-+		{ "Line", 0x2 },
-+		{ "CD", 0x3 },
-+	},
-+};
-+
-+/* create input playback/capture controls for the given pin */
-+static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
-+				    const char *ctlname, int idx)
-+{
-+	char name[32];
-+	int err;
-+
-+	sprintf(name, "%s Playback Volume", ctlname);
-+	if (nid == 0x14) {
-+		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-+				  HDA_COMPOSE_AMP_VAL(0x02, 3, idx,
-+						      HDA_OUTPUT));
-+		if (err < 0)
-+			return err;
-+	} else if (nid == 0x15) {
-+		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-+				  HDA_COMPOSE_AMP_VAL(0x03, 3, idx,
-+						      HDA_OUTPUT));
-+		if (err < 0)
-+			return err;
-+	} else
-+		return -1;
-+	sprintf(name, "%s Playback Switch", ctlname);
-+	err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
-+			  HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
-+	if (err < 0)
-+		return err;
-+	return 0;
-+}
-+
-+/* add playback controls from the parsed DAC table */
-+static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
-+					     const struct auto_pin_cfg *cfg)
-+{
-+	hda_nid_t nid;
-+	int err;
-+
-+	spec->multiout.num_dacs = 2;	/* only use one dac */
-+	spec->multiout.dac_nids = spec->private_dac_nids;
-+	spec->multiout.dac_nids[0] = 2;
-+	spec->multiout.dac_nids[1] = 3;
-+
-+	nid = cfg->line_out_pins[0];
-+	if (nid)
-+		alc268_new_analog_output(spec, nid, "Front", 0);	
-+
-+	nid = cfg->speaker_pins[0];
-+	if (nid == 0x1d) {
-+		err = add_control(spec, ALC_CTL_WIDGET_VOL,
-+				  "Speaker Playback Volume",
-+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
-+		if (err < 0)
-+			return err;
-+	}
-+	nid = cfg->hp_pins[0];
-+	if (nid)
-+		alc268_new_analog_output(spec, nid, "Headphone", 0);
-+
-+	nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
-+	if (nid == 0x16) {
-+		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-+				  "Mono Playback Switch",
-+				  HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT));
-+		if (err < 0)
-+			return err;
-+	}
-+	return 0;	
-+}
-+
-+/* create playback/capture controls for input pins */
-+static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
-+						const struct auto_pin_cfg *cfg)
-+{
-+	struct hda_input_mux *imux = &spec->private_imux;
-+	int i, idx1;
-+
-+	for (i = 0; i < AUTO_PIN_LAST; i++) {
-+		switch(cfg->input_pins[i]) {
-+		case 0x18:
-+			idx1 = 0;	/* Mic 1 */
-+			break;
-+		case 0x19:
-+			idx1 = 1;	/* Mic 2 */
-+			break;
-+		case 0x1a:
-+			idx1 = 2;	/* Line In */
-+			break;
-+		case 0x1c:	
-+			idx1 = 3;	/* CD */
-+			break;
-+		default:
-+			continue;
-+		}
-+		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-+		imux->items[imux->num_items].index = idx1;
-+		imux->num_items++;	
-+	}
-+	return 0;
-+}
-+
-+static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
-+{
-+	struct alc_spec *spec = codec->spec;
-+	hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
-+	hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-+	hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
-+	unsigned int	dac_vol1, dac_vol2;
-+
-+	if (speaker_nid) {
-+		snd_hda_codec_write(codec, speaker_nid, 0,
-+				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-+		snd_hda_codec_write(codec, 0x0f, 0,
-+				    AC_VERB_SET_AMP_GAIN_MUTE,
-+				    AMP_IN_UNMUTE(1));
-+		snd_hda_codec_write(codec, 0x10, 0,
-+				    AC_VERB_SET_AMP_GAIN_MUTE,
-+				    AMP_IN_UNMUTE(1));
-+	} else {
-+		snd_hda_codec_write(codec, 0x0f, 0,
-+				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
-+		snd_hda_codec_write(codec, 0x10, 0,
-+				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
-+	}
-+
-+	dac_vol1 = dac_vol2 = 0xb000 | 0x40;	/* set max volume  */
-+	if (line_nid == 0x14)	
-+		dac_vol2 = AMP_OUT_ZERO;
-+	else if (line_nid == 0x15)
-+		dac_vol1 = AMP_OUT_ZERO;
-+	if (hp_nid == 0x14)	
-+		dac_vol2 = AMP_OUT_ZERO;
-+	else if (hp_nid == 0x15)
-+		dac_vol1 = AMP_OUT_ZERO;
-+	if (line_nid != 0x16 || hp_nid != 0x16 ||
-+	    spec->autocfg.line_out_pins[1] != 0x16 ||
-+	    spec->autocfg.line_out_pins[2] != 0x16)
-+		dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
-+
-+	snd_hda_codec_write(codec, 0x02, 0,
-+			    AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
-+	snd_hda_codec_write(codec, 0x03, 0,
-+			    AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
-+}
-+
-+/* pcm configuration: identiacal with ALC880 */
-+#define alc268_pcm_analog_playback	alc880_pcm_analog_playback
-+#define alc268_pcm_analog_capture	alc880_pcm_analog_capture
-+#define alc268_pcm_digital_playback	alc880_pcm_digital_playback
-+
-+/*
-+ * BIOS auto configuration
-+ */
-+static int alc268_parse_auto_config(struct hda_codec *codec)
-+{
-+	struct alc_spec *spec = codec->spec;
-+	int err;
-+	static hda_nid_t alc268_ignore[] = { 0 };
-+
-+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-+					   alc268_ignore);
-+	if (err < 0)
-+		return err;
-+	if (!spec->autocfg.line_outs)
-+		return 0; /* can't find valid BIOS pin config */
-+
-+	err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
-+	if (err < 0)
-+		return err;
-+	err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg);
-+	if (err < 0)
-+		return err;
-+
-+	spec->multiout.max_channels = 2;
-+
-+	/* digital only support output */
-+	if (spec->autocfg.dig_out_pin)
-+		spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
-+
-+	if (spec->kctl_alloc)
-+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
-+
-+	spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
-+	spec->num_mux_defs = 1;
-+	spec->input_mux = &spec->private_imux;
-+
-+	return 1;
-+}
-+
-+#define alc268_auto_init_multi_out	alc882_auto_init_multi_out
-+#define alc268_auto_init_hp_out		alc882_auto_init_hp_out
-+#define alc268_auto_init_analog_input	alc882_auto_init_analog_input
-+
-+/* init callback for auto-configuration model -- overriding the default init */
-+static void alc268_auto_init(struct hda_codec *codec)
-+{
-+	alc268_auto_init_multi_out(codec);
-+	alc268_auto_init_hp_out(codec);
-+	alc268_auto_init_mono_speaker_out(codec);
-+	alc268_auto_init_analog_input(codec);
-+}
-+
-+/*
-+ * configuration and preset
-+ */
-+static const char *alc268_models[ALC268_MODEL_LAST] = {
-+	[ALC268_3ST]		= "3stack",
-+	[ALC268_AUTO]		= "auto",
-+};
-+
-+static struct snd_pci_quirk alc268_cfg_tbl[] = {
-+	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
-+	{}
-+};
-+
-+static struct alc_config_preset alc268_presets[] = {
-+	[ALC268_3ST] = {
-+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
-+		.init_verbs = { alc268_base_init_verbs },
-+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-+		.dac_nids = alc268_dac_nids,
-+                .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-+                .adc_nids = alc268_adc_nids_alt,
-+		.hp_nid = 0x03,
-+		.dig_out_nid = ALC268_DIGOUT_NID,
-+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-+		.channel_mode = alc268_modes,
-+		.input_mux = &alc268_capture_source,
-+	},
-+};
-+
-+static int patch_alc268(struct hda_codec *codec)
-+{
-+	struct alc_spec *spec;
-+	int board_config;
-+	int err;
-+
-+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
-+	if (spec == NULL)
-+		return -ENOMEM;
-+
-+	codec->spec = spec;
-+
-+	board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
-+						  alc268_models,
-+						  alc268_cfg_tbl);
-+
-+	if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
-+		printk(KERN_INFO "hda_codec: Unknown model for ALC268, "
-+		       "trying auto-probe from BIOS...\n");
-+		board_config = ALC268_AUTO;
-+	}
-+
-+	if (board_config == ALC268_AUTO) {
-+		/* automatic parse from the BIOS config */
-+		err = alc268_parse_auto_config(codec);
-+		if (err < 0) {
-+			alc_free(codec);
-+			return err;
-+		} else if (!err) {
-+			printk(KERN_INFO
-+			       "hda_codec: Cannot set up configuration "
-+			       "from BIOS.  Using base mode...\n");
-+			board_config = ALC268_3ST;
-+		}
-+	}
-+
-+	if (board_config != ALC268_AUTO)
-+		setup_preset(spec, &alc268_presets[board_config]);
-+
-+	spec->stream_name_analog = "ALC268 Analog";
-+	spec->stream_analog_playback = &alc268_pcm_analog_playback;
-+	spec->stream_analog_capture = &alc268_pcm_analog_capture;
-+
-+	spec->stream_name_digital = "ALC268 Digital";
-+	spec->stream_digital_playback = &alc268_pcm_digital_playback;
-+
-+	if (board_config == ALC268_AUTO) {
-+		if (!spec->adc_nids && spec->input_mux) {
-+			/* check whether NID 0x07 is valid */
-+			unsigned int wcap = get_wcaps(codec, 0x07);
-+
-+			/* get type */
-+			wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-+			if (wcap != AC_WID_AUD_IN) {
-+				spec->adc_nids = alc268_adc_nids_alt;
-+				spec->num_adc_nids =
-+					ARRAY_SIZE(alc268_adc_nids_alt);
-+				spec->mixers[spec->num_mixers] =
-+					alc268_capture_alt_mixer;
-+				spec->num_mixers++;
-+			} else {
-+				spec->adc_nids = alc268_adc_nids;
-+				spec->num_adc_nids =
-+					ARRAY_SIZE(alc268_adc_nids);
-+				spec->mixers[spec->num_mixers] =
-+					alc268_capture_mixer;
-+				spec->num_mixers++;
-+			}
-+		}
-+	}
-+	codec->patch_ops = alc_patch_ops;
-+	if (board_config == ALC268_AUTO)
-+		spec->init_hook = alc268_auto_init;
-+		
-+	return 0;
-+}
-+
-+/*
-+ *  ALC861 channel source setting (2/6 channel selection for 3-stack)
-+ */
-+
-+/*
-+ * set the path ways for 2 channel output
-+ * need to set the codec line out and mic 1 pin widgets to inputs
-+ */
-+static struct hda_verb alc861_threestack_ch2_init[] = {
-+	/* set pin widget 1Ah (line in) for input */
-+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-+	/* set pin widget 18h (mic1/2) for input, for mic also enable
-+	 * the vref
-+	 */
-+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-+
-+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
-+#if 0
-+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
-+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
-+#endif
-+	{ } /* end */
-+};
-+/*
-+ * 6ch mode
-+ * need to set the codec line out and mic 1 pin widgets to outputs
-  */
- static struct hda_verb alc861_threestack_ch6_init[] = {
- 	/* set pin widget 1Ah (line in) for output (Back Surround)*/
-@@ -8767,13 +9620,21 @@
- 	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
- 	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
- 	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
-+	SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
- 	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
-+	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
- 	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
--	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
-+	/* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
-+	 *        Any other models that need this preset?
-+	 */
-+	/* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
- 	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
-+	SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31),
- 	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
- 	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
- 	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
-+	SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
-+	SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
- 	{}
- };
- 
-@@ -9464,6 +10325,7 @@
-  */
- static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
- 	[ALC660VD_3ST]		= "3stack-660",
-+	[ALC660VD_3ST_DIG]= "3stack-660-digout",
- 	[ALC861VD_3ST]		= "3stack",
- 	[ALC861VD_3ST_DIG]	= "3stack-digout",
- 	[ALC861VD_6ST_DIG]	= "6stack-digout",
-@@ -9475,7 +10337,7 @@
- static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
- 	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
- 	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
--	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST),
-+	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
- 	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
- 	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
- 
-@@ -9483,6 +10345,7 @@
- 	SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
- 	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
- 	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
-+	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
- 	{}
- };
- 
-@@ -9499,6 +10362,19 @@
- 		.channel_mode = alc861vd_3stack_2ch_modes,
- 		.input_mux = &alc861vd_capture_source,
- 	},
-+	[ALC660VD_3ST_DIG] = {
-+		.mixers = { alc861vd_3st_mixer },
-+		.init_verbs = { alc861vd_volume_init_verbs,
-+				 alc861vd_3stack_init_verbs },
-+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
-+		.dac_nids = alc660vd_dac_nids,
-+		.dig_out_nid = ALC861VD_DIGOUT_NID,
-+		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-+		.adc_nids = alc861vd_adc_nids,
-+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-+		.channel_mode = alc861vd_3stack_2ch_modes,
-+		.input_mux = &alc861vd_capture_source,
-+	},
- 	[ALC861VD_3ST] = {
- 		.mixers = { alc861vd_3st_mixer },
- 		.init_verbs = { alc861vd_volume_init_verbs,
-@@ -10420,7 +11296,7 @@
- 	for (i = 0; i < cfg->line_outs; i++) {
- 		if (!spec->multiout.dac_nids[i])
- 			continue;
--		nid = alc880_idx_to_dac(i);
-+		nid = alc880_idx_to_mixer(i);
- 		if (i == 2) {
- 			/* Center/LFE */
- 			err = add_control(spec, ALC_CTL_WIDGET_VOL,
-@@ -10643,14 +11519,10 @@
- 	spec->num_mux_defs = 1;
- 	spec->input_mux = &spec->private_imux;
- 	
--	if (err < 0)
--		return err;
--	else if (err > 0)
--		/* hack - override the init verbs */
--		spec->init_verbs[0] = alc662_auto_init_verbs;
-+	spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
- 	spec->mixers[spec->num_mixers] = alc662_capture_mixer;
- 	spec->num_mixers++;
--	return err;
-+	return 1;
- }
- 
- /* additional initialization for auto-configuration model */
-@@ -10687,7 +11559,7 @@
- 		if (err < 0) {
- 			alc_free(codec);
- 			return err;
--		} else if (err) {
-+		} else if (!err) {
- 			printk(KERN_INFO
- 			       "hda_codec: Cannot set up configuration "
- 			       "from BIOS.  Using base mode...\n");
-@@ -10724,6 +11596,7 @@
- struct hda_codec_preset snd_hda_preset_realtek[] = {
- 	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
- 	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
-+	{ .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
- 	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
- 	  .patch = patch_alc861 },
- 	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
---- linux-2.6.22.1.orig/sound/pci/hda/patch_si3054.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_si3054.c
-@@ -304,8 +304,12 @@
-  	{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
-  	{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
-  	{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
-+	/* VIA HDA on Clevo m540 */
-+	{ .id = 0x11063288, .name = "Si3054", .patch = patch_si3054 },
- 	/* Asus A8J Modem (SM56) */
- 	{ .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 },
-+	/* LG LW20 modem */
-+	{ .id = 0x18540018, .name = "Si3054", .patch = patch_si3054 },
- 	{}
- };
- 
---- linux-2.6.22.1.orig/sound/pci/hda/patch_sigmatel.c
-+++ linux-2.6.22.1/sound/pci/hda/patch_sigmatel.c
-@@ -44,6 +44,7 @@
- 
- enum {
- 	STAC_9205_REF,
-+	STAC_M43xx,
- 	STAC_9205_MODELS
- };
- 
-@@ -59,11 +60,19 @@
- 	STAC_D945_REF,
- 	STAC_D945GTP3,
- 	STAC_D945GTP5,
-+	STAC_922X_DELL,
-+	STAC_INTEL_MAC_V1,
-+	STAC_INTEL_MAC_V2,
-+	STAC_INTEL_MAC_V3,
-+	STAC_INTEL_MAC_V4,
-+	STAC_INTEL_MAC_V5,
-+	/* for backward compitability */
- 	STAC_MACMINI,
- 	STAC_MACBOOK,
- 	STAC_MACBOOK_PRO_V1,
- 	STAC_MACBOOK_PRO_V2,
- 	STAC_IMAC_INTEL,
-+	STAC_IMAC_INTEL_20,
- 	STAC_922X_MODELS
- };
- 
-@@ -210,7 +219,6 @@
- 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
- 	0x0f, 0x14, 0x16, 0x17, 0x18,
- 	0x21, 0x22,
--	
- };
- 
- static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,
-@@ -326,8 +334,6 @@
- };
- 
- static struct snd_kcontrol_new stac925x_mixer[] = {
--	HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
--	HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
- 	{
- 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- 		.name = "Input Source",
-@@ -549,44 +555,78 @@
- 	0x02a19320, 0x40000100,
- };
- 
--static unsigned int macbook_pro_v1_pin_configs[10] = {
--	0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010,
--	0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e,
--	0x02a19320, 0x400000fb
-+static unsigned int intel_mac_v1_pin_configs[10] = {
-+	0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd,
-+	0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240,
-+	0x400000fc, 0x400000fb,
-+};
-+
-+static unsigned int intel_mac_v2_pin_configs[10] = {
-+	0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
-+	0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa,
-+	0x400000fc, 0x400000fb,
-+};
-+
-+static unsigned int intel_mac_v3_pin_configs[10] = {
-+	0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
-+	0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240,
-+	0x400000fc, 0x400000fb,
- };
- 
--static unsigned int macbook_pro_v2_pin_configs[10] = {
--	0x0221401f, 0x90a70120, 0x01813024, 0x01014010,
--	0x400000fd, 0x01016011, 0x1345e240, 0x13c5e22e,
-+static unsigned int intel_mac_v4_pin_configs[10] = {
-+	0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
-+	0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
- 	0x400000fc, 0x400000fb,
- };
- 
--static unsigned int imac_intel_pin_configs[10] = {
--	0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe,
--	0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa,
-+static unsigned int intel_mac_v5_pin_configs[10] = {
-+	0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
-+	0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
- 	0x400000fc, 0x400000fb,
- };
- 
-+static unsigned int stac922x_dell_pin_configs[10] = {
-+	0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310,
-+	0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2,
-+	0x50a003f3, 0x405003f4
-+};
-+
- static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
- 	[STAC_D945_REF] = ref922x_pin_configs,
- 	[STAC_D945GTP3] = d945gtp3_pin_configs,
- 	[STAC_D945GTP5] = d945gtp5_pin_configs,
--	[STAC_MACMINI] = macbook_pro_v1_pin_configs,
--	[STAC_MACBOOK] = macbook_pro_v1_pin_configs,
--	[STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs,
--	[STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs,
--	[STAC_IMAC_INTEL] = imac_intel_pin_configs,
-+	[STAC_922X_DELL] = stac922x_dell_pin_configs,
-+	[STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs,
-+	[STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs,
-+	[STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs,
-+	[STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs,
-+	[STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs,
-+	/* for backward compitability */
-+	[STAC_MACMINI] = intel_mac_v3_pin_configs,
-+	[STAC_MACBOOK] = intel_mac_v5_pin_configs,
-+	[STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs,
-+	[STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs,
-+	[STAC_IMAC_INTEL] = intel_mac_v2_pin_configs,
-+	[STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs,
- };
- 
- static const char *stac922x_models[STAC_922X_MODELS] = {
- 	[STAC_D945_REF]	= "ref",
- 	[STAC_D945GTP5]	= "5stack",
- 	[STAC_D945GTP3]	= "3stack",
-+	[STAC_922X_DELL] = "dell",
-+	[STAC_INTEL_MAC_V1] = "intel-mac-v1",
-+	[STAC_INTEL_MAC_V2] = "intel-mac-v2",
-+	[STAC_INTEL_MAC_V3] = "intel-mac-v3",
-+	[STAC_INTEL_MAC_V4] = "intel-mac-v4",
-+	[STAC_INTEL_MAC_V5] = "intel-mac-v5",
-+	/* for backward compitability */
- 	[STAC_MACMINI]	= "macmini",
- 	[STAC_MACBOOK]	= "macbook",
- 	[STAC_MACBOOK_PRO_V1]	= "macbook-pro-v1",
- 	[STAC_MACBOOK_PRO_V2]	= "macbook-pro",
- 	[STAC_IMAC_INTEL] = "imac-intel",
-+	[STAC_IMAC_INTEL_20] = "imac-intel-20",
- };
- 
- static struct snd_pci_quirk stac922x_cfg_tbl[] = {
-@@ -649,7 +689,10 @@
- 	/* other systems  */
- 	/* Apple Mac Mini (early 2006) */
- 	SND_PCI_QUIRK(0x8384, 0x7680,
--		      "Mac Mini", STAC_MACMINI),
-+		      "Mac Mini", STAC_INTEL_MAC_V3),
-+	/* Dell */
-+	SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL),
-+
- 	{} /* terminator */
- };
- 
-@@ -730,7 +773,8 @@
- };
- 
- static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
--	ref9205_pin_configs,
-+	[STAC_REF] = ref9205_pin_configs,
-+	[STAC_M43xx] = NULL,
- };
- 
- static const char *stac9205_models[STAC_9205_MODELS] = {
-@@ -741,6 +785,10 @@
- 	/* SigmaTel reference board */
- 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- 		      "DFI LanParty", STAC_9205_REF),
-+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8,
-+		      "Dell Precision", STAC_M43xx),
-+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff,
-+		      "Dell Precision", STAC_M43xx),
- 	{} /* terminator */
- };
- 
-@@ -770,33 +818,56 @@
- 	return 0;
- }
- 
-+static void stac92xx_set_config_reg(struct hda_codec *codec,
-+				    hda_nid_t pin_nid, unsigned int pin_config)
-+{
-+	int i;
-+	snd_hda_codec_write(codec, pin_nid, 0,
-+			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
-+			    pin_config & 0x000000ff);
-+	snd_hda_codec_write(codec, pin_nid, 0,
-+			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
-+			    (pin_config & 0x0000ff00) >> 8);
-+	snd_hda_codec_write(codec, pin_nid, 0,
-+			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
-+			    (pin_config & 0x00ff0000) >> 16);
-+	snd_hda_codec_write(codec, pin_nid, 0,
-+			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
-+			    pin_config >> 24);
-+	i = snd_hda_codec_read(codec, pin_nid, 0,
-+			       AC_VERB_GET_CONFIG_DEFAULT,
-+			       0x00);	
-+	snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n",
-+		    pin_nid, i);
-+}
-+
- static void stac92xx_set_config_regs(struct hda_codec *codec)
- {
- 	int i;
- 	struct sigmatel_spec *spec = codec->spec;
--	unsigned int pin_cfg;
- 
--	if (! spec->pin_nids || ! spec->pin_configs)
--		return;
-+ 	if (!spec->pin_configs)
-+ 		return;
- 
--	for (i = 0; i < spec->num_pins; i++) {
--		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
--				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
--				    spec->pin_configs[i] & 0x000000ff);
--		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
--				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
--				    (spec->pin_configs[i] & 0x0000ff00) >> 8);
--		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
--				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
--				    (spec->pin_configs[i] & 0x00ff0000) >> 16);
--		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
--				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
--				    spec->pin_configs[i] >> 24);
--		pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
--					     AC_VERB_GET_CONFIG_DEFAULT,
--					     0x00);	
--		snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
--	}
-+	for (i = 0; i < spec->num_pins; i++)
-+		stac92xx_set_config_reg(codec, spec->pin_nids[i],
-+					spec->pin_configs[i]);
-+}
-+
-+static void stac92xx_enable_gpio_mask(struct hda_codec *codec,
-+				      int gpio_mask, int gpio_data)
-+{
-+	/* Configure GPIOx as output */
-+	snd_hda_codec_write(codec, codec->afg, 0,
-+			    AC_VERB_SET_GPIO_DIRECTION, gpio_mask);
-+	/* Configure GPIOx as CMOS */
-+	snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
-+	/* Assert GPIOx */
-+	snd_hda_codec_write(codec, codec->afg, 0,
-+			    AC_VERB_SET_GPIO_DATA, gpio_data);
-+	/* Enable GPIOx */
-+	snd_hda_codec_write(codec, codec->afg, 0,
-+			    AC_VERB_SET_GPIO_MASK, gpio_mask);
- }
- 
- /*
-@@ -1168,7 +1239,7 @@
-  * and 9202/925x. For those, dac_nids[] must be hard-coded.
-  */
- static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
--				       const struct auto_pin_cfg *cfg)
-+				       struct auto_pin_cfg *cfg)
- {
- 	struct sigmatel_spec *spec = codec->spec;
- 	int i, j, conn_len = 0; 
-@@ -1193,6 +1264,13 @@
- 		}
- 
- 		if (j == conn_len) {
-+			if (spec->multiout.num_dacs > 0) {
-+				/* we have already working output pins,
-+				 * so let's drop the broken ones again
-+				 */
-+				cfg->line_outs = spec->multiout.num_dacs;
-+				break;
-+			}
- 			/* error out, no available DAC found */
- 			snd_printk(KERN_ERR
- 				   "%s: No available DAC for pin 0x%x\n",
-@@ -1334,7 +1412,15 @@
- 			continue;
- 		add_spec_dacs(spec, nid);
- 	}
--
-+	for (i = 0; i < cfg->line_outs; i++) {
-+		nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0,
-+					AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-+		if (check_in_dac_nids(spec, nid))
-+			nid = 0;
-+		if (! nid)
-+			continue;
-+		add_spec_dacs(spec, nid);
-+	}
- 	for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
- 		static const char *pfxs[] = {
- 			"Speaker", "External Speaker", "Speaker2",
-@@ -1891,7 +1977,7 @@
- 		return -ENOMEM;
- 
- 	codec->spec = spec;
--	spec->num_pins = 8;
-+	spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
- 	spec->pin_nids = stac9200_pin_nids;
- 	spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
- 							stac9200_models,
-@@ -1941,7 +2027,7 @@
- 		return -ENOMEM;
- 
- 	codec->spec = spec;
--	spec->num_pins = 8;
-+	spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
- 	spec->pin_nids = stac925x_pin_nids;
- 	spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
- 							stac925x_models,
-@@ -2013,29 +2099,41 @@
- 		return -ENOMEM;
- 
- 	codec->spec = spec;
--	spec->num_pins = 10;
-+	spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
- 	spec->pin_nids = stac922x_pin_nids;
- 	spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
- 							stac922x_models,
- 							stac922x_cfg_tbl);
--	if (spec->board_config == STAC_MACMINI) {
-+	if (spec->board_config == STAC_INTEL_MAC_V3) {
- 		spec->gpio_mute = 1;
- 		/* Intel Macs have all same PCI SSID, so we need to check
- 		 * codec SSID to distinguish the exact models
- 		 */
- 		printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id);
- 		switch (codec->subsystem_id) {
--		case 0x106b0a00: /* MacBook First generatoin */
--			spec->board_config = STAC_MACBOOK;
-+
-+		case 0x106b0800:
-+			spec->board_config = STAC_INTEL_MAC_V1;
-+			break;
-+		case 0x106b0600:
-+		case 0x106b0700:
-+			spec->board_config = STAC_INTEL_MAC_V2;
- 			break;
--		case 0x106b0200: /* MacBook Pro first generation */
--			spec->board_config = STAC_MACBOOK_PRO_V1;
-+		case 0x106b0e00:
-+		case 0x106b0f00:
-+		case 0x106b1600:
-+		case 0x106b1700:
-+		case 0x106b0200:
-+		case 0x106b1e00:
-+			spec->board_config = STAC_INTEL_MAC_V3;
- 			break;
--		case 0x106b1e00: /* MacBook Pro second generation */
--			spec->board_config = STAC_MACBOOK_PRO_V2;
-+		case 0x106b1a00:
-+		case 0x00000100:
-+			spec->board_config = STAC_INTEL_MAC_V4;
- 			break;
--		case 0x106b0700: /* Intel-based iMac */
--			spec->board_config = STAC_IMAC_INTEL;
-+		case 0x106b0a00:
-+		case 0x106b2200:
-+			spec->board_config = STAC_INTEL_MAC_V5;
- 			break;
- 		}
- 	}
-@@ -2082,6 +2180,13 @@
- 
- 	codec->patch_ops = stac92xx_patch_ops;
- 
-+	/* Fix Mux capture level; max to 2 */
-+	snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
-+				  (0 << AC_AMPCAP_OFFSET_SHIFT) |
-+				  (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-+				  (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-+				  (0 << AC_AMPCAP_MUTE_SHIFT));
-+
- 	return 0;
- }
- 
-@@ -2095,7 +2200,7 @@
- 		return -ENOMEM;
- 
- 	codec->spec = spec;
--	spec->num_pins = 14;
-+	spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
- 	spec->pin_nids = stac927x_pin_nids;
- 	spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
- 							stac927x_models,
-@@ -2141,7 +2246,9 @@
- 	}
- 
- 	spec->multiout.dac_nids = spec->dac_nids;
--
-+	/* GPIO0 High = Enable EAPD */
-+	stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001);
-+	
- 	err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
- 	if (!err) {
- 		if (spec->board_config < 0) {
-@@ -2159,27 +2266,20 @@
- 
- 	codec->patch_ops = stac92xx_patch_ops;
- 
--	/* Fix Mux capture level; max to 2 */
--	snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
--				  (0 << AC_AMPCAP_OFFSET_SHIFT) |
--				  (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
--				  (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
--				  (0 << AC_AMPCAP_MUTE_SHIFT));
--
- 	return 0;
- }
- 
- static int patch_stac9205(struct hda_codec *codec)
- {
- 	struct sigmatel_spec *spec;
--	int err;
-+	int err, gpio_mask, gpio_data;
- 
- 	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
- 	if (spec == NULL)
- 		return -ENOMEM;
- 
- 	codec->spec = spec;
--	spec->num_pins = 14;
-+	spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
- 	spec->pin_nids = stac9205_pin_nids;
- 	spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
- 							stac9205_models,
-@@ -2209,19 +2309,21 @@
- 	spec->mixer = stac9205_mixer;
- 
- 	spec->multiout.dac_nids = spec->dac_nids;
-+	
-+	if (spec->board_config == STAC_M43xx) {
-+		/* Enable SPDIF in/out */
-+		stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
-+		stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
-+
-+		gpio_mask = 0x00000007; /* GPIO0-2 */
-+		/* GPIO0 High = EAPD, GPIO1 Low = DRM,
-+		 * GPIO2 High = Headphone Mute
-+		 */
-+		gpio_data = 0x00000005;
-+	} else
-+		gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */
- 
--	/* Configure GPIO0 as EAPD output */
--	snd_hda_codec_write(codec, codec->afg, 0,
--			    AC_VERB_SET_GPIO_DIRECTION, 0x00000001);
--	/* Configure GPIO0 as CMOS */
--	snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
--	/* Assert GPIO0 high */
--	snd_hda_codec_write(codec, codec->afg, 0,
--			    AC_VERB_SET_GPIO_DATA, 0x00000001);
--	/* Enable GPIO0 */
--	snd_hda_codec_write(codec, codec->afg, 0,
--			    AC_VERB_SET_GPIO_MASK, 0x00000001);
--
-+	stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data);
- 	err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
- 	if (!err) {
- 		if (spec->board_config < 0) {
-@@ -2256,8 +2358,8 @@
- 	.num_items = 2,
- 	.items = {
- 		/* { "HP", 0x0 }, */
--		{ "Line", 0x1 },
--		{ "Mic", 0x2 },
-+		{ "Mic Jack", 0x1 },
-+		{ "Internal Mic", 0x2 },
- 		{ "PCM", 0x3 },
- 	}
- };
-@@ -2268,7 +2370,7 @@
- 	{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
- 	{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
- 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
--	{0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */
-+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
- 	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
- 	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
- 	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
-@@ -2284,7 +2386,7 @@
- 	{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
- /*	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
- 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
--	{0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */
-+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
- 	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
- 	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
- /*	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
---- linux-2.6.22.1.orig/sound/pci/ice1712/revo.c
-+++ linux-2.6.22.1/sound/pci/ice1712/revo.c
-@@ -186,7 +186,12 @@
- #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch }
- 
- static const struct snd_akm4xxx_dac_channel revo71_front[] = {
--	AK_DAC("PCM Playback Volume", 2)
-+	{
-+		.name = "PCM Playback Volume",
-+		.num_channels = 2,
-+		/* front channels DAC supports muting */
-+		.switch_name = "PCM Playback Switch",
-+	},
- };
- 
- static const struct snd_akm4xxx_dac_channel revo71_surround[] = {
---- linux-2.6.22.1.orig/sound/pci/nm256/nm256.c
-+++ linux-2.6.22.1/sound/pci/nm256/nm256.c
-@@ -1533,7 +1533,8 @@
- 				printk(KERN_ERR "  force the driver to load by "
- 				       "passing in the module parameter\n");
- 				printk(KERN_ERR "    force_ac97=1\n");
--				printk(KERN_ERR "  or try sb16 or cs423x drivers instead.\n");
-+				printk(KERN_ERR "  or try sb16, opl3sa2, or "
-+				       "cs423x drivers instead.\n");
- 				err = -ENXIO;
- 				goto __error;
- 			}
---- linux-2.6.22.1.orig/sound/pci/rme9652/rme9652.c
-+++ linux-2.6.22.1/sound/pci/rme9652/rme9652.c
-@@ -406,7 +406,7 @@
- 		} else if (!frag)
- 			return 0;
- 		offset -= rme9652->max_jitter;
--		if (offset < 0)
-+		if ((int)offset < 0)
- 			offset += period_size * 2;
- 	} else {
- 		if (offset > period_size + rme9652->max_jitter) {
---- linux-2.6.22.1.orig/sound/pci/via82xx.c
-+++ linux-2.6.22.1/sound/pci/via82xx.c
-@@ -2098,7 +2098,7 @@
- 		pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
- 		if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
- 			break;
--		schedule_timeout_uninterruptible(1);
-+		schedule_timeout(1);
- 	} while (time_before(jiffies, end_time));
- 
- 	if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
-@@ -2117,7 +2117,7 @@
- 			chip->ac97_secondary = 1;
- 			goto __ac97_ok2;
- 		}
--		schedule_timeout_interruptible(1);
-+		schedule_timeout(1);
- 	} while (time_before(jiffies, end_time));
- 	/* This is ok, the most of motherboards have only one codec */
- 
---- linux-2.6.22.1.orig/sound/pci/via82xx_modem.c
-+++ linux-2.6.22.1/sound/pci/via82xx_modem.c
-@@ -983,7 +983,7 @@
- 		pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
- 		if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
- 			break;
--		schedule_timeout_uninterruptible(1);
-+		schedule_timeout(1);
- 	} while (time_before(jiffies, end_time));
- 
- 	if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
-@@ -1001,7 +1001,7 @@
- 			chip->ac97_secondary = 1;
- 			goto __ac97_ok2;
- 		}
--		schedule_timeout_interruptible(1);
-+		schedule_timeout(1);
- 	} while (time_before(jiffies, end_time));
- 	/* This is ok, the most of motherboards have only one codec */
- 
---- linux-2.6.22.1.orig/sound/ppc/Kconfig
-+++ linux-2.6.22.1/sound/ppc/Kconfig
-@@ -33,3 +33,23 @@
- 	  option.
- 
- endmenu
-+
-+menu "ALSA PowerPC devices"
-+	depends on SND!=n && ( PPC64 || PPC32 )
-+
-+config SND_PS3
-+	tristate "PS3 Audio support"
-+	depends on SND && PS3_PS3AV
-+	select SND_PCM
-+	default m
-+	help
-+	  Say Y here to include support for audio on the PS3
-+
-+	  To compile this driver as a module, choose M here: the module
-+	  will be called snd_ps3.
-+
-+config SND_PS3_DEFAULT_START_DELAY
-+	int "Startup delay time in ms"
-+	depends on SND_PS3
-+	default "2000"
-+endmenu
---- linux-2.6.22.1.orig/sound/ppc/Makefile
-+++ linux-2.6.22.1/sound/ppc/Makefile
-@@ -6,4 +6,5 @@
- snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
- 
- # Toplevel Module Dependency
--obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
-+obj-$(CONFIG_SND_POWERMAC)	+= snd-powermac.o
-+obj-$(CONFIG_SND_PS3)		+= snd_ps3.o
---- /dev/null
-+++ linux-2.6.22.1/sound/ppc/snd_ps3.c
-@@ -0,0 +1,1125 @@
-+/*
-+ * Audio support for PS3
-+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
-+ * All rights reserved.
-+ * Copyright 2006, 2007 Sony Corporation
-+ *
-+ * 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; version 2 of the Licence.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/io.h>
-+#include <linux/interrupt.h>
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+#include <sound/asound.h>
-+#include <sound/memalloc.h>
-+#include <sound/pcm_params.h>
-+#include <sound/control.h>
-+#include <linux/dmapool.h>
-+#include <linux/dma-mapping.h>
-+#include <asm/firmware.h>
-+#include <linux/io.h>
-+#include <asm/dma.h>
-+#include <asm/lv1call.h>
-+#include <asm/ps3.h>
-+#include <asm/ps3av.h>
-+
-+#include "snd_ps3_reg.h"
-+#include "snd_ps3.h"
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("PS3 sound driver");
-+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
-+
-+/* module  entries */
-+static int __init snd_ps3_init(void);
-+static void __exit snd_ps3_exit(void);
-+
-+/* ALSA snd driver ops */
-+static int snd_ps3_pcm_open(struct snd_pcm_substream *substream);
-+static int snd_ps3_pcm_close(struct snd_pcm_substream *substream);
-+static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream);
-+static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream,
-+				 int cmd);
-+static snd_pcm_uframes_t snd_ps3_pcm_pointer(struct snd_pcm_substream
-+					     *substream);
-+static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream,
-+				 struct snd_pcm_hw_params *hw_params);
-+static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream);
-+
-+
-+/* ps3_system_bus_driver entries */
-+static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev);
-+static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev);
-+
-+/* address setup */
-+static int snd_ps3_map_mmio(void);
-+static void snd_ps3_unmap_mmio(void);
-+static int snd_ps3_allocate_irq(void);
-+static void snd_ps3_free_irq(void);
-+static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start);
-+
-+/* interrupt handler */
-+static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id);
-+
-+
-+/* set sampling rate/format */
-+static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream);
-+/* take effect parameter change */
-+static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card);
-+/* initialize avsetting and take it effect */
-+static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card);
-+/* setup dma */
-+static int snd_ps3_program_dma(struct snd_ps3_card_info *card,
-+			       enum snd_ps3_dma_filltype filltype);
-+static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card);
-+
-+static dma_addr_t v_to_bus(struct snd_ps3_card_info *, void  *vaddr, int ch);
-+
-+
-+module_init(snd_ps3_init);
-+module_exit(snd_ps3_exit);
-+
-+/*
-+ * global
-+ */
-+static struct snd_ps3_card_info the_card;
-+
-+static int snd_ps3_start_delay = CONFIG_SND_PS3_DEFAULT_START_DELAY;
-+
-+module_param_named(start_delay, snd_ps3_start_delay, uint, 0644);
-+MODULE_PARM_DESC(start_delay, "time to insert silent data in milisec");
-+
-+static int index = SNDRV_DEFAULT_IDX1;
-+static char *id = SNDRV_DEFAULT_STR1;
-+
-+module_param(index, int, 0444);
-+MODULE_PARM_DESC(index, "Index value for PS3 soundchip.");
-+module_param(id, charp, 0444);
-+MODULE_PARM_DESC(id, "ID string for PS3 soundchip.");
-+
-+
-+/*
-+ * PS3 audio register access
-+ */
-+static inline u32 read_reg(unsigned int reg)
-+{
-+	return in_be32(the_card.mapped_mmio_vaddr + reg);
-+}
-+static inline void write_reg(unsigned int reg, u32 val)
-+{
-+	out_be32(the_card.mapped_mmio_vaddr + reg, val);
-+}
-+static inline void update_reg(unsigned int reg, u32 or_val)
-+{
-+	u32 newval = read_reg(reg) | or_val;
-+	write_reg(reg, newval);
-+}
-+static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val)
-+{
-+	u32 newval = (read_reg(reg) & mask) | or_val;
-+	write_reg(reg, newval);
-+}
-+
-+/*
-+ * ALSA defs
-+ */
-+const static struct snd_pcm_hardware snd_ps3_pcm_hw = {
-+	.info = (SNDRV_PCM_INFO_MMAP |
-+		 SNDRV_PCM_INFO_NONINTERLEAVED |
-+		 SNDRV_PCM_INFO_MMAP_VALID),
-+	.formats = (SNDRV_PCM_FMTBIT_S16_BE |
-+		    SNDRV_PCM_FMTBIT_S24_BE),
-+	.rates = (SNDRV_PCM_RATE_44100 |
-+		  SNDRV_PCM_RATE_48000 |
-+		  SNDRV_PCM_RATE_88200 |
-+		  SNDRV_PCM_RATE_96000),
-+	.rate_min = 44100,
-+	.rate_max = 96000,
-+
-+	.channels_min = 2, /* stereo only */
-+	.channels_max = 2,
-+
-+	.buffer_bytes_max = PS3_AUDIO_FIFO_SIZE * 64,
-+
-+	/* interrupt by four stages */
-+	.period_bytes_min = PS3_AUDIO_FIFO_STAGE_SIZE * 4,
-+	.period_bytes_max = PS3_AUDIO_FIFO_STAGE_SIZE * 4,
-+
-+	.periods_min = 16,
-+	.periods_max = 32, /* buffer_size_max/ period_bytes_max */
-+
-+	.fifo_size = PS3_AUDIO_FIFO_SIZE
-+};
-+
-+static struct snd_pcm_ops snd_ps3_pcm_spdif_ops =
-+{
-+	.open = snd_ps3_pcm_open,
-+	.close = snd_ps3_pcm_close,
-+	.prepare = snd_ps3_pcm_prepare,
-+	.ioctl = snd_pcm_lib_ioctl,
-+	.trigger = snd_ps3_pcm_trigger,
-+	.pointer = snd_ps3_pcm_pointer,
-+	.hw_params = snd_ps3_pcm_hw_params,
-+	.hw_free = snd_ps3_pcm_hw_free
-+};
-+
-+static int snd_ps3_verify_dma_stop(struct snd_ps3_card_info *card,
-+				   int count, int force_stop)
-+{
-+	int dma_ch, done, retries, stop_forced = 0;
-+	uint32_t status;
-+
-+	for (dma_ch = 0; dma_ch < 8; dma_ch ++) {
-+		retries = count;
-+		do {
-+			status = read_reg(PS3_AUDIO_KICK(dma_ch)) &
-+				PS3_AUDIO_KICK_STATUS_MASK;
-+			switch (status) {
-+			case PS3_AUDIO_KICK_STATUS_DONE:
-+			case PS3_AUDIO_KICK_STATUS_NOTIFY:
-+			case PS3_AUDIO_KICK_STATUS_CLEAR:
-+			case PS3_AUDIO_KICK_STATUS_ERROR:
-+				done = 1;
-+				break;
-+			default:
-+				done = 0;
-+				udelay(10);
-+			}
-+		} while (!done && --retries);
-+		if (!retries && force_stop) {
-+			pr_info("%s: DMA ch %d is not stopped.",
-+				__func__, dma_ch);
-+			/* last resort. force to stop dma.
-+			 *  NOTE: this cause DMA done interrupts
-+			 */
-+			update_reg(PS3_AUDIO_CONFIG, PS3_AUDIO_CONFIG_CLEAR);
-+			stop_forced = 1;
-+		}
-+	}
-+	return stop_forced;
-+}
-+
-+/*
-+ * wait for all dma is done.
-+ * NOTE: caller should reset card->running before call.
-+ *       If not, the interrupt handler will re-start DMA,
-+ *       then DMA is never stopped.
-+ */
-+static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card)
-+{
-+	int stop_forced;
-+	/*
-+	 * wait for the last dma is done
-+	 */
-+
-+	/*
-+	 * expected maximum DMA done time is 5.7ms + something (DMA itself).
-+	 * 5.7ms is from 16bit/sample 2ch 44.1Khz; the time next
-+	 * DMA kick event would occur.
-+	 */
-+	stop_forced = snd_ps3_verify_dma_stop(card, 700, 1);
-+
-+	/*
-+	 * clear outstanding interrupts.
-+	 */
-+	update_reg(PS3_AUDIO_INTR_0, 0);
-+	update_reg(PS3_AUDIO_AX_IS, 0);
-+
-+	/*
-+	 *revert CLEAR bit since it will not reset automatically after DMA stop
-+	 */
-+	if (stop_forced)
-+		update_mask_reg(PS3_AUDIO_CONFIG, ~PS3_AUDIO_CONFIG_CLEAR, 0);
-+	/* ensure the hardware sees changes */
-+	wmb();
-+}
-+
-+static void snd_ps3_kick_dma(struct snd_ps3_card_info *card)
-+{
-+
-+	update_reg(PS3_AUDIO_KICK(0), PS3_AUDIO_KICK_REQUEST);
-+	/* ensure the hardware sees the change */
-+	wmb();
-+}
-+
-+/*
-+ * convert virtual addr to ioif bus addr.
-+ */
-+static dma_addr_t v_to_bus(struct snd_ps3_card_info *card,
-+			   void * paddr,
-+			   int ch)
-+{
-+	return card->dma_start_bus_addr[ch] +
-+		(paddr - card->dma_start_vaddr[ch]);
-+};
-+
-+
-+/*
-+ * increment ring buffer pointer.
-+ * NOTE: caller must hold write spinlock
-+ */
-+static void snd_ps3_bump_buffer(struct snd_ps3_card_info *card,
-+				enum snd_ps3_ch ch, size_t byte_count,
-+				int stage)
-+{
-+	if (!stage)
-+		card->dma_last_transfer_vaddr[ch] =
-+			card->dma_next_transfer_vaddr[ch];
-+	card->dma_next_transfer_vaddr[ch] += byte_count;
-+	if ((card->dma_start_vaddr[ch] + (card->dma_buffer_size / 2)) <=
-+	    card->dma_next_transfer_vaddr[ch]) {
-+		card->dma_next_transfer_vaddr[ch] = card->dma_start_vaddr[ch];
-+	}
-+}
-+/*
-+ * setup dmac to send data to audio and attenuate samples on the ring buffer
-+ */
-+static int snd_ps3_program_dma(struct snd_ps3_card_info *card,
-+			       enum snd_ps3_dma_filltype filltype)
-+{
-+	/* this dmac does not support over 4G */
-+	uint32_t dma_addr;
-+	int fill_stages, dma_ch, stage;
-+	enum snd_ps3_ch ch;
-+	uint32_t ch0_kick_event = 0; /* initialize to mute gcc */
-+	void *start_vaddr;
-+	unsigned long irqsave;
-+	int silent = 0;
-+
-+	switch (filltype) {
-+	case SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL:
-+		silent = 1;
-+		/* intentionally fall thru */
-+	case SND_PS3_DMA_FILLTYPE_FIRSTFILL:
-+		ch0_kick_event = PS3_AUDIO_KICK_EVENT_ALWAYS;
-+		break;
-+
-+	case SND_PS3_DMA_FILLTYPE_SILENT_RUNNING:
-+		silent = 1;
-+		/* intentionally fall thru */
-+	case SND_PS3_DMA_FILLTYPE_RUNNING:
-+		ch0_kick_event = PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY;
-+		break;
-+	}
-+
-+	snd_ps3_verify_dma_stop(card, 700, 0);
-+	fill_stages = 4;
-+	spin_lock_irqsave(&card->dma_lock, irqsave);
-+	for (ch = 0; ch < 2; ch++) {
-+		start_vaddr = card->dma_next_transfer_vaddr[0];
-+		for (stage = 0; stage < fill_stages; stage ++) {
-+			dma_ch = stage * 2 + ch;
-+			if (silent)
-+				dma_addr = card->null_buffer_start_dma_addr;
-+			else
-+				dma_addr =
-+				v_to_bus(card,
-+					 card->dma_next_transfer_vaddr[ch],
-+					 ch);
-+
-+			write_reg(PS3_AUDIO_SOURCE(dma_ch),
-+				  (PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY |
-+				   dma_addr));
-+
-+			/* dst: fixed to 3wire#0 */
-+			if (ch == 0)
-+				write_reg(PS3_AUDIO_DEST(dma_ch),
-+					  (PS3_AUDIO_DEST_TARGET_AUDIOFIFO |
-+					   PS3_AUDIO_AO_3W_LDATA(0)));
-+			else
-+				write_reg(PS3_AUDIO_DEST(dma_ch),
-+					  (PS3_AUDIO_DEST_TARGET_AUDIOFIFO |
-+					   PS3_AUDIO_AO_3W_RDATA(0)));
-+
-+			/* count always 1 DMA block (1/2 stage = 128 bytes) */
-+			write_reg(PS3_AUDIO_DMASIZE(dma_ch), 0);
-+			/* bump pointer if needed */
-+			if (!silent)
-+				snd_ps3_bump_buffer(card, ch,
-+						    PS3_AUDIO_DMAC_BLOCK_SIZE,
-+						    stage);
-+
-+			/* kick event  */
-+			if (dma_ch == 0)
-+				write_reg(PS3_AUDIO_KICK(dma_ch),
-+					  ch0_kick_event);
-+			else
-+				write_reg(PS3_AUDIO_KICK(dma_ch),
-+					  PS3_AUDIO_KICK_EVENT_AUDIO_DMA(dma_ch
-+									 - 1) |
-+					  PS3_AUDIO_KICK_REQUEST);
-+		}
-+	}
-+	/* ensure the hardware sees the change */
-+	wmb();
-+	spin_unlock_irqrestore(&card->dma_lock, irqsave);
-+
-+	return 0;
-+}
-+
-+/*
-+ * audio mute on/off
-+ * mute_on : 0 output enabled
-+ *           1 mute
-+ */
-+static int snd_ps3_mute(int mute_on)
-+{
-+	return ps3av_audio_mute(mute_on);
-+}
-+
-+/*
-+ * PCM operators
-+ */
-+static int snd_ps3_pcm_open(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
-+	int pcm_index;
-+
-+	pcm_index = substream->pcm->device;
-+	/* to retrieve substream/runtime in interrupt handler */
-+	card->substream = substream;
-+
-+	runtime->hw = snd_ps3_pcm_hw;
-+
-+	card->start_delay = snd_ps3_start_delay;
-+
-+	/* mute off */
-+	snd_ps3_mute(0); /* this function sleep */
-+
-+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-+				   PS3_AUDIO_FIFO_STAGE_SIZE * 4 * 2);
-+	return 0;
-+};
-+
-+static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream,
-+				 struct snd_pcm_hw_params *hw_params)
-+{
-+	size_t size;
-+
-+	/* alloc transport buffer */
-+	size = params_buffer_bytes(hw_params);
-+	snd_pcm_lib_malloc_pages(substream, size);
-+	return 0;
-+};
-+
-+static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream,
-+				  unsigned int delay_ms)
-+{
-+	int ret;
-+	int rate ;
-+
-+	rate = substream->runtime->rate;
-+	ret = snd_pcm_format_size(substream->runtime->format,
-+				  rate * delay_ms / 1000)
-+		* substream->runtime->channels;
-+
-+	pr_debug(KERN_ERR "%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n",
-+		 __func__,
-+		 delay_ms,
-+		 rate,
-+		 snd_pcm_format_size(substream->runtime->format, rate),
-+		 rate * delay_ms / 1000,
-+		 ret);
-+
-+	return ret;
-+};
-+
-+static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
-+	unsigned long irqsave;
-+
-+	if (!snd_ps3_set_avsetting(substream)) {
-+		/* some parameter changed */
-+		write_reg(PS3_AUDIO_AX_IE,
-+			  PS3_AUDIO_AX_IE_ASOBEIE(0) |
-+			  PS3_AUDIO_AX_IE_ASOBUIE(0));
-+		/*
-+		 * let SPDIF device re-lock with SPDIF signal,
-+		 * start with some silence
-+		 */
-+		card->silent = snd_ps3_delay_to_bytes(substream,
-+						      card->start_delay) /
-+			(PS3_AUDIO_FIFO_STAGE_SIZE * 4); /* every 4 times */
-+	}
-+
-+	/* restart ring buffer pointer */
-+	spin_lock_irqsave(&card->dma_lock, irqsave);
-+	{
-+		card->dma_buffer_size = runtime->dma_bytes;
-+
-+		card->dma_last_transfer_vaddr[SND_PS3_CH_L] =
-+			card->dma_next_transfer_vaddr[SND_PS3_CH_L] =
-+			card->dma_start_vaddr[SND_PS3_CH_L] =
-+			runtime->dma_area;
-+		card->dma_start_bus_addr[SND_PS3_CH_L] = runtime->dma_addr;
-+
-+		card->dma_last_transfer_vaddr[SND_PS3_CH_R] =
-+			card->dma_next_transfer_vaddr[SND_PS3_CH_R] =
-+			card->dma_start_vaddr[SND_PS3_CH_R] =
-+			runtime->dma_area + (runtime->dma_bytes / 2);
-+		card->dma_start_bus_addr[SND_PS3_CH_R] =
-+			runtime->dma_addr + (runtime->dma_bytes / 2);
-+
-+		pr_debug("%s: vaddr=%p bus=%#lx\n", __func__,
-+			 card->dma_start_vaddr[SND_PS3_CH_L],
-+			 card->dma_start_bus_addr[SND_PS3_CH_L]);
-+
-+	}
-+	spin_unlock_irqrestore(&card->dma_lock, irqsave);
-+
-+	/* ensure the hardware sees the change */
-+	mb();
-+
-+	return 0;
-+};
-+
-+static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream,
-+			       int cmd)
-+{
-+	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
-+	int ret = 0;
-+
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		/* clear outstanding interrupts  */
-+		update_reg(PS3_AUDIO_AX_IS, 0);
-+
-+		spin_lock(&card->dma_lock);
-+		{
-+			card->running = 1;
-+		}
-+		spin_unlock(&card->dma_lock);
-+
-+		snd_ps3_program_dma(card,
-+				    SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
-+		snd_ps3_kick_dma(card);
-+		while (read_reg(PS3_AUDIO_KICK(7)) &
-+		       PS3_AUDIO_KICK_STATUS_MASK) {
-+			udelay(1);
-+		}
-+		snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_RUNNING);
-+		snd_ps3_kick_dma(card);
-+		break;
-+
-+	case SNDRV_PCM_TRIGGER_STOP:
-+		spin_lock(&card->dma_lock);
-+		{
-+			card->running = 0;
-+		}
-+		spin_unlock(&card->dma_lock);
-+		snd_ps3_wait_for_dma_stop(card);
-+		break;
-+	default:
-+		break;
-+
-+	}
-+
-+	return ret;
-+};
-+
-+/*
-+ * report current pointer
-+ */
-+static snd_pcm_uframes_t snd_ps3_pcm_pointer(
-+	struct snd_pcm_substream *substream)
-+{
-+	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
-+	size_t bytes;
-+	snd_pcm_uframes_t ret;
-+
-+	spin_lock(&card->dma_lock);
-+	{
-+		bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] -
-+				 card->dma_start_vaddr[SND_PS3_CH_L]);
-+	}
-+	spin_unlock(&card->dma_lock);
-+
-+	ret = bytes_to_frames(substream->runtime, bytes * 2);
-+
-+	return ret;
-+};
-+
-+static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream)
-+{
-+	int ret;
-+	ret = snd_pcm_lib_free_pages(substream);
-+	return ret;
-+};
-+
-+static int snd_ps3_pcm_close(struct snd_pcm_substream *substream)
-+{
-+	/* mute on */
-+	snd_ps3_mute(1);
-+	return 0;
-+};
-+
-+static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
-+{
-+	/*
-+	 * avsetting driver seems to never change the followings
-+	 * so, init them here once
-+	 */
-+
-+	/* no dma interrupt needed */
-+	write_reg(PS3_AUDIO_INTR_EN_0, 0);
-+
-+	/* use every 4 buffer empty interrupt */
-+	update_mask_reg(PS3_AUDIO_AX_IC,
-+			PS3_AUDIO_AX_IC_AASOIMD_MASK,
-+			PS3_AUDIO_AX_IC_AASOIMD_EVERY4);
-+
-+	/* enable 3wire clocks */
-+	update_mask_reg(PS3_AUDIO_AO_3WMCTRL,
-+			~(PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED |
-+			  PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED),
-+			0);
-+	update_reg(PS3_AUDIO_AO_3WMCTRL,
-+		   PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT);
-+}
-+
-+/*
-+ * av setting
-+ * NOTE: calling this function may generate audio interrupt.
-+ */
-+static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card)
-+{
-+	int ret, retries, i;
-+	pr_debug("%s: start\n", __func__);
-+
-+	ret = ps3av_set_audio_mode(card->avs.avs_audio_ch,
-+				  card->avs.avs_audio_rate,
-+				  card->avs.avs_audio_width,
-+				  card->avs.avs_audio_format,
-+				  card->avs.avs_audio_source);
-+	/*
-+	 * Reset the following unwanted settings:
-+	 */
-+
-+	/* disable all 3wire buffers */
-+	update_mask_reg(PS3_AUDIO_AO_3WMCTRL,
-+			~(PS3_AUDIO_AO_3WMCTRL_ASOEN(0) |
-+			  PS3_AUDIO_AO_3WMCTRL_ASOEN(1) |
-+			  PS3_AUDIO_AO_3WMCTRL_ASOEN(2) |
-+			  PS3_AUDIO_AO_3WMCTRL_ASOEN(3)),
-+			0);
-+	wmb(); 	/* ensure the hardware sees the change */
-+	/* wait for actually stopped */
-+	retries = 1000;
-+	while ((read_reg(PS3_AUDIO_AO_3WMCTRL) &
-+		(PS3_AUDIO_AO_3WMCTRL_ASORUN(0) |
-+		 PS3_AUDIO_AO_3WMCTRL_ASORUN(1) |
-+		 PS3_AUDIO_AO_3WMCTRL_ASORUN(2) |
-+		 PS3_AUDIO_AO_3WMCTRL_ASORUN(3))) &&
-+	       --retries) {
-+		udelay(1);
-+	}
-+
-+	/* reset buffer pointer */
-+	for (i = 0; i < 4; i++) {
-+		update_reg(PS3_AUDIO_AO_3WCTRL(i),
-+			   PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET);
-+		udelay(10);
-+	}
-+	wmb(); /* ensure the hardware actually start resetting */
-+
-+	/* enable 3wire#0 buffer */
-+	update_reg(PS3_AUDIO_AO_3WMCTRL, PS3_AUDIO_AO_3WMCTRL_ASOEN(0));
-+
-+
-+	/* In 24bit mode,ALSA inserts a zero byte at first byte of per sample */
-+	update_mask_reg(PS3_AUDIO_AO_3WCTRL(0),
-+			~PS3_AUDIO_AO_3WCTRL_ASODF,
-+			PS3_AUDIO_AO_3WCTRL_ASODF_LSB);
-+	update_mask_reg(PS3_AUDIO_AO_SPDCTRL(0),
-+			~PS3_AUDIO_AO_SPDCTRL_SPODF,
-+			PS3_AUDIO_AO_SPDCTRL_SPODF_LSB);
-+	/* ensure all the setting above is written back to register */
-+	wmb();
-+	/* avsetting driver altered AX_IE, caller must reset it if you want */
-+	pr_debug("%s: end\n", __func__);
-+	return ret;
-+}
-+
-+static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
-+{
-+	int ret;
-+	pr_debug("%s: start\n", __func__);
-+	card->avs.avs_audio_ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;
-+	card->avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K;
-+	card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
-+	card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM;
-+	card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
-+
-+	ret = snd_ps3_change_avsetting(card);
-+
-+	snd_ps3_audio_fixup(card);
-+
-+	/* to start to generate SPDIF signal, fill data */
-+	snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
-+	snd_ps3_kick_dma(card);
-+	pr_debug("%s: end\n", __func__);
-+	return ret;
-+}
-+
-+/*
-+ *  set sampling rate according to the substream
-+ */
-+static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
-+{
-+	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
-+	struct snd_ps3_avsetting_info avs;
-+
-+	avs = card->avs;
-+
-+	pr_debug("%s: called freq=%d width=%d\n", __func__,
-+		 substream->runtime->rate,
-+		 snd_pcm_format_width(substream->runtime->format));
-+
-+	pr_debug("%s: before freq=%d width=%d\n", __func__,
-+		 card->avs.avs_audio_rate, card->avs.avs_audio_width);
-+
-+	/* sample rate */
-+	switch (substream->runtime->rate) {
-+	case 44100:
-+		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_44K;
-+		break;
-+	case 48000:
-+		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K;
-+		break;
-+	case 88200:
-+		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_88K;
-+		break;
-+	case 96000:
-+		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_96K;
-+		break;
-+	default:
-+		pr_info("%s: invalid rate %d\n", __func__,
-+			substream->runtime->rate);
-+		return 1;
-+	}
-+
-+	/* width */
-+	switch (snd_pcm_format_width(substream->runtime->format)) {
-+	case 16:
-+		avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
-+		break;
-+	case 24:
-+		avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_24;
-+		break;
-+	default:
-+		pr_info("%s: invalid width %d\n", __func__,
-+			snd_pcm_format_width(substream->runtime->format));
-+		return 1;
-+	}
-+
-+	if ((card->avs.avs_audio_width != avs.avs_audio_width) ||
-+	    (card->avs.avs_audio_rate != avs.avs_audio_rate)) {
-+		card->avs = avs;
-+		snd_ps3_change_avsetting(card);
-+
-+		pr_debug("%s: after freq=%d width=%d\n", __func__,
-+			 card->avs.avs_audio_rate, card->avs.avs_audio_width);
-+
-+		return 0;
-+	} else
-+		return 1;
-+}
-+
-+
-+
-+static int snd_ps3_map_mmio(void)
-+{
-+	the_card.mapped_mmio_vaddr =
-+		ioremap(the_card.ps3_dev->m_region->bus_addr,
-+			the_card.ps3_dev->m_region->len);
-+
-+	if (!the_card.mapped_mmio_vaddr) {
-+		pr_info("%s: ioremap 0 failed p=%#lx l=%#lx \n",
-+		       __func__, the_card.ps3_dev->m_region->lpar_addr,
-+		       the_card.ps3_dev->m_region->len);
-+		return -ENXIO;
-+	}
-+
-+	return 0;
-+};
-+
-+static void snd_ps3_unmap_mmio(void)
-+{
-+	iounmap(the_card.mapped_mmio_vaddr);
-+	the_card.mapped_mmio_vaddr = NULL;
-+}
-+
-+static int snd_ps3_allocate_irq(void)
-+{
-+	int ret;
-+	u64 lpar_addr, lpar_size;
-+	u64 __iomem *mapped;
-+
-+	/* FIXME: move this to device_init (H/W probe) */
-+
-+	/* get irq outlet */
-+	ret = lv1_gpu_device_map(1, &lpar_addr, &lpar_size);
-+	if (ret) {
-+		pr_info("%s: device map 1 failed %d\n", __func__,
-+			ret);
-+		return -ENXIO;
-+	}
-+
-+	mapped = ioremap(lpar_addr, lpar_size);
-+	if (!mapped) {
-+		pr_info("%s: ioremap 1 failed \n", __func__);
-+		return -ENXIO;
-+	}
-+
-+	the_card.audio_irq_outlet = in_be64(mapped);
-+
-+	iounmap(mapped);
-+	ret = lv1_gpu_device_unmap(1);
-+	if (ret)
-+		pr_info("%s: unmap 1 failed\n", __func__);
-+
-+	/* irq */
-+	ret = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY,
-+				 the_card.audio_irq_outlet,
-+				 &the_card.irq_no);
-+	if (ret) {
-+		pr_info("%s:ps3_alloc_irq failed (%d)\n", __func__, ret);
-+		return ret;
-+	}
-+
-+	ret = request_irq(the_card.irq_no, snd_ps3_interrupt, IRQF_DISABLED,
-+			  SND_PS3_DRIVER_NAME, &the_card);
-+	if (ret) {
-+		pr_info("%s: request_irq failed (%d)\n", __func__, ret);
-+		goto cleanup_irq;
-+	}
-+
-+	return 0;
-+
-+ cleanup_irq:
-+	ps3_irq_plug_destroy(the_card.irq_no);
-+	return ret;
-+};
-+
-+static void snd_ps3_free_irq(void)
-+{
-+	free_irq(the_card.irq_no, &the_card);
-+	ps3_irq_plug_destroy(the_card.irq_no);
-+}
-+
-+static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
-+{
-+	uint64_t val;
-+	int ret;
-+
-+	val = (ioaddr_start & (0x0fUL << 32)) >> (32 - 20) |
-+		(0x03UL << 24) |
-+		(0x0fUL << 12) |
-+		(PS3_AUDIO_IOID);
-+
-+	ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0);
-+	if (ret)
-+		pr_info("%s: gpu_attribute failed %d\n", __func__,
-+			ret);
-+}
-+
-+static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
-+{
-+	int ret;
-+	u64 lpar_addr, lpar_size;
-+
-+	BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
-+	BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND);
-+
-+	the_card.ps3_dev = dev;
-+
-+	ret = ps3_open_hv_device(dev);
-+
-+	if (ret)
-+		return -ENXIO;
-+
-+	/* setup MMIO */
-+	ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size);
-+	if (ret) {
-+		pr_info("%s: device map 2 failed %d\n", __func__, ret);
-+		goto clean_open;
-+	}
-+	ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size,
-+		PAGE_SHIFT);
-+
-+	ret = snd_ps3_map_mmio();
-+	if (ret)
-+		goto clean_dev_map;
-+
-+	/* setup DMA area */
-+	ps3_dma_region_init(dev, dev->d_region,
-+			    PAGE_SHIFT, /* use system page size */
-+			    0, /* dma type; not used */
-+			    NULL,
-+			    _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE));
-+	dev->d_region->ioid = PS3_AUDIO_IOID;
-+
-+	ret = ps3_dma_region_create(dev->d_region);
-+	if (ret) {
-+		pr_info("%s: region_create\n", __func__);
-+		goto clean_mmio;
-+	}
-+
-+	snd_ps3_audio_set_base_addr(dev->d_region->bus_addr);
-+
-+	/* CONFIG_SND_PS3_DEFAULT_START_DELAY */
-+	the_card.start_delay = snd_ps3_start_delay;
-+
-+	/* irq */
-+	if (snd_ps3_allocate_irq()) {
-+		ret = -ENXIO;
-+		goto clean_dma_region;
-+	}
-+
-+	/* create card instance */
-+	the_card.card = snd_card_new(index, id, THIS_MODULE, 0);
-+	if (!the_card.card) {
-+		ret = -ENXIO;
-+		goto clean_irq;
-+	}
-+
-+	strcpy(the_card.card->driver, "PS3");
-+	strcpy(the_card.card->shortname, "PS3");
-+	strcpy(the_card.card->longname, "PS3 sound");
-+	/* create PCM devices instance */
-+	/* NOTE:this driver works assuming pcm:substream = 1:1 */
-+	ret = snd_pcm_new(the_card.card,
-+			  "SPDIF",
-+			  0, /* instance index, will be stored pcm.device*/
-+			  1, /* output substream */
-+			  0, /* input substream */
-+			  &(the_card.pcm));
-+	if (ret)
-+		goto clean_card;
-+
-+	the_card.pcm->private_data = &the_card;
-+	strcpy(the_card.pcm->name, "SPDIF");
-+
-+	/* set pcm ops */
-+	snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+			&snd_ps3_pcm_spdif_ops);
-+
-+	the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED;
-+	/* pre-alloc PCM DMA buffer*/
-+	ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm,
-+					SNDRV_DMA_TYPE_DEV,
-+					&dev->core,
-+					SND_PS3_PCM_PREALLOC_SIZE,
-+					SND_PS3_PCM_PREALLOC_SIZE);
-+	if (ret < 0) {
-+		pr_info("%s: prealloc failed\n", __func__);
-+		goto clean_card;
-+	}
-+
-+	/*
-+	 * allocate null buffer
-+	 * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2
-+	 * PAGE_SIZE is enogh
-+	 */
-+	if (!(the_card.null_buffer_start_vaddr =
-+	      dma_alloc_coherent(&the_card.ps3_dev->core,
-+				 PAGE_SIZE,
-+				 &the_card.null_buffer_start_dma_addr,
-+				 GFP_KERNEL))) {
-+		pr_info("%s: nullbuffer alloc failed\n", __func__);
-+		goto clean_preallocate;
-+	}
-+	pr_debug("%s: null vaddr=%p dma=%#lx\n", __func__,
-+		 the_card.null_buffer_start_vaddr,
-+		 the_card.null_buffer_start_dma_addr);
-+	/* set default sample rate/word width */
-+	snd_ps3_init_avsetting(&the_card);
-+
-+	/* register the card */
-+	ret = snd_card_register(the_card.card);
-+	if (ret < 0)
-+		goto clean_dma_map;
-+
-+	pr_info("%s started. start_delay=%dms\n",
-+		the_card.card->longname, the_card.start_delay);
-+	return 0;
-+
-+clean_dma_map:
-+	dma_free_coherent(&the_card.ps3_dev->core,
-+			  PAGE_SIZE,
-+			  the_card.null_buffer_start_vaddr,
-+			  the_card.null_buffer_start_dma_addr);
-+clean_preallocate:
-+	snd_pcm_lib_preallocate_free_for_all(the_card.pcm);
-+clean_card:
-+	snd_card_free(the_card.card);
-+clean_irq:
-+	snd_ps3_free_irq();
-+clean_dma_region:
-+	ps3_dma_region_free(dev->d_region);
-+clean_mmio:
-+	snd_ps3_unmap_mmio();
-+clean_dev_map:
-+	lv1_gpu_device_unmap(2);
-+clean_open:
-+	ps3_close_hv_device(dev);
-+	/*
-+	 * there is no destructor function to pcm.
-+	 * midlayer automatically releases if the card removed
-+	 */
-+	return ret;
-+}; /* snd_ps3_probe */
-+
-+/* called when module removal */
-+static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev)
-+{
-+	int ret;
-+	pr_info("%s:start id=%d\n", __func__,  dev->match_id);
-+	if (dev->match_id != PS3_MATCH_ID_SOUND)
-+		return -ENXIO;
-+
-+	/*
-+	 * ctl and preallocate buffer will be freed in
-+	 * snd_card_free
-+	 */
-+	ret = snd_card_free(the_card.card);
-+	if (ret)
-+		pr_info("%s: ctl freecard=%d\n", __func__, ret);
-+
-+	dma_free_coherent(&dev->core,
-+			  PAGE_SIZE,
-+			  the_card.null_buffer_start_vaddr,
-+			  the_card.null_buffer_start_dma_addr);
-+
-+	ps3_dma_region_free(dev->d_region);
-+
-+	snd_ps3_free_irq();
-+	snd_ps3_unmap_mmio();
-+
-+	lv1_gpu_device_unmap(2);
-+	ps3_close_hv_device(dev);
-+	pr_info("%s:end id=%d\n", __func__, dev->match_id);
-+	return 0;
-+} /* snd_ps3_remove */
-+
-+static struct ps3_system_bus_driver snd_ps3_bus_driver_info = {
-+	.match_id = PS3_MATCH_ID_SOUND,
-+	.probe = snd_ps3_driver_probe,
-+	.remove = snd_ps3_driver_remove,
-+	.shutdown = snd_ps3_driver_remove,
-+	.core = {
-+		.name = SND_PS3_DRIVER_NAME,
-+		.owner = THIS_MODULE,
-+	},
-+};
-+
-+
-+/*
-+ * Interrupt handler
-+ */
-+static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id)
-+{
-+
-+	uint32_t port_intr;
-+	int underflow_occured = 0;
-+	struct snd_ps3_card_info *card = dev_id;
-+
-+	if (!card->running) {
-+		update_reg(PS3_AUDIO_AX_IS, 0);
-+		update_reg(PS3_AUDIO_INTR_0, 0);
-+		return IRQ_HANDLED;
-+	}
-+
-+	port_intr = read_reg(PS3_AUDIO_AX_IS);
-+	/*
-+	 *serial buffer empty detected (every 4 times),
-+	 *program next dma and kick it
-+	 */
-+	if (port_intr & PS3_AUDIO_AX_IE_ASOBEIE(0)) {
-+		write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBEIE(0));
-+		if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) {
-+			write_reg(PS3_AUDIO_AX_IS, port_intr);
-+			underflow_occured = 1;
-+		}
-+		if (card->silent) {
-+			/* we are still in silent time */
-+			snd_ps3_program_dma(card,
-+				(underflow_occured) ?
-+				SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL :
-+				SND_PS3_DMA_FILLTYPE_SILENT_RUNNING);
-+			snd_ps3_kick_dma(card);
-+			card->silent --;
-+		} else {
-+			snd_ps3_program_dma(card,
-+				(underflow_occured) ?
-+				SND_PS3_DMA_FILLTYPE_FIRSTFILL :
-+				SND_PS3_DMA_FILLTYPE_RUNNING);
-+			snd_ps3_kick_dma(card);
-+			snd_pcm_period_elapsed(card->substream);
-+		}
-+	} else if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) {
-+		write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBUIE(0));
-+		/*
-+		 * serial out underflow, but buffer empty not detected.
-+		 * in this case, fill fifo with 0 to recover.  After
-+		 * filling dummy data, serial automatically start to
-+		 * consume them and then will generate normal buffer
-+		 * empty interrupts.
-+		 * If both buffer underflow and buffer empty are occured,
-+		 * it is better to do nomal data transfer than empty one
-+		 */
-+		snd_ps3_program_dma(card,
-+				    SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
-+		snd_ps3_kick_dma(card);
-+		snd_ps3_program_dma(card,
-+				    SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
-+		snd_ps3_kick_dma(card);
-+	}
-+	/* clear interrupt cause */
-+	return IRQ_HANDLED;
-+};
-+
-+/*
-+ * module/subsystem initialize/terminate
-+ */
-+static int __init snd_ps3_init(void)
-+{
-+	int ret;
-+
-+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
-+		return -ENXIO;
-+
-+	memset(&the_card, 0, sizeof(the_card));
-+	spin_lock_init(&the_card.dma_lock);
-+
-+	/* register systembus DRIVER, this calls our probe() func */
-+	ret = ps3_system_bus_driver_register(&snd_ps3_bus_driver_info);
-+
-+	return ret;
-+}
-+
-+static void __exit snd_ps3_exit(void)
-+{
-+	ps3_system_bus_driver_unregister(&snd_ps3_bus_driver_info);
-+}
-+
-+MODULE_ALIAS(PS3_MODULE_ALIAS_SOUND);
---- /dev/null
-+++ linux-2.6.22.1/sound/ppc/snd_ps3.h
-@@ -0,0 +1,135 @@
-+/*
-+ * Audio support for PS3
-+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
-+ * All rights reserved.
-+ * Copyright 2006, 2007 Sony Corporation
-+ *
-+ * 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; version 2 of the Licence.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ */
-+
-+#if !defined(_SND_PS3_H_)
-+#define _SND_PS3_H_
-+
-+#include <linux/irqreturn.h>
-+
-+#define SND_PS3_DRIVER_NAME "snd_ps3"
-+
-+enum snd_ps3_out_channel {
-+	SND_PS3_OUT_SPDIF_0,
-+	SND_PS3_OUT_SPDIF_1,
-+	SND_PS3_OUT_SERIAL_0,
-+	SND_PS3_OUT_DEVS
-+};
-+
-+enum snd_ps3_dma_filltype {
-+	SND_PS3_DMA_FILLTYPE_FIRSTFILL,
-+	SND_PS3_DMA_FILLTYPE_RUNNING,
-+	SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL,
-+	SND_PS3_DMA_FILLTYPE_SILENT_RUNNING
-+};
-+
-+enum snd_ps3_ch {
-+	SND_PS3_CH_L = 0,
-+	SND_PS3_CH_R = 1,
-+	SND_PS3_CH_MAX = 2
-+};
-+
-+struct snd_ps3_avsetting_info {
-+	uint32_t avs_audio_ch;     /* fixed */
-+	uint32_t avs_audio_rate;
-+	uint32_t avs_audio_width;
-+	uint32_t avs_audio_format; /* fixed */
-+	uint32_t avs_audio_source; /* fixed */
-+};
-+/*
-+ * PS3 audio 'card' instance
-+ * there should be only ONE hardware.
-+ */
-+struct snd_ps3_card_info {
-+	struct ps3_system_bus_device *ps3_dev;
-+	struct snd_card *card;
-+
-+	struct snd_pcm *pcm;
-+	struct snd_pcm_substream *substream;
-+
-+	/* hvc info */
-+	u64 audio_lpar_addr;
-+	u64 audio_lpar_size;
-+
-+	/* registers */
-+	void __iomem *mapped_mmio_vaddr;
-+
-+	/* irq */
-+	u64 audio_irq_outlet;
-+	unsigned int irq_no;
-+
-+	/* remember avsetting */
-+	struct snd_ps3_avsetting_info avs;
-+
-+	/* dma buffer management */
-+	spinlock_t dma_lock;
-+		/* dma_lock start */
-+		void * dma_start_vaddr[2]; /* 0 for L, 1 for R */
-+		dma_addr_t dma_start_bus_addr[2];
-+		size_t dma_buffer_size;
-+		void * dma_last_transfer_vaddr[2];
-+		void * dma_next_transfer_vaddr[2];
-+		int    silent;
-+		/* dma_lock end */
-+
-+	int running;
-+
-+	/* null buffer */
-+	void *null_buffer_start_vaddr;
-+	dma_addr_t null_buffer_start_dma_addr;
-+
-+	/* start delay */
-+	unsigned int start_delay;
-+
-+};
-+
-+
-+/* PS3 audio DMAC block size in bytes */
-+#define PS3_AUDIO_DMAC_BLOCK_SIZE (128)
-+/* one stage (stereo)  of audio FIFO in bytes */
-+#define PS3_AUDIO_FIFO_STAGE_SIZE (256)
-+/* how many stages the fifo have */
-+#define PS3_AUDIO_FIFO_STAGE_COUNT (8)
-+/* fifo size 128 bytes * 8 stages * stereo (2ch) */
-+#define PS3_AUDIO_FIFO_SIZE \
-+	(PS3_AUDIO_FIFO_STAGE_SIZE * PS3_AUDIO_FIFO_STAGE_COUNT)
-+
-+/* PS3 audio DMAC max block count in one dma shot = 128 (0x80) blocks*/
-+#define PS3_AUDIO_DMAC_MAX_BLOCKS  (PS3_AUDIO_DMASIZE_BLOCKS_MASK + 1)
-+
-+#define PS3_AUDIO_NORMAL_DMA_START_CH (0)
-+#define PS3_AUDIO_NORMAL_DMA_COUNT    (8)
-+#define PS3_AUDIO_NULL_DMA_START_CH \
-+	(PS3_AUDIO_NORMAL_DMA_START_CH + PS3_AUDIO_NORMAL_DMA_COUNT)
-+#define PS3_AUDIO_NULL_DMA_COUNT      (2)
-+
-+#define SND_PS3_MAX_VOL (0x0F)
-+#define SND_PS3_MIN_VOL (0x00)
-+#define SND_PS3_MIN_ATT SND_PS3_MIN_VOL
-+#define SND_PS3_MAX_ATT SND_PS3_MAX_VOL
-+
-+#define SND_PS3_PCM_PREALLOC_SIZE \
-+	(PS3_AUDIO_DMAC_BLOCK_SIZE * PS3_AUDIO_DMAC_MAX_BLOCKS * 4)
-+
-+#define SND_PS3_DMA_REGION_SIZE \
-+	(SND_PS3_PCM_PREALLOC_SIZE + PAGE_SIZE)
-+
-+#define PS3_AUDIO_IOID       (1UL)
-+
-+#endif /* _SND_PS3_H_ */
---- /dev/null
-+++ linux-2.6.22.1/sound/ppc/snd_ps3_reg.h
-@@ -0,0 +1,891 @@
-+/*
-+ * Audio support for PS3
-+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
-+ * Copyright 2006, 2007 Sony Corporation
-+ * All rights reserved.
-+ *
-+ * 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; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ */
-+
-+/*
-+ * interrupt / configure registers
-+ */
-+
-+#define PS3_AUDIO_INTR_0                 (0x00000100)
-+#define PS3_AUDIO_INTR_EN_0              (0x00000140)
-+#define PS3_AUDIO_CONFIG                 (0x00000200)
-+
-+/*
-+ * DMAC registers
-+ * n:0..9
-+ */
-+#define PS3_AUDIO_DMAC_REGBASE(x)         (0x0000210 + 0x20 * (x))
-+
-+#define PS3_AUDIO_KICK(n)                 (PS3_AUDIO_DMAC_REGBASE(n) + 0x00)
-+#define PS3_AUDIO_SOURCE(n)               (PS3_AUDIO_DMAC_REGBASE(n) + 0x04)
-+#define PS3_AUDIO_DEST(n)                 (PS3_AUDIO_DMAC_REGBASE(n) + 0x08)
-+#define PS3_AUDIO_DMASIZE(n)              (PS3_AUDIO_DMAC_REGBASE(n) + 0x0C)
-+
-+/*
-+ * mute control
-+ */
-+#define PS3_AUDIO_AX_MCTRL                (0x00004000)
-+#define PS3_AUDIO_AX_ISBP                 (0x00004004)
-+#define PS3_AUDIO_AX_AOBP                 (0x00004008)
-+#define PS3_AUDIO_AX_IC                   (0x00004010)
-+#define PS3_AUDIO_AX_IE                   (0x00004014)
-+#define PS3_AUDIO_AX_IS                   (0x00004018)
-+
-+/*
-+ * three wire serial
-+ * n:0..3
-+ */
-+#define PS3_AUDIO_AO_MCTRL                (0x00006000)
-+#define PS3_AUDIO_AO_3WMCTRL              (0x00006004)
-+
-+#define PS3_AUDIO_AO_3WCTRL(n)            (0x00006200 + 0x200 * (n))
-+
-+/*
-+ * S/PDIF
-+ * n:0..1
-+ * x:0..11
-+ * y:0..5
-+ */
-+#define PS3_AUDIO_AO_SPD_REGBASE(n)       (0x00007200 + 0x200 * (n))
-+
-+#define PS3_AUDIO_AO_SPDCTRL(n) \
-+	(PS3_AUDIO_AO_SPD_REGBASE(n) + 0x00)
-+#define PS3_AUDIO_AO_SPDUB(n, x) \
-+	(PS3_AUDIO_AO_SPD_REGBASE(n) + 0x04 + 0x04 * (x))
-+#define PS3_AUDIO_AO_SPDCS(n, y) \
-+	(PS3_AUDIO_AO_SPD_REGBASE(n) + 0x34 + 0x04 * (y))
-+
-+
-+/*
-+  PS3_AUDIO_INTR_0 register tells an interrupt handler which audio
-+  DMA channel triggered the interrupt.  The interrupt status for a channel
-+  can be cleared by writing a '1' to the corresponding bit.  A new interrupt
-+  cannot be generated until the previous interrupt has been cleared.
-+
-+  Note that the status reported by PS3_AUDIO_INTR_0 is independent of the
-+  value of PS3_AUDIO_INTR_EN_0.
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+#define PS3_AUDIO_INTR_0_CHAN(n)	(1 << ((n) * 2))
-+#define PS3_AUDIO_INTR_0_CHAN9     PS3_AUDIO_INTR_0_CHAN(9)
-+#define PS3_AUDIO_INTR_0_CHAN8     PS3_AUDIO_INTR_0_CHAN(8)
-+#define PS3_AUDIO_INTR_0_CHAN7     PS3_AUDIO_INTR_0_CHAN(7)
-+#define PS3_AUDIO_INTR_0_CHAN6     PS3_AUDIO_INTR_0_CHAN(6)
-+#define PS3_AUDIO_INTR_0_CHAN5     PS3_AUDIO_INTR_0_CHAN(5)
-+#define PS3_AUDIO_INTR_0_CHAN4     PS3_AUDIO_INTR_0_CHAN(4)
-+#define PS3_AUDIO_INTR_0_CHAN3     PS3_AUDIO_INTR_0_CHAN(3)
-+#define PS3_AUDIO_INTR_0_CHAN2     PS3_AUDIO_INTR_0_CHAN(2)
-+#define PS3_AUDIO_INTR_0_CHAN1     PS3_AUDIO_INTR_0_CHAN(1)
-+#define PS3_AUDIO_INTR_0_CHAN0     PS3_AUDIO_INTR_0_CHAN(0)
-+
-+/*
-+  The PS3_AUDIO_INTR_EN_0 register specifies which DMA channels can generate
-+  an interrupt to the PU.  Each bit of PS3_AUDIO_INTR_EN_0 is ANDed with the
-+  corresponding bit in PS3_AUDIO_INTR_0.  The resulting bits are OR'd together
-+  to generate the Audio interrupt.
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_EN_0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+  Bit assignments are same as PS3_AUDIO_INTR_0
-+*/
-+
-+/*
-+  PS3_AUDIO_CONFIG
-+  31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 C|0 0 0 0 0 0 0 0| CONFIG
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+*/
-+
-+/* The CLEAR field cancels all pending transfers, and stops any running DMA
-+   transfers.  Any interrupts associated with the canceled transfers
-+   will occur as if the transfer had finished.
-+   Since this bit is designed to recover from DMA related issues
-+   which are caused by unpredictable situations, it is prefered to wait
-+   for normal DMA transfer end without using this bit.
-+*/
-+#define PS3_AUDIO_CONFIG_CLEAR          (1 << 8)  /* RWIVF */
-+
-+/*
-+  PS3_AUDIO_AX_MCTRL: Audio Port Mute Control Register
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|A|A|0 0 0 0 0 0 0|S|S|A|A|A|A| AX_MCTRL
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+/* 3 Wire Audio Serial Output Channel Mutes (0..3)  */
-+#define PS3_AUDIO_AX_MCTRL_ASOMT(n)     (1 << (3 - (n)))  /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_ASO3MT       (1 << 0)          /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_ASO2MT       (1 << 1)          /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_ASO1MT       (1 << 2)          /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_ASO0MT       (1 << 3)          /* RWIVF */
-+
-+/* S/PDIF mutes (0,1)*/
-+#define PS3_AUDIO_AX_MCTRL_SPOMT(n)     (1 << (5 - (n)))  /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_SPO1MT       (1 << 4)          /* RWIVF */
-+#define PS3_AUDIO_AX_MCTRL_SPO0MT       (1 << 5)          /* RWIVF */
-+
-+/* All 3 Wire Serial Outputs Mute */
-+#define PS3_AUDIO_AX_MCTRL_AASOMT       (1 << 13)         /* RWIVF */
-+
-+/* All S/PDIF Mute */
-+#define PS3_AUDIO_AX_MCTRL_ASPOMT       (1 << 14)         /* RWIVF */
-+
-+/* All Audio Outputs Mute */
-+#define PS3_AUDIO_AX_MCTRL_AAOMT        (1 << 15)         /* RWIVF */
-+
-+/*
-+  S/PDIF Outputs Buffer Read/Write Pointer Register
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B|0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B| AX_ISBP
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+*/
-+/*
-+ S/PDIF Output Channel Read Buffer Numbers
-+ Buffer number is  value of field.
-+ Indicates current read access buffer ID from Audio Data
-+ Transfer controller of S/PDIF Output
-+*/
-+
-+#define PS3_AUDIO_AX_ISBP_SPOBRN_MASK(n) (0x7 << 4 * (1 - (n))) /* R-IUF */
-+#define PS3_AUDIO_AX_ISBP_SPO1BRN_MASK		(0x7 << 0) /* R-IUF */
-+#define PS3_AUDIO_AX_ISBP_SPO0BRN_MASK		(0x7 << 4) /* R-IUF */
-+
-+/*
-+S/PDIF Output Channel Buffer Write Numbers
-+Indicates current write access buffer ID from bus master.
-+*/
-+#define PS3_AUDIO_AX_ISBP_SPOBWN_MASK(n) (0x7 <<  4 * (5 - (n))) /* R-IUF */
-+#define PS3_AUDIO_AX_ISBP_SPO1BWN_MASK		(0x7 << 16) /* R-IUF */
-+#define PS3_AUDIO_AX_ISBP_SPO0BWN_MASK		(0x7 << 20) /* R-IUF */
-+
-+/*
-+  3 Wire Audio Serial Outputs Buffer Read/Write
-+  Pointer Register
-+  Buffer number is  value of field
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B|0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B| AX_AOBP
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+/*
-+3 Wire Audio Serial Output Channel Buffer Read Numbers
-+Indicates current read access buffer Id from Audio Data Transfer
-+Controller of 3 Wire Audio Serial Output Channels
-+*/
-+#define PS3_AUDIO_AX_AOBP_ASOBRN_MASK(n) (0x7 << 4 * (3 - (n))) /* R-IUF */
-+
-+#define PS3_AUDIO_AX_AOBP_ASO3BRN_MASK	(0x7 << 0) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO2BRN_MASK	(0x7 << 4) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO1BRN_MASK	(0x7 << 8) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO0BRN_MASK	(0x7 << 12) /* R-IUF */
-+
-+/*
-+3 Wire Audio Serial Output Channel Buffer Write Numbers
-+Indicates current write access buffer ID from bus master.
-+*/
-+#define PS3_AUDIO_AX_AOBP_ASOBWN_MASK(n) (0x7 << 4 * (7 - (n))) /* R-IUF */
-+
-+#define PS3_AUDIO_AX_AOBP_ASO3BWN_MASK        (0x7 << 16) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO2BWN_MASK        (0x7 << 20) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO1BWN_MASK        (0x7 << 24) /* R-IUF */
-+#define PS3_AUDIO_AX_AOBP_ASO0BWN_MASK        (0x7 << 28) /* R-IUF */
-+
-+
-+
-+/*
-+Audio Port Interrupt Condition Register
-+For the fields in this register, the following values apply:
-+0 = Interrupt is generated every interrupt event.
-+1 = Interrupt is generated every 2 interrupt events.
-+2 = Interrupt is generated every 4 interrupt events.
-+3 = Reserved
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0|0 0|SPO|0 0|SPO|0 0|AAS|0 0 0 0 0 0 0 0 0 0 0 0| AX_IC
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+/*
-+All 3-Wire Audio Serial Outputs Interrupt Mode
-+Configures the Interrupt and Signal Notification
-+condition of all 3-wire Audio Serial Outputs.
-+*/
-+#define PS3_AUDIO_AX_IC_AASOIMD_MASK          (0x3 << 12) /* RWIVF */
-+#define PS3_AUDIO_AX_IC_AASOIMD_EVERY1        (0x0 << 12) /* RWI-V */
-+#define PS3_AUDIO_AX_IC_AASOIMD_EVERY2        (0x1 << 12) /* RW--V */
-+#define PS3_AUDIO_AX_IC_AASOIMD_EVERY4        (0x2 << 12) /* RW--V */
-+
-+/*
-+S/PDIF Output Channel Interrupt Modes
-+Configures the Interrupt and signal Notification
-+conditions of S/PDIF output channels.
-+*/
-+#define PS3_AUDIO_AX_IC_SPO1IMD_MASK          (0x3 << 16) /* RWIVF */
-+#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY1        (0x0 << 16) /* RWI-V */
-+#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY2        (0x1 << 16) /* RW--V */
-+#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY4        (0x2 << 16) /* RW--V */
-+
-+#define PS3_AUDIO_AX_IC_SPO0IMD_MASK          (0x3 << 20) /* RWIVF */
-+#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY1        (0x0 << 20) /* RWI-V */
-+#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY2        (0x1 << 20) /* RW--V */
-+#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY4        (0x2 << 20) /* RW--V */
-+
-+/*
-+Audio Port interrupt Enable Register
-+Configures whether to enable or disable each Interrupt Generation.
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IE
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+*/
-+
-+/*
-+3 Wire Audio Serial Output Channel Buffer Underflow
-+Interrupt Enables
-+Select enable/disable of Buffer Underflow Interrupts for
-+3-Wire Audio Serial Output Channels
-+DISABLED=Interrupt generation disabled.
-+*/
-+#define PS3_AUDIO_AX_IE_ASOBUIE(n)      (1 << (3 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO3BUIE        (1 << 0) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO2BUIE        (1 << 1) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO1BUIE        (1 << 2) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO0BUIE        (1 << 3) /* RWIVF */
-+
-+/* S/PDIF Output Channel Buffer Underflow Interrupt Enables */
-+
-+#define PS3_AUDIO_AX_IE_SPOBUIE(n)      (1 << (7 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO1BUIE        (1 << 6) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO0BUIE        (1 << 7) /* RWIVF */
-+
-+/* S/PDIF Output Channel One Block Transfer Completion Interrupt Enables */
-+
-+#define PS3_AUDIO_AX_IE_SPOBTCIE(n)     (1 << (11 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO1BTCIE       (1 << 10) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO0BTCIE       (1 << 11) /* RWIVF */
-+
-+/* 3-Wire Audio Serial Output Channel Buffer Empty Interrupt Enables */
-+
-+#define PS3_AUDIO_AX_IE_ASOBEIE(n)      (1 << (19 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO3BEIE        (1 << 16) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO2BEIE        (1 << 17) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO1BEIE        (1 << 18) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_ASO0BEIE        (1 << 19) /* RWIVF */
-+
-+/* S/PDIF Output Channel Buffer Empty Interrupt Enables */
-+
-+#define PS3_AUDIO_AX_IE_SPOBEIE(n)      (1 << (23 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO1BEIE        (1 << 22) /* RWIVF */
-+#define PS3_AUDIO_AX_IE_SPO0BEIE        (1 << 23) /* RWIVF */
-+
-+/*
-+Audio Port Interrupt Status Register
-+Indicates Interrupt status, which interrupt has occured, and can clear
-+each interrupt in this register.
-+Writing 1b to a field containing 1b clears field and de-asserts interrupt.
-+Writing 0b to a field has no effect.
-+Field vaules are the following:
-+0 - Interrupt hasn't occured.
-+1 - Interrupt has occured.
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IS
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+ Bit assignment are same as AX_IE
-+*/
-+
-+/*
-+Audio Output Master Control Register
-+Configures Master Clock and other master Audio Output Settings
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0|SCKSE|0|SCKSE|  MR0  |  MR1  |MCL|MCL|0 0 0 0|0 0 0 0 0 0 0 0| AO_MCTRL
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+/*
-+MCLK Output Control
-+Controls mclko[1] output.
-+0 - Disable output (fixed at High)
-+1 - Output clock produced by clock selected
-+with scksel1 by mr1
-+2 - Reserved
-+3 - Reserved
-+*/
-+
-+#define PS3_AUDIO_AO_MCTRL_MCLKC1_MASK		(0x3 << 12) /* RWIVF */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC1_DISABLED	(0x0 << 12) /* RWI-V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC1_ENABLED	(0x1 << 12) /* RW--V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD2	(0x2 << 12) /* RW--V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD3	(0x3 << 12) /* RW--V */
-+
-+/*
-+MCLK Output Control
-+Controls mclko[0] output.
-+0 - Disable output (fixed at High)
-+1 - Output clock produced by clock selected
-+with SCKSEL0 by MR0
-+2 - Reserved
-+3 - Reserved
-+*/
-+#define PS3_AUDIO_AO_MCTRL_MCLKC0_MASK		(0x3 << 14) /* RWIVF */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC0_DISABLED	(0x0 << 14) /* RWI-V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC0_ENABLED	(0x1 << 14) /* RW--V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD2	(0x2 << 14) /* RW--V */
-+#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD3	(0x3 << 14) /* RW--V */
-+/*
-+Master Clock Rate 1
-+Sets the divide ration of Master Clock1 (clock output from
-+mclko[1] for the input clock selected by scksel1.
-+*/
-+#define PS3_AUDIO_AO_MCTRL_MR1_MASK	(0xf << 16)
-+#define PS3_AUDIO_AO_MCTRL_MR1_DEFAULT	(0x0 << 16) /* RWI-V */
-+/*
-+Master Clock Rate 0
-+Sets the divide ratio of Master Clock0 (clock output from
-+mclko[0] for the input clock selected by scksel0).
-+*/
-+#define PS3_AUDIO_AO_MCTRL_MR0_MASK	(0xf << 20) /* RWIVF */
-+#define PS3_AUDIO_AO_MCTRL_MR0_DEFAULT	(0x0 << 20) /* RWI-V */
-+/*
-+System Clock Select 0/1
-+Selects the system clock to be used as Master Clock 0/1
-+Input the system clock that is appropriate for the sampling
-+rate.
-+*/
-+#define PS3_AUDIO_AO_MCTRL_SCKSEL1_MASK		(0x7 << 24) /* RWIVF */
-+#define PS3_AUDIO_AO_MCTRL_SCKSEL1_DEFAULT	(0x2 << 24) /* RWI-V */
-+
-+#define PS3_AUDIO_AO_MCTRL_SCKSEL0_MASK		(0x7 << 28) /* RWIVF */
-+#define PS3_AUDIO_AO_MCTRL_SCKSEL0_DEFAULT	(0x2 << 28) /* RWI-V */
-+
-+
-+/*
-+3-Wire Audio Output Master Control Register
-+Configures clock, 3-Wire Audio Serial Output Enable, and
-+other 3-Wire Audio Serial Output Master Settings
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |A|A|A|A|0 0 0|A| ASOSR |0 0 0 0|A|A|A|A|A|A|0|1|0 0 0 0 0 0 0 0| AO_3WMCTRL
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+
-+/*
-+LRCKO Polarity
-+0 - Reserved
-+1 - default
-+*/
-+#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK 		(1 << 8) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT	(1 << 8) /* RW--V */
-+
-+/* LRCK Output Disable */
-+
-+#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD		(1 << 10) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_ENABLED	(0 << 10) /* RW--V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED	(1 << 10) /* RWI-V */
-+
-+/* Bit Clock Output Disable */
-+
-+#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD		(1 << 11) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_ENABLED	(0 << 11) /* RW--V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED	(1 << 11) /* RWI-V */
-+
-+/*
-+3-Wire Audio Serial Output Channel 0-3 Operational
-+Status.  Each bit becomes 1 after each 3-Wire Audio
-+Serial Output Channel N is in action by setting 1 to
-+asoen.
-+Each bit becomes 0 after each 3-Wire Audio Serial Output
-+Channel N is out of action by setting 0 to asoen.
-+*/
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN(n)		(1 << (15 - (n))) /* R-IVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(n)	(0 << (15 - (n))) /* R-I-V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(n)	(1 << (15 - (n))) /* R---V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN0		\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN(0)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_STOPPED	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(0)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_RUNNING	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(0)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN1		\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN(1)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_STOPPED	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(1)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_RUNNING	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(1)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN2		\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN(2)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_STOPPED	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(2)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_RUNNING	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(2)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN3		\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN(3)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_STOPPED	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(3)
-+#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_RUNNING	\
-+	PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(3)
-+
-+/*
-+Sampling Rate
-+Specifies the divide ratio of the bit clock (clock output
-+from bclko) used by the 3-wire Audio Output Clock, whcih
-+is applied to the master clock selected by mcksel.
-+Data output is synchronized with this clock.
-+*/
-+#define PS3_AUDIO_AO_3WMCTRL_ASOSR_MASK		(0xf << 20) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV2		(0x1 << 20) /* RWI-V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV4		(0x2 << 20) /* RW--V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV8		(0x4 << 20) /* RW--V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV12	(0x6 << 20) /* RW--V */
-+
-+/*
-+Master Clock Select
-+0 - Master Clock 0
-+1 - Master Clock 1
-+*/
-+#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL		(1 << 24) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK0	(0 << 24) /* RWI-V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK1	(1 << 24) /* RW--V */
-+
-+/*
-+Enables and disables 4ch 3-Wire Audio Serial Output
-+operation.  Each Bit from 0 to 3 corresponds to an
-+output channel, which means that each output channel
-+can be enabled or disabled individually.  When
-+multiple channels are enabled at the same time, output
-+operations are performed in synchronization.
-+Bit 0 - Output Channel 0 (SDOUT[0])
-+Bit 1 - Output Channel 1 (SDOUT[1])
-+Bit 2 - Output Channel 2 (SDOUT[2])
-+Bit 3 - Output Channel 3 (SDOUT[3])
-+*/
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN(n)		(1 << (31 - (n))) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(n)	(0 << (31 - (n))) /* RWI-V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(n)	(1 << (31 - (n))) /* RW--V */
-+
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN0 \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN(0) /* RWIVF */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_DISABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(0) /* RWI-V */
-+#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_ENABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(0) /* RW--V */
-+#define PS3_AUDIO_A1_3WMCTRL_ASOEN0 \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN(1) /* RWIVF */
-+#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_DISABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(1) /* RWI-V */
-+#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_ENABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(1) /* RW--V */
-+#define PS3_AUDIO_A2_3WMCTRL_ASOEN0 \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN(2) /* RWIVF */
-+#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_DISABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(2) /* RWI-V */
-+#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_ENABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(2) /* RW--V */
-+#define PS3_AUDIO_A3_3WMCTRL_ASOEN0 \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN(3) /* RWIVF */
-+#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_DISABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(3) /* RWI-V */
-+#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_ENABLED \
-+	PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(3) /* RW--V */
-+
-+/*
-+3-Wire Audio Serial output Channel 0-3 Control Register
-+Configures settings for 3-Wire Serial Audio Output Channel 0-3
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|0 0 0 0|A|0|ASO|0 0 0|0|0|0|0|0| AO_3WCTRL
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+*/
-+/*
-+Data Bit Mode
-+Specifies the number of data bits
-+0 - 16 bits
-+1 - reserved
-+2 - 20 bits
-+3 - 24 bits
-+*/
-+#define PS3_AUDIO_AO_3WCTRL_ASODB_MASK	(0x3 << 8) /* RWIVF */
-+#define PS3_AUDIO_AO_3WCTRL_ASODB_16BIT	(0x0 << 8) /* RWI-V */
-+#define PS3_AUDIO_AO_3WCTRL_ASODB_RESVD	(0x1 << 8) /* RWI-V */
-+#define PS3_AUDIO_AO_3WCTRL_ASODB_20BIT	(0x2 << 8) /* RW--V */
-+#define PS3_AUDIO_AO_3WCTRL_ASODB_24BIT	(0x3 << 8) /* RW--V */
-+/*
-+Data Format Mode
-+Specifies the data format where (LSB side or MSB) the data(in 20 bit
-+or 24 bit resolution mode) is put in a 32 bit field.
-+0 - Data put on LSB side
-+1 - Data put on MSB side
-+*/
-+#define PS3_AUDIO_AO_3WCTRL_ASODF 	(1 << 11) /* RWIVF */
-+#define PS3_AUDIO_AO_3WCTRL_ASODF_LSB	(0 << 11) /* RWI-V */
-+#define PS3_AUDIO_AO_3WCTRL_ASODF_MSB	(1 << 11) /* RW--V */
-+/*
-+Buffer Reset
-+Performs buffer reset.  Writing 1 to this bit initializes the
-+corresponding 3-Wire Audio Output buffers(both L and R).
-+*/
-+#define PS3_AUDIO_AO_3WCTRL_ASOBRST 		(1 << 16) /* CWIVF */
-+#define PS3_AUDIO_AO_3WCTRL_ASOBRST_IDLE	(0 << 16) /* -WI-V */
-+#define PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET	(1 << 16) /* -W--T */
-+
-+/*
-+S/PDIF Audio Output Channel 0/1 Control Register
-+Configures settings for S/PDIF Audio Output Channel 0/1.
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |S|0 0 0|S|0 0|S| SPOSR |0 0|SPO|0 0 0 0|S|0|SPO|0 0 0 0 0 0 0|S| AO_SPDCTRL
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+/*
-+Buffer reset.  Writing 1 to this bit initializes the
-+corresponding S/PDIF output buffer pointer.
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPOBRST		(1 << 0) /* CWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_IDLE	(0 << 0) /* -WI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_RESET	(1 << 0) /* -W--T */
-+
-+/*
-+Data Bit Mode
-+Specifies number of data bits
-+0 - 16 bits
-+1 - Reserved
-+2 - 20 bits
-+3 - 24 bits
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPODB_MASK		(0x3 << 8) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODB_16BIT	(0x0 << 8) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODB_RESVD	(0x1 << 8) /* RW--V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODB_20BIT	(0x2 << 8) /* RW--V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODB_24BIT	(0x3 << 8) /* RW--V */
-+/*
-+Data format Mode
-+Specifies the data format, where (LSB side or MSB)
-+the data(in 20 or 24 bit resolution) is put in the
-+32 bit field.
-+0 - LSB Side
-+1 - MSB Side
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPODF	(1 << 11) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODF_LSB	(0 << 11) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPODF_MSB	(1 << 11) /* RW--V */
-+/*
-+Source Select
-+Specifies the source of the S/PDIF output.  When 0, output
-+operation is controlled by 3wen[0] of AO_3WMCTRL register.
-+The SR must have the same setting as the a0_3wmctrl reg.
-+0 - 3-Wire Audio OUT Ch0 Buffer
-+1 - S/PDIF buffer
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSS_MASK		(0x3 << 16) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSS_3WEN		(0x0 << 16) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSS_SPDIF	(0x1 << 16) /* RW--V */
-+/*
-+Sampling Rate
-+Specifies the divide ratio of the bit clock (clock output
-+from bclko) used by the S/PDIF Output Clock, which
-+is applied to the master clock selected by mcksel.
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSR		(0xf << 20) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV2		(0x1 << 20) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV4		(0x2 << 20) /* RW--V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV8		(0x4 << 20) /* RW--V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV12	(0x6 << 20) /* RW--V */
-+/*
-+Master Clock Select
-+0 - Master Clock 0
-+1 - Master Clock 1
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL		(1 << 24) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK0	(0 << 24) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK1	(1 << 24) /* RW--V */
-+
-+/*
-+S/PDIF Output Channel Operational Status
-+This bit becomes 1 after S/PDIF Output Channel is in
-+action by setting 1 to spoen.  This bit becomes 0
-+after S/PDIF Output Channel is out of action by setting
-+0 to spoen.
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPORUN		(1 << 27) /* R-IVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPORUN_STOPPED	(0 << 27) /* R-I-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPORUN_RUNNING	(1 << 27) /* R---V */
-+
-+/*
-+S/PDIF Audio Output Channel Output Enable
-+Enables and disables output operation.  This bit is used
-+only when sposs = 1
-+*/
-+#define PS3_AUDIO_AO_SPDCTRL_SPOEN		(1 << 31) /* RWIVF */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOEN_DISABLED	(0 << 31) /* RWI-V */
-+#define PS3_AUDIO_AO_SPDCTRL_SPOEN_ENABLED	(1 << 31) /* RW--V */
-+
-+/*
-+S/PDIF Audio Output Channel Channel Status
-+Setting Registers.
-+Configures channel status bit settings for each block
-+(192 bits).
-+Output is performed from the MSB(AO_SPDCS0 register bit 31).
-+The same value is added for subframes within the same frame.
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |                             SPOCS                             | AO_SPDCS
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+
-+S/PDIF Audio Output Channel User Bit Setting
-+Configures user bit settings for each block (384 bits).
-+Output is performed from the MSB(ao_spdub0 register bit 31).
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |                             SPOUB                             | AO_SPDUB
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+/*****************************************************************************
-+ *
-+ * DMAC register
-+ *
-+ *****************************************************************************/
-+/*
-+The PS3_AUDIO_KICK register is used to initiate a DMA transfer and monitor
-+its status
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0|STATU|0 0 0|  EVENT  |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|R| KICK
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+/*
-+The REQUEST field is written to ACTIVE to initiate a DMA request when EVENT
-+occurs.
-+It will return to the DONE state when the request is completed.
-+The registers for a DMA channel should only be written if REQUEST is IDLE.
-+*/
-+
-+#define PS3_AUDIO_KICK_REQUEST                (1 << 0) /* RWIVF */
-+#define PS3_AUDIO_KICK_REQUEST_IDLE           (0 << 0) /* RWI-V */
-+#define PS3_AUDIO_KICK_REQUEST_ACTIVE         (1 << 0) /* -W--T */
-+
-+/*
-+ *The EVENT field is used to set the event in which
-+ *the DMA request becomes active.
-+ */
-+#define PS3_AUDIO_KICK_EVENT_MASK             (0x1f << 16) /* RWIVF */
-+#define PS3_AUDIO_KICK_EVENT_ALWAYS           (0x00 << 16) /* RWI-V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY (0x01 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_UNDERFLOW	(0x02 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_EMPTY		(0x03 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_UNDERFLOW	(0x04 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_EMPTY		(0x05 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_UNDERFLOW	(0x06 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_EMPTY		(0x07 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_UNDERFLOW	(0x08 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF0_BLOCKTRANSFERCOMPLETE \
-+	(0x09 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF0_UNDERFLOW		(0x0A << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF0_EMPTY		(0x0B << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF1_BLOCKTRANSFERCOMPLETE \
-+	(0x0C << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF1_UNDERFLOW		(0x0D << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_SPDIF1_EMPTY		(0x0E << 16) /* RW--V */
-+
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA(n) \
-+	((0x13 + (n)) << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA0         (0x13 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA1         (0x14 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA2         (0x15 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA3         (0x16 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA4         (0x17 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA5         (0x18 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA6         (0x19 << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA7         (0x1A << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA8         (0x1B << 16) /* RW--V */
-+#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA9         (0x1C << 16) /* RW--V */
-+
-+/*
-+The STATUS field can be used to monitor the progress of a DMA request.
-+DONE indicates the previous request has completed.
-+EVENT indicates that the DMA engine is waiting for the EVENT to occur.
-+PENDING indicates that the DMA engine has not started processing this
-+request, but the EVENT has occured.
-+DMA indicates that the data transfer is in progress.
-+NOTIFY indicates that the notifier signalling end of transfer is being written.
-+CLEAR indicated that the previous transfer was cleared.
-+ERROR indicates the previous transfer requested an unsupported
-+source/destination combination.
-+*/
-+
-+#define PS3_AUDIO_KICK_STATUS_MASK	(0x7 << 24) /* R-IVF */
-+#define PS3_AUDIO_KICK_STATUS_DONE	(0x0 << 24) /* R-I-V */
-+#define PS3_AUDIO_KICK_STATUS_EVENT	(0x1 << 24) /* R---V */
-+#define PS3_AUDIO_KICK_STATUS_PENDING	(0x2 << 24) /* R---V */
-+#define PS3_AUDIO_KICK_STATUS_DMA	(0x3 << 24) /* R---V */
-+#define PS3_AUDIO_KICK_STATUS_NOTIFY	(0x4 << 24) /* R---V */
-+#define PS3_AUDIO_KICK_STATUS_CLEAR	(0x5 << 24) /* R---V */
-+#define PS3_AUDIO_KICK_STATUS_ERROR	(0x6 << 24) /* R---V */
-+
-+/*
-+The PS3_AUDIO_SOURCE register specifies the source address for transfers.
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |                      START                      |0 0 0 0 0|TAR| SOURCE
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+/*
-+The Audio DMA engine uses 128-byte transfers, thus the address must be aligned
-+to a 128 byte boundary.  The low seven bits are assumed to be 0.
-+*/
-+
-+#define PS3_AUDIO_SOURCE_START_MASK	(0x01FFFFFF << 7) /* RWIUF */
-+
-+/*
-+The TARGET field specifies the memory space containing the source address.
-+*/
-+
-+#define PS3_AUDIO_SOURCE_TARGET_MASK 		(3 << 0) /* RWIVF */
-+#define PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY	(2 << 0) /* RW--V */
-+
-+/*
-+The PS3_AUDIO_DEST register specifies the destination address for transfers.
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |                      START                      |0 0 0 0 0|TAR| DEST
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+/*
-+The Audio DMA engine uses 128-byte transfers, thus the address must be aligned
-+to a 128 byte boundary.  The low seven bits are assumed to be 0.
-+*/
-+
-+#define PS3_AUDIO_DEST_START_MASK	(0x01FFFFFF << 7) /* RWIUF */
-+
-+/*
-+The TARGET field specifies the memory space containing the destination address
-+AUDIOFIFO = Audio WriteData FIFO,
-+*/
-+
-+#define PS3_AUDIO_DEST_TARGET_MASK		(3 << 0) /* RWIVF */
-+#define PS3_AUDIO_DEST_TARGET_AUDIOFIFO		(1 << 0) /* RW--V */
-+
-+/*
-+PS3_AUDIO_DMASIZE specifies the number of 128-byte blocks + 1 to transfer.
-+So a value of 0 means 128-bytes will get transfered.
-+
-+
-+ 31            24 23           16 15            8 7             0
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+ |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|   BLOCKS    | DMASIZE
-+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
-+*/
-+
-+
-+#define PS3_AUDIO_DMASIZE_BLOCKS_MASK 	(0x7f << 0) /* RWIUF */
-+
-+/*
-+ * source/destination address for internal fifos
-+ */
-+#define PS3_AUDIO_AO_3W_LDATA(n)	(0x1000 + (0x100 * (n)))
-+#define PS3_AUDIO_AO_3W_RDATA(n)	(0x1080 + (0x100 * (n)))
-+
-+#define PS3_AUDIO_AO_SPD_DATA(n)	(0x2000 + (0x400 * (n)))
-+
-+
-+/*
-+ * field attiribute
-+ *
-+ *	Read
-+ *	  ' ' = Other Information
-+ *	  '-' = Field is part of a write-only register
-+ *	  'C' = Value read is always the same, constant value line follows (C)
-+ *	  'R' = Value is read
-+ *
-+ *	Write
-+ *	  ' ' = Other Information
-+ *	  '-' = Must not be written (D), value ignored when written (R,A,F)
-+ *	  'W' = Can be written
-+ *
-+ *	Internal State
-+ *	  ' ' = Other Information
-+ *	  '-' = No internal state
-+ *	  'X' = Internal state, initial value is unknown
-+ *	  'I' = Internal state, initial value is known and follows (I)
-+ *
-+ *	Declaration/Size
-+ *	  ' ' = Other Information
-+ *	  '-' = Does Not Apply
-+ *	  'V' = Type is void
-+ *	  'U' = Type is unsigned integer
-+ *	  'S' = Type is signed integer
-+ *	  'F' = Type is IEEE floating point
-+ *	  '1' = Byte size (008)
-+ *	  '2' = Short size (016)
-+ *	  '3' = Three byte size (024)
-+ *	  '4' = Word size (032)
-+ *	  '8' = Double size (064)
-+ *
-+ *	Define Indicator
-+ *	  ' ' = Other Information
-+ *	  'D' = Device
-+ *	  'M' = Memory
-+ *	  'R' = Register
-+ *	  'A' = Array of Registers
-+ *	  'F' = Field
-+ *	  'V' = Value
-+ *	  'T' = Task
-+ */
-+
---- /dev/null
-+++ linux-2.6.22.1/sound/sh/Kconfig
-@@ -0,0 +1,14 @@
-+# ALSA SH drivers
-+
-+menu "SUPERH devices"
-+	depends on SND!=n && SUPERH
-+
-+config SND_AICA
-+	tristate "Dreamcast Yamaha AICA sound"
-+	depends on SH_DREAMCAST && SND
-+	select SND_PCM
-+	help
-+	  ALSA Sound driver for the SEGA Dreamcast console.
-+
-+endmenu
-+
---- /dev/null
-+++ linux-2.6.22.1/sound/sh/Makefile
-@@ -0,0 +1,8 @@
-+#
-+# Makefile for ALSA
-+#
-+
-+snd-aica-objs := aica.o
-+
-+# Toplevel Module Dependency
-+obj-$(CONFIG_SND_AICA) += snd-aica.o
---- /dev/null
-+++ linux-2.6.22.1/sound/sh/aica.c
-@@ -0,0 +1,665 @@
-+/*
-+* This code is licenced under 
-+* the General Public Licence
-+* version 2
-+*
-+* Copyright Adrian McMenamin 2005, 2006, 2007
-+* <adrian at mcmen.demon.co.uk>
-+* Requires firmware (BSD licenced) available from:
-+* http://linuxdc.cvs.sourceforge.net/linuxdc/linux-sh-dc/sound/oss/aica/firmware/
-+* or the maintainer
-+*
-+* This program is free software; you can redistribute it and/or modify
-+* it under the terms of version 2 of the GNU General Public License as published by
-+* the Free Software Foundation.
-+*
-+* This program is distributed in the hope that it will be useful,
-+* but WITHOUT ANY WARRANTY; without even the implied warranty of
-+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+* GNU General Public License for more details.
-+*
-+* You should have received a copy of the GNU General Public License
-+* along with this program; if not, write to the Free Software
-+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+*
-+*/
-+
-+#include <linux/init.h>
-+#include <linux/jiffies.h>
-+#include <linux/slab.h>
-+#include <linux/time.h>
-+#include <linux/wait.h>
-+#include <linux/moduleparam.h>
-+#include <linux/platform_device.h>
-+#include <linux/firmware.h>
-+#include <linux/timer.h>
-+#include <linux/delay.h>
-+#include <linux/workqueue.h>
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/control.h>
-+#include <sound/pcm.h>
-+#include <sound/initval.h>
-+#include <sound/info.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/dreamcast/sysasic.h>
-+#include "aica.h"
-+
-+MODULE_AUTHOR("Adrian McMenamin <adrian at mcmen.demon.co.uk>");
-+MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver");
-+MODULE_LICENSE("GPL");
-+MODULE_SUPPORTED_DEVICE("{{Yamaha/SEGA, AICA}}");
-+
-+/* module parameters */
-+#define CARD_NAME "AICA"
-+static int index = -1;
-+static char *id;
-+static int enable = 1;
-+module_param(index, int, 0444);
-+MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-+module_param(id, charp, 0444);
-+MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-+module_param(enable, bool, 0644);
-+MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-+
-+/* Use workqueue */
-+static struct workqueue_struct *aica_queue;
-+
-+/* Simple platform device */
-+static struct platform_device *pd;
-+static struct resource aica_memory_space[2] = {
-+	{
-+	 .name = "AICA ARM CONTROL",
-+	 .start = ARM_RESET_REGISTER,
-+	 .flags = IORESOURCE_MEM,
-+	 .end = ARM_RESET_REGISTER + 3,
-+	 },
-+	{
-+	 .name = "AICA Sound RAM",
-+	 .start = SPU_MEMORY_BASE,
-+	 .flags = IORESOURCE_MEM,
-+	 .end = SPU_MEMORY_BASE + 0x200000 - 1,
-+	 },
-+};
-+
-+/* SPU specific functions */
-+/* spu_write_wait - wait for G2-SH FIFO to clear */
-+static void spu_write_wait(void)
-+{
-+	int time_count;
-+	time_count = 0;
-+	while (1) {
-+		if (!(readl(G2_FIFO) & 0x11))
-+			break;
-+		/* To ensure hardware failure doesn't wedge kernel */
-+		time_count++;
-+		if (time_count > 0x10000) {
-+			snd_printk
-+			    ("WARNING: G2 FIFO appears to be blocked.\n");
-+			break;
-+		}
-+	}
-+}
-+
-+/* spu_memset - write to memory in SPU address space */
-+static void spu_memset(u32 toi, u32 what, int length)
-+{
-+	int i;
-+	snd_assert(length % 4 == 0, return);
-+	for (i = 0; i < length; i++) {
-+		if (!(i % 8))
-+			spu_write_wait();
-+		writel(what, toi + SPU_MEMORY_BASE);
-+		toi++;
-+	}
-+}
-+
-+/* spu_memload - write to SPU address space */
-+static void spu_memload(u32 toi, void *from, int length)
-+{
-+	u32 *froml = from;
-+	u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
-+	int i;
-+	u32 val;
-+	length = DIV_ROUND_UP(length, 4);
-+	spu_write_wait();
-+	for (i = 0; i < length; i++) {
-+		if (!(i % 8))
-+			spu_write_wait();
-+		val = *froml;
-+		writel(val, to);
-+		froml++;
-+		to++;
-+	}
-+}
-+
-+/* spu_disable - set spu registers to stop sound output */
-+static void spu_disable(void)
-+{
-+	int i;
-+	u32 regval;
-+	spu_write_wait();
-+	regval = readl(ARM_RESET_REGISTER);
-+	regval |= 1;
-+	spu_write_wait();
-+	writel(regval, ARM_RESET_REGISTER);
-+	for (i = 0; i < 64; i++) {
-+		spu_write_wait();
-+		regval = readl(SPU_REGISTER_BASE + (i * 0x80));
-+		regval = (regval & ~0x4000) | 0x8000;
-+		spu_write_wait();
-+		writel(regval, SPU_REGISTER_BASE + (i * 0x80));
-+	}
-+}
-+
-+/* spu_enable - set spu registers to enable sound output */
-+static void spu_enable(void)
-+{
-+	u32 regval = readl(ARM_RESET_REGISTER);
-+	regval &= ~1;
-+	spu_write_wait();
-+	writel(regval, ARM_RESET_REGISTER);
-+}
-+
-+/* 
-+ * Halt the sound processor, clear the memory,
-+ * load some default ARM7 code, and then restart ARM7
-+*/
-+static void spu_reset(void)
-+{
-+	spu_disable();
-+	spu_memset(0, 0, 0x200000 / 4);
-+	/* Put ARM7 in endless loop */
-+	ctrl_outl(0xea000002, SPU_MEMORY_BASE);
-+	spu_enable();
-+}
-+
-+/* aica_chn_start - write to spu to start playback */
-+static void aica_chn_start(void)
-+{
-+	spu_write_wait();
-+	writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
-+}
-+
-+/* aica_chn_halt - write to spu to halt playback */
-+static void aica_chn_halt(void)
-+{
-+	spu_write_wait();
-+	writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
-+}
-+
-+/* ALSA code below */
-+static struct snd_pcm_hardware snd_pcm_aica_playback_hw = {
-+	.info = (SNDRV_PCM_INFO_NONINTERLEAVED),
-+	.formats =
-+	    (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
-+	     SNDRV_PCM_FMTBIT_IMA_ADPCM),
-+	.rates = SNDRV_PCM_RATE_8000_48000,
-+	.rate_min = 8000,
-+	.rate_max = 48000,
-+	.channels_min = 1,
-+	.channels_max = 2,
-+	.buffer_bytes_max = AICA_BUFFER_SIZE,
-+	.period_bytes_min = AICA_PERIOD_SIZE,
-+	.period_bytes_max = AICA_PERIOD_SIZE,
-+	.periods_min = AICA_PERIOD_NUMBER,
-+	.periods_max = AICA_PERIOD_NUMBER,
-+};
-+
-+static int aica_dma_transfer(int channels, int buffer_size,
-+			     struct snd_pcm_substream *substream)
-+{
-+	int q, err, period_offset;
-+	struct snd_card_aica *dreamcastcard;
-+	struct snd_pcm_runtime *runtime;
-+	err = 0;
-+	dreamcastcard = substream->pcm->private_data;
-+	period_offset = dreamcastcard->clicks;
-+	period_offset %= (AICA_PERIOD_NUMBER / channels);
-+	runtime = substream->runtime;
-+	for (q = 0; q < channels; q++) {
-+		err = dma_xfer(AICA_DMA_CHANNEL,
-+			       (unsigned long) (runtime->dma_area +
-+						(AICA_BUFFER_SIZE * q) /
-+						channels +
-+						AICA_PERIOD_SIZE *
-+						period_offset),
-+			       AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
-+			       AICA_PERIOD_SIZE * period_offset,
-+			       buffer_size / channels, AICA_DMA_MODE);
-+		if (unlikely(err < 0))
-+			break;
-+		dma_wait_for_completion(AICA_DMA_CHANNEL);
-+	}
-+	return err;
-+}
-+
-+static void startup_aica(struct snd_card_aica *dreamcastcard)
-+{
-+	spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
-+		    dreamcastcard->channel, sizeof(struct aica_channel));
-+	aica_chn_start();
-+}
-+
-+static void run_spu_dma(struct work_struct *work)
-+{
-+	int buffer_size;
-+	struct snd_pcm_runtime *runtime;
-+	struct snd_card_aica *dreamcastcard;
-+	dreamcastcard =
-+	    container_of(work, struct snd_card_aica, spu_dma_work);
-+	runtime = dreamcastcard->substream->runtime;
-+	if (unlikely(dreamcastcard->dma_check == 0)) {
-+		buffer_size =
-+		    frames_to_bytes(runtime, runtime->buffer_size);
-+		if (runtime->channels > 1)
-+			dreamcastcard->channel->flags |= 0x01;
-+		aica_dma_transfer(runtime->channels, buffer_size,
-+				  dreamcastcard->substream);
-+		startup_aica(dreamcastcard);
-+		dreamcastcard->clicks =
-+		    buffer_size / (AICA_PERIOD_SIZE * runtime->channels);
-+		return;
-+	} else {
-+		aica_dma_transfer(runtime->channels,
-+				  AICA_PERIOD_SIZE * runtime->channels,
-+				  dreamcastcard->substream);
-+		snd_pcm_period_elapsed(dreamcastcard->substream);
-+		dreamcastcard->clicks++;
-+		if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER))
-+			dreamcastcard->clicks %= AICA_PERIOD_NUMBER;
-+		mod_timer(&dreamcastcard->timer, jiffies + 1);
-+	}
-+}
-+
-+static void aica_period_elapsed(unsigned long timer_var)
-+{
-+	/*timer function - so cannot sleep */
-+	int play_period;
-+	struct snd_pcm_runtime *runtime;
-+	struct snd_pcm_substream *substream;
-+	struct snd_card_aica *dreamcastcard;
-+	substream = (struct snd_pcm_substream *) timer_var;
-+	runtime = substream->runtime;
-+	dreamcastcard = substream->pcm->private_data;
-+	/* Have we played out an additional period? */
-+	play_period =
-+	    frames_to_bytes(runtime,
-+			    readl
-+			    (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) /
-+	    AICA_PERIOD_SIZE;
-+	if (play_period == dreamcastcard->current_period) {
-+		/* reschedule the timer */
-+		mod_timer(&(dreamcastcard->timer), jiffies + 1);
-+		return;
-+	}
-+	if (runtime->channels > 1)
-+		dreamcastcard->current_period = play_period;
-+	if (unlikely(dreamcastcard->dma_check == 0))
-+		dreamcastcard->dma_check = 1;
-+	queue_work(aica_queue, &(dreamcastcard->spu_dma_work));
-+}
-+
-+static void spu_begin_dma(struct snd_pcm_substream *substream)
-+{
-+	struct snd_card_aica *dreamcastcard;
-+	struct snd_pcm_runtime *runtime;
-+	runtime = substream->runtime;
-+	dreamcastcard = substream->pcm->private_data;
-+	/*get the queue to do the work */
-+	queue_work(aica_queue, &(dreamcastcard->spu_dma_work));
-+	/* Timer may already be running */
-+	if (unlikely(dreamcastcard->timer.data)) {
-+		mod_timer(&dreamcastcard->timer, jiffies + 4);
-+		return;
-+	}
-+	init_timer(&(dreamcastcard->timer));
-+	dreamcastcard->timer.data = (unsigned long) substream;
-+	dreamcastcard->timer.function = aica_period_elapsed;
-+	dreamcastcard->timer.expires = jiffies + 4;
-+	add_timer(&(dreamcastcard->timer));
-+}
-+
-+static int snd_aicapcm_pcm_open(struct snd_pcm_substream
-+				*substream)
-+{
-+	struct snd_pcm_runtime *runtime;
-+	struct aica_channel *channel;
-+	struct snd_card_aica *dreamcastcard;
-+	if (!enable)
-+		return -ENOENT;
-+	dreamcastcard = substream->pcm->private_data;
-+	channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL);
-+	if (!channel)
-+		return -ENOMEM;
-+	/* set defaults for channel */
-+	channel->sfmt = SM_8BIT;
-+	channel->cmd = AICA_CMD_START;
-+	channel->vol = dreamcastcard->master_volume;
-+	channel->pan = 0x80;
-+	channel->pos = 0;
-+	channel->flags = 0;	/* default to mono */
-+	dreamcastcard->channel = channel;
-+	runtime = substream->runtime;
-+	runtime->hw = snd_pcm_aica_playback_hw;
-+	spu_enable();
-+	dreamcastcard->clicks = 0;
-+	dreamcastcard->current_period = 0;
-+	dreamcastcard->dma_check = 0;
-+	return 0;
-+}
-+
-+static int snd_aicapcm_pcm_close(struct snd_pcm_substream
-+				 *substream)
-+{
-+	struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
-+	flush_workqueue(aica_queue);
-+	if (dreamcastcard->timer.data)
-+		del_timer(&dreamcastcard->timer);
-+	kfree(dreamcastcard->channel);
-+	spu_disable();
-+	return 0;
-+}
-+
-+static int snd_aicapcm_pcm_hw_free(struct snd_pcm_substream
-+				   *substream)
-+{
-+	/* Free the DMA buffer */
-+	return snd_pcm_lib_free_pages(substream);
-+}
-+
-+static int snd_aicapcm_pcm_hw_params(struct snd_pcm_substream
-+				     *substream, struct snd_pcm_hw_params
-+				     *hw_params)
-+{
-+	/* Allocate a DMA buffer using ALSA built-ins */
-+	return
-+	    snd_pcm_lib_malloc_pages(substream,
-+				     params_buffer_bytes(hw_params));
-+}
-+
-+static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream
-+				   *substream)
-+{
-+	struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
-+	if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE)
-+		dreamcastcard->channel->sfmt = SM_16BIT;
-+	dreamcastcard->channel->freq = substream->runtime->rate;
-+	dreamcastcard->substream = substream;
-+	return 0;
-+}
-+
-+static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream
-+				   *substream, int cmd)
-+{
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		spu_begin_dma(substream);
-+		break;
-+	case SNDRV_PCM_TRIGGER_STOP:
-+		aica_chn_halt();
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+	return 0;
-+}
-+
-+static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream
-+					     *substream)
-+{
-+	return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER);
-+}
-+
-+static struct snd_pcm_ops snd_aicapcm_playback_ops = {
-+	.open = snd_aicapcm_pcm_open,
-+	.close = snd_aicapcm_pcm_close,
-+	.ioctl = snd_pcm_lib_ioctl,
-+	.hw_params = snd_aicapcm_pcm_hw_params,
-+	.hw_free = snd_aicapcm_pcm_hw_free,
-+	.prepare = snd_aicapcm_pcm_prepare,
-+	.trigger = snd_aicapcm_pcm_trigger,
-+	.pointer = snd_aicapcm_pcm_pointer,
-+};
-+
-+/* TO DO: set up to handle more than one pcm instance */
-+static int __init snd_aicapcmchip(struct snd_card_aica
-+				  *dreamcastcard, int pcm_index)
-+{
-+	struct snd_pcm *pcm;
-+	int err;
-+	/* AICA has no capture ability */
-+	err =
-+	    snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0,
-+			&pcm);
-+	if (unlikely(err < 0))
-+		return err;
-+	pcm->private_data = dreamcastcard;
-+	strcpy(pcm->name, "AICA PCM");
-+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+			&snd_aicapcm_playback_ops);
-+	/* Allocate the DMA buffers */
-+	err =
-+	    snd_pcm_lib_preallocate_pages_for_all(pcm,
-+						  SNDRV_DMA_TYPE_CONTINUOUS,
-+						  snd_dma_continuous_data
-+						  (GFP_KERNEL),
-+						  AICA_BUFFER_SIZE,
-+						  AICA_BUFFER_SIZE);
-+	return err;
-+}
-+
-+/* Mixer controls */
-+static int aica_pcmswitch_info(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;
-+}
-+
-+static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol,
-+			      struct snd_ctl_elem_value *ucontrol)
-+{
-+	ucontrol->value.integer.value[0] = 1;	/* TO DO: Fix me */
-+	return 0;
-+}
-+
-+static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol,
-+			      struct snd_ctl_elem_value *ucontrol)
-+{
-+	if (ucontrol->value.integer.value[0] == 1)
-+		return 0;	/* TO DO: Fix me */
-+	else
-+		aica_chn_halt();
-+	return 0;
-+}
-+
-+static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol,
-+			       struct snd_ctl_elem_info *uinfo)
-+{
-+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+	uinfo->count = 1;
-+	uinfo->value.integer.min = 0;
-+	uinfo->value.integer.max = 0xFF;
-+	return 0;
-+}
-+
-+static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol,
-+			      struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct snd_card_aica *dreamcastcard;
-+	dreamcastcard = kcontrol->private_data;
-+	if (unlikely(!dreamcastcard->channel))
-+		return -ETXTBSY;	/* we've not yet been set up */
-+	ucontrol->value.integer.value[0] = dreamcastcard->channel->vol;
-+	return 0;
-+}
-+
-+static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
-+			      struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct snd_card_aica *dreamcastcard;
-+	dreamcastcard = kcontrol->private_data;
-+	if (unlikely(!dreamcastcard->channel))
-+		return -ETXTBSY;
-+	if (unlikely(dreamcastcard->channel->vol ==
-+		     ucontrol->value.integer.value[0]))
-+		return 0;
-+	dreamcastcard->channel->vol = ucontrol->value.integer.value[0];
-+	dreamcastcard->master_volume = ucontrol->value.integer.value[0];
-+	spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
-+		    dreamcastcard->channel, sizeof(struct aica_channel));
-+	return 1;
-+}
-+
-+static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
-+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+	.name = "PCM Playback Switch",
-+	.index = 0,
-+	.info = aica_pcmswitch_info,
-+	.get = aica_pcmswitch_get,
-+	.put = aica_pcmswitch_put
-+};
-+
-+static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = {
-+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+	.name = "PCM Playback Volume",
-+	.index = 0,
-+	.info = aica_pcmvolume_info,
-+	.get = aica_pcmvolume_get,
-+	.put = aica_pcmvolume_put
-+};
-+
-+static int load_aica_firmware(void)
-+{
-+	int err;
-+	const struct firmware *fw_entry;
-+	spu_reset();
-+	err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev);
-+	if (unlikely(err))
-+		return err;
-+	/* write firware into memory */
-+	spu_disable();
-+	spu_memload(0, fw_entry->data, fw_entry->size);
-+	spu_enable();
-+	release_firmware(fw_entry);
-+	return err;
-+}
-+
-+static int __devinit add_aicamixer_controls(struct snd_card_aica
-+					    *dreamcastcard)
-+{
-+	int err;
-+	err = snd_ctl_add
-+	    (dreamcastcard->card,
-+	     snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard));
-+	if (unlikely(err < 0))
-+		return err;
-+	err = snd_ctl_add
-+	    (dreamcastcard->card,
-+	     snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard));
-+	if (unlikely(err < 0))
-+		return err;
-+	return 0;
-+}
-+
-+static int snd_aica_remove(struct platform_device *devptr)
-+{
-+	struct snd_card_aica *dreamcastcard;
-+	dreamcastcard = platform_get_drvdata(devptr);
-+	if (unlikely(!dreamcastcard))
-+		return -ENODEV;
-+	snd_card_free(dreamcastcard->card);
-+	kfree(dreamcastcard);
-+	platform_set_drvdata(devptr, NULL);
-+	return 0;
-+}
-+
-+static int __init snd_aica_probe(struct platform_device *devptr)
-+{
-+	int err;
-+	struct snd_card_aica *dreamcastcard;
-+	dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL);
-+	if (unlikely(!dreamcastcard))
-+		return -ENOMEM;
-+	dreamcastcard->card =
-+	    snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0);
-+	if (unlikely(!dreamcastcard->card)) {
-+		kfree(dreamcastcard);
-+		return -ENODEV;
-+	}
-+	strcpy(dreamcastcard->card->driver, "snd_aica");
-+	strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER);
-+	strcpy(dreamcastcard->card->longname,
-+	       "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast");
-+	/* Prepare to use the queue */
-+	INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma);
-+	/* Load the PCM 'chip' */
-+	err = snd_aicapcmchip(dreamcastcard, 0);
-+	if (unlikely(err < 0))
-+		goto freedreamcast;
-+	snd_card_set_dev(dreamcastcard->card, &devptr->dev);
-+	dreamcastcard->timer.data = 0;
-+	dreamcastcard->channel = NULL;
-+	/* Add basic controls */
-+	err = add_aicamixer_controls(dreamcastcard);
-+	if (unlikely(err < 0))
-+		goto freedreamcast;
-+	/* Register the card with ALSA subsystem */
-+	err = snd_card_register(dreamcastcard->card);
-+	if (unlikely(err < 0))
-+		goto freedreamcast;
-+	platform_set_drvdata(devptr, dreamcastcard);
-+	aica_queue = create_workqueue(CARD_NAME);
-+	if (unlikely(!aica_queue))
-+		goto freedreamcast;
-+	snd_printk
-+	    ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n");
-+	return 0;
-+      freedreamcast:
-+	snd_card_free(dreamcastcard->card);
-+	kfree(dreamcastcard);
-+	return err;
-+}
-+
-+static struct platform_driver snd_aica_driver = {
-+	.probe = snd_aica_probe,
-+	.remove = snd_aica_remove,
-+	.driver = {
-+		   .name = SND_AICA_DRIVER},
-+};
-+
-+static int __init aica_init(void)
-+{
-+	int err;
-+	err = platform_driver_register(&snd_aica_driver);
-+	if (unlikely(err < 0))
-+		return err;
-+	pd = platform_device_register_simple(SND_AICA_DRIVER, -1,
-+					     aica_memory_space, 2);
-+	if (unlikely(IS_ERR(pd))) {
-+		platform_driver_unregister(&snd_aica_driver);
-+		return PTR_ERR(pd);
-+	}
-+	/* Load the firmware */
-+	return load_aica_firmware();
-+}
-+
-+static void __exit aica_exit(void)
-+{
-+	/* Destroy the aica kernel thread            *
-+	 * being extra cautious to check if it exists*/
-+	if (likely(aica_queue))
-+		destroy_workqueue(aica_queue);
-+	platform_device_unregister(pd);
-+	platform_driver_unregister(&snd_aica_driver);
-+	/* Kill any sound still playing and reset ARM7 to safe state */
-+	spu_reset();
-+}
-+
-+module_init(aica_init);
-+module_exit(aica_exit);
---- /dev/null
-+++ linux-2.6.22.1/sound/sh/aica.h
-@@ -0,0 +1,81 @@
-+/* aica.h
-+ * Header file for ALSA driver for
-+ * Sega Dreamcast Yamaha AICA sound
-+ * Copyright Adrian McMenamin
-+ * <adrian at mcmen.demon.co.uk>
-+ * 2006
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as published by
-+ * the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ */
-+
-+/* SPU memory and register constants etc */
-+#define G2_FIFO 0xa05f688c
-+#define SPU_MEMORY_BASE 0xA0800000
-+#define ARM_RESET_REGISTER 0xA0702C00
-+#define SPU_REGISTER_BASE 0xA0700000
-+
-+/* AICA channels stuff */
-+#define AICA_CONTROL_POINT 0xA0810000
-+#define AICA_CONTROL_CHANNEL_SAMPLE_NUMBER 0xA0810008
-+#define AICA_CHANNEL0_CONTROL_OFFSET 0x10004
-+
-+/* Command values */
-+#define AICA_CMD_KICK 0x80000000
-+#define AICA_CMD_NONE 0
-+#define AICA_CMD_START 1
-+#define AICA_CMD_STOP 2
-+#define AICA_CMD_VOL 3
-+
-+/* Sound modes */
-+#define SM_8BIT		1
-+#define SM_16BIT	0
-+#define SM_ADPCM	2
-+
-+/* Buffer and period size */
-+#define AICA_BUFFER_SIZE 0x8000
-+#define AICA_PERIOD_SIZE 0x800
-+#define AICA_PERIOD_NUMBER 16
-+
-+#define AICA_CHANNEL0_OFFSET 0x11000
-+#define AICA_CHANNEL1_OFFSET 0x21000
-+#define CHANNEL_OFFSET 0x10000
-+
-+#define AICA_DMA_CHANNEL 0
-+#define AICA_DMA_MODE 5
-+
-+#define SND_AICA_DRIVER "AICA"
-+
-+struct aica_channel {
-+	uint32_t cmd;		/* Command ID           */
-+	uint32_t pos;		/* Sample position      */
-+	uint32_t length;	/* Sample length        */
-+	uint32_t freq;		/* Frequency            */
-+	uint32_t vol;		/* Volume 0-255         */
-+	uint32_t pan;		/* Pan 0-255            */
-+	uint32_t sfmt;		/* Sound format         */
-+	uint32_t flags;		/* Bit flags            */
-+};
-+
-+struct snd_card_aica {
-+	struct work_struct spu_dma_work;
-+	struct snd_card *card;
-+	struct aica_channel *channel;
-+	struct snd_pcm_substream *substream;
-+	int clicks;
-+	int current_period;
-+	struct timer_list timer;
-+	int master_volume;
-+	int dma_check;
-+};
---- linux-2.6.22.1.orig/sound/soc/Kconfig
-+++ linux-2.6.22.1/sound/soc/Kconfig
-@@ -27,6 +27,7 @@
- source "sound/soc/at91/Kconfig"
- source "sound/soc/pxa/Kconfig"
- source "sound/soc/s3c24xx/Kconfig"
-+source "sound/soc/sh/Kconfig"
- 
- # Supported codecs
- source "sound/soc/codecs/Kconfig"
---- linux-2.6.22.1.orig/sound/soc/Makefile
-+++ linux-2.6.22.1/sound/soc/Makefile
-@@ -1,4 +1,4 @@
- snd-soc-core-objs := soc-core.o soc-dapm.o
- 
- obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
--obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/
-+obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/ sh/
---- linux-2.6.22.1.orig/sound/soc/s3c24xx/Kconfig
-+++ linux-2.6.22.1/sound/soc/s3c24xx/Kconfig
-@@ -1,6 +1,7 @@
- config SND_S3C24XX_SOC
- 	tristate "SoC Audio for the Samsung S3C24XX chips"
- 	depends on ARCH_S3C2410 && SND_SOC
-+	select SND_PCM
- 	help
- 	  Say Y or M if you want to add support for codecs attached to
- 	  the S3C24XX AC97, I2S or SSP interface. You will also need
-@@ -8,3 +9,29 @@
- 
- config SND_S3C24XX_SOC_I2S
- 	tristate
-+
-+config SND_S3C2443_SOC_AC97
-+	tristate
-+	select AC97_BUS
-+	select SND_AC97_CODEC
-+	select SND_SOC_AC97_BUS
-+	
-+config SND_S3C24XX_SOC_NEO1973_WM8753
-+	tristate "SoC I2S Audio support for NEO1973 - WM8753"
-+	depends on SND_S3C24XX_SOC && MACH_GTA01
-+	select SND_S3C24XX_SOC_I2S
-+	select SND_SOC_WM8753
-+	help
-+	  Say Y if you want to add support for SoC audio on smdk2440
-+	  with the WM8753.
-+
-+config SND_S3C24XX_SOC_SMDK2443_WM9710
-+	tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
-+	depends on SND_S3C24XX_SOC && MACH_SMDK2443
-+	select SND_S3C2443_SOC_AC97
-+	select SND_SOC_AC97_CODEC
-+	help
-+	  Say Y if you want to add support for SoC audio on smdk2443
-+	  with the WM9710.
-+
-+
---- linux-2.6.22.1.orig/sound/soc/s3c24xx/Makefile
-+++ linux-2.6.22.1/sound/soc/s3c24xx/Makefile
-@@ -1,6 +1,15 @@
- # S3c24XX Platform Support
- snd-soc-s3c24xx-objs := s3c24xx-pcm.o
- snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
-+snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o
- 
- obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
- obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
-+obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
-+
-+# S3C24XX Machine Support
-+snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
-+snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
-+
-+obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
-+obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/s3c24xx/lm4857.h
-@@ -0,0 +1,32 @@
-+/*
-+ * lm4857.h  --  ALSA Soc Audio Layer
-+ *
-+ * Copyright 2007 Wolfson Microelectronics PLC.
-+ * Author: Graeme Gregory
-+ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  Revision history
-+ *    18th Jun 2007   Initial version.
-+ */
-+
-+#ifndef LM4857_H_
-+#define LM4857_H_
-+
-+/* The register offsets in the cache array */
-+#define LM4857_MVOL 0
-+#define LM4857_LVOL 1
-+#define LM4857_RVOL 2
-+#define LM4857_CTRL 3
-+
-+/* the shifts required to set these bits */
-+#define LM4857_3D 5
-+#define LM4857_WAKEUP 5
-+#define LM4857_EPGAIN 4
-+
-+#endif /*LM4857_H_*/
-+
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/s3c24xx/neo1973_wm8753.c
-@@ -0,0 +1,670 @@
-+/*
-+ * neo1973_wm8753.c  --  SoC audio for Neo1973
-+ *
-+ * Copyright 2007 Wolfson Microelectronics PLC.
-+ * Author: Graeme Gregory
-+ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  Revision history
-+ *    20th Jan 2007   Initial version.
-+ *    05th Feb 2007   Rename all to Neo1973
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/timer.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/i2c.h>
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/soc.h>
-+#include <sound/soc-dapm.h>
-+
-+#include <asm/mach-types.h>
-+#include <asm/hardware/scoop.h>
-+#include <asm/arch/regs-iis.h>
-+#include <asm/arch/regs-clock.h>
-+#include <asm/arch/regs-gpio.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/audio.h>
-+#include <asm/io.h>
-+#include <asm/arch/spi-gpio.h>
-+#include "../codecs/wm8753.h"
-+#include "lm4857.h"
-+#include "s3c24xx-pcm.h"
-+#include "s3c24xx-i2s.h"
-+
-+/* define the scenarios */
-+#define NEO_AUDIO_OFF			0
-+#define NEO_GSM_CALL_AUDIO_HANDSET	1
-+#define NEO_GSM_CALL_AUDIO_HEADSET	2
-+#define NEO_GSM_CALL_AUDIO_BLUETOOTH	3
-+#define NEO_STEREO_TO_SPEAKERS		4
-+#define NEO_STEREO_TO_HEADPHONES	5
-+#define NEO_CAPTURE_HANDSET		6
-+#define NEO_CAPTURE_HEADSET		7
-+#define NEO_CAPTURE_BLUETOOTH		8
-+
-+static struct snd_soc_machine neo1973;
-+static struct i2c_client *i2c;
-+
-+static int neo1973_hifi_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 pll_out = 0, bclk = 0;
-+	int ret = 0;
-+	unsigned long iis_clkrate;
-+
-+	iis_clkrate = s3c24xx_i2s_get_clockrate();
-+
-+	switch (params_rate(params)) {
-+	case 8000:
-+	case 16000:
-+		pll_out = 12288000;
-+		break;
-+	case 48000:
-+		bclk = WM8753_BCLK_DIV_4;
-+		pll_out = 12288000;
-+		break;
-+	case 96000:
-+		bclk = WM8753_BCLK_DIV_2;
-+		pll_out = 12288000;
-+		break;
-+	case 11025:
-+		bclk = WM8753_BCLK_DIV_16;
-+		pll_out = 11289600;
-+		break;
-+	case 22050:
-+		bclk = WM8753_BCLK_DIV_8;
-+		pll_out = 11289600;
-+		break;
-+	case 44100:
-+		bclk = WM8753_BCLK_DIV_4;
-+		pll_out = 11289600;
-+		break;
-+	case 88200:
-+		bclk = WM8753_BCLK_DIV_2;
-+		pll_out = 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_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;
-+
-+	/* set the codec system clock for DAC and ADC */
-+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set MCLK division for sample rate */
-+	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
-+		S3C2410_IISMOD_32FS );
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set codec BCLK division for sample rate */
-+	ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set prescaler division for sample rate */
-+	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
-+		S3C24XX_PRESCALE(4,4));
-+	if (ret < 0)
-+		return ret;
-+
-+	/* codec PLL input is PCLK/4 */
-+	ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1,
-+		iis_clkrate / 4, pll_out);
-+	if (ret < 0)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+
-+	/* disable the PLL */
-+	return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0);
-+}
-+
-+/*
-+ * Neo1973 WM8753 HiFi DAI opserations.
-+ */
-+static struct snd_soc_ops neo1973_hifi_ops = {
-+	.hw_params = neo1973_hifi_hw_params,
-+	.hw_free = neo1973_hifi_hw_free,
-+};
-+
-+static int neo1973_voice_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;
-+	unsigned int pcmdiv = 0;
-+	int ret = 0;
-+	unsigned long iis_clkrate;
-+
-+	iis_clkrate = s3c24xx_i2s_get_clockrate();
-+
-+	if (params_rate(params) != 8000)
-+		return -EINVAL;
-+	if (params_channels(params) != 1)
-+		return -EINVAL;
-+
-+	pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
-+
-+	/* todo: gg check mode (DSP_B) against CSR datasheet */
-+	/* set codec DAI configuration */
-+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
-+		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, WM8753_PCMCLK, 12288000,
-+		SND_SOC_CLOCK_IN);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* set codec PCM division for sample rate */
-+	ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
-+	if (ret < 0)
-+		return ret;
-+
-+	/* configue and enable PLL for 12.288MHz output */
-+	ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2,
-+		iis_clkrate / 4, 12288000);
-+	if (ret < 0)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-+
-+	/* disable the PLL */
-+	return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0);
-+}
-+
-+static struct snd_soc_ops neo1973_voice_ops = {
-+	.hw_params = neo1973_voice_hw_params,
-+	.hw_free = neo1973_voice_hw_free,
-+};
-+
-+static int neo1973_scenario = 0;
-+
-+static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	ucontrol->value.integer.value[0] = neo1973_scenario;
-+	return 0;
-+}
-+
-+static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
-+{
-+	switch(neo1973_scenario) {
-+	case NEO_AUDIO_OFF:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_GSM_CALL_AUDIO_HANDSET:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
-+		break;
-+	case NEO_GSM_CALL_AUDIO_HEADSET:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_GSM_CALL_AUDIO_BLUETOOTH:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_STEREO_TO_SPEAKERS:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_STEREO_TO_HEADPHONES:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_CAPTURE_HANDSET:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
-+		break;
-+	case NEO_CAPTURE_HEADSET:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	case NEO_CAPTURE_BLUETOOTH:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+		break;
-+	default:
-+		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-+		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-+		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
-+	}
-+
-+	snd_soc_dapm_sync_endpoints(codec);
-+
-+	return 0;
-+}
-+
-+static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-+
-+	if (neo1973_scenario == ucontrol->value.integer.value[0])
-+		return 0;
-+
-+	neo1973_scenario = ucontrol->value.integer.value[0];
-+	set_scenario_endpoints(codec, neo1973_scenario);
-+	return 1;
-+}
-+
-+static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
-+
-+static void lm4857_write_regs(void)
-+{
-+	if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
-+		printk(KERN_ERR "lm4857: i2c write failed\n");
-+}
-+
-+static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	int reg=kcontrol->private_value & 0xFF;
-+	int shift = (kcontrol->private_value >> 8) & 0x0F;
-+	int mask = (kcontrol->private_value >> 16) & 0xFF;
-+
-+	ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
-+	return 0;
-+}
-+
-+static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	int reg = kcontrol->private_value & 0xFF;
-+	int shift = (kcontrol->private_value >> 8) & 0x0F;
-+	int mask = (kcontrol->private_value >> 16) & 0xFF;
-+
-+	if (((lm4857_regs[reg] >> shift ) & mask) ==
-+		ucontrol->value.integer.value[0])
-+		return 0;
-+
-+	lm4857_regs[reg] &= ~ (mask << shift);
-+	lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
-+	lm4857_write_regs();
-+	return 1;
-+}
-+
-+static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
-+
-+	if (value)
-+		value -= 5;
-+
-+	ucontrol->value.integer.value[0] = value;
-+	return 0;
-+}
-+
-+static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	u8 value = ucontrol->value.integer.value[0];
-+
-+	if (value)
-+		value += 5;
-+
-+	if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
-+		return 0;
-+
-+	lm4857_regs[LM4857_CTRL] &= 0xF0;
-+	lm4857_regs[LM4857_CTRL] |= value;
-+	lm4857_write_regs();
-+	return 1;
-+}
-+
-+static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
-+	SND_SOC_DAPM_LINE("Audio Out", NULL),
-+	SND_SOC_DAPM_LINE("GSM Line Out", NULL),
-+	SND_SOC_DAPM_LINE("GSM Line In", NULL),
-+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-+	SND_SOC_DAPM_MIC("Call Mic", NULL),
-+};
-+
-+
-+/* example machine audio_mapnections */
-+static const char* audio_map[][3] = {
-+
-+	/* Connections to the lm4857 amp */
-+	{"Audio Out", NULL, "LOUT1"},
-+	{"Audio Out", NULL, "ROUT1"},
-+
-+	/* Connections to the GSM Module */
-+	{"GSM Line Out", NULL, "MONO1"},
-+	{"GSM Line Out", NULL, "MONO2"},
-+	{"RXP", NULL, "GSM Line In"},
-+	{"RXN", NULL, "GSM Line In"},
-+
-+	/* Connections to Headset */
-+	{"MIC1", NULL, "Mic Bias"},
-+	{"Mic Bias", NULL, "Headset Mic"},
-+
-+	/* Call Mic */
-+	{"MIC2", NULL, "Mic Bias"},
-+	{"MIC2N", NULL, "Mic Bias"},
-+	{"Mic Bias", NULL, "Call Mic"},
-+
-+	/* Connect the ALC pins */
-+	{"ACIN", NULL, "ACOP"},
-+
-+	{NULL, NULL, NULL},
-+};
-+
-+static const char *lm4857_mode[] = {
-+	"Off",
-+	"Call Speaker",
-+	"Stereo Speakers",
-+	"Stereo Speakers + Headphones",
-+	"Headphones"
-+};
-+
-+static const struct soc_enum lm4857_mode_enum[] = {
-+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
-+};
-+
-+static const char *neo_scenarios[] = {
-+	"Off",
-+	"GSM Handset",
-+	"GSM Headset",
-+	"GSM Bluetooth",
-+	"Speakers",
-+	"Headphones",
-+	"Capture Handset",
-+	"Capture Headset",
-+	"Capture Bluetooth"
-+};
-+
-+static const struct soc_enum neo_scenario_enum[] = {
-+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios),neo_scenarios),
-+};
-+
-+static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
-+	SOC_SINGLE_EXT("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_SINGLE_EXT("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_SINGLE_EXT("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
-+		lm4857_get_mode, lm4857_set_mode),
-+	SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
-+		neo1973_get_scenario, neo1973_set_scenario),
-+	SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+	SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
-+		lm4857_get_reg, lm4857_set_reg),
-+};
-+
-+/*
-+ * This is an example machine initialisation for a wm8753 connected to a
-+ * neo1973 II. It is missing logic to detect hp/mic insertions and logic
-+ * to re-route the audio in such an event.
-+ */
-+static int neo1973_wm8753_init(struct snd_soc_codec *codec)
-+{
-+	int i, err;
-+
-+	/* set up NC codec pins */
-+	snd_soc_dapm_set_endpoint(codec, "LOUT2", 0);
-+	snd_soc_dapm_set_endpoint(codec, "ROUT2", 0);
-+	snd_soc_dapm_set_endpoint(codec, "OUT3",  0);
-+	snd_soc_dapm_set_endpoint(codec, "OUT4",  0);
-+	snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
-+	snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
-+
-+
-+	/* set endpoints to default mode */
-+	set_scenario_endpoints(codec, NEO_AUDIO_OFF);
-+
-+	/* Add neo1973 specific widgets */
-+	for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
-+		snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
-+
-+	/* add neo1973 specific controls */
-+	for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
-+		err = snd_ctl_add(codec->card,
-+				snd_soc_cnew(&wm8753_neo1973_controls[i],
-+				codec, NULL));
-+		if (err < 0)
-+			return err;
-+	}
-+
-+	/* set up neo1973 specific audio path audio_mapnects */
-+	for (i = 0; audio_map[i][0] != NULL; i++) {
-+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
-+			audio_map[i][1], audio_map[i][2]);
-+	}
-+
-+	snd_soc_dapm_sync_endpoints(codec);
-+	return 0;
-+}
-+
-+/*
-+ * BT Codec DAI
-+ */
-+static struct snd_soc_cpu_dai bt_dai =
-+{	.name = "Bluetooth",
-+	.id = 0,
-+	.type = SND_SOC_DAI_PCM,
-+	.playback = {
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = SNDRV_PCM_RATE_8000,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = SNDRV_PCM_RATE_8000,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+};
-+
-+static struct snd_soc_dai_link neo1973_dai[] = {
-+{ /* Hifi Playback - for similatious use with voice below */
-+	.name = "WM8753",
-+	.stream_name = "WM8753 HiFi",
-+	.cpu_dai = &s3c24xx_i2s_dai,
-+	.codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
-+	.init = neo1973_wm8753_init,
-+	.ops = &neo1973_hifi_ops,
-+},
-+{ /* Voice via BT */
-+	.name = "Bluetooth",
-+	.stream_name = "Voice",
-+	.cpu_dai = &bt_dai,
-+	.codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
-+	.ops = &neo1973_voice_ops,
-+},
-+};
-+
-+static struct snd_soc_machine neo1973 = {
-+	.name = "neo1973",
-+	.dai_link = neo1973_dai,
-+	.num_links = ARRAY_SIZE(neo1973_dai),
-+};
-+
-+static struct wm8753_setup_data neo1973_wm8753_setup = {
-+	.i2c_address = 0x1a,
-+};
-+
-+static struct snd_soc_device neo1973_snd_devdata = {
-+	.machine = &neo1973,
-+	.platform = &s3c24xx_soc_platform,
-+	.codec_dev = &soc_codec_dev_wm8753,
-+	.codec_data = &neo1973_wm8753_setup,
-+};
-+
-+static struct i2c_client client_template;
-+
-+static unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END };
-+
-+/* Magic definition of all other variables and things */
-+I2C_CLIENT_INSMOD;
-+
-+static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind)
-+{
-+	int ret;
-+
-+	client_template.adapter = adap;
-+	client_template.addr = addr;
-+
-+	i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
-+	if (i2c == NULL)
-+		return -ENOMEM;
-+
-+	ret = i2c_attach_client(i2c);
-+	if (ret < 0) {
-+		printk(KERN_ERR "LM4857 failed to attach at addr %x\n", addr);
-+		goto exit_err;
-+	}
-+
-+	lm4857_write_regs();
-+	return ret;
-+
-+exit_err:
-+	kfree(i2c);
-+	return ret;
-+}
-+
-+static int lm4857_i2c_detach(struct i2c_client *client)
-+{
-+	i2c_detach_client(client);
-+	kfree(client);
-+	return 0;
-+}
-+
-+static int lm4857_i2c_attach(struct i2c_adapter *adap)
-+{
-+	return i2c_probe(adap, &addr_data, lm4857_amp_probe);
-+}
-+
-+/* corgi i2c codec control layer */
-+static struct i2c_driver lm4857_i2c_driver = {
-+	.driver = {
-+		.name = "LM4857 I2C Amp",
-+		.owner = THIS_MODULE,
-+	},
-+	.id =             I2C_DRIVERID_LM4857,
-+	.attach_adapter = lm4857_i2c_attach,
-+	.detach_client =  lm4857_i2c_detach,
-+	.command =        NULL,
-+};
-+
-+static struct i2c_client client_template = {
-+	.name =   "LM4857",
-+	.driver = &lm4857_i2c_driver,
-+};
-+
-+static struct platform_device *neo1973_snd_device;
-+
-+static int __init neo1973_init(void)
-+{
-+	int ret;
-+
-+	neo1973_snd_device = platform_device_alloc("soc-audio", -1);
-+	if (!neo1973_snd_device)
-+		return -ENOMEM;
-+
-+	platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata);
-+	neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
-+	ret = platform_device_add(neo1973_snd_device);
-+
-+	if (ret)
-+		platform_device_put(neo1973_snd_device);
-+
-+	ret = i2c_add_driver(&lm4857_i2c_driver);
-+	if (ret != 0)
-+		printk(KERN_ERR "can't add i2c driver");
-+
-+	return ret;
-+}
-+
-+static void __exit neo1973_exit(void)
-+{
-+	platform_device_unregister(neo1973_snd_device);
-+}
-+
-+module_init(neo1973_init);
-+module_exit(neo1973_exit);
-+
-+/* Module information */
-+MODULE_AUTHOR("Graeme Gregory, graeme.gregory at wolfsonmicro.com, www.wolfsonmicro.com");
-+MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/s3c24xx/s3c2443-ac97.c
-@@ -0,0 +1,401 @@
-+/*
-+ * s3c2443-ac97.c  --  ALSA Soc Audio Layer
-+ *
-+ * (c) 2007 Wolfson Microelectronics PLC.
-+ * Graeme Gregory graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *
-+ *  Copyright (C) 2005, Sean Choi <sh428.choi at samsung.com>
-+ *  All rights reserved.
-+ *
-+ *  This program is free software; you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License version 2 as
-+ *  published by the Free Software Foundation.
-+ *
-+ *  Revision history
-+ *	21st Mar 2007   Initial Version
-+ */
-+
-+#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 <linux/clk.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/hardware.h>
-+#include <asm/io.h>
-+#include <asm/arch/regs-ac97.h>
-+#include <asm/arch/regs-gpio.h>
-+#include <asm/arch/regs-clock.h>
-+#include <asm/arch/audio.h>
-+#include <asm/dma.h>
-+#include <asm/arch/dma.h>
-+
-+#include "s3c24xx-pcm.h"
-+#include "s3c24xx-ac97.h"
-+
-+struct s3c24xx_ac97_info {
-+	void __iomem	*regs;
-+	struct clk	*ac97_clk;
-+};
-+static struct s3c24xx_ac97_info s3c24xx_ac97;
-+
-+DECLARE_COMPLETION(ac97_completion);
-+static u32 codec_ready;
-+static DECLARE_MUTEX(ac97_mutex);
-+
-+static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
-+	unsigned short reg)
-+{
-+	u32 ac_glbctrl;
-+	u32 ac_codec_cmd;
-+	u32 stat, addr, data;
-+
-+	down(&ac97_mutex);
-+
-+	codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
-+	ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+	ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg);
-+	writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+
-+	udelay(50);
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+
-+	wait_for_completion(&ac97_completion);
-+
-+	stat = readl(s3c24xx_ac97.regs + S3C_AC97_STAT);
-+	addr = (stat >> 16) & 0x7f;
-+	data = (stat & 0xffff);
-+
-+	if (addr != reg)
-+		printk(KERN_ERR "s3c24xx-ac97: req addr = %02x,"
-+				" rep addr = %02x\n", reg, addr);
-+
-+	up(&ac97_mutex);
-+
-+	return (unsigned short)data;
-+}
-+
-+static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
-+	unsigned short val)
-+{
-+	u32 ac_glbctrl;
-+	u32 ac_codec_cmd;
-+
-+	down(&ac97_mutex);
-+
-+	codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
-+	ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+	ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val);
-+	writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+
-+	udelay(50);
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+
-+	wait_for_completion(&ac97_completion);
-+
-+	ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+	ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
-+	writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
-+
-+	up(&ac97_mutex);
-+
-+}
-+
-+static void s3c2443_ac97_warm_reset(struct snd_ac97 *ac97)
-+{
-+	u32 ac_glbctrl;
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl = S3C_AC97_GLBCTRL_WARMRESET;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl = 0;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+}
-+
-+static void s3c2443_ac97_cold_reset(struct snd_ac97 *ac97)
-+{
-+	u32 ac_glbctrl;
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl = 0;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA |
-+		S3C_AC97_GLBCTRL_PCMINTM_DMA | S3C_AC97_GLBCTRL_MICINTM_DMA;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+}
-+
-+static irqreturn_t s3c2443_ac97_irq(int irq, void *dev_id)
-+{
-+	int status;
-+	u32 ac_glbctrl;
-+
-+	status = readl(s3c24xx_ac97.regs + S3C_AC97_GLBSTAT) & codec_ready;
-+
-+	if (status) {
-+		ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+		ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE;
-+		writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+		complete(&ac97_completion);
-+	}
-+	return IRQ_HANDLED;
-+}
-+
-+struct snd_ac97_bus_ops soc_ac97_ops = {
-+	.read	= s3c2443_ac97_read,
-+	.write	= s3c2443_ac97_write,
-+	.warm_reset	= s3c2443_ac97_warm_reset,
-+	.reset	= s3c2443_ac97_cold_reset,
-+};
-+
-+static struct s3c2410_dma_client s3c2443_dma_client_out = {
-+	.name = "AC97 PCM Stereo out"
-+};
-+
-+static struct s3c2410_dma_client s3c2443_dma_client_in = {
-+	.name = "AC97 PCM Stereo in"
-+};
-+
-+static struct s3c2410_dma_client s3c2443_dma_client_micin = {
-+	.name = "AC97 Mic Mono in"
-+};
-+
-+static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_out = {
-+	.client		= &s3c2443_dma_client_out,
-+	.channel	= DMACH_PCM_OUT,
-+	.dma_addr	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
-+	.dma_size	= 4,
-+};
-+
-+static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_in = {
-+	.client		= &s3c2443_dma_client_in,
-+	.channel	= DMACH_PCM_IN,
-+	.dma_addr	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
-+	.dma_size	= 4,
-+};
-+
-+static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = {
-+	.client		= &s3c2443_dma_client_micin,
-+	.channel	= DMACH_MIC_IN,
-+	.dma_addr	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
-+	.dma_size	= 4,
-+};
-+
-+static int s3c2443_ac97_probe(struct platform_device *pdev)
-+{
-+	int ret;
-+	u32 ac_glbctrl;
-+
-+	s3c24xx_ac97.regs = ioremap(S3C2440_PA_AC97, 0x100);
-+	if (s3c24xx_ac97.regs == NULL)
-+		return -ENXIO;
-+
-+	s3c24xx_ac97.ac97_clk = clk_get(&pdev->dev, "ac97");
-+	if (s3c24xx_ac97.ac97_clk == NULL) {
-+		printk(KERN_ERR "s3c2443-ac97 failed to get ac97_clock\n");
-+		iounmap(s3c24xx_ac97.regs);
-+		return -ENODEV;
-+	}
-+	clk_enable(s3c24xx_ac97.ac97_clk);
-+
-+	s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2443_GPE0_AC_nRESET);
-+	s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2443_GPE1_AC_SYNC);
-+	s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2443_GPE2_AC_BITCLK);
-+	s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2443_GPE3_AC_SDI);
-+	s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2443_GPE4_AC_SDO);
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl = 0;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	msleep(1);
-+
-+	ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE;
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+
-+	ret = request_irq(IRQ_S3C2443_AC97, s3c2443_ac97_irq,
-+		IRQF_DISABLED, "AC97", NULL);
-+	if (ret < 0) {
-+		printk(KERN_ERR "s3c24xx-ac97: interrupt request failed.\n");
-+		clk_disable(s3c24xx_ac97.ac97_clk);
-+		clk_put(s3c24xx_ac97.ac97_clk);
-+		iounmap(s3c24xx_ac97.regs);
-+	}
-+	return ret;
-+}
-+
-+static void s3c2443_ac97_remove(struct platform_device *pdev)
-+{
-+	free_irq(IRQ_S3C2443_AC97, NULL);
-+	clk_disable(s3c24xx_ac97.ac97_clk);
-+	clk_put(s3c24xx_ac97.ac97_clk);
-+	iounmap(s3c24xx_ac97.regs);
-+}
-+
-+static int s3c2443_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 = &s3c2443_ac97_pcm_stereo_out;
-+	else
-+		cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_in;
-+
-+	return 0;
-+}
-+
-+static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+	u32 ac_glbctrl;
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	switch(cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+	case SNDRV_PCM_TRIGGER_RESUME:
-+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-+			ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA;
-+		else
-+			ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA;
-+		break;
-+	case SNDRV_PCM_TRIGGER_STOP:
-+	case SNDRV_PCM_TRIGGER_SUSPEND:
-+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-+			ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK;
-+		else
-+			ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK;
-+		break;
-+	}
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+
-+	return 0;
-+}
-+
-+static int s3c2443_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 = &s3c2443_ac97_mic_mono_in;
-+
-+	return 0;
-+}
-+
-+static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
-+	int cmd)
-+{
-+	u32 ac_glbctrl;
-+
-+	ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+	switch(cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+	case SNDRV_PCM_TRIGGER_RESUME:
-+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+		ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA;
-+		break;
-+	case SNDRV_PCM_TRIGGER_STOP:
-+	case SNDRV_PCM_TRIGGER_SUSPEND:
-+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+		ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK;
-+	}
-+	writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
-+
-+	return 0;
-+}
-+
-+#define s3c2443_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)
-+
-+struct snd_soc_cpu_dai s3c2443_ac97_dai[] = {
-+{
-+	.name = "s3c2443-ac97",
-+	.id = 0,
-+	.type = SND_SOC_DAI_AC97,
-+	.probe = s3c2443_ac97_probe,
-+	.remove = s3c2443_ac97_remove,
-+	.playback = {
-+		.stream_name = "AC97 Playback",
-+		.channels_min = 2,
-+		.channels_max = 2,
-+		.rates = s3c2443_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.capture = {
-+		.stream_name = "AC97 Capture",
-+		.channels_min = 2,
-+		.channels_max = 2,
-+		.rates = s3c2443_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.hw_params = s3c2443_ac97_hw_params,
-+		.trigger = s3c2443_ac97_trigger},
-+},
-+{
-+	.name = "pxa2xx-ac97-mic",
-+	.id = 1,
-+	.type = SND_SOC_DAI_AC97,
-+	.capture = {
-+		.stream_name = "AC97 Mic Capture",
-+		.channels_min = 1,
-+		.channels_max = 1,
-+		.rates = s3c2443_AC97_RATES,
-+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-+	.ops = {
-+		.hw_params = s3c2443_ac97_hw_mic_params,
-+		.trigger = s3c2443_ac97_mic_trigger,},
-+},
-+};
-+
-+EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
-+EXPORT_SYMBOL_GPL(soc_ac97_ops);
-+
-+MODULE_AUTHOR("Graeme Gregory");
-+MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/s3c24xx/s3c24xx-ac97.h
-@@ -0,0 +1,25 @@
-+/*
-+ * s3c24xx-ac97.c  --  ALSA Soc Audio Layer
-+ *
-+ * (c) 2007 Wolfson Microelectronics PLC.
-+ * Author: Graeme Gregory
-+ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  Revision history
-+ *    10th Nov 2006   Initial version.
-+ */
-+
-+#ifndef S3C24XXAC97_H_
-+#define S3C24XXAC97_H_
-+
-+#define AC_CMD_ADDR(x) (x << 16)
-+#define AC_CMD_DATA(x) (x & 0xffff)
-+
-+extern struct snd_soc_cpu_dai s3c2443_ac97_dai[];
-+
-+#endif /*S3C24XXAC97_H_*/
---- linux-2.6.22.1.orig/sound/soc/s3c24xx/s3c24xx-i2s.c
-+++ linux-2.6.22.1/sound/soc/s3c24xx/s3c24xx-i2s.c
-@@ -344,11 +344,11 @@
- 	DBG("Entered %s\n", __FUNCTION__);
- 
- 	switch (div_id) {
--	case S3C24XX_DIV_MCLK:
-+	case S3C24XX_DIV_BCLK:
- 		reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK;
- 		writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
- 		break;
--	case S3C24XX_DIV_BCLK:
-+	case S3C24XX_DIV_MCLK:
- 		reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS);
- 		writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
- 		break;
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/s3c24xx/smdk2443_wm9710.c
-@@ -0,0 +1,85 @@
-+/*
-+ * smdk2443_wm9710.c  --  SoC audio for smdk2443
-+ *
-+ * Copyright 2007 Wolfson Microelectronics PLC.
-+ * Author: Graeme Gregory
-+ *         graeme.gregory at wolfsonmicro.com or linux at wolfsonmicro.com
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  Revision history
-+ *    8th Mar 2007   Initial version.
-+ *
-+ */
-+
-+#include <linux/module.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 "../codecs/ac97.h"
-+#include "s3c24xx-pcm.h"
-+#include "s3c24xx-ac97.h"
-+
-+static struct snd_soc_machine smdk2443;
-+
-+static struct snd_soc_dai_link smdk2443_dai[] = {
-+{
-+	.name = "AC97",
-+	.stream_name = "AC97 HiFi",
-+	.cpu_dai = &s3c2443_ac97_dai[0],
-+	.codec_dai = &ac97_dai,
-+},
-+};
-+
-+static struct snd_soc_machine smdk2443 = {
-+	.name = "SMDK2443",
-+	.dai_link = smdk2443_dai,
-+	.num_links = ARRAY_SIZE(smdk2443_dai),
-+};
-+
-+static struct snd_soc_device smdk2443_snd_ac97_devdata = {
-+	.machine = &smdk2443,
-+	.platform = &s3c24xx_soc_platform,
-+	.codec_dev = &soc_codec_dev_ac97,
-+};
-+
-+static struct platform_device *smdk2443_snd_ac97_device;
-+
-+static int __init smdk2443_init(void)
-+{
-+	int ret;
-+
-+	smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1);
-+	if (!smdk2443_snd_ac97_device)
-+		return -ENOMEM;
-+
-+	platform_set_drvdata(smdk2443_snd_ac97_device,
-+				&smdk2443_snd_ac97_devdata);
-+	smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev;
-+	ret = platform_device_add(smdk2443_snd_ac97_device);
-+
-+	if (ret)
-+		platform_device_put(smdk2443_snd_ac97_device);
-+
-+	return ret;
-+}
-+
-+static void __exit smdk2443_exit(void)
-+{
-+	platform_device_unregister(smdk2443_snd_ac97_device);
-+}
-+
-+module_init(smdk2443_init);
-+module_exit(smdk2443_exit);
-+
-+/* Module information */
-+MODULE_AUTHOR("Graeme Gregory, graeme.gregory at wolfsonmicro.com, www.wolfsonmicro.com");
-+MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/Kconfig
-@@ -0,0 +1,38 @@
-+menu "SoC Audio support for SuperH"
-+
-+config SND_SOC_PCM_SH7760
-+	tristate "SoC Audio support for Renesas SH7760"
-+	depends on CPU_SUBTYPE_SH7760 && SND_SOC && SH_DMABRG
-+	help
-+	  Enable this option for SH7760 AC97/I2S audio support.
-+
-+
-+##
-+## Audio unit modules
-+##
-+
-+config SND_SOC_SH4_HAC
-+	select AC97_BUS
-+	select SND_SOC_AC97_BUS
-+	select SND_AC97_CODEC
-+	tristate
-+
-+config SND_SOC_SH4_SSI
-+	tristate
-+
-+
-+
-+##
-+## Boards
-+##
-+
-+config SND_SH7760_AC97
-+	tristate "SH7760 AC97 sound support"
-+	depends on CPU_SUBTYPE_SH7760 && SND_SOC_PCM_SH7760
-+	select SND_SOC_SH4_HAC
-+	select SND_SOC_AC97_CODEC
-+	help
-+	  This option enables generic sound support for the first
-+	  AC97 unit of the SH7760.
-+
-+endmenu
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/Makefile
-@@ -0,0 +1,14 @@
-+## DMA engines
-+snd-soc-dma-sh7760-objs	:= dma-sh7760.o
-+obj-$(CONFIG_SND_SOC_PCM_SH7760)	+= snd-soc-dma-sh7760.o
-+
-+## audio units found on some SH-4
-+snd-soc-hac-objs	:= hac.o
-+snd-soc-ssi-objs	:= ssi.o
-+obj-$(CONFIG_SND_SOC_SH4_HAC)	+= snd-soc-hac.o
-+obj-$(CONFIG_SND_SOC_SH4_SSI)	+= snd-soc-ssi.o
-+
-+## boards
-+snd-soc-sh7760-ac97-objs	:= sh7760-ac97.o
-+
-+obj-$(CONFIG_SND_SH7760_AC97)	+= snd-soc-sh7760-ac97.o
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/dma-sh7760.c
-@@ -0,0 +1,354 @@
-+/*
-+ * SH7760 ("camelot") DMABRG audio DMA unit support
-+ *
-+ * Copyright (C) 2007 Manuel Lauss <mano at roarinelk.homelinux.net>
-+ *  licensed under the terms outlined in the file COPYING at the root
-+ *  of the linux kernel sources.
-+ *
-+ * The SH7760 DMABRG provides 4 dma channels (2x rec, 2x play), which
-+ * trigger an interrupt when one half of the programmed transfer size
-+ * has been xmitted.
-+ *
-+ * FIXME: little-endian only for now
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.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/dmabrg.h>
-+
-+
-+/* registers and bits */
-+#define BRGATXSAR	0x00
-+#define BRGARXDAR	0x04
-+#define BRGATXTCR	0x08
-+#define BRGARXTCR	0x0C
-+#define BRGACR		0x10
-+#define BRGATXTCNT	0x14
-+#define BRGARXTCNT	0x18
-+
-+#define ACR_RAR		(1 << 18)
-+#define ACR_RDS		(1 << 17)
-+#define ACR_RDE		(1 << 16)
-+#define ACR_TAR		(1 << 2)
-+#define ACR_TDS		(1 << 1)
-+#define ACR_TDE		(1 << 0)
-+
-+/* receiver/transmitter data alignment */
-+#define ACR_RAM_NONE	(0 << 24)
-+#define ACR_RAM_4BYTE	(1 << 24)
-+#define ACR_RAM_2WORD	(2 << 24)
-+#define ACR_TAM_NONE	(0 << 8)
-+#define ACR_TAM_4BYTE	(1 << 8)
-+#define ACR_TAM_2WORD	(2 << 8)
-+
-+
-+struct camelot_pcm {
-+	unsigned long mmio;  /* DMABRG audio channel control reg MMIO */
-+	unsigned int txid;    /* ID of first DMABRG IRQ for this unit */
-+
-+	struct snd_pcm_substream *tx_ss;
-+	unsigned long tx_period_size;
-+	unsigned int  tx_period;
-+
-+	struct snd_pcm_substream *rx_ss;
-+	unsigned long rx_period_size;
-+	unsigned int  rx_period;
-+
-+} cam_pcm_data[2] = {
-+	{
-+		.mmio	=	0xFE3C0040,
-+		.txid	=	DMABRGIRQ_A0TXF,
-+	},
-+	{
-+		.mmio	=	0xFE3C0060,
-+		.txid	=	DMABRGIRQ_A1TXF,
-+	},
-+};
-+
-+#define BRGREG(x)	(*(unsigned long *)(cam->mmio + (x)))
-+
-+/*
-+ * set a minimum of 16kb per period, to avoid interrupt-"storm" and
-+ * resulting skipping. In general, the bigger the minimum size, the
-+ * better for overall system performance. (The SH7760 is a puny CPU
-+ * with a slow SDRAM interface and poor internal bus bandwidth,
-+ * *especially* when the LCDC is active).  The minimum for the DMAC
-+ * is 8 bytes; 16kbytes are enough to get skip-free playback of a
-+ * 44kHz/16bit/stereo MP3 on a lightly loaded system, and maintain
-+ * reasonable responsiveness in MPlayer.
-+ */
-+#define DMABRG_PERIOD_MIN		16 * 1024
-+#define DMABRG_PERIOD_MAX		0x03fffffc
-+#define DMABRG_PREALLOC_BUFFER		32 * 1024
-+#define DMABRG_PREALLOC_BUFFER_MAX	32 * 1024
-+
-+/* support everything the SSI supports */
-+#define DMABRG_RATES	\
-+	SNDRV_PCM_RATE_8000_192000
-+
-+#define DMABRG_FMTS	\
-+	(SNDRV_PCM_FMTBIT_S8      | SNDRV_PCM_FMTBIT_U8      |	\
-+	 SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_U16_LE  |	\
-+	 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |	\
-+	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |	\
-+	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
-+
-+static struct snd_pcm_hardware camelot_pcm_hardware = {
-+	.info = (SNDRV_PCM_INFO_MMAP |
-+		SNDRV_PCM_INFO_INTERLEAVED |
-+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+		SNDRV_PCM_INFO_MMAP_VALID),
-+	.formats =	DMABRG_FMTS,
-+	.rates =	DMABRG_RATES,
-+	.rate_min =		8000,
-+	.rate_max =		192000,
-+	.channels_min =		2,
-+	.channels_max =		8,		/* max of the SSI */
-+	.buffer_bytes_max =	DMABRG_PERIOD_MAX,
-+	.period_bytes_min =	DMABRG_PERIOD_MIN,
-+	.period_bytes_max =	DMABRG_PERIOD_MAX / 2,
-+	.periods_min =		2,
-+	.periods_max =		2,
-+	.fifo_size =		128,
-+};
-+
-+static void camelot_txdma(void *data)
-+{
-+	struct camelot_pcm *cam = data;
-+	cam->tx_period ^= 1;
-+	snd_pcm_period_elapsed(cam->tx_ss);
-+}
-+
-+static void camelot_rxdma(void *data)
-+{
-+	struct camelot_pcm *cam = data;
-+	cam->rx_period ^= 1;
-+	snd_pcm_period_elapsed(cam->rx_ss);
-+}
-+
-+static int camelot_pcm_open(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-+	int ret, dmairq;
-+
-+	snd_soc_set_runtime_hwparams(substream, &camelot_pcm_hardware);
-+
-+	/* DMABRG buffer half/full events */
-+	dmairq = (recv) ? cam->txid + 2 : cam->txid;
-+	if (recv) {
-+		cam->rx_ss = substream;
-+		ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam);
-+		if (unlikely(ret)) {
-+			pr_debug("audio unit %d irqs already taken!\n",
-+			     rtd->dai->cpu_dai->id);
-+			return -EBUSY;
-+		}
-+		(void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam);
-+	} else {
-+		cam->tx_ss = substream;
-+		ret = dmabrg_request_irq(dmairq, camelot_txdma, cam);
-+		if (unlikely(ret)) {
-+			pr_debug("audio unit %d irqs already taken!\n",
-+			     rtd->dai->cpu_dai->id);
-+			return -EBUSY;
-+		}
-+		(void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam);
-+	}
-+	return 0;
-+}
-+
-+static int camelot_pcm_close(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-+	int dmairq;
-+
-+	dmairq = (recv) ? cam->txid + 2 : cam->txid;
-+
-+	if (recv)
-+		cam->rx_ss = NULL;
-+	else
-+		cam->tx_ss = NULL;
-+
-+	dmabrg_free_irq(dmairq + 1);
-+	dmabrg_free_irq(dmairq);
-+
-+	return 0;
-+}
-+
-+static int camelot_hw_params(struct snd_pcm_substream *substream,
-+			     struct snd_pcm_hw_params *hw_params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-+	int ret;
-+
-+	ret = snd_pcm_lib_malloc_pages(substream,
-+				       params_buffer_bytes(hw_params));
-+	if (ret < 0)
-+		return ret;
-+
-+	if (recv) {
-+		cam->rx_period_size = params_period_bytes(hw_params);
-+		cam->rx_period = 0;
-+	} else {
-+		cam->tx_period_size = params_period_bytes(hw_params);
-+		cam->tx_period = 0;
-+	}
-+	return 0;
-+}
-+
-+static int camelot_hw_free(struct snd_pcm_substream *substream)
-+{
-+	return snd_pcm_lib_free_pages(substream);
-+}
-+
-+static int camelot_prepare(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+
-+	pr_debug("PCM data: addr 0x%08ulx len %d\n",
-+		 (u32)runtime->dma_addr, runtime->dma_bytes);
-+ 
-+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+		BRGREG(BRGATXSAR) = (unsigned long)runtime->dma_area;
-+		BRGREG(BRGATXTCR) = runtime->dma_bytes;
-+	} else {
-+		BRGREG(BRGARXDAR) = (unsigned long)runtime->dma_area;
-+		BRGREG(BRGARXTCR) = runtime->dma_bytes;
-+	}
-+
-+	return 0;
-+}
-+
-+static inline void dmabrg_play_dma_start(struct camelot_pcm *cam)
-+{
-+	unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
-+	/* start DMABRG engine: XFER start, auto-addr-reload */
-+	BRGREG(BRGACR) = acr | ACR_TDE | ACR_TAR | ACR_TAM_2WORD;
-+}
-+
-+static inline void dmabrg_play_dma_stop(struct camelot_pcm *cam)
-+{
-+	unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
-+	/* forcibly terminate data transmission */
-+	BRGREG(BRGACR) = acr | ACR_TDS;
-+}
-+
-+static inline void dmabrg_rec_dma_start(struct camelot_pcm *cam)
-+{
-+	unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
-+	/* start DMABRG engine: recv start, auto-reload */
-+	BRGREG(BRGACR) = acr | ACR_RDE | ACR_RAR | ACR_RAM_2WORD;
-+}
-+
-+static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)
-+{
-+	unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
-+	/* forcibly terminate data receiver */
-+	BRGREG(BRGACR) = acr | ACR_RDS;
-+}
-+
-+static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-+
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		if (recv)
-+			dmabrg_rec_dma_start(cam);
-+		else
-+			dmabrg_play_dma_start(cam);
-+		break;
-+	case SNDRV_PCM_TRIGGER_STOP:
-+		if (recv)
-+			dmabrg_rec_dma_stop(cam);
-+		else
-+			dmabrg_play_dma_stop(cam);
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
-+	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-+	unsigned long pos;
-+
-+	/* cannot use the DMABRG pointer register: under load, by the
-+	 * time ALSA comes around to read the register, it is already
-+	 * far ahead (or worse, already done with the fragment) of the
-+	 * position at the time the IRQ was triggered, which results in
-+	 * fast-playback sound in my test application (ScummVM)
-+	 */
-+	if (recv)
-+		pos = cam->rx_period ? cam->rx_period_size : 0;
-+	else
-+		pos = cam->tx_period ? cam->tx_period_size : 0;
-+
-+	return bytes_to_frames(runtime, pos);
-+}
-+
-+static struct snd_pcm_ops camelot_pcm_ops = {
-+	.open		= camelot_pcm_open,
-+	.close		= camelot_pcm_close,
-+	.ioctl		= snd_pcm_lib_ioctl,
-+	.hw_params	= camelot_hw_params,
-+	.hw_free	= camelot_hw_free,
-+	.prepare	= camelot_prepare,
-+	.trigger	= camelot_trigger,
-+	.pointer	= camelot_pos,
-+};
-+
-+static void camelot_pcm_free(struct snd_pcm *pcm)
-+{
-+	snd_pcm_lib_preallocate_free_for_all(pcm);
-+}
-+
-+static int camelot_pcm_new(struct snd_card *card,
-+			   struct snd_soc_codec_dai *dai,
-+			   struct snd_pcm *pcm)
-+{
-+	/* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
-+	 * in MMAP mode (i.e. aplay -M)
-+	 */
-+	snd_pcm_lib_preallocate_pages_for_all(pcm,
-+		SNDRV_DMA_TYPE_CONTINUOUS,
-+		snd_dma_continuous_data(GFP_KERNEL),
-+		DMABRG_PREALLOC_BUFFER,	DMABRG_PREALLOC_BUFFER_MAX);
-+
-+	return 0;
-+}
-+
-+struct snd_soc_platform sh7760_soc_platform = {
-+	.name		= "sh7760-pcm",
-+	.pcm_ops 	= &camelot_pcm_ops,
-+	.pcm_new	= camelot_pcm_new,
-+	.pcm_free	= camelot_pcm_free,
-+};
-+EXPORT_SYMBOL_GPL(sh7760_soc_platform);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
-+MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/hac.c
-@@ -0,0 +1,322 @@
-+/*
-+ * Hitachi Audio Controller (AC97) support for SH7760/SH7780
-+ *
-+ * Copyright (c) 2007 Manuel Lauss <mano at roarinelk.homelinux.net>
-+ *  licensed under the terms outlined in the file COPYING at the root
-+ *  of the linux kernel sources.
-+ *
-+ * dont forget to set IPSEL/OMSEL register bits (in your board code) to
-+ * enable HAC output pins!
-+ */
-+
-+/* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only
-+ * the FIRST can be used since ASoC does not pass any information to the
-+ * ac97_read/write() functions regarding WHICH unit to use.  You'll have
-+ * to edit the code a bit to use the other AC97 unit.		--mlau
-+ */
-+
-+#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>
-+
-+/* regs and bits */
-+#define HACCR		0x08
-+#define HACCSAR		0x20
-+#define HACCSDR		0x24
-+#define HACPCML		0x28
-+#define HACPCMR		0x2C
-+#define HACTIER		0x50
-+#define	HACTSR		0x54
-+#define HACRIER		0x58
-+#define HACRSR		0x5C
-+#define HACACR		0x60
-+
-+#define CR_CR		(1 << 15)	/* "codec-ready" indicator */
-+#define CR_CDRT		(1 << 11)	/* cold reset */
-+#define CR_WMRT		(1 << 10)	/* warm reset */
-+#define CR_B9		(1 << 9)	/* the mysterious "bit 9" */
-+#define CR_ST		(1 << 5)	/* AC97 link start bit */
-+
-+#define CSAR_RD		(1 << 19)	/* AC97 data read bit */
-+#define CSAR_WR		(0)
-+
-+#define TSR_CMDAMT	(1 << 31)
-+#define TSR_CMDDMT	(1 << 30)
-+
-+#define RSR_STARY	(1 << 22)
-+#define RSR_STDRY	(1 << 21)
-+
-+#define ACR_DMARX16	(1 << 30)
-+#define ACR_DMATX16	(1 << 29)
-+#define ACR_TX12ATOM	(1 << 26)
-+#define ACR_DMARX20	((1 << 24) | (1 << 22))
-+#define ACR_DMATX20	((1 << 23) | (1 << 21))
-+
-+#define CSDR_SHIFT	4
-+#define CSDR_MASK	(0xffff << CSDR_SHIFT)
-+#define CSAR_SHIFT	12
-+#define CSAR_MASK	(0x7f << CSAR_SHIFT)
-+
-+#define AC97_WRITE_RETRY	1
-+#define AC97_READ_RETRY		5
-+
-+/* manual-suggested AC97 codec access timeouts (us) */
-+#define TMO_E1	500	/* 21 < E1 < 1000 */
-+#define TMO_E2	13	/* 13 < E2 */
-+#define TMO_E3	21	/* 21 < E3 */
-+#define TMO_E4	500	/* 21 < E4 < 1000 */
-+
-+struct hac_priv {
-+	unsigned long mmio;	/* HAC base address */
-+} hac_cpu_data[] = {
-+#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-+	{
-+		.mmio	= 0xFE240000,
-+	},
-+	{
-+		.mmio	= 0xFE250000,
-+	},
-+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-+	{
-+		.mmio	= 0xFFE40000,
-+	},
-+#else
-+#error "Unsupported SuperH SoC"
-+#endif
-+};
-+
-+#define HACREG(reg)	(*(unsigned long *)(hac->mmio + (reg)))
-+
-+/*
-+ * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906)
-+ */
-+static int hac_get_codec_data(struct hac_priv *hac, unsigned short r,
-+			      unsigned short *v)
-+{
-+	unsigned int to1, to2, i;
-+	unsigned short adr;
-+
-+	for (i = 0; i < AC97_READ_RETRY; ++i) {
-+		*v = 0;
-+		/* wait for HAC to receive something from the codec */
-+		for (to1 = TMO_E4;
-+		     to1 && !(HACREG(HACRSR) & RSR_STARY);
-+		     --to1)
-+			udelay(1);
-+		for (to2 = TMO_E4; 
-+		     to2 && !(HACREG(HACRSR) & RSR_STDRY);
-+		     --to2)
-+			udelay(1);
-+
-+		if (!to1 && !to2)
-+			return 0;	/* codec comm is down */
-+
-+		adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT);
-+		*v  = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT);
-+
-+		HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
-+
-+		if (r == adr)
-+			break;
-+
-+		/* manual says: wait at least 21 usec before retrying */
-+		udelay(21);
-+	}
-+	HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
-+	return (i < AC97_READ_RETRY);
-+}
-+
-+static unsigned short hac_read_codec_aux(struct hac_priv *hac,
-+					 unsigned short reg)
-+{
-+	unsigned short val;
-+	unsigned int i, to;
-+
-+	for (i = 0; i < AC97_READ_RETRY; i++) {
-+		/* send_read_request */
-+		local_irq_disable();
-+		HACREG(HACTSR) &= ~(TSR_CMDAMT);
-+		HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD;
-+		local_irq_enable();
-+
-+		for (to = TMO_E3;
-+		     to && !(HACREG(HACTSR) & TSR_CMDAMT);
-+		     --to)
-+			udelay(1);
-+
-+		HACREG(HACTSR) &= ~TSR_CMDAMT;
-+		val = 0;
-+		if (hac_get_codec_data(hac, reg, &val) != 0)
-+			break;
-+	}
-+
-+	if (i == AC97_READ_RETRY)
-+		return ~0;
-+
-+	return val;
-+}
-+
-+static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
-+			   unsigned short val)
-+{
-+	int unit_id = 0 /* ac97->private_data */;
-+	struct hac_priv *hac = &hac_cpu_data[unit_id];
-+	unsigned int i, to;
-+	/* write_codec_aux */
-+	for (i = 0; i < AC97_WRITE_RETRY; i++) {
-+		/* send_write_request */
-+		local_irq_disable();
-+		HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT);
-+		HACREG(HACCSDR) = (val << CSDR_SHIFT);
-+		HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD);
-+		local_irq_enable();
-+
-+		/* poll-wait for CMDAMT and CMDDMT */
-+		for (to = TMO_E1;
-+		     to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT));
-+		     --to)
-+			udelay(1);
-+
-+		HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT);
-+		if (to)
-+			break;
-+		/* timeout, try again */
-+	}
-+}
-+
-+static unsigned short hac_ac97_read(struct snd_ac97 *ac97,
-+				    unsigned short reg)
-+{
-+	int unit_id = 0 /* ac97->private_data */;
-+	struct hac_priv *hac = &hac_cpu_data[unit_id];
-+	return hac_read_codec_aux(hac, reg);
-+}
-+
-+static void hac_ac97_warmrst(struct snd_ac97 *ac97)
-+{
-+	int unit_id = 0 /* ac97->private_data */;
-+	struct hac_priv *hac = &hac_cpu_data[unit_id];
-+	unsigned int tmo;
-+
-+	HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9;
-+	msleep(10);
-+	HACREG(HACCR) = CR_ST | CR_B9;
-+	for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--)
-+		udelay(1);
-+
-+	if (!tmo)
-+		printk(KERN_INFO "hac: reset: AC97 link down!\n");
-+	/* settings this bit lets us have a conversation with codec */
-+	HACREG(HACACR) |= ACR_TX12ATOM;
-+}
-+
-+static void hac_ac97_coldrst(struct snd_ac97 *ac97)
-+{
-+	int unit_id = 0 /* ac97->private_data */;
-+	struct hac_priv *hac;
-+	hac = &hac_cpu_data[unit_id];
-+
-+	HACREG(HACCR) = 0;
-+	HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9;
-+	msleep(10);
-+	hac_ac97_warmrst(ac97);
-+}
-+
-+struct snd_ac97_bus_ops soc_ac97_ops = {
-+	.read	= hac_ac97_read,
-+	.write	= hac_ac97_write,
-+	.reset	= hac_ac97_coldrst,
-+	.warm_reset = hac_ac97_warmrst,
-+};
-+EXPORT_SYMBOL_GPL(soc_ac97_ops);
-+
-+static int hac_hw_params(struct snd_pcm_substream *substream,
-+			 struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
-+	int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-+
-+	switch (params->msbits) {
-+	case 16:
-+		HACREG(HACACR) |= d ?  ACR_DMARX16 :  ACR_DMATX16;
-+		HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20;
-+		break;
-+	case 20:
-+		HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16;
-+		HACREG(HACACR) |= d ?  ACR_DMARX20 :  ACR_DMATX20;
-+		break;
-+	default:
-+		pr_debug("hac: invalid depth %d bit\n", params->msbits);
-+		return -EINVAL;
-+		break;
-+	}
-+
-+	return 0;
-+}
-+
-+#define AC97_RATES	\
-+	SNDRV_PCM_RATE_8000_192000
-+
-+#define AC97_FMTS	\
-+	SNDRV_PCM_FMTBIT_S16_LE
-+
-+struct snd_soc_cpu_dai sh4_hac_dai[] = {
-+{
-+	.name			= "HAC0",
-+	.id			= 0,
-+	.type			= SND_SOC_DAI_AC97,
-+	.playback = {
-+		.rates		= AC97_RATES,
-+		.formats	= AC97_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 2,
-+	},
-+	.capture = {
-+		.rates		= AC97_RATES,
-+		.formats	= AC97_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 2,
-+	},
-+	.ops = {
-+		.hw_params	= hac_hw_params,
-+	},
-+},
-+#ifdef CONFIG_CPU_SUBTYPE_SH7760
-+{
-+	.name			= "HAC1",
-+	.id			= 1,
-+	.type			= SND_SOC_DAI_AC97,
-+	.playback = {
-+		.rates		= AC97_RATES,
-+		.formats	= AC97_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 2,
-+	},
-+	.capture = {
-+		.rates		= AC97_RATES,
-+		.formats	= AC97_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 2,
-+	},
-+	.ops = {
-+		.hw_params	= hac_hw_params,
-+	},
-+
-+},
-+#endif
-+};
-+EXPORT_SYMBOL_GPL(sh4_hac_dai);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
-+MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/sh7760-ac97.c
-@@ -0,0 +1,92 @@
-+/*
-+ * Generic AC97 sound support for SH7760
-+ *
-+ * (c) 2007 Manuel Lauss
-+ *
-+ * Licensed under the GPLv2.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.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/io.h>
-+
-+#include "../codecs/ac97.h"
-+
-+#define IPSEL 0xFE400034
-+
-+/* platform specific structs can be declared here */
-+extern struct snd_soc_cpu_dai sh4_hac_dai[2];
-+extern struct snd_soc_platform sh7760_soc_platform;
-+
-+static int machine_init(struct snd_soc_codec *codec)
-+{
-+	snd_soc_dapm_sync_endpoints(codec);
-+	return 0;
-+}
-+
-+static struct snd_soc_dai_link sh7760_ac97_dai = {
-+	.name = "AC97",
-+	.stream_name = "AC97 HiFi",
-+	.cpu_dai = &sh4_hac_dai[0],	/* HAC0 */
-+	.codec_dai = &ac97_dai,
-+	.init = machine_init,
-+	.ops = NULL,
-+};
-+
-+static struct snd_soc_machine sh7760_ac97_soc_machine  = {
-+	.name = "SH7760 AC97",
-+	.dai_link = &sh7760_ac97_dai,
-+	.num_links = 1,
-+};
-+
-+static struct snd_soc_device sh7760_ac97_snd_devdata = {
-+	.machine = &sh7760_ac97_soc_machine,
-+	.platform = &sh7760_soc_platform,
-+	.codec_dev = &soc_codec_dev_ac97,
-+};
-+
-+static struct platform_device *sh7760_ac97_snd_device;
-+
-+static int __init sh7760_ac97_init(void)
-+{
-+	int ret;
-+	unsigned short ipsel;
-+
-+	/* enable both AC97 controllers in pinmux reg */
-+	ipsel = ctrl_inw(IPSEL);
-+	ctrl_outw(ipsel | (3 << 10), IPSEL);
-+
-+	ret = -ENOMEM;
-+	sh7760_ac97_snd_device = platform_device_alloc("soc-audio", -1);
-+	if (!sh7760_ac97_snd_device)
-+		goto out;
-+
-+	platform_set_drvdata(sh7760_ac97_snd_device,
-+			     &sh7760_ac97_snd_devdata);
-+	sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev;
-+	ret = platform_device_add(sh7760_ac97_snd_device);
-+
-+	if (ret)
-+		platform_device_put(sh7760_ac97_snd_device);
-+
-+out:
-+	return ret;
-+}
-+
-+static void __exit sh7760_ac97_exit(void)
-+{
-+	platform_device_unregister(sh7760_ac97_snd_device);
-+}
-+
-+module_init(sh7760_ac97_init);
-+module_exit(sh7760_ac97_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic SH7760 AC97 sound machine");
-+MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
---- /dev/null
-+++ linux-2.6.22.1/sound/soc/sh/ssi.c
-@@ -0,0 +1,400 @@
-+/*
-+ * Serial Sound Interface (I2S) support for SH7760/SH7780
-+ *
-+ * Copyright (c) 2007 Manuel Lauss <mano at roarinelk.homelinux.net>
-+ *
-+ *  licensed under the terms outlined in the file COPYING at the root
-+ *  of the linux kernel sources.
-+ *
-+ * dont forget to set IPSEL/OMSEL register bits (in your board code) to
-+ * enable SSI output pins!
-+ */
-+
-+/*
-+ * LIMITATIONS:
-+ *	The SSI unit has only one physical data line, so full duplex is
-+ *	impossible.  This can be remedied  on the  SH7760 by  using the
-+ *	other SSI unit for recording; however the SH7780 has only 1 SSI
-+ *	unit, and its pins are shared with the AC97 unit,  among others.
-+ *
-+ * FEATURES:
-+ *	The SSI features "compressed mode": in this mode it continuously
-+ *	streams PCM data over the I2S lines and uses LRCK as a handshake
-+ *	signal.  Can be used to send compressed data (AC3/DTS) to a DSP.
-+ *	The number of bits sent over the wire in a frame can be adjusted
-+ *	and can be independent from the actual sample bit depth. This is
-+ *	useful to support TDM mode codecs like the AD1939 which have a
-+ *	fixed TDM slot size, regardless of sample resolution.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/initval.h>
-+#include <sound/soc.h>
-+#include <asm/io.h>
-+
-+#define SSICR	0x00
-+#define SSISR	0x04
-+
-+#define CR_DMAEN	(1 << 28)
-+#define CR_CHNL_SHIFT	22
-+#define CR_CHNL_MASK	(3 << CR_CHNL_SHIFT)
-+#define CR_DWL_SHIFT	19
-+#define CR_DWL_MASK	(7 << CR_DWL_SHIFT)
-+#define CR_SWL_SHIFT	16
-+#define CR_SWL_MASK	(7 << CR_SWL_SHIFT)
-+#define CR_SCK_MASTER	(1 << 15)	/* bitclock master bit */
-+#define CR_SWS_MASTER	(1 << 14)	/* wordselect master bit */
-+#define CR_SCKP		(1 << 13)	/* I2Sclock polarity */
-+#define CR_SWSP		(1 << 12)	/* LRCK polarity */
-+#define CR_SPDP		(1 << 11)
-+#define CR_SDTA		(1 << 10)	/* i2s alignment (msb/lsb) */
-+#define CR_PDTA		(1 << 9)	/* fifo data alignment */
-+#define CR_DEL		(1 << 8)	/* delay data by 1 i2sclk */
-+#define CR_BREN		(1 << 7)	/* clock gating in burst mode */
-+#define CR_CKDIV_SHIFT	4
-+#define CR_CKDIV_MASK	(7 << CR_CKDIV_SHIFT)	/* bitclock divider */
-+#define CR_MUTE		(1 << 3)	/* SSI mute */
-+#define CR_CPEN		(1 << 2)	/* compressed mode */
-+#define CR_TRMD		(1 << 1)	/* transmit/receive select */
-+#define CR_EN		(1 << 0)	/* enable SSI */
-+
-+#define SSIREG(reg)	(*(unsigned long *)(ssi->mmio + (reg)))
-+
-+struct ssi_priv {
-+	unsigned long mmio;
-+	unsigned long sysclk;
-+	int inuse;
-+} ssi_cpu_data[] = {
-+#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-+	{
-+		.mmio	= 0xFE680000,
-+	},
-+	{
-+		.mmio	= 0xFE690000,
-+	},
-+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-+	{
-+		.mmio	= 0xFFE70000,
-+	},
-+#else
-+#error "Unsupported SuperH SoC"
-+#endif
-+};
-+
-+/*
-+ * track usage of the SSI; it is simplex-only so prevent attempts of
-+ * concurrent playback + capture. FIXME: any locking required?
-+ */
-+static int ssi_startup(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
-+	if (ssi->inuse) {
-+		pr_debug("ssi: already in use!\n");
-+		return -EBUSY;
-+	} else
-+		ssi->inuse = 1;
-+	return 0;
-+}
-+
-+static void ssi_shutdown(struct snd_pcm_substream *substream)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
-+
-+	ssi->inuse = 0;
-+}
-+
-+static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
-+
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		SSIREG(SSICR) |= CR_DMAEN | CR_EN;
-+		break;
-+	case SNDRV_PCM_TRIGGER_STOP:
-+		SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN);
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static int ssi_hw_params(struct snd_pcm_substream *substream,
-+			 struct snd_pcm_hw_params *params)
-+{
-+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
-+	unsigned long ssicr = SSIREG(SSICR);
-+	unsigned int bits, channels, swl, recv, i;
-+
-+	channels = params_channels(params);
-+	bits = params->msbits;
-+	recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
-+
-+	pr_debug("ssi_hw_params() enter\nssicr was    %08lx\n", ssicr);
-+	pr_debug("bits: %d channels: %d\n", bits, channels);
-+
-+	ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA |
-+		   CR_SWL_MASK);
-+
-+	/* direction (send/receive) */
-+	if (!recv)
-+		ssicr |= CR_TRMD;	/* transmit */
-+
-+	/* channels */
-+	if ((channels < 2) || (channels > 8) || (channels & 1)) {
-+		pr_debug("ssi: invalid number of channels\n");
-+		return -EINVAL;
-+	}
-+	ssicr |= ((channels >> 1) - 1) << CR_CHNL_SHIFT;
-+
-+	/* DATA WORD LENGTH (DWL): databits in audio sample */
-+	i = 0;
-+	switch (bits) {
-+	case 32: ++i;
-+	case 24: ++i;
-+	case 22: ++i;
-+	case 20: ++i;
-+	case 18: ++i;
-+	case 16: ++i;
-+		 ssicr |= i << CR_DWL_SHIFT;
-+	case 8:	 break;
-+	default:
-+		pr_debug("ssi: invalid sample width\n");
-+		return -EINVAL;
-+	}
-+
-+	/*
-+	 * SYSTEM WORD LENGTH: size in bits of half a frame over the I2S
-+	 * wires. This is usually bits_per_sample x channels/2;  i.e. in
-+	 * Stereo mode  the SWL equals DWL.  SWL can  be bigger than the
-+	 * product of (channels_per_slot x samplebits), e.g.  for codecs
-+	 * like the AD1939 which  only accept 32bit wide TDM slots.  For
-+	 * "standard" I2S operation we set SWL = chans / 2 * DWL here.
-+	 * Waiting for ASoC to get TDM support ;-)
-+	 */
-+	if ((bits > 16) && (bits <= 24)) {
-+		bits = 24;	/* these are padded by the SSI */
-+		/*ssicr |= CR_PDTA;*/ /* cpu/data endianness ? */
-+	}
-+	i = 0;
-+	swl = (bits * channels) / 2;
-+	switch (swl) {
-+	case 256: ++i;
-+	case 128: ++i;
-+	case 64:  ++i;
-+	case 48:  ++i;
-+	case 32:  ++i;
-+	case 16:  ++i;
-+		  ssicr |= i << CR_SWL_SHIFT;
-+	case 8:   break;
-+	default:
-+		pr_debug("ssi: invalid system word length computed\n");
-+		return -EINVAL;
-+	}
-+
-+	SSIREG(SSICR) = ssicr;
-+
-+	pr_debug("ssi_hw_params() leave\nssicr is now %08lx\n", ssicr);
-+	return 0;
-+}
-+
-+static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id,
-+			  unsigned int freq, int dir)
-+{
-+	struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id];
-+
-+	ssi->sysclk = freq;
-+
-+	return 0;
-+}
-+
-+/*
-+ * This divider is used to generate the SSI_SCK (I2S bitclock) from the
-+ * clock at the HAC_BIT_CLK ("oversampling clock") pin.
-+ */
-+static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div)
-+{
-+	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
-+	unsigned long ssicr;
-+	int i;
-+
-+	i = 0;
-+	ssicr = SSIREG(SSICR) & ~CR_CKDIV_MASK;
-+	switch (div) {
-+	case 16: ++i;
-+	case 8:  ++i;
-+	case 4:  ++i;
-+	case 2:  ++i;
-+		 SSIREG(SSICR) = ssicr | (i << CR_CKDIV_SHIFT);
-+	case 1:  break;
-+	default:
-+		pr_debug("ssi: invalid sck divider %d\n", div);
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt)
-+{
-+	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
-+	unsigned long ssicr = SSIREG(SSICR);
-+
-+	pr_debug("ssi_set_fmt()\nssicr was    0x%08lx\n", ssicr);
-+
-+	ssicr &= ~(CR_DEL | CR_PDTA | CR_BREN | CR_SWSP | CR_SCKP |
-+		   CR_SWS_MASTER | CR_SCK_MASTER);
-+
-+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+	case SND_SOC_DAIFMT_I2S:
-+		break;
-+	case SND_SOC_DAIFMT_RIGHT_J:
-+		ssicr |= CR_DEL | CR_PDTA;
-+		break;
-+	case SND_SOC_DAIFMT_LEFT_J:
-+		ssicr |= CR_DEL;
-+		break;
-+	default:
-+		pr_debug("ssi: unsupported format\n");
-+		return -EINVAL;
-+	}
-+
-+	switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
-+	case SND_SOC_DAIFMT_CONT:
-+		break;
-+	case SND_SOC_DAIFMT_GATED:
-+		ssicr |= CR_BREN;
-+		break;
-+	}
-+
-+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+	case SND_SOC_DAIFMT_NB_NF:
-+		ssicr |= CR_SCKP;	/* sample data at low clkedge */
-+		break;
-+	case SND_SOC_DAIFMT_NB_IF:
-+		ssicr |= CR_SCKP | CR_SWSP;
-+		break;
-+	case SND_SOC_DAIFMT_IB_NF:
-+		break;
-+	case SND_SOC_DAIFMT_IB_IF:
-+		ssicr |= CR_SWSP;	/* word select starts low */
-+		break;
-+	default:
-+		pr_debug("ssi: invalid inversion\n");
-+		return -EINVAL;
-+	}
-+
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+		break;
-+	case SND_SOC_DAIFMT_CBS_CFM:
-+		ssicr |= CR_SCK_MASTER;
-+		break;
-+	case SND_SOC_DAIFMT_CBM_CFS:
-+		ssicr |= CR_SWS_MASTER;
-+		break;
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		ssicr |= CR_SWS_MASTER | CR_SCK_MASTER;
-+		break;
-+	default:
-+		pr_debug("ssi: invalid master/slave configuration\n");
-+		return -EINVAL;
-+	}
-+
-+	SSIREG(SSICR) = ssicr;
-+	pr_debug("ssi_set_fmt() leave\nssicr is now 0x%08lx\n", ssicr);
-+
-+	return 0;
-+}
-+
-+/* the SSI depends on an external clocksource (at HAC_BIT_CLK) even in
-+ * Master mode,  so really this is board specific;  the SSI can do any
-+ * rate with the right bitclk and divider settings.
-+ */
-+#define SSI_RATES	\
-+	SNDRV_PCM_RATE_8000_192000
-+
-+/* the SSI can do 8-32 bit samples, with 8 possible channels */
-+#define SSI_FMTS	\
-+	(SNDRV_PCM_FMTBIT_S8      | SNDRV_PCM_FMTBIT_U8      |	\
-+	 SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_U16_LE  |	\
-+	 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |	\
-+	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |	\
-+	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
-+
-+struct snd_soc_cpu_dai sh4_ssi_dai[] = {
-+{
-+	.name			= "SSI0",
-+	.id			= 0,
-+	.type			= SND_SOC_DAI_I2S,
-+	.playback = {
-+		.rates		= SSI_RATES,
-+		.formats	= SSI_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 8,
-+	},
-+	.capture = {
-+		.rates		= SSI_RATES,
-+		.formats	= SSI_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 8,
-+	},
-+	.ops = {
-+		.startup	= ssi_startup,
-+		.shutdown	= ssi_shutdown,
-+		.trigger	= ssi_trigger,
-+		.hw_params	= ssi_hw_params,
-+	},
-+	.dai_ops = {
-+		.set_sysclk	= ssi_set_sysclk,
-+		.set_clkdiv	= ssi_set_clkdiv,
-+		.set_fmt	= ssi_set_fmt,
-+	},
-+},
-+#ifdef CONFIG_CPU_SUBTYPE_SH7760
-+{
-+	.name			= "SSI1",
-+	.id			= 1,
-+	.type			= SND_SOC_DAI_I2S,
-+	.playback = {
-+		.rates		= SSI_RATES,
-+		.formats	= SSI_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 8,
-+	},
-+	.capture = {
-+		.rates		= SSI_RATES,
-+		.formats	= SSI_FMTS,
-+		.channels_min	= 2,
-+		.channels_max	= 8,
-+	},
-+	.ops = {
-+		.startup	= ssi_startup,
-+		.shutdown	= ssi_shutdown,
-+		.trigger	= ssi_trigger,
-+		.hw_params	= ssi_hw_params,
-+	},
-+	.dai_ops = {
-+		.set_sysclk	= ssi_set_sysclk,
-+		.set_clkdiv	= ssi_set_clkdiv,
-+		.set_fmt	= ssi_set_fmt,
-+	},
-+},
-+#endif
-+};
-+EXPORT_SYMBOL_GPL(sh4_ssi_dai);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
-+MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
---- linux-2.6.22.1.orig/sound/usb/usbaudio.c
-+++ linux-2.6.22.1/sound/usb/usbaudio.c
-@@ -2350,7 +2350,9 @@
- 			return 1;
- 		break;
- 	case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
--		return 1;
-+		if (device_setup[chip->index] == 0x00 ||
-+		    fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
-+			return 1;
- 	}
- 	return 0;
- }
-@@ -2530,7 +2532,18 @@
- 		 *        but we give normal PCM format to get the existing
- 		 *        apps working...
- 		 */
--		pcm_format = SNDRV_PCM_FORMAT_S16_LE;
-+		switch (chip->usb_id) {
-+
-+		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
-+			if (device_setup[chip->index] == 0x00 && 
-+			    fp->altsetting == 6)
-+				pcm_format = SNDRV_PCM_FORMAT_S16_BE;
-+			else
-+				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
-+			break;
-+		default:
-+			pcm_format = SNDRV_PCM_FORMAT_S16_LE;
-+		}
- 	} else {
- 		pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
- 		if (pcm_format < 0)
-@@ -3251,6 +3264,11 @@
- static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
- 					 int iface, int altno)
- {
-+	/* Reset ALL ifaces to 0 altsetting.
-+	 * Call it for every possible altsetting of every interface.
-+	 */
-+	usb_set_interface(chip->dev, iface, 0);
-+
- 	if (device_setup[chip->index] & AUDIOPHILE_SET) {
- 		if ((device_setup[chip->index] & AUDIOPHILE_SET_DTS)
- 		    && altno != 6)
---- linux-2.6.22.1.orig/sound/usb/usbquirks.h
-+++ linux-2.6.22.1/sound/usb/usbquirks.h
-@@ -57,6 +57,24 @@
- 		       USB_DEVICE_ID_MATCH_INT_CLASS |
- 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
- 	.idVendor = 0x046d,
-+	.idProduct = 0x08ae,
-+	.bInterfaceClass = USB_CLASS_AUDIO,
-+	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
-+},
-+{
-+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
-+		       USB_DEVICE_ID_MATCH_INT_CLASS |
-+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
-+	.idVendor = 0x046d,
-+	.idProduct = 0x08c6,
-+	.bInterfaceClass = USB_CLASS_AUDIO,
-+	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
-+},
-+{
-+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
-+		       USB_DEVICE_ID_MATCH_INT_CLASS |
-+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
-+	.idVendor = 0x046d,
- 	.idProduct = 0x08f0,
- 	.bInterfaceClass = USB_CLASS_AUDIO,
- 	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
-@@ -1051,7 +1069,15 @@
- 		.type = QUIRK_MIDI_STANDARD_INTERFACE
- 	}
- },
--	/* TODO: add Roland EXR support */
-+{
-+	USB_DEVICE(0x0582, 0x0060),
-+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-+		.vendor_name = "Roland",
-+		.product_name = "EXR Series",
-+		.ifnum = 0,
-+		.type = QUIRK_MIDI_STANDARD_INTERFACE
-+	}
-+},
- {
- 	/* has ID 0x0067 when not in "Advanced Driver" mode */
- 	USB_DEVICE(0x0582, 0x0065),
-@@ -1094,6 +1120,19 @@
- 		}
- 	}
- },
-+{
-+	USB_DEVICE(0x582, 0x00a6),
-+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-+		.vendor_name = "Roland",
-+		.product_name = "Juno-G",
-+		.ifnum = 0,
-+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-+		.data = & (const struct snd_usb_midi_endpoint_info) {
-+			.out_cables = 0x0001,
-+			.in_cables  = 0x0001
-+		}
-+	}
-+},
- {	/*
- 	 * This quirk is for the "Advanced" modes of the Edirol UA-25.
- 	 * If the switch is not in an advanced setting, the UA-25 has
-@@ -1230,6 +1269,37 @@
- 	}
- },
- 	/* TODO: add Edirol MD-P1 support */
-+{
-+	/* Roland SH-201 */
-+	USB_DEVICE(0x0582, 0x00ad),
-+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-+		.vendor_name = "Roland",
-+		.product_name = "SH-201",
-+		.ifnum = QUIRK_ANY_INTERFACE,
-+		.type = QUIRK_COMPOSITE,
-+		.data = (const struct snd_usb_audio_quirk[]) {
-+			{
-+				.ifnum = 0,
-+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
-+			},
-+			{
-+				.ifnum = 1,
-+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
-+			},
-+			{
-+				.ifnum = 2,
-+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
-+				.data = & (const struct snd_usb_midi_endpoint_info) {
-+					.out_cables = 0x0001,
-+					.in_cables  = 0x0001
-+				}
-+			},
-+			{
-+				.ifnum = -1
-+			}
-+		}
-+	}
-+},
- 
- /* Guillemot devices */
- {
---- linux-2.6.22.1.orig/sound/usb/usx2y/usbusx2yaudio.c
-+++ linux-2.6.22.1/sound/usb/usx2y/usbusx2yaudio.c
-@@ -935,10 +935,9 @@
-  */
- static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream)
- {
--	if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) {
--		kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
--		usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL;
--	}
-+	kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
-+	usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL;
-+
- 	kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]);
- 	usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL;
- }

Deleted: branches/src/target/kernel/2.6.23.x/patches/s3c2410_udc_from_upstream.patch
===================================================================
--- branches/src/target/kernel/2.6.23.x/patches/s3c2410_udc_from_upstream.patch	2007-09-26 16:12:59 UTC (rev 3046)
+++ branches/src/target/kernel/2.6.23.x/patches/s3c2410_udc_from_upstream.patch	2007-09-26 16:16:04 UTC (rev 3047)
@@ -1,2265 +0,0 @@
-From: Arnaud Patard <arnaud.patard at rtp-net.org>
-Date: Thu, 7 Jun 2007 04:05:49 +0000 (-0700)
-Subject: USB Gadget driver for Samsung s3c2410 ARM SoC
-X-Git-Tag: v2.6.23-rc1~1083^2~86
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3fc154b6b8134b98bb94d60cad9a46ec1ffbe372;hp=7a4eb7fd50d4df99fc1f623e6d90680d9fca3d82
-
-USB Gadget driver for Samsung s3c2410 ARM SoC
-
-This patch adds the support for the Usb Device Controller on Samsung
-S3C24xx SoCs.  This driver passes all tests from testusb (including #13)
-and has been tested on S3C2410, S3C24212, and S3C2440 SoCs.
-
-Whitespace updates, minor cleanups by David
-
-Signed-off-by: Arnaud Patard <arnaud.patard at rtp-net.org>
-Signed-off-by: Ben Dooks <ben-linux at fluff.org>
-Cc: Herbert Pötzl <herbert at 13thfloor.at>
-Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
----
-
-diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
-index 0576888..74eaa7d 100644
---- a/drivers/usb/gadget/Kconfig
-+++ b/drivers/usb/gadget/Kconfig
-@@ -208,6 +208,27 @@ config USB_OTG
- 
- 	   Select this only if your OMAP board has a Mini-AB connector.
- 
-+config USB_GADGET_S3C2410
-+	boolean "S3C2410 USB Device Controller"
-+	depends on ARCH_S3C2410
-+	help
-+	  Samsung's S3C2410 is an ARM-4 processor with an integrated
-+	  full speed USB 1.1 device controller.  It has 4 configurable
-+	  endpoints, as well as endpoint zero (for control transfers).
-+
-+	  This driver has been tested on the S3C2410, S3C2412, and
-+	  S3C2440 processors.
-+
-+config USB_S3C2410
-+	tristate
-+	depends on USB_GADGET_S3C2410
-+	default USB_GADGET
-+	select USB_GADGET_SELECTED
-+
-+config USB_S3C2410_DEBUG
-+	boolean "S3C2410 udc debug messages"
-+	depends on USB_GADGET_S3C2410
-+
- config USB_GADGET_AT91
- 	boolean "AT91 USB Device Port"
- 	depends on ARCH_AT91 && !ARCH_AT91SAM9RL
-diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
-index 2d41e84..bff2783 100644
---- a/drivers/usb/gadget/Makefile
-+++ b/drivers/usb/gadget/Makefile
-@@ -7,6 +7,7 @@ obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
- obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
- obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
- obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
-+obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
- obj-$(CONFIG_USB_AT91)		+= at91_udc.o
- obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
- obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
-diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
-new file mode 100644
-index 0000000..d60748a
---- /dev/null
-+++ b/drivers/usb/gadget/s3c2410_udc.c
-@@ -0,0 +1,2078 @@
-+/*
-+ * linux/drivers/usb/gadget/s3c2410_udc.c
-+ *
-+ * Samsung S3C24xx series on-chip full speed USB device controllers
-+ *
-+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
-+ *	Additional cleanups by Ben Dooks <ben-linux at fluff.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/ioport.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/smp_lock.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/timer.h>
-+#include <linux/list.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/version.h>
-+#include <linux/clk.h>
-+
-+#include <linux/debugfs.h>
-+#include <linux/seq_file.h>
-+
-+#include <linux/usb.h>
-+#include <linux/usb_gadget.h>
-+
-+#include <asm/byteorder.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/unaligned.h>
-+#include <asm/arch/irqs.h>
-+
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/regs-clock.h>
-+#include <asm/arch/regs-gpio.h>
-+#include <asm/arch/regs-udc.h>
-+#include <asm/arch/udc.h>
-+
-+#include <asm/mach-types.h>
-+
-+#include "s3c2410_udc.h"
-+
-+#define DRIVER_DESC	"S3C2410 USB Device Controller Gadget"
-+#define DRIVER_VERSION	"29 Apr 2007"
-+#define DRIVER_AUTHOR	"Herbert Pötzl <herbert at 13thfloor.at>, " \
-+			"Arnaud Patard <arnaud.patard at rtp-net.org>"
-+
-+static const char		gadget_name[] = "s3c2410_udc";
-+static const char		driver_desc[] = DRIVER_DESC;
-+
-+static struct s3c2410_udc	*the_controller;
-+static struct clk		*udc_clock;
-+static struct clk		*usb_bus_clock;
-+static void __iomem		*base_addr;
-+static u64			rsrc_start;
-+static u64			rsrc_len;
-+static struct dentry		*s3c2410_udc_debugfs_root;
-+
-+static inline u32 udc_read(u32 reg)
-+{
-+	return readb(base_addr + reg);
-+}
-+
-+static inline void udc_write(u32 value, u32 reg)
-+{
-+	writeb(value, base_addr + reg);
-+}
-+
-+static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
-+{
-+	writeb(value, base + reg);
-+}
-+
-+static struct s3c2410_udc_mach_info *udc_info;
-+
-+/*************************** DEBUG FUNCTION ***************************/
-+#define DEBUG_NORMAL	1
-+#define DEBUG_VERBOSE	2
-+
-+#ifdef CONFIG_USB_S3C2410_DEBUG
-+#define USB_S3C2410_DEBUG_LEVEL 0
-+
-+static uint32_t s3c2410_ticks = 0;
-+
-+static int dprintk(int level, const char *fmt, ...)
-+{
-+	static char printk_buf[1024];
-+	static long prevticks;
-+	static int invocation;
-+	va_list args;
-+	int len;
-+
-+	if (level > USB_S3C2410_DEBUG_LEVEL)
-+		return 0;
-+
-+	if (s3c2410_ticks != prevticks) {
-+		prevticks = s3c2410_ticks;
-+		invocation = 0;
-+	}
-+
-+	len = scnprintf(printk_buf,
-+			sizeof(printk_buf), "%1lu.%02d USB: ",
-+			prevticks, invocation++);
-+
-+	va_start(args, fmt);
-+	len = vscnprintf(printk_buf+len,
-+			sizeof(printk_buf)-len, fmt, args);
-+	va_end(args);
-+
-+	return printk(KERN_DEBUG "%s", printk_buf);
-+}
-+#else
-+static int dprintk(int level, const char *fmt, ...)
-+{
-+	return 0;
-+}
-+#endif
-+static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
-+{
-+	u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
-+	u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
-+	u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
-+	u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
-+
-+	addr_reg       = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
-+	pwr_reg        = udc_read(S3C2410_UDC_PWR_REG);
-+	ep_int_reg     = udc_read(S3C2410_UDC_EP_INT_REG);
-+	usb_int_reg    = udc_read(S3C2410_UDC_USB_INT_REG);
-+	ep_int_en_reg  = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-+	usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
-+	udc_write(0, S3C2410_UDC_INDEX_REG);
-+	ep0_csr        = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+	udc_write(1, S3C2410_UDC_INDEX_REG);
-+	ep1_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+	ep1_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-+	ep1_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+	ep1_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-+	udc_write(2, S3C2410_UDC_INDEX_REG);
-+	ep2_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+	ep2_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-+	ep2_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+	ep2_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-+
-+	seq_printf(m, "FUNC_ADDR_REG  : 0x%04X\n"
-+		 "PWR_REG        : 0x%04X\n"
-+		 "EP_INT_REG     : 0x%04X\n"
-+		 "USB_INT_REG    : 0x%04X\n"
-+		 "EP_INT_EN_REG  : 0x%04X\n"
-+		 "USB_INT_EN_REG : 0x%04X\n"
-+		 "EP0_CSR        : 0x%04X\n"
-+		 "EP1_I_CSR1     : 0x%04X\n"
-+		 "EP1_I_CSR2     : 0x%04X\n"
-+		 "EP1_O_CSR1     : 0x%04X\n"
-+		 "EP1_O_CSR2     : 0x%04X\n"
-+		 "EP2_I_CSR1     : 0x%04X\n"
-+		 "EP2_I_CSR2     : 0x%04X\n"
-+		 "EP2_O_CSR1     : 0x%04X\n"
-+		 "EP2_O_CSR2     : 0x%04X\n",
-+			addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
-+			ep_int_en_reg, usb_int_en_reg, ep0_csr,
-+			ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
-+			ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
-+		);
-+
-+	return 0;
-+}
-+
-+static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
-+					 struct file *file)
-+{
-+	return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
-+}
-+
-+static const struct file_operations s3c2410_udc_debugfs_fops = {
-+	.open		= s3c2410_udc_debugfs_fops_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+	.owner		= THIS_MODULE,
-+};
-+
-+/* io macros */
-+
-+static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
-+			S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
-+{
-+	udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+
-+	udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
-+				| S3C2410_UDC_EP0_CSR_DE),
-+			S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
-+				| S3C2410_UDC_EP0_CSR_SSE),
-+			S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
-+{
-+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
-+			| S3C2410_UDC_EP0_CSR_DE),
-+		S3C2410_UDC_EP0_CSR_REG);
-+}
-+
-+/*------------------------- I/O ----------------------------------*/
-+
-+/*
-+ *	s3c2410_udc_done
-+ */
-+static void s3c2410_udc_done(struct s3c2410_ep *ep,
-+		struct s3c2410_request *req, int status)
-+{
-+	unsigned halted = ep->halted;
-+
-+	list_del_init(&req->queue);
-+
-+	if (likely (req->req.status == -EINPROGRESS))
-+		req->req.status = status;
-+	else
-+		status = req->req.status;
-+
-+	ep->halted = 1;
-+	req->req.complete(&ep->ep, &req->req);
-+	ep->halted = halted;
-+}
-+
-+static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
-+		struct s3c2410_ep *ep, int status)
-+{
-+	/* Sanity check */
-+	if (&ep->queue == NULL)
-+		return;
-+
-+	while (!list_empty (&ep->queue)) {
-+		struct s3c2410_request *req;
-+		req = list_entry (ep->queue.next, struct s3c2410_request,
-+				queue);
-+		s3c2410_udc_done(ep, req, status);
-+	}
-+}
-+
-+static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
-+{
-+	unsigned i;
-+
-+	/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
-+	 * fifos, and pending transactions mustn't be continued in any case.
-+	 */
-+
-+	for (i = 1; i < S3C2410_ENDPOINTS; i++)
-+		s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
-+}
-+
-+static inline int s3c2410_udc_fifo_count_out(void)
-+{
-+	int tmp;
-+
-+	tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
-+	tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
-+	return tmp;
-+}
-+
-+/*
-+ *	s3c2410_udc_write_packet
-+ */
-+static inline int s3c2410_udc_write_packet(int fifo,
-+		struct s3c2410_request *req,
-+		unsigned max)
-+{
-+	unsigned len = min(req->req.length - req->req.actual, max);
-+	u8 *buf = req->req.buf + req->req.actual;
-+
-+	prefetch(buf);
-+
-+	dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
-+		req->req.actual, req->req.length, len, req->req.actual + len);
-+
-+	req->req.actual += len;
-+
-+	udelay(5);
-+	writesb(base_addr + fifo, buf, len);
-+	return len;
-+}
-+
-+/*
-+ *	s3c2410_udc_write_fifo
-+ *
-+ * return:  0 = still running, 1 = completed, negative = errno
-+ */
-+static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
-+		struct s3c2410_request *req)
-+{
-+	unsigned	count;
-+	int		is_last;
-+	u32		idx;
-+	int		fifo_reg;
-+	u32		ep_csr;
-+
-+	idx = ep->bEndpointAddress & 0x7F;
-+	switch (idx) {
-+	default:
-+		idx = 0;
-+	case 0:
-+		fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
-+		break;
-+	case 1:
-+		fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
-+		break;
-+	case 2:
-+		fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
-+		break;
-+	case 3:
-+		fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
-+		break;
-+	case 4:
-+		fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
-+		break;
-+	}
-+
-+	count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
-+
-+	/* last packet is often short (sometimes a zlp) */
-+	if (count != ep->ep.maxpacket)
-+		is_last = 1;
-+	else if (req->req.length != req->req.actual || req->req.zero)
-+		is_last = 0;
-+	else
-+		is_last = 2;
-+
-+	/* Only ep0 debug messages are interesting */
-+	if (idx == 0)
-+		dprintk(DEBUG_NORMAL,
-+			"Written ep%d %d.%d of %d b [last %d,z %d]\n",
-+			idx, count, req->req.actual, req->req.length,
-+			is_last, req->req.zero);
-+
-+	if (is_last) {
-+		/* The order is important. It prevents sending 2 packets
-+		 * at the same time */
-+
-+		if (idx == 0) {
-+			/* Reset signal => no need to say 'data sent' */
-+			if (! (udc_read(S3C2410_UDC_USB_INT_REG)
-+					& S3C2410_UDC_USBINT_RESET))
-+				s3c2410_udc_set_ep0_de_in(base_addr);
-+			ep->dev->ep0state=EP0_IDLE;
-+		} else {
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
-+					S3C2410_UDC_IN_CSR1_REG);
-+		}
-+
-+		s3c2410_udc_done(ep, req, 0);
-+		is_last = 1;
-+	} else {
-+		if (idx == 0) {
-+			/* Reset signal => no need to say 'data sent' */
-+			if (! (udc_read(S3C2410_UDC_USB_INT_REG)
-+					& S3C2410_UDC_USBINT_RESET))
-+				s3c2410_udc_set_ep0_ipr(base_addr);
-+		} else {
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
-+					S3C2410_UDC_IN_CSR1_REG);
-+		}
-+	}
-+
-+	return is_last;
-+}
-+
-+static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
-+		struct s3c2410_request *req, unsigned avail)
-+{
-+	unsigned len;
-+
-+	len = min(req->req.length - req->req.actual, avail);
-+	req->req.actual += len;
-+
-+	readsb(fifo + base_addr, buf, len);
-+	return len;
-+}
-+
-+/*
-+ * return:  0 = still running, 1 = queue empty, negative = errno
-+ */
-+static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
-+				 struct s3c2410_request *req)
-+{
-+	u8		*buf;
-+	u32		ep_csr;
-+	unsigned	bufferspace;
-+	int		is_last=1;
-+	unsigned	avail;
-+	int		fifo_count = 0;
-+	u32		idx;
-+	int		fifo_reg;
-+
-+	idx = ep->bEndpointAddress & 0x7F;
-+
-+	switch (idx) {
-+	default:
-+		idx = 0;
-+	case 0:
-+		fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
-+		break;
-+	case 1:
-+		fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
-+		break;
-+	case 2:
-+		fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
-+		break;
-+	case 3:
-+		fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
-+		break;
-+	case 4:
-+		fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
-+		break;
-+	}
-+
-+	if (!req->req.length)
-+		return 1;
-+
-+	buf = req->req.buf + req->req.actual;
-+	bufferspace = req->req.length - req->req.actual;
-+	if (!bufferspace) {
-+		dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
-+		return -1;
-+	}
-+
-+	udc_write(idx, S3C2410_UDC_INDEX_REG);
-+
-+	fifo_count = s3c2410_udc_fifo_count_out();
-+	dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
-+
-+	if (fifo_count > ep->ep.maxpacket)
-+		avail = ep->ep.maxpacket;
-+	else
-+		avail = fifo_count;
-+
-+	fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
-+
-+	/* checking this with ep0 is not accurate as we already
-+	 * read a control request
-+	 **/
-+	if (idx != 0 && fifo_count < ep->ep.maxpacket) {
-+		is_last = 1;
-+		/* overflowed this request?  flush extra data */
-+		if (fifo_count != avail)
-+			req->req.status = -EOVERFLOW;
-+	} else {
-+		is_last = (req->req.length <= req->req.actual) ? 1 : 0;
-+	}
-+
-+	udc_write(idx, S3C2410_UDC_INDEX_REG);
-+	fifo_count = s3c2410_udc_fifo_count_out();
-+
-+	/* Only ep0 debug messages are interesting */
-+	if (idx == 0)
-+		dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
-+			__func__, fifo_count,is_last);
-+
-+	if (is_last) {
-+		if (idx == 0) {
-+			s3c2410_udc_set_ep0_de_out(base_addr);
-+			ep->dev->ep0state = EP0_IDLE;
-+		} else {
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
-+					S3C2410_UDC_OUT_CSR1_REG);
-+		}
-+
-+		s3c2410_udc_done(ep, req, 0);
-+	} else {
-+		if (idx == 0) {
-+			s3c2410_udc_clear_ep0_opr(base_addr);
-+		} else {
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
-+					S3C2410_UDC_OUT_CSR1_REG);
-+		}
-+	}
-+
-+	return is_last;
-+}
-+
-+static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
-+{
-+	unsigned char *outbuf = (unsigned char*)crq;
-+	int bytes_read = 0;
-+
-+	udc_write(0, S3C2410_UDC_INDEX_REG);
-+
-+	bytes_read = s3c2410_udc_fifo_count_out();
-+
-+	dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
-+
-+	if (bytes_read > sizeof(struct usb_ctrlrequest))
-+		bytes_read = sizeof(struct usb_ctrlrequest);
-+
-+	readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
-+
-+	dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
-+		bytes_read, crq->bRequest, crq->bRequestType,
-+		crq->wValue, crq->wIndex, crq->wLength);
-+
-+	return bytes_read;
-+}
-+
-+static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
-+		struct usb_ctrlrequest *crq)
-+{
-+	u16 status = 0;
-+	u8 ep_num = crq->wIndex & 0x7F;
-+	u8 is_in = crq->wIndex & USB_DIR_IN;
-+
-+	switch (crq->bRequestType & USB_RECIP_MASK) {
-+	case USB_RECIP_INTERFACE:
-+		break;
-+
-+	case USB_RECIP_DEVICE:
-+		status = dev->devstatus;
-+		break;
-+
-+	case USB_RECIP_ENDPOINT:
-+		if (ep_num > 4 || crq->wLength > 2)
-+			return 1;
-+
-+		if (ep_num == 0) {
-+			udc_write(0, S3C2410_UDC_INDEX_REG);
-+			status = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+			status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
-+		} else {
-+			udc_write(ep_num, S3C2410_UDC_INDEX_REG);
-+			if (is_in) {
-+				status = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+				status = status & S3C2410_UDC_ICSR1_SENDSTL;
-+			} else {
-+				status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-+				status = status & S3C2410_UDC_OCSR1_SENDSTL;
-+			}
-+		}
-+
-+		status = status ? 1 : 0;
-+		break;
-+
-+	default:
-+		return 1;
-+	}
-+
-+	/* Seems to be needed to get it working. ouch :( */
-+	udelay(5);
-+	udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
-+	udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
-+	s3c2410_udc_set_ep0_de_in(base_addr);
-+
-+	return 0;
-+}
-+/*------------------------- usb state machine -------------------------------*/
-+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
-+
-+static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
-+					struct s3c2410_ep *ep,
-+					struct usb_ctrlrequest *crq,
-+					u32 ep0csr)
-+{
-+	int len, ret, tmp;
-+
-+	/* start control request? */
-+	if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
-+		return;
-+
-+	s3c2410_udc_nuke(dev, ep, -EPROTO);
-+
-+	len = s3c2410_udc_read_fifo_crq(crq);
-+	if (len != sizeof(*crq)) {
-+		dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
-+			" wanted %d bytes got %d. Stalling out...\n",
-+			sizeof(*crq), len);
-+		s3c2410_udc_set_ep0_ss(base_addr);
-+		return;
-+	}
-+
-+	dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
-+		crq->bRequest, crq->bRequestType, crq->wLength);
-+
-+	/* cope with automagic for some standard requests. */
-+	dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
-+		== USB_TYPE_STANDARD;
-+	dev->req_config = 0;
-+	dev->req_pending = 1;
-+
-+	switch (crq->bRequest) {
-+	case USB_REQ_SET_CONFIGURATION:
-+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n");
-+
-+		if (crq->bRequestType == USB_RECIP_DEVICE) {
-+			dev->req_config = 1;
-+			s3c2410_udc_set_ep0_de_out(base_addr);
-+		}
-+		break;
-+
-+	case USB_REQ_SET_INTERFACE:
-+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n");
-+
-+		if (crq->bRequestType == USB_RECIP_INTERFACE) {
-+			dev->req_config = 1;
-+			s3c2410_udc_set_ep0_de_out(base_addr);
-+		}
-+		break;
-+
-+	case USB_REQ_SET_ADDRESS:
-+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n");
-+
-+		if (crq->bRequestType == USB_RECIP_DEVICE) {
-+			tmp = crq->wValue & 0x7F;
-+			dev->address = tmp;
-+			udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
-+					S3C2410_UDC_FUNC_ADDR_REG);
-+			s3c2410_udc_set_ep0_de_out(base_addr);
-+			return;
-+		}
-+		break;
-+
-+	case USB_REQ_GET_STATUS:
-+		dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n");
-+		s3c2410_udc_clear_ep0_opr(base_addr);
-+
-+		if (dev->req_std) {
-+			if (!s3c2410_udc_get_status(dev, crq)) {
-+				return;
-+			}
-+		}
-+		break;
-+
-+	case USB_REQ_CLEAR_FEATURE:
-+		s3c2410_udc_clear_ep0_opr(base_addr);
-+
-+		if (crq->bRequestType != USB_RECIP_ENDPOINT)
-+			break;
-+
-+		if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
-+			break;
-+
-+		s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
-+		s3c2410_udc_set_ep0_de_out(base_addr);
-+		return;
-+
-+	case USB_REQ_SET_FEATURE:
-+		s3c2410_udc_clear_ep0_opr(base_addr);
-+
-+		if (crq->bRequestType != USB_RECIP_ENDPOINT)
-+			break;
-+
-+		if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
-+			break;
-+
-+		s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
-+		s3c2410_udc_set_ep0_de_out(base_addr);
-+		return;
-+
-+	default:
-+		s3c2410_udc_clear_ep0_opr(base_addr);
-+		break;
-+	}
-+
-+	if (crq->bRequestType & USB_DIR_IN)
-+		dev->ep0state = EP0_IN_DATA_PHASE;
-+	else
-+		dev->ep0state = EP0_OUT_DATA_PHASE;
-+
-+	ret = dev->driver->setup(&dev->gadget, crq);
-+	if (ret < 0) {
-+		if (dev->req_config) {
-+			dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
-+				crq->bRequest, ret);
-+			return;
-+		}
-+
-+		if (ret == -EOPNOTSUPP)
-+			dprintk(DEBUG_NORMAL, "Operation not supported\n");
-+		else
-+			dprintk(DEBUG_NORMAL,
-+				"dev->driver->setup failed. (%d)\n", ret);
-+
-+		udelay(5);
-+		s3c2410_udc_set_ep0_ss(base_addr);
-+		s3c2410_udc_set_ep0_de_out(base_addr);
-+		dev->ep0state = EP0_IDLE;
-+		/* deferred i/o == no response yet */
-+	} else if (dev->req_pending) {
-+		dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
-+		dev->req_pending=0;
-+	}
-+
-+	dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
-+}
-+
-+static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
-+{
-+	u32			ep0csr;
-+	struct s3c2410_ep	*ep = &dev->ep[0];
-+	struct s3c2410_request	*req;
-+	struct usb_ctrlrequest	crq;
-+
-+	if (list_empty(&ep->queue))
-+		req = NULL;
-+	else
-+		req = list_entry(ep->queue.next, struct s3c2410_request, queue);
-+
-+	/* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
-+	 * S3C2410_UDC_EP0_CSR_REG when index is zero */
-+
-+	udc_write(0, S3C2410_UDC_INDEX_REG);
-+	ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+
-+	dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
-+		ep0csr, ep0states[dev->ep0state]);
-+
-+	/* clear stall status */
-+	if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
-+		s3c2410_udc_nuke(dev, ep, -EPIPE);
-+		dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
-+		s3c2410_udc_clear_ep0_sst(base_addr);
-+		dev->ep0state = EP0_IDLE;
-+		return;
-+	}
-+
-+	/* clear setup end */
-+	if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
-+		dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
-+		s3c2410_udc_nuke(dev, ep, 0);
-+		s3c2410_udc_clear_ep0_se(base_addr);
-+		dev->ep0state = EP0_IDLE;
-+	}
-+
-+	switch (dev->ep0state) {
-+	case EP0_IDLE:
-+		s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
-+		break;
-+
-+	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */
-+		dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
-+		if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
-+			s3c2410_udc_write_fifo(ep, req);
-+		}
-+		break;
-+
-+	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */
-+		dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
-+		if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
-+			s3c2410_udc_read_fifo(ep,req);
-+		}
-+		break;
-+
-+	case EP0_END_XFER:
-+		dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
-+		dev->ep0state = EP0_IDLE;
-+		break;
-+
-+	case EP0_STALL:
-+		dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
-+		dev->ep0state = EP0_IDLE;
-+		break;
-+	}
-+}
-+
-+/*
-+ *	handle_ep - Manage I/O endpoints
-+ */
-+
-+static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
-+{
-+	struct s3c2410_request	*req;
-+	int			is_in = ep->bEndpointAddress & USB_DIR_IN;
-+	u32			ep_csr1;
-+	u32			idx;
-+
-+	if (likely (!list_empty(&ep->queue)))
-+		req = list_entry(ep->queue.next,
-+				struct s3c2410_request, queue);
-+	else
-+		req = NULL;
-+
-+	idx = ep->bEndpointAddress & 0x7F;
-+
-+	if (is_in) {
-+		udc_write(idx, S3C2410_UDC_INDEX_REG);
-+		ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+		dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
-+			idx, ep_csr1, req ? 1 : 0);
-+
-+		if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
-+			dprintk(DEBUG_VERBOSE, "st\n");
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
-+					S3C2410_UDC_IN_CSR1_REG);
-+			return;
-+		}
-+
-+		if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
-+			s3c2410_udc_write_fifo(ep,req);
-+		}
-+	} else {
-+		udc_write(idx, S3C2410_UDC_INDEX_REG);
-+		ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-+		dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
-+
-+		if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
-+			udc_write(idx, S3C2410_UDC_INDEX_REG);
-+			udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
-+					S3C2410_UDC_OUT_CSR1_REG);
-+			return;
-+		}
-+
-+		if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
-+			s3c2410_udc_read_fifo(ep,req);
-+		}
-+	}
-+}
-+
-+#include <asm/arch/regs-irq.h>
-+
-+/*
-+ *	s3c2410_udc_irq - interrupt handler
-+ */
-+static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
-+{
-+	struct s3c2410_udc *dev = _dev;
-+	int usb_status;
-+	int usbd_status;
-+	int pwr_reg;
-+	int ep0csr;
-+	int i;
-+	u32 idx;
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&dev->lock, flags);
-+
-+	/* Driver connected ? */
-+	if (!dev->driver) {
-+		/* Clear interrupts */
-+		udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
-+				S3C2410_UDC_USB_INT_REG);
-+		udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
-+				S3C2410_UDC_EP_INT_REG);
-+	}
-+
-+	/* Save index */
-+	idx = udc_read(S3C2410_UDC_INDEX_REG);
-+
-+	/* Read status registers */
-+	usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
-+	usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
-+	pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
-+
-+	udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-+	ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+
-+	dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
-+		usb_status, usbd_status, pwr_reg, ep0csr);
-+
-+	/*
-+	 * Now, handle interrupts. There's two types :
-+	 * - Reset, Resume, Suspend coming -> usb_int_reg
-+	 * - EP -> ep_int_reg
-+	 */
-+
-+	/* RESET */
-+	if (usb_status & S3C2410_UDC_USBINT_RESET) {
-+		/* two kind of reset :
-+		 * - reset start -> pwr reg = 8
-+		 * - reset end   -> pwr reg = 0
-+		 **/
-+		dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
-+			ep0csr, pwr_reg);
-+
-+		dev->gadget.speed = USB_SPEED_UNKNOWN;
-+		udc_write(0x00, S3C2410_UDC_INDEX_REG);
-+		udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
-+				S3C2410_UDC_MAXP_REG);
-+		dev->address = 0;
-+
-+		dev->ep0state = EP0_IDLE;
-+		dev->gadget.speed = USB_SPEED_FULL;
-+
-+		/* clear interrupt */
-+		udc_write(S3C2410_UDC_USBINT_RESET,
-+				S3C2410_UDC_USB_INT_REG);
-+
-+		udc_write(idx, S3C2410_UDC_INDEX_REG);
-+		spin_unlock_irqrestore(&dev->lock, flags);
-+		return IRQ_HANDLED;
-+	}
-+
-+	/* RESUME */
-+	if (usb_status & S3C2410_UDC_USBINT_RESUME) {
-+		dprintk(DEBUG_NORMAL, "USB resume\n");
-+
-+		/* clear interrupt */
-+		udc_write(S3C2410_UDC_USBINT_RESUME,
-+				S3C2410_UDC_USB_INT_REG);
-+
-+		if (dev->gadget.speed != USB_SPEED_UNKNOWN
-+				&& dev->driver
-+				&& dev->driver->resume)
-+			dev->driver->resume(&dev->gadget);
-+	}
-+
-+	/* SUSPEND */
-+	if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
-+		dprintk(DEBUG_NORMAL, "USB suspend\n");
-+
-+		/* clear interrupt */
-+		udc_write(S3C2410_UDC_USBINT_SUSPEND,
-+				S3C2410_UDC_USB_INT_REG);
-+
-+		if (dev->gadget.speed != USB_SPEED_UNKNOWN
-+				&& dev->driver
-+				&& dev->driver->suspend)
-+			dev->driver->suspend(&dev->gadget);
-+
-+		dev->ep0state = EP0_IDLE;
-+	}
-+
-+	/* EP */
-+	/* control traffic */
-+	/* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
-+	 * generate an interrupt
-+	 */
-+	if (usbd_status & S3C2410_UDC_INT_EP0) {
-+		dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
-+		/* Clear the interrupt bit by setting it to 1 */
-+		udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
-+		s3c2410_udc_handle_ep0(dev);
-+	}
-+
-+	/* endpoint data transfers */
-+	for (i = 1; i < S3C2410_ENDPOINTS; i++) {
-+		u32 tmp = 1 << i;
-+		if (usbd_status & tmp) {
-+			dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
-+
-+			/* Clear the interrupt bit by setting it to 1 */
-+			udc_write(tmp, S3C2410_UDC_EP_INT_REG);
-+			s3c2410_udc_handle_ep(&dev->ep[i]);
-+		}
-+	}
-+
-+	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
-+
-+	/* Restore old index */
-+	udc_write(idx, S3C2410_UDC_INDEX_REG);
-+
-+	spin_unlock_irqrestore(&dev->lock, flags);
-+
-+	return IRQ_HANDLED;
-+}
-+/*------------------------- s3c2410_ep_ops ----------------------------------*/
-+
-+static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
-+{
-+	return container_of(ep, struct s3c2410_ep, ep);
-+}
-+
-+static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
-+{
-+	return container_of(gadget, struct s3c2410_udc, gadget);
-+}
-+
-+static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
-+{
-+	return container_of(req, struct s3c2410_request, req);
-+}
-+
-+/*
-+ *	s3c2410_udc_ep_enable
-+ */
-+static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
-+				 const struct usb_endpoint_descriptor *desc)
-+{
-+	struct s3c2410_udc	*dev;
-+	struct s3c2410_ep	*ep;
-+	u32			max, tmp;
-+	unsigned long		flags;
-+	u32			csr1,csr2;
-+	u32			int_en_reg;
-+
-+	ep = to_s3c2410_ep(_ep);
-+
-+	if (!_ep || !desc || ep->desc
-+			|| _ep->name == ep0name
-+			|| desc->bDescriptorType != USB_DT_ENDPOINT)
-+		return -EINVAL;
-+
-+	dev = ep->dev;
-+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-+		return -ESHUTDOWN;
-+
-+	max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
-+
-+	local_irq_save (flags);
-+	_ep->maxpacket = max & 0x7ff;
-+	ep->desc = desc;
-+	ep->halted = 0;
-+	ep->bEndpointAddress = desc->bEndpointAddress;
-+
-+	/* set max packet */
-+	udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+	udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
-+
-+	/* set type, direction, address; reset fifo counters */
-+	if (desc->bEndpointAddress & USB_DIR_IN) {
-+		csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
-+		csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
-+
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
-+	} else {
-+		/* don't flush in fifo or it will cause endpoint interrupt */
-+		csr1 = S3C2410_UDC_ICSR1_CLRDT;
-+		csr2 = S3C2410_UDC_ICSR2_DMAIEN;
-+
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
-+
-+		csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
-+		csr2 = S3C2410_UDC_OCSR2_DMAIEN;
-+
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
-+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-+		udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
-+	}
-+
-+	/* enable irqs */
-+	int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-+	udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
-+
-+	/* print some debug message */
-+	tmp = desc->bEndpointAddress;
-+	dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
-+		 _ep->name,ep->num, tmp,
-+		 desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
-+
-+	local_irq_restore (flags);
-+	s3c2410_udc_set_halt(_ep, 0);
-+
-+	return 0;
-+}
-+
-+/*
-+ * s3c2410_udc_ep_disable
-+ */
-+static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
-+{
-+	struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
-+	unsigned long flags;
-+	u32 int_en_reg;
-+
-+	if (!_ep || !ep->desc) {
-+		dprintk(DEBUG_NORMAL, "%s not enabled\n",
-+			_ep ? ep->ep.name : NULL);
-+		return -EINVAL;
-+	}
-+
-+	local_irq_save(flags);
-+
-+	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
-+
-+	ep->desc = NULL;
-+	ep->halted = 1;
-+
-+	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
-+
-+	/* disable irqs */
-+	int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-+	udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
-+
-+	local_irq_restore(flags);
-+
-+	dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
-+
-+	return 0;
-+}
-+
-+/*
-+ * s3c2410_udc_alloc_request
-+ */
-+static struct usb_request *
-+s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
-+{
-+	struct s3c2410_request *req;
-+
-+	dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags);
-+
-+	if (!_ep)
-+		return NULL;
-+
-+	req = kzalloc (sizeof(struct s3c2410_request), mem_flags);
-+	if (!req)
-+		return NULL;
-+
-+	INIT_LIST_HEAD (&req->queue);
-+	return &req->req;
-+}
-+
-+/*
-+ * s3c2410_udc_free_request
-+ */
-+static void
-+s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
-+{
-+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
-+	struct s3c2410_request	*req = to_s3c2410_req(_req);
-+
-+	dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
-+
-+	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
-+		return;
-+
-+	WARN_ON (!list_empty (&req->queue));
-+	kfree(req);
-+}
-+
-+/*
-+ *	s3c2410_udc_alloc_buffer
-+ */
-+static void *s3c2410_udc_alloc_buffer(struct usb_ep *_ep,
-+		unsigned bytes, dma_addr_t *dma, gfp_t mem_flags)
-+{
-+	char *retval;
-+
-+	dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
-+
-+	if (!the_controller->driver)
-+		return NULL;
-+
-+	retval = kmalloc (bytes, mem_flags);
-+	*dma = (dma_addr_t) retval;
-+	return retval;
-+}
-+
-+/*
-+ * s3c2410_udc_free_buffer
-+ */
-+static void s3c2410_udc_free_buffer (struct usb_ep *_ep, void *buf,
-+		dma_addr_t dma, unsigned bytes)
-+{
-+	dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
-+
-+	if (bytes)
-+		kfree (buf);
-+}
-+
-+/*
-+ *	s3c2410_udc_queue
-+ */
-+static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
-+		gfp_t gfp_flags)
-+{
-+	struct s3c2410_request	*req = to_s3c2410_req(_req);
-+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
-+	struct s3c2410_udc	*dev;
-+	u32			ep_csr = 0;
-+	int			fifo_count = 0;
-+	unsigned long		flags;
-+
-+	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-+		dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
-+		return -EINVAL;
-+	}
-+
-+	dev = ep->dev;
-+	if (unlikely (!dev->driver
-+			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-+		return -ESHUTDOWN;
-+	}
-+
-+	local_irq_save (flags);
-+
-+	if (unlikely(!_req || !_req->complete
-+			|| !_req->buf || !list_empty(&req->queue))) {
-+		if (!_req)
-+			dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
-+		else {
-+			dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
-+				__func__, !_req->complete,!_req->buf,
-+				!list_empty(&req->queue));
-+		}
-+
-+		local_irq_restore(flags);
-+		return -EINVAL;
-+	}
-+
-+	_req->status = -EINPROGRESS;
-+	_req->actual = 0;
-+
-+	dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
-+		 __func__, ep->bEndpointAddress, _req->length);
-+
-+	if (ep->bEndpointAddress) {
-+		udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
-+
-+		ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
-+				? S3C2410_UDC_IN_CSR1_REG
-+				: S3C2410_UDC_OUT_CSR1_REG);
-+		fifo_count = s3c2410_udc_fifo_count_out();
-+	} else {
-+		udc_write(0, S3C2410_UDC_INDEX_REG);
-+		ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-+		fifo_count = s3c2410_udc_fifo_count_out();
-+	}
-+
-+	/* kickstart this i/o queue? */
-+	if (list_empty(&ep->queue) && !ep->halted) {
-+		if (ep->bEndpointAddress == 0 /* ep0 */) {
-+			switch (dev->ep0state) {
-+			case EP0_IN_DATA_PHASE:
-+				if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
-+						&& s3c2410_udc_write_fifo(ep,
-+							req)) {
-+					dev->ep0state = EP0_IDLE;
-+					req = NULL;
-+				}
-+				break;
-+
-+			case EP0_OUT_DATA_PHASE:
-+				if ((!_req->length)
-+					|| ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
-+						&& s3c2410_udc_read_fifo(ep,
-+							req))) {
-+					dev->ep0state = EP0_IDLE;
-+					req = NULL;
-+				}
-+				break;
-+
-+			default:
-+				local_irq_restore(flags);
-+				return -EL2HLT;
-+			}
-+		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-+				&& (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
-+				&& s3c2410_udc_write_fifo(ep, req)) {
-+			req = NULL;
-+		} else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
-+				&& fifo_count
-+				&& s3c2410_udc_read_fifo(ep, req)) {
-+			req = NULL;
-+		}
-+	}
-+
-+	/* pio or dma irq handler advances the queue. */
-+	if (likely (req != 0))
-+		list_add_tail(&req->queue, &ep->queue);
-+
-+	local_irq_restore(flags);
-+
-+	dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
-+	return 0;
-+}
-+
-+/*
-+ *	s3c2410_udc_dequeue
-+ */
-+static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-+{
-+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
-+	struct s3c2410_udc	*udc;
-+	int			retval = -EINVAL;
-+	unsigned long		flags;
-+	struct s3c2410_request	*req = NULL;
-+
-+	dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
-+
-+	if (!the_controller->driver)
-+		return -ESHUTDOWN;
-+
-+	if (!_ep || !_req)
-+		return retval;
-+
-+	udc = to_s3c2410_udc(ep->gadget);
-+
-+	local_irq_save (flags);
-+
-+	list_for_each_entry (req, &ep->queue, queue) {
-+		if (&req->req == _req) {
-+			list_del_init (&req->queue);
-+			_req->status = -ECONNRESET;
-+			retval = 0;
-+			break;
-+		}
-+	}
-+
-+	if (retval == 0) {
-+		dprintk(DEBUG_VERBOSE,
-+			"dequeued req %p from %s, len %d buf %p\n",
-+			req, _ep->name, _req->length, _req->buf);
-+
-+		s3c2410_udc_done(ep, req, -ECONNRESET);
-+	}
-+
-+	local_irq_restore (flags);
-+	return retval;
-+}
-+
-+/*
-+ * s3c2410_udc_set_halt
-+ */
-+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
-+{
-+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
-+	u32			ep_csr = 0;
-+	unsigned long		flags;
-+	u32			idx;
-+
-+	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-+		dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
-+		return -EINVAL;
-+	}
-+
-+	local_irq_save (flags);
-+
-+	idx = ep->bEndpointAddress & 0x7F;
-+
-+	if (idx == 0) {
-+		s3c2410_udc_set_ep0_ss(base_addr);
-+		s3c2410_udc_set_ep0_de_out(base_addr);
-+	} else {
-+		udc_write(idx, S3C2410_UDC_INDEX_REG);
-+		ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN)
-+				? S3C2410_UDC_IN_CSR1_REG
-+				: S3C2410_UDC_OUT_CSR1_REG);
-+
-+		if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
-+			if (value)
-+				udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
-+					S3C2410_UDC_IN_CSR1_REG);
-+			else {
-+				ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
-+				udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
-+				ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
-+				udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
-+			}
-+		} else {
-+			if (value)
-+				udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
-+					S3C2410_UDC_OUT_CSR1_REG);
-+			else {
-+				ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
-+				udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
-+				ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
-+				udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
-+			}
-+		}
-+	}
-+
-+	ep->halted = value ? 1 : 0;
-+	local_irq_restore (flags);
-+
-+	return 0;
-+}
-+
-+static const struct usb_ep_ops s3c2410_ep_ops = {
-+	.enable		= s3c2410_udc_ep_enable,
-+	.disable	= s3c2410_udc_ep_disable,
-+
-+	.alloc_request	= s3c2410_udc_alloc_request,
-+	.free_request	= s3c2410_udc_free_request,
-+
-+	.alloc_buffer	= s3c2410_udc_alloc_buffer,
-+	.free_buffer	= s3c2410_udc_free_buffer,
-+
-+	.queue		= s3c2410_udc_queue,
-+	.dequeue	= s3c2410_udc_dequeue,
-+
-+	.set_halt	= s3c2410_udc_set_halt,
-+};
-+
-+/*------------------------- usb_gadget_ops ----------------------------------*/
-+
-+/*
-+ *	s3c2410_udc_get_frame
-+ */
-+static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
-+{
-+	int tmp;
-+
-+	dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
-+
-+	tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
-+	tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
-+	return tmp;
-+}
-+
-+/*
-+ *	s3c2410_udc_wakeup
-+ */
-+static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
-+{
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+	return 0;
-+}
-+
-+/*
-+ *	s3c2410_udc_set_selfpowered
-+ */
-+static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
-+{
-+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-+
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	if (value)
-+		udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
-+	else
-+		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
-+
-+	return 0;
-+}
-+
-+static void s3c2410_udc_disable(struct s3c2410_udc *dev);
-+static void s3c2410_udc_enable(struct s3c2410_udc *dev);
-+
-+static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
-+{
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	if (udc_info && udc_info->udc_command) {
-+		if (is_on)
-+			s3c2410_udc_enable(udc);
-+		else {
-+			if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-+				if (udc->driver && udc->driver->disconnect)
-+					udc->driver->disconnect(&udc->gadget);
-+
-+			}
-+			s3c2410_udc_disable(udc);
-+		}
-+	}
-+	else
-+		return -EOPNOTSUPP;
-+
-+	return 0;
-+}
-+
-+static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
-+{
-+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-+
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	udc->vbus = (is_active != 0);
-+	s3c2410_udc_set_pullup(udc, is_active);
-+	return 0;
-+}
-+
-+static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
-+{
-+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-+
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
-+	return 0;
-+}
-+
-+static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
-+{
-+	struct s3c2410_udc	*dev = _dev;
-+	unsigned int		value;
-+
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+	value = s3c2410_gpio_getpin(udc_info->vbus_pin);
-+
-+	if (udc_info->vbus_pin_inverted)
-+		value = !value;
-+
-+	if (value != dev->vbus)
-+		s3c2410_udc_vbus_session(&dev->gadget, value);
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
-+{
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	if (udc_info && udc_info->vbus_draw) {
-+		udc_info->vbus_draw(ma);
-+		return 0;
-+	}
-+
-+	return -ENOTSUPP;
-+}
-+
-+static const struct usb_gadget_ops s3c2410_ops = {
-+	.get_frame		= s3c2410_udc_get_frame,
-+	.wakeup			= s3c2410_udc_wakeup,
-+	.set_selfpowered	= s3c2410_udc_set_selfpowered,
-+	.pullup			= s3c2410_udc_pullup,
-+	.vbus_session		= s3c2410_udc_vbus_session,
-+	.vbus_draw		= s3c2410_vbus_draw,
-+};
-+
-+/*------------------------- gadget driver handling---------------------------*/
-+/*
-+ * s3c2410_udc_disable
-+ */
-+static void s3c2410_udc_disable(struct s3c2410_udc *dev)
-+{
-+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-+
-+	/* Disable all interrupts */
-+	udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
-+	udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
-+
-+	/* Clear the interrupt registers */
-+	udc_write(S3C2410_UDC_USBINT_RESET
-+				| S3C2410_UDC_USBINT_RESUME
-+				| S3C2410_UDC_USBINT_SUSPEND,
-+			S3C2410_UDC_USB_INT_REG);
-+
-+	udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
-+
-+	/* Good bye, cruel world */
-+	if (udc_info && udc_info->udc_command)
-+		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
-+
-+	/* Set speed to unknown */
-+	dev->gadget.speed = USB_SPEED_UNKNOWN;
-+}
-+
-+/*
-+ * s3c2410_udc_reinit
-+ */
-+static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
-+{
-+	u32 i;
-+
-+	/* device/ep0 records init */
-+	INIT_LIST_HEAD (&dev->gadget.ep_list);
-+	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-+	dev->ep0state = EP0_IDLE;
-+
-+	for (i = 0; i < S3C2410_ENDPOINTS; i++) {
-+		struct s3c2410_ep *ep = &dev->ep[i];
-+
-+		if (i != 0)
-+			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-+
-+		ep->dev = dev;
-+		ep->desc = NULL;
-+		ep->halted = 0;
-+		INIT_LIST_HEAD (&ep->queue);
-+	}
-+}
-+
-+/*
-+ * s3c2410_udc_enable
-+ */
-+static void s3c2410_udc_enable(struct s3c2410_udc *dev)
-+{
-+	int i;
-+
-+	dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
-+
-+	/* dev->gadget.speed = USB_SPEED_UNKNOWN; */
-+	dev->gadget.speed = USB_SPEED_FULL;
-+
-+	/* Set MAXP for all endpoints */
-+	for (i = 0; i < S3C2410_ENDPOINTS; i++) {
-+		udc_write(i, S3C2410_UDC_INDEX_REG);
-+		udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
-+				S3C2410_UDC_MAXP_REG);
-+	}
-+
-+	/* Set default power state */
-+	udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
-+
-+	/* Enable reset and suspend interrupt interrupts */
-+	udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
-+			S3C2410_UDC_USB_INT_EN_REG);
-+
-+	/* Enable ep0 interrupt */
-+	udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
-+
-+	/* time to say "hello, world" */
-+	if (udc_info && udc_info->udc_command)
-+		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
-+}
-+
-+/*
-+ *	usb_gadget_register_driver
-+ */
-+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
-+{
-+	struct s3c2410_udc *udc = the_controller;
-+	int		retval;
-+
-+	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
-+		driver->driver.name);
-+
-+	/* Sanity checks */
-+	if (!udc)
-+		return -ENODEV;
-+
-+	if (udc->driver)
-+		return -EBUSY;
-+
-+	if (!driver->bind || !driver->setup
-+			|| driver->speed != USB_SPEED_FULL) {
-+		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
-+			driver->bind, driver->setup, driver->speed);
-+		return -EINVAL;
-+	}
-+#if defined(MODULE)
-+	if (!driver->unbind) {
-+		printk(KERN_ERR "Invalid driver: no unbind method\n");
-+		return -EINVAL;
-+	}
-+#endif
-+
-+	/* Hook the driver */
-+	udc->driver = driver;
-+	udc->gadget.dev.driver = &driver->driver;
-+
-+	/* Bind the driver */
-+	if ((retval = device_add(&udc->gadget.dev)) != 0) {
-+		printk(KERN_ERR "Error in device_add() : %d\n",retval);
-+		goto register_error;
-+	}
-+
-+	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
-+		driver->driver.name);
-+
-+	if ((retval = driver->bind (&udc->gadget)) != 0) {
-+		device_del(&udc->gadget.dev);
-+		goto register_error;
-+	}
-+
-+	/* Enable udc */
-+	s3c2410_udc_enable(udc);
-+
-+	return 0;
-+
-+register_error:
-+	udc->driver = NULL;
-+	udc->gadget.dev.driver = NULL;
-+	return retval;
-+}
-+
-+/*
-+ *	usb_gadget_unregister_driver
-+ */
-+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-+{
-+	struct s3c2410_udc *udc = the_controller;
-+
-+	if (!udc)
-+		return -ENODEV;
-+
-+	if (!driver || driver != udc->driver || !driver->unbind)
-+		return -EINVAL;
-+
-+	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
-+		driver->driver.name);
-+
-+	if (driver->disconnect)
-+		driver->disconnect(&udc->gadget);
-+
-+	device_del(&udc->gadget.dev);
-+	udc->driver = NULL;
-+
-+	/* Disable udc */
-+	s3c2410_udc_disable(udc);
-+
-+	return 0;
-+}
-+
-+/*---------------------------------------------------------------------------*/
-+static struct s3c2410_udc memory = {
-+	.gadget = {
-+		.ops		= &s3c2410_ops,
-+		.ep0		= &memory.ep[0].ep,
-+		.name		= gadget_name,
-+		.dev = {
-+			.bus_id		= "gadget",
-+		},
-+	},
-+
-+	/* control endpoint */
-+	.ep[0] = {
-+		.num		= 0,
-+		.ep = {
-+			.name		= ep0name,
-+			.ops		= &s3c2410_ep_ops,
-+			.maxpacket	= EP0_FIFO_SIZE,
-+		},
-+		.dev		= &memory,
-+	},
-+
-+	/* first group of endpoints */
-+	.ep[1] = {
-+		.num		= 1,
-+		.ep = {
-+			.name		= "ep1-bulk",
-+			.ops		= &s3c2410_ep_ops,
-+			.maxpacket	= EP_FIFO_SIZE,
-+		},
-+		.dev		= &memory,
-+		.fifo_size	= EP_FIFO_SIZE,
-+		.bEndpointAddress = 1,
-+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-+	},
-+	.ep[2] = {
-+		.num		= 2,
-+		.ep = {
-+			.name		= "ep2-bulk",
-+			.ops		= &s3c2410_ep_ops,
-+			.maxpacket	= EP_FIFO_SIZE,
-+		},
-+		.dev		= &memory,
-+		.fifo_size	= EP_FIFO_SIZE,
-+		.bEndpointAddress = 2,
-+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-+	},
-+	.ep[3] = {
-+		.num		= 3,
-+		.ep = {
-+			.name		= "ep3-bulk",
-+			.ops		= &s3c2410_ep_ops,
-+			.maxpacket	= EP_FIFO_SIZE,
-+		},
-+		.dev		= &memory,
-+		.fifo_size	= EP_FIFO_SIZE,
-+		.bEndpointAddress = 3,
-+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-+	},
-+	.ep[4] = {
-+		.num		= 4,
-+		.ep = {
-+			.name		= "ep4-bulk",
-+			.ops		= &s3c2410_ep_ops,
-+			.maxpacket	= EP_FIFO_SIZE,
-+		},
-+		.dev		= &memory,
-+		.fifo_size	= EP_FIFO_SIZE,
-+		.bEndpointAddress = 4,
-+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-+	}
-+
-+};
-+
-+/*
-+ *	probe - binds to the platform device
-+ */
-+static int s3c2410_udc_probe(struct platform_device *pdev)
-+{
-+	struct s3c2410_udc *udc = &memory;
-+	struct device *dev = &pdev->dev;
-+	int retval;
-+	unsigned int irq;
-+
-+	dev_dbg(dev, "%s()\n", __func__);
-+
-+	usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
-+	if (IS_ERR(usb_bus_clock)) {
-+		dev_err(dev, "failed to get usb bus clock source\n");
-+		return PTR_ERR(usb_bus_clock);
-+	}
-+
-+	clk_enable(usb_bus_clock);
-+
-+	udc_clock = clk_get(NULL, "usb-device");
-+	if (IS_ERR(udc_clock)) {
-+		dev_err(dev, "failed to get udc clock source\n");
-+		return PTR_ERR(udc_clock);
-+	}
-+
-+	clk_enable(udc_clock);
-+
-+	mdelay(10);
-+
-+	dev_dbg(dev, "got and enabled clocks\n");
-+
-+	if (strncmp(pdev->name, "s3c2440", 7) == 0) {
-+		dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
-+		memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
-+		memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
-+		memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
-+		memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
-+	}
-+
-+	spin_lock_init (&udc->lock);
-+	udc_info = pdev->dev.platform_data;
-+
-+	rsrc_start = S3C2410_PA_USBDEV;
-+	rsrc_len   = S3C24XX_SZ_USBDEV;
-+
-+	if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
-+		return -EBUSY;
-+
-+	base_addr = ioremap(rsrc_start, rsrc_len);
-+	if (!base_addr) {
-+		retval = -ENOMEM;
-+		goto err_mem;
-+	}
-+
-+	device_initialize(&udc->gadget.dev);
-+	udc->gadget.dev.parent = &pdev->dev;
-+	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-+
-+	the_controller = udc;
-+	platform_set_drvdata(pdev, udc);
-+
-+	s3c2410_udc_disable(udc);
-+	s3c2410_udc_reinit(udc);
-+
-+	/* irq setup after old hardware state is cleaned up */
-+	retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
-+			IRQF_DISABLED, gadget_name, udc);
-+
-+	if (retval != 0) {
-+		dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
-+		retval = -EBUSY;
-+		goto err_map;
-+	}
-+
-+	dev_dbg(dev, "got irq %i\n", IRQ_USBD);
-+
-+	if (udc_info && udc_info->vbus_pin > 0) {
-+		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
-+		retval = request_irq(irq, s3c2410_udc_vbus_irq,
-+				IRQF_DISABLED | IRQF_TRIGGER_RISING
-+				| IRQF_TRIGGER_FALLING,
-+				gadget_name, udc);
-+
-+		if (retval != 0) {
-+			dev_err(dev, "can't get vbus irq %i, err %d\n",
-+				irq, retval);
-+			retval = -EBUSY;
-+			goto err_int;
-+		}
-+
-+		dev_dbg(dev, "got irq %i\n", irq);
-+	} else {
-+		udc->vbus = 1;
-+	}
-+
-+	if (s3c2410_udc_debugfs_root) {
-+		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
-+				s3c2410_udc_debugfs_root,
-+				udc, &s3c2410_udc_debugfs_fops);
-+		if (IS_ERR(udc->regs_info)) {
-+			dev_warn(dev, "debugfs file creation failed %ld\n",
-+				 PTR_ERR(udc->regs_info));
-+			udc->regs_info = NULL;
-+		}
-+	}
-+
-+	dev_dbg(dev, "probe ok\n");
-+
-+	return 0;
-+
-+err_int:
-+	free_irq(IRQ_USBD, udc);
-+err_map:
-+	iounmap(base_addr);
-+err_mem:
-+	release_mem_region(rsrc_start, rsrc_len);
-+
-+	return retval;
-+}
-+
-+/*
-+ *	s3c2410_udc_remove
-+ */
-+static int s3c2410_udc_remove(struct platform_device *pdev)
-+{
-+	struct s3c2410_udc *udc = platform_get_drvdata(pdev);
-+	unsigned int irq;
-+
-+	dev_dbg(&pdev->dev, "%s()\n", __func__);
-+	if (udc->driver)
-+		return -EBUSY;
-+
-+	debugfs_remove(udc->regs_info);
-+
-+	if (udc_info && udc_info->vbus_pin > 0) {
-+		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
-+		free_irq(irq, udc);
-+	}
-+
-+	free_irq(IRQ_USBD, udc);
-+
-+	iounmap(base_addr);
-+	release_mem_region(rsrc_start, rsrc_len);
-+
-+	platform_set_drvdata(pdev, NULL);
-+
-+	if (!IS_ERR(udc_clock) && udc_clock != NULL) {
-+		clk_disable(udc_clock);
-+		clk_put(udc_clock);
-+		udc_clock = NULL;
-+	}
-+
-+	if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
-+		clk_disable(usb_bus_clock);
-+		clk_put(usb_bus_clock);
-+		usb_bus_clock = NULL;
-+	}
-+
-+	dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
-+	return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
-+{
-+	if (udc_info && udc_info->udc_command)
-+		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
-+
-+	return 0;
-+}
-+
-+static int s3c2410_udc_resume(struct platform_device *pdev)
-+{
-+	if (udc_info && udc_info->udc_command)
-+		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
-+
-+	return 0;
-+}
-+#else
-+#define s3c2410_udc_suspend	NULL
-+#define s3c2410_udc_resume	NULL
-+#endif
-+
-+static struct platform_driver udc_driver_2410 = {
-+	.driver		= {
-+		.name	= "s3c2410-usbgadget",
-+		.owner	= THIS_MODULE,
-+	},
-+	.probe		= s3c2410_udc_probe,
-+	.remove		= s3c2410_udc_remove,
-+	.suspend	= s3c2410_udc_suspend,
-+	.resume		= s3c2410_udc_resume,
-+};
-+
-+static struct platform_driver udc_driver_2440 = {
-+	.driver		= {
-+		.name	= "s3c2440-usbgadget",
-+		.owner	= THIS_MODULE,
-+	},
-+	.probe		= s3c2410_udc_probe,
-+	.remove		= s3c2410_udc_remove,
-+	.suspend	= s3c2410_udc_suspend,
-+	.resume		= s3c2410_udc_resume,
-+};
-+
-+static int __init udc_init(void)
-+{
-+	int retval;
-+
-+	dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
-+
-+	s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
-+	if (IS_ERR(s3c2410_udc_debugfs_root)) {
-+		printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
-+			gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
-+		s3c2410_udc_debugfs_root = NULL;
-+	}
-+
-+	retval = platform_driver_register(&udc_driver_2410);
-+	if (retval)
-+		goto err;
-+
-+	retval = platform_driver_register(&udc_driver_2440);
-+	if (retval)
-+		goto err;
-+
-+	return 0;
-+
-+err:
-+	debugfs_remove(s3c2410_udc_debugfs_root);
-+	return retval;
-+}
-+
-+static void __exit udc_exit(void)
-+{
-+	platform_driver_unregister(&udc_driver_2410);
-+	platform_driver_unregister(&udc_driver_2440);
-+	debugfs_remove(s3c2410_udc_debugfs_root);
-+}
-+
-+EXPORT_SYMBOL(usb_gadget_unregister_driver);
-+EXPORT_SYMBOL(usb_gadget_register_driver);
-+
-+module_init(udc_init);
-+module_exit(udc_exit);
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
-new file mode 100644
-index 0000000..9e0bece
---- /dev/null
-+++ b/drivers/usb/gadget/s3c2410_udc.h
-@@ -0,0 +1,110 @@
-+/*
-+ * linux/drivers/usb/gadget/s3c2410_udc.h
-+ * Samsung on-chip full speed USB device controllers
-+ *
-+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
-+ *	Additional cleanups by Ben Dooks <ben-linux at fluff.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ */
-+
-+#ifndef _S3C2410_UDC_H
-+#define _S3C2410_UDC_H
-+
-+struct s3c2410_ep {
-+	struct list_head		queue;
-+	unsigned long			last_io;	/* jiffies timestamp */
-+	struct usb_gadget		*gadget;
-+	struct s3c2410_udc		*dev;
-+	const struct usb_endpoint_descriptor *desc;
-+	struct usb_ep			ep;
-+	u8				num;
-+
-+	unsigned short			fifo_size;
-+	u8				bEndpointAddress;
-+	u8				bmAttributes;
-+
-+	unsigned			halted : 1;
-+	unsigned			already_seen : 1;
-+	unsigned			setup_stage : 1;
-+};
-+
-+
-+/* Warning : ep0 has a fifo of 16 bytes */
-+/* Don't try to set 32 or 64            */
-+/* also testusb 14 fails  wit 16 but is */
-+/* fine with 8                          */
-+#define EP0_FIFO_SIZE		 8
-+#define EP_FIFO_SIZE		64
-+#define DEFAULT_POWER_STATE	0x00
-+
-+#define S3C2440_EP_FIFO_SIZE	128
-+
-+static const char ep0name [] = "ep0";
-+
-+static const char *const ep_name[] = {
-+	ep0name,                                /* everyone has ep0 */
-+	/* s3c2410 four bidirectional bulk endpoints */
-+	"ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
-+};
-+
-+#define S3C2410_ENDPOINTS       ARRAY_SIZE(ep_name)
-+
-+struct s3c2410_request {
-+	struct list_head		queue;		/* ep's requests */
-+	struct usb_request		req;
-+};
-+
-+enum ep0_state {
-+        EP0_IDLE,
-+        EP0_IN_DATA_PHASE,
-+        EP0_OUT_DATA_PHASE,
-+        EP0_END_XFER,
-+        EP0_STALL,
-+};
-+
-+static const char *ep0states[]= {
-+        "EP0_IDLE",
-+        "EP0_IN_DATA_PHASE",
-+        "EP0_OUT_DATA_PHASE",
-+        "EP0_END_XFER",
-+        "EP0_STALL",
-+};
-+
-+struct s3c2410_udc {
-+	spinlock_t			lock;
-+
-+	struct s3c2410_ep		ep[S3C2410_ENDPOINTS];
-+	int				address;
-+	struct usb_gadget		gadget;
-+	struct usb_gadget_driver	*driver;
-+	struct s3c2410_request		fifo_req;
-+	u8				fifo_buf[EP_FIFO_SIZE];
-+	u16				devstatus;
-+
-+	u32				port_status;
-+	int				ep0state;
-+
-+	unsigned			got_irq : 1;
-+
-+	unsigned			req_std : 1;
-+	unsigned			req_config : 1;
-+	unsigned			req_pending : 1;
-+	u8				vbus;
-+	struct dentry			*regs_info;
-+};
-+
-+#endif

Modified: branches/src/target/kernel/2.6.23.x/patches/series
===================================================================
--- branches/src/target/kernel/2.6.23.x/patches/series	2007-09-26 16:12:59 UTC (rev 3046)
+++ branches/src/target/kernel/2.6.23.x/patches/series	2007-09-26 16:16:04 UTC (rev 3047)
@@ -1,4 +1,3 @@
-#alsa-2.6.23-rc1-commit.dif (merged upstream)
 asoc-platform-hw_init-pcm_emulation-fix.patch
 asoc-kconfig-fix.patch
 missing_defs.patch
@@ -12,7 +11,6 @@
 #s3c2410_udc_from_upstream.p (merged upstream)
 s3c2410_touchscreen.patch
 s3c2410-bbt.patch
-#udc-nomodule-misccr.patch (already dropped for 2.6.22.x)
 s3c_mci.patch
 s3cmci_dbg.patch
 s3cmci-dma-free.patch





More information about the commitlog mailing list