Merge branch 'mirror':

ALSA: Release v1.0.22
    83173ffd313e68586a3b9be71f1b7ddac9dddfe3
diff --git a/alsa/.gitignore b/alsa/.gitignore
new file mode 100644
index 0000000..2b7e15d
--- /dev/null
+++ b/alsa/.gitignore
@@ -0,0 +1,135 @@
+*~
+*.o.cmd
+*.orig
+*.o
+*.ko
+*.mod.c
+.*.d
+.*.cmd
+modules.order
+Module.markers
+
+acinclude.m4
+aclocal.m4
+autom4te.cache/*
+config.log
+config.status
+configure
+Makefile.conf
+snddevices
+toplevel.config
+toplevel.config.in
+version
+Module*.symvers
+.tmp_versions/*
+
+alsa-kernel
+scripts
+linux
+
+acore/control.c
+acore/hrtimer.c
+acore/hwdep.c
+acore/info.c
+acore/init.c
+acore/memalloc.c
+acore/misc.c
+acore/pcm.c
+acore/oss/mixer_oss.c
+acore/oss/pcm_oss.c
+acore/pcm_native.c
+acore/rawmidi.c
+acore/seq/oss/seq_oss.c
+acore/seq/seq.c
+acore/seq/seq_clientmgr.c
+acore/seq/seq_memory.c
+acore/sound.c
+acore/timer.c
+drivers/mpu401/mpu401.c
+drivers/mts64.c
+drivers/pcsp/pcsp.c
+drivers/portman2x4.c
+drivers/opl3/opl3_lib.c
+isa/sb/sb16_csp.c
+isa/wavefront/wavefront_fx.c
+isa/wavefront/wavefront_synth.c
+include/autoconf-extra.h
+include/config.h
+include/config1.h
+include/config1.h.in
+include/asm/
+include/linux/*
+include/media/*
+include/pci_ids_compat.h
+include/i2c-id_compat.h
+include/version.h
+include/sound/.includes
+include/sound/*.h
+pci/ac97/ac97_bus.c
+pci/ac97/ac97_codec.c
+pci/ad1889.c
+pci/ali5451/ali5451.c
+pci/atiixp.c
+pci/atiixp_modem.c
+pci/au88x0/au88x0.c
+pci/bt87x.c
+pci/ca0106/ca0106_main.c
+pci/cmipci.c
+pci/ctxfi/ctatc.c
+pci/ens1370.c
+pci/echoaudio/darla20.c
+pci/echoaudio/darla24.c
+pci/echoaudio/echo3g.c
+pci/echoaudio/echoaudio.c
+pci/echoaudio/gina20.c
+pci/echoaudio/gina24.c
+pci/echoaudio/indigo.c
+pci/echoaudio/indigodj.c
+pci/echoaudio/indigodjx.c
+pci/echoaudio/indigoio.c
+pci/echoaudio/indigoiox.c
+pci/echoaudio/layla20.c
+pci/echoaudio/layla24.c
+pci/echoaudio/mia.c
+pci/echoaudio/mona.c
+pci/emu10k1/emu10k1_main.c
+pci/emu10k1/emu10k1x.c
+pci/fm801.c
+pci/hda/hda_beep.c
+pci/hda/hda_intel.c
+pci/intel8x0.c
+pci/korg1212/korg1212.c
+pci/maestro3.c
+pci/oxygen/virtuoso.c
+pci/riptide/riptide.c
+pci/ymfpci/ymfpci_main.c
+pci/via82xx.c
+pci/via82xx_modem.c
+ppc/awacs.c
+ppc/beep.c
+ppc/tumbler.c
+soc/soc-core.c
+sparc/amd7930.c
+sparc/cs4231.c
+sparc/dbri.c
+usb/usbaudio.c
+usb/usbmidi.c
+usb/usbmixer.c
+usb/caiaq/audio.c
+usb/caiaq/device.c
+usb/caiaq/input.c
+usb/usx2y/usX2Yhwdep.c
+usb/usx2y/usbusx2y.c
+usb/usx2y/usbusx2yaudio.c
+usb/usx2y/usx2yhwdeppcm.c
+utils/alsa-driver.spec
+utils/alsasound
+utils/alsasound.posix
+utils/buildrpm
+utils/docproc
+utils/mod-deps
+doc/DocBook/*.xml
+doc/DocBook/*.sgml
+doc/DocBook/*.pdf
+doc/DocBook/alsa-driver-api
+doc/DocBook/writing-an-alsa-driver
diff --git a/alsa/CARDS-STATUS b/alsa/CARDS-STATUS
new file mode 100644
index 0000000..58dcf48
--- /dev/null
+++ b/alsa/CARDS-STATUS
@@ -0,0 +1,247 @@
+card name:referent:check date:comment
+
+referents:
+ab: Abramo Bagnara <abramo@alsa-project.org>
+jk: Jaroslav Kysela <perex@alsa-project.org>
+ti: Takashi Iwai <tiwai@suse.de>
+(The referent is between parenthesis if the card is not owned but it's
+ supposed to be equivalent to another owned)
+
+check date format: yymmaa
+
+- snd-ad1816a
+Highscreen Sound-Boostar 16 3D
+Analog Devices AD1815
+Analog Devices AD1816A:ti
+TerraTec Base 64
+
+- snd-ad1848
+Analog Devices AD1848
+Analog Devices AD1847
+Crystal Semiconductors CS4248
+
+- snd-als100
+Avance Logic ALS100 - PRO16PNP
+Avance Logic ALS110
+3D Melody MF1000
+Digimate 3D Sound
+Avance Logic ALS120
+RTL RTL3000
+
+- snd-azt2320
+Aztech Systems PRO16V
+Aztech Systems AZT2320
+Aztech Systems AT3300
+Aztech Systems AZT3000
+
+- snd-cmi8330
+C-Media CMI8330:ab
+
+- snd-cmipci
+C-Media CMI8738:ti
+C-Media CMI8338A
+C-Media CMI8338B
+
+- snd-cs4231
+Crystal Semiconductors CS4231
+
+- snd-cs4232
+Turtle Beach TBS-2000
+Turtle Beach Tropez Plus
+AudioSystem EWS64
+SIC CrystalWave 32
+
+- snd-cs4236
+Genius Sound Maker 3DJ
+Crystal Semiconductors CS4235:jk
+Crystal Semiconductors CS4236B
+Hewlett Packard HP6330 sound
+Acer AW37
+EliteGroup P5TX-LA sound
+Crystal 3D
+NewClear 3D
+Dell Optiplex GX1
+Dell Workstation 400 sound
+Turtle Beach Malibu:jk
+Maxi Sound 16 PnP
+Gallant SC-70P
+Acer AW37/Pro
+Acer AW35/Pro
+
+- snd-cs46xx
+Cirrus Logic Sound Fusion (CS4280/CS4610/CS4612):jk
+Cirrus Logic Sound Fusion (CS4612)
+Cirrus Logic Sound Fusion (CS4615)
+
+- snd-dt019x
+Diamond Technologies DT-0196
+Diamond Technologies DT-0197H
+Avance Logic ALS-007
+
+- snd-emu10k1
+Creative Labs SB Live!/PCI512/E-mu APS:ti,jk
+
+- snd-ens1370
+Ensoniq AudioPCI-97 ES1370:jk
+Creative Labs SB PCI64/128 (ES1370)
+
+- snd-ens1371
+Ensoniq AudioPCI ES1371/73:ti,jk
+Ensoniq AudioPCI ES1373
+Creative Labs Ectiva EV1938
+Creative Labs SB PCI64/128 (ES1371/73)
+Creative Labs Vibra PCI128
+Ectiva EV1938
+
+- snd-es1688
+ESS ES688 PnP AudioDrive
+ESS ES1688 PnP AudioDrive
+ESS ES688 AudioDrive
+ESS ES1688 AudioDrive
+
+- snd-es18xx
+ESS ES1868 PnP AudioDrive:ab:000628:
+ESS ES1869 PnP AudioDrive:ab,jk:000628:Incomplete 16 bit dma support
+ESS ES1878 PnP AudioDrive:(ab):U:Incomplete 16 bit dma support
+ESS ES1879 PnP AudioDrive:(ab):U:Incomplete 16 bit dma support
+ESS ES1887 PnP AudioDrive:(ab):U:Incomplete 16 bit dma support
+ESS ES1888 PnP AudioDrive:(ab):U:Incomplete 16 bit dma support
+ESS ES1887 AudioDrive:(ab):U:Incomplete 16 bit dma support
+ESS ES1888 AudioDrive:(ab):U:Incomplete 16 bit dma support
+
+- snd-es1938
+ESS ES1938:ab:000715:See notes inside driver
+TerraTec 128i PCI
+
+- snd-es1968
+ESS Maestro 2e
+ESS Maestro 2
+ESS Maestro 1
+TerraTec DMX
+
+- snd-es968
+ESS AudioDrive ES968
+
+- snd-fm801
+ForteMedia FM801:ab,jk
+
+- snd-gusclassic
+Gravis UltraSound Classic:jk
+
+- snd-gusextreme
+Gravis UltraSound Extreme:jk
+
+- snd-gusmax
+Gravis UltraSound MAX:jk
+
+- snd-ice1712
+MidiMan M Audio Audiophile:jk:
+MidiMan M Audio Delta 1010:jk:
+MidiMan M Audio Delta DiO 2496
+MidiMan M Audio Delta 66:ab:000716:See notes inside driver
+MidiMan M Audio Delta 44:ab:000716:
+Hoontech AudioTrack DSP24:jk
+Hoontech AudioTrack DSP24 Value:jk
+ICEnsemble Generic ICE1712
+ICEnsemble Generic Envy24
+
+- snd-intel8x0
+Intel 82801AA:jk
+Intel 82901AB
+Intel MX440
+
+- snd-interwave-stb
+AMD InterWave STB with TEA6330T:jk
+
+- snd-interwave
+Gravis UltraSound Plug & Play:jk
+STB SoundRage32
+MED MED3210
+Dynasonix Dynasonix Pro
+Panasonic PCA761AW
+
+- snd-mtpav
+MOTU MidiTimePiece AV multiport MIDI
+
+- snd-opl3sa2
+Yamaha YMF719E-S
+Genius Sound Maker 3DX
+Yamaha OPL3SA3
+Intel AL440LX sound
+
+- snd-opti92x-ad1848
+OPTi 82C924 (AD1848):ti
+OPTi 82C925 (AD1848):ti
+
+- snd-opti92x-cs4231
+OPTi 82C924 (CS4231)
+OPTi 82C925 (CS4231)
+
+- snd-opti93x:ti
+OPTi 82C931/3
+
+- snd-pdplus
+SMarian Prodif Plus
+
+- snd-rme96
+RME Digi96
+RME Digi96/8
+RME Digi96/8 PRO
+RME Digi96/8 PST
+RME Digi96/8 PAD
+
+- snd-rme9652
+RME Hammerfall
+RME Hammerfall-Light:ab,jk:000715:
+
+- snd-sb16
+Creative Labs SB 16:ti
+Creative Labs SB Vibra16S
+Creative Labs SB Vibra16C
+Creative Labs SB Vibra16CL
+Creative Labs SB Vibra16X
+
+- snd-sb8
+Creative Labs SB 1.0/SB 2.0/SB Pro
+
+- snd-sbawe
+Creative Labs SB AWE 32
+Creative Labs SB AWE 64:ti,jk
+Creative Labs SB AWE 64 Gold
+
+- snd-serial-u16550
+ALSA MIDI serial
+
+- snd-sgalaxy
+Aztech Systems Sound Galaxy
+
+- snd-sonicvibes
+S3 SonicVibes PCI
+
+- snd-trident
+Trident 4DWave DX
+Trident 4DWave NX:ti,jk
+SiS 7018 PCI Audio:jk
+Best Union Miss Melody 4DWave PCI
+HIS 4DWave PCI
+Warpspeed ONSpeed 4DWave PCI
+Aztech Systems PCI 64-Q3D
+Addonics SV 750
+CHIC True Sound 4Dwave
+Shark Predator4D-PCI
+Jaton SonicWave 4D
+Hoontech SoundTrack Digital 4DWave NX
+
+- snd-via686a
+VIA VT82C686A:jk,ti
+
+- snd-wavefront
+Turtle Beach Maui/Tropez/Tropez+
+
+- snd-ymfpci
+Yamaha YMF724
+Yamaha YMF724F
+Yamaha YMF740
+Yamaha YMF740C:ti
+Yamaha YMF744:ti,jk
+Yamaha YMF754
diff --git a/alsa/COPYING b/alsa/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/alsa/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/alsa/FAQ b/alsa/FAQ
new file mode 100644
index 0000000..cb215db
--- /dev/null
+++ b/alsa/FAQ
@@ -0,0 +1,61 @@
+		Advanced Linux Sound Architecture - Driver
+		==========================================
+	             FAQ - Frequently Asked Questions
+
+Q: My card is not detected at all and is ISA based - non Plug & Play.
+   Can I try something?
+A: If you have compiled driver with the ISA PnP support, you must force
+   the detection of non-PnP version of your card with some drivers (use
+   snd_isapnp=0 parameter - check the INSTALL file). This problem may
+   occur mostly in portable computers where vendors suppressed the ISA PnP
+   extension of sound chips.
+
+Q: When I play something and I try to play something other the second attempt
+   will not fail but instead it hangs waiting for the completion of the first
+   sound.
+A: This is definitely the standard behaviour as described in many official
+   documents that now ALSA follows. There is no reasons to complain about that
+   for the following reasons:
+   - it's the right (standard) way
+   - the application that want a different behaviour can open the device in 
+     O_NONBLOCK mode
+   - all modern OSS drivers in mainstream kernel (cmpci, es1370, es1371,
+     esssolo1, maestro, sonicvibes, vwsnd) works in the same ways and the 
+     others have to be intended buggy
+   - we want you ask to broken applications author to fix them ;-)
+
+Q: The driver is installed and successfully loaded in the runtime kernel,
+   but it does not produce any sound. What's wrong?
+A: You should raise the volume for mixer channels and/or unmute mixer channels.
+   Look for the alsa-utils package at http://www.alsa-project.org. There are
+   native mixers.
+
+Q: How can I store and restore mixer settings?
+A: Use the native alsactl program (strongly preferred) or an another ALSA mixer
+   program.
+
+Q: The driver is loaded, but OSS programs say: Can't open /dev/mixer.
+   What is wrong?
+A: The OSS compatible mixer emulation comes as an add-on module which is not
+   loaded by default. If you have got modified /etc/conf.module as suggested
+   in the INSTALL file, it should be loaded with kerneld or kmod. Check it -
+   if this method for some reason doesn't work - you need to insert
+   the 'snd-mixer-oss' module manually.
+
+Q: The driver is loaded, but OSS programs say: Can't open /dev/dsp.
+   What is wrong?
+A: The OSS compatible PCM (digital audio) emulation comes as an add-on module
+   which is not loaded by default. If you have got modified /etc/conf.module
+   as suggested in the INSTALL file, it should be loaded with kerneld or kmod.
+   Check it - if this method for some reason doesn't work - you need to insert
+   the 'snd-pcm-oss' module manually.
+
+Q: Can I specify which DMA channel will be used for a specific direction with
+   Sound Blaster 16/AWE soundcards?
+A: Yes, you may change the default settings (which is auto) through alsactl
+   utility. Look for "DMA 16-bit" switch in the alsactl.conf file.
+
+Q: Noises in X-win?
+A: Try comment out line in your XF86Config file:
+   #Option "pci_retry"    # faster, but problematic for ISA/PCI soundcards
+   More information: http://www.xfree86.org/3.3.3.1/S39.html
diff --git a/alsa/INSTALL b/alsa/INSTALL
new file mode 100644
index 0000000..347d0a1
--- /dev/null
+++ b/alsa/INSTALL
@@ -0,0 +1,350 @@
+
+		Advanced Linux Sound Architecture - Driver
+		==========================================
+			    Installation guide
+
+
+The ALSA driver replaces the OSS/Free driver.  Since version 0.4.0,
+ALSA has supported only 2.2 or later kernels. The 2.0 kernels are no
+longer supported.
+
+You must compile the kernel with sound support (CONFIG_SOUND on
+2.2/2.4 kernels) either as module or built-in.  You do not need to
+select any of the other sound modules apart from sound support.
+
+Before installing this driver, it will be helpful to read carefully
+the documentation for insmod, modprobe, kmod and for the isapnp
+module if you have an ISA PnP soundcard.
+
+
+Module option name change after 0.9.0rc3
+========================================
+
+Note that module option names were changed in 0.9.0rc4. The 'snd_' prefix
+was removed. You may use script in utils directory (module-options) to
+convert your older /etc/modules.conf to newer one.
+
+
+Quick install
+=============
+
+1) You must have full configured source for the Linux kernel which you
+   want to use for the ALSA drivers. Note that ALSA drivers are part
+   of the kernel, so there is necessary to resolve all symbol dependencies
+   between the used kernel and ALSA driver code. Partly installed kernels
+   (for example from distributor makers) can be unuseable for this action.
+
+2) You must turn on sound support (soundcore module).
+
+3) Run './configure' script.
+
+ * General Options
+   If you do not want ISA PnP support, use --with-isapnp=no switch.
+   If you do not want sequencer support, use --with-sequencer=no switch.
+   If you do not want OSS/Free emulation, use --with-oss=no switch.
+   If you have udev or devfs and want to use more than eight cards, use
+   --enable-dynamic-minors switch.
+   If you want to turn on debug mode, use --with-debug=full switch.
+   If you want to debug soundcard detection, try --with-debug=detect switch.
+
+ * Kernel Source Tree
+   On 2.4/2.6 kernels, the location of the kernel source tree is
+   parsed automatilly from the running kernel.
+   If it's not in the standard place, specify the path via
+   --with-kernel=<kernel_directory>. 
+   On 2.6 kernels, the build directory has to be given via
+   --with-build=<kernel_build_dir> option additionally, too.
+
+ * Drivers to Compile
+   The card drivers to be compiled can be selected via --with-cards option.
+   Pass the card driver name without "snd-" prefix.  To specify
+   multiple drivers, list names with comma (,).
+   Passing "all" will compile all possible drivers (and this is the
+   default choice).
+   Some drivers have compile options.  They can be passed via
+   --with-card-options option.  Multiple options can be passed with comma,
+   too.  The default is "all".
+   For available cards and options, see ./configure --help.
+
+   Note that you have to specify all items you want to enable unless
+   you pass "all".  Or, pass "all" and additionally "NAME=n".  This will
+   enable all but the ones that with =n suffix.  See examples below.
+
+ * Module installation path
+   By passing --with-moddir, you can specify the path to install
+   modules.  When an absolute path is given, the modules are installed
+   to the given directory.  When a relative path is given,
+   e.g. --with-moddir=updates, the modules will be installed to
+   /lib/modules/$VERSION/updates directory.  The directory name might
+   depend on distributions, but in general, "updates" should work.
+
+   Note that when no moddir option is given, the newly built modules
+   will _replace_ the existing modules in
+   /lib/modules/$VERSION/kernel/sound. 
+   So, if you want to keep the original binaries, better to use
+   --with-moddir=updates.
+
+ * Example
+      ./configure --with-debug=full
+          Enable debug option "full"
+
+      ./configure --with-cards=sb16,emu10k1 --with-card-options=sb16-csp
+          Build for cards sb16 and emu10k1 drivers and enable sb16-csp
+          option.  But all other card options are *disabled*.
+
+      ./configure --with-cards=all,hda-intel=n
+          Build drivers except for hda-intel.
+
+ * Tips
+  - You shouldn't try to save the build time too much.  Better to
+    avoid to pass --with-cards and especially --with-card-options
+    options unless you really know what you are doing.  Depending
+    on the combination of options, you can screw up the build pretty
+    easily!
+
+  - The --withdebug=full option is in general recommended.
+
+  - On modern distros with 2.6 kernel, you are likely using udev.
+    Don't forget to add --enable-dynamic-minors option.  Otherwise a
+    device-file mismatch might happen.
+
+  - In short, a safe combination for the recent distros is:
+	./configure --with-debug=full --enable-dynamic-minors \
+		--with-moddir=updates
+
+4) Run 'make'.
+
+5) Run 'make install' as root.
+   If you have already a system with ALSA init script, you should install
+   just only modules via 'make install-modules' so that the existing init
+   script won't be replaced.
+
+6) Run the './snddevices' script to create new sound devices in /dev directory.
+   Skip this step, if you have already /dev/snd/* files, or if you're
+   using a DEVFS or udev.
+
+7) Edit your kernel module config (either /etc/modprobe.conf or
+   /etc/modules.conf, depending on the kernel version).
+   The recent distros don't need special setups (except for some ISA
+   or static drivers), so you can skip this.
+   If you are not sure what to do, you may try the alsaconf script
+   available in the alsa-utils package.
+
+8) Run 'modprobe snd-xxxx' where xxxx is the name of your card.
+   Note: All ALSA ISA drivers support ISA PnP natively, so you don't need
+         isapnptools any more.  Don't use both together.  It will
+         conflict.  For disabling the ALSA ISA PnP support, specify
+         --with-isapnp=no configure switch.
+
+You can also look at the utils/alsasound file. This script is designed for
+the RedHat distribution, but it can be used with other distributions which
+use System V style rc init scripts.
+
+Note: All mixer channels are muted by default. You must use a native
+      or OSS mixer program to unmute appropriate channels (for example a
+      mixer from the alsa-utils package).
+
+Note: This document notices the /etc/modules.conf file. Many current
+      distributions uses the old /etc/conf.modules file. Both names are
+      valid.
+
+
+Kernel Module Configurations
+============================
+
+See alsa-kernel/Documentation/ALSA-Configuration.txt
+(or Documentation/sounds/alsa/ALSA-Configuration.txt in linux-2.6
+ kernel tree).
+
+
+Driver cannot be activated?
+===========================
+
+1) You can check your soundcard setup again and read this install file
+   (module parameters) carefully.
+2) If you have got ISA PnP soundcard:
+   native ISA PnP support: is your setup in /proc/isapnp correct?
+3) If you have *non*-ISA PnP card:
+   set isapnp=0 module option?  Otherwise the driver probes only the
+   ISA PnP cards.
+3) The driver is not still working: remake driver with:
+     ./configure --with-debug=detect; make clean; make
+   Reinsert new driver modules to kernel and look to /var/log/messages if
+   there are some messages. If these messages do not help you, please
+   create a new ticket in our bug reporting system.
+
+
+Compilation from GIT sources
+============================
+
+You need GNU packages autoconf and automake installed in your system
+to compile GIT sources of alsa-driver package.
+
+For compilation you can use these commands:
+
+	make ALSAKERNELDIR=../alsa-kernel all-deps
+		(if the alsa-kernel-dir is really there)
+	aclocal
+	autoconf
+	./configure
+	make dep
+	make
+
+The included gitcompile script does this job for you.
+
+Note: Some automake packages have missing aclocal program. Use newer version
+      in the case.
+
+
+Compilation from Linux kernel tree
+==================================
+
+If you have the linux kernel tree containing the corresponding ALSA
+kernel codes (the version must match), you can build with that instead
+of a separate alsa-kernel tree.  In this case, run
+utils/setup-alsa-kernel script in alsa-driver directory:
+
+	utils/setup-alsa-kernel YOUR-LINUX-KERNEL-TREE-PATH
+
+Then this script will create alsa-kernel sub-directory and make
+necessary symlinks automatically.  If you would like to copy the files
+instead of symlinks (e.g. make an alsa-driver tarball), pass -c option
+to setup-alsa-kernel
+
+	utils/setup-alsa-kernel -c YOUR-LINUX-KERNEL-TREE-PATH
+
+After that, run gitcompile script.
+
+
+Cross-compiling
+===============
+
+Use '--with-cross=prefix' parameter for the configure script.
+
+Example:
+  './configure --with-cross=arm-linux- --with-kernel=/home/ipaq/kernel/linux'.
+
+For 2.6 kernels, pass the same kernel path to --with-build option, too. 
+
+
+Autoloading on 2.2/2.4 Kernels
+==============================
+
+On 2.2 or 2.4 kernels, you have to set the additional aliases for
+auto-loading via kmod in /etc/modules.conf:
+
+----- /etc/modules.conf
+# ALSA portion
+alias char-major-116 snd
+# OSS/Free portion
+alias char-major-14 soundcore
+alias sound-service-0-0 snd-mixer-oss
+alias sound-service-0-1 snd-seq-oss
+alias sound-service-0-3 snd-pcm-oss
+alias sound-service-0-8 snd-seq-oss
+alias sound-service-0-12 snd-pcm-oss
+----- /etc/modules.conf
+
+The aliases sound-service-x-y define the add-on modules for ALSA
+OSS emulation.  For the second or later card, define more aliases
+for mixer and pcm in addition, such as:
+
+----- /etc/modules.conf
+# OSS/Free portion - card #2
+alias sound-service-1-0 snd-mixer-oss
+alias sound-service-1-3 snd-pcm-oss
+alias sound-service-1-12 snd-pcm-oss
+----- /etc/modules.conf
+
+You don't need to define service 1 and 8 for the second or later
+cards.
+
+If you want to autoclean your modules, you should put below line to your
+/etc/crontab:
+
+*/10 * * * *   root  /sbin/modprobe -rs snd-card-0 snd-card-1; /sbin/rmmod -as
+
+You may also want to extend the soundcard list to follow your requirements.
+
+
+DEVFS support
+=============
+
+The ALSA driver fully supports the devfs extension.
+You should add lines below to your devfsd.conf file:
+
+LOOKUP snd MODLOAD ACTION snd
+REGISTER ^sound/.* PERMISSIONS root.audio 660
+REGISTER ^snd/.* PERMISSIONS root.audio 660
+
+Warning: These lines assume that you have the audio group in your system.
+         Otherwise replace audio word with another group name (root for
+         example).
+
+When DEVFS is enabled, snd module has the following option:
+
+    device_mode
+		- permission mask for dynamic sound device filesystem
+		- This is available only when DEVFS is enabled
+		- Default: 0666
+		- E.g.: device_mode=0660
+
+
+Information about Additional Modules
+====================================
+
+  Module snd-pdplus
+  -----------------
+
+    Module for Sek'D/Marian Prodif Plus soundcards.
+
+    silent_exit	- Do not reset when driver is unloaded.
+    init_adat	- Initialise the card in ADAT mode (instead of in digital stereo).
+
+    This module supports multiple cards.
+
+  Module snd-serialmidi
+  ---------------------
+
+    Module for generic serial MIDI adapters.
+
+    sdev	- Device file string for serial device
+		  (default = "/dev/ttyS0")
+    speed	- Speed in bauds. (9600,19200,38400,57600,115200)
+		  (default = 38400)
+    adaptor	- Type of adaptor.
+                  0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
+		  3 = MS-124W M/B
+    devices	- Number of devices assigned to the card.  Default is 1.
+  		  When this is more than 1, multiple serial devices (up
+		  to 8) are assigned to a single card.  The number of
+		  the tail of the device file name is increased for
+		  each device.
+    handshake	- Enable/disable handshaking (default = 1)	
+
+    This module supports multiple devices.
+
+  Module snd-asihpi
+  -----------------
+
+    Module for AudioScience ASI soundcards
+
+    This module supports multiple cards.
+    The driver requires the firmware loader support on kernel.
+
+
+Trouble Shooting
+================
+
+Unresolved symbol with RedHat 9
+-------------------------------
+
+Run depmod -ae and check which symbol is missing.
+If the unresolved symbol is "schedule_work", this is because RedHat
+shipped the kernel with incomplete implementation of workqueue.
+For solving this problem, run the following on the top of alsa-driver
+directory:
+
+	% touch include/linux/workqueue.h
+
+and run "make clean", "make" again.
diff --git a/alsa/Makefile b/alsa/Makefile
new file mode 100644
index 0000000..134cce4
--- /dev/null
+++ b/alsa/Makefile
@@ -0,0 +1,341 @@
+#
+# Makefile for ALSA driver
+# Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>
+#
+
+ifneq ($(KERNELRELEASE),)
+# call from 2.6 kernel build system
+
+obj-m += acore/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ sh/ pcmcia/ aoa/ soc/ misc/
+
+else
+
+ifndef IGROUP
+IGROUP = root
+endif
+ifndef IUSER
+IUSER = root
+endif
+ALSAKERNELFILE = alsa-kernel/sound_core.c
+
+ifeq (Makefile.conf,$(wildcard Makefile.conf))
+include Makefile.conf
+include toplevel.config
+else
+.PHONY: dummy1
+dummy1:
+	$(MAKE) all-deps
+	@echo
+	@echo "Please, run the configure script as first..."
+	@echo
+MAINSRCDIR := $(shell /bin/pwd)
+endif
+
+SND_TOPDIR   = $(MAINSRCDIR)
+export SND_TOPDIR
+
+ifeq (,$(wildcard acinclude.m4))
+.PHONY: dummy2
+dummy2:
+	$(MAKE) all-deps
+	@echo
+	@echo "Please, run the configure script as first..."
+	@echo
+endif
+
+ifdef NEW_KBUILD
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    KBUILD_VERBOSE = $(V)
+  endif
+endif
+ifndef KBUILD_VERBOSE
+  KBUILD_VERBOSE = 0
+endif
+ifdef C
+  ifeq ("$(origin C)", "command line")
+    KBUILD_CHECKSRC = $(C)
+  endif
+endif
+ifndef KBUILD_CHECKSRC
+  KBUILD_CHECKSRC = 0
+endif
+export KBUILD_VERBOSE KBUILD_CHECKSRC
+endif
+
+SUBDIRS  = include acore i2c drivers isa synth pci aoa soc
+CSUBDIRS =
+
+ifndef NEW_KBUILD
+SUBDIRS += support
+endif
+
+ifeq (y,$(CONFIG_ARM))
+SUBDIRS  += arm
+endif
+ifeq (y,$(CONFIG_PPC))
+SUBDIRS  += ppc
+endif
+ifeq (y,$(CONFIG_SPARC32))
+SUBDIRS  += sparc
+else
+ifeq (y,$(CONFIG_SPARC64))
+SUBDIRS  += sparc
+endif
+endif
+ifeq (y,$(CONFIG_MIPS))
+SUBDIRS  += mips
+endif
+ifeq (y,$(CONFIG_SGI))
+SUBDIRS  += hal2
+endif
+ifeq (y,$(CONFIG_USB))
+SUBDIRS  += usb
+endif
+ifeq (y,$(CONFIG_PCMCIA))
+SUBDIRS  += pcmcia
+endif
+ifeq (y,$(CONFIG_PARISC))
+SUBDIRS  += parisc
+endif
+ifeq (y,$(CONFIG_SUPERH))
+SUBDIRS  += sh
+endif
+ifeq (m,$(CONFIG_AC97_BUS))
+SUBDIRS  += misc
+endif
+CSUBDIRS += test utils
+
+KCONFIG_FILES = $(shell find $(SND_TOPDIR) -name Kconfig) $(shell find $(SND_TOPDIR)/alsa-kernel/ -name Kconfig)
+
+.PHONY: all
+all: compile
+
+$(ALSAKERNELFILE):
+	{ \
+	rm -rf alsa-kernel ; \
+	if [ ! -z "$(ALSAKERNELDIR)" ]; then \
+		if [ -f $(ALSAKERNELDIR)/kernel/sched.c ]; then \
+			# whole linux kernel source tree \
+			mkdir alsa-kernel; \
+			for i in $(ALSAKERNELDIR)/sound/* ; do \
+				ln -sf $$i alsa-kernel ; \
+			done ; \
+			ln -sf $(ALSAKERNELDIR)/include/sound \
+						alsa-kernel/include ; \
+			ln -sf $(ALSAKERNELDIR)/Documentation/sound/alsa \
+						alsa-kernel/Documentation ; \
+		else \
+			# alsa-kmirror tree \
+			ln -sf $(ALSAKERNELDIR) alsa-kernel ; \
+			ln -sf alsa-kernel sound ; \
+		fi; \
+	fi \
+	}
+
+# to use newalsakernel target:
+# ALSAKERNELDIR=yourlinuxtree_or_kmirrortree make newalsakernel
+.PHONY: newalsakernel
+newalsakernel: $(ALSAKERNELFILE) clean
+	rm -rf alsa-kernel
+	$(MAKE) $(ALSAKERNELFILE)
+
+utils/mod-deps: utils/mod-deps.c
+	gcc utils/mod-deps.c -o utils/mod-deps
+
+toplevel.config.in: $(KCONFIG_FILES) $(ALSAKERNELFILE) utils/mod-deps kconfig-vers
+	utils/mod-deps --basedir $(SND_TOPDIR)/alsa-kernel --hiddendir $(SND_TOPDIR) --versiondep $(SND_TOPDIR)/kconfig-vers --makeconf > toplevel.config.in
+
+acinclude.m4: $(KCONFIG_FILES) $(ALSAKERNELFILE) utils/mod-deps kconfig-vers
+	utils/mod-deps --basedir $(SND_TOPDIR)/alsa-kernel --hiddendir $(SND_TOPDIR) --versiondep $(SND_TOPDIR)/kconfig-vers --acinclude > acinclude.m4
+
+include/config1.h.in: $(KCONFIG_FILES) $(ALSAKERNELFILE) utils/mod-deps kconfig-vers
+	utils/mod-deps --basedir $(SND_TOPDIR)/alsa-kernel --hiddendir $(SND_TOPDIR) --versiondep $(SND_TOPDIR)/kconfig-vers --include > include/config1.h.in
+
+all-deps: toplevel.config.in acinclude.m4 include/config1.h.in
+
+include/sndversions.h:
+	$(MAKE) dep
+
+.PHONY: compile
+compile: include/sndversions.h
+ifdef NEW_KBUILD
+	$(MAKE) -C $(CONFIG_SND_KERNELDIR) SUBDIRS=$(MAINSRCDIR) $(MAKE_ADDS) CPP="$(CPP)" CC="$(CC)" modules
+	utils/link-modules $(SND_TOPDIR)
+else
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d; then exit 1; fi; done
+endif
+	@echo
+	@echo "ALSA modules were successfully compiled."
+	@echo
+
+.PHONY: dep
+dep:
+ifdef NEW_KBUILD
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d prepare; then exit 1; fi; done
+else
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d fastdep; then exit 1; fi; done
+endif
+
+.PHONY: map
+map:
+	awk "{ if ( length( $$1 ) != 0 ) print $$1 }" snd.map | sort -o snd.map1
+	mv -f snd.map1 snd.map
+
+.PHONY: install
+install: install-headers install-modules install-scripts check-snd-prefix
+	@if [ -L /dev/snd ]; then \
+		echo "The ALSA devices were removed from /proc/asound/dev directory." ; \
+		echo "Creating static device entries in /dev/snd." ; \
+		$(SND_TOPDIR)/snddevices ; \
+	fi
+	cat WARNING
+
+.PHONY: install-headers
+install-headers:
+	if [ -L $(DESTDIR)$(prefix)/include/sound ]; then \
+		rm -f $(DESTDIR)$(prefix)/include/sound; \
+		ln -sf $(MAINSRCDIR)/include/sound $(DESTDIR)$(prefix)/include/sound; \
+	else \
+		rm -rf $(DESTDIR)$(prefix)/include/sound; \
+		install -d -m 755 -g $(IGROUP) -o $(IUSER) $(DESTDIR)$(prefix)/include/sound; \
+		for f in include/sound/*.h; do \
+			install -m 644 -g $(IGROUP) -o $(IUSER) $$f $(DESTDIR)$(prefix)/include/sound; \
+		done \
+	fi
+
+ifeq ($(CONFIG_SND_KERNELDIR)/System.map,$(wildcard $(CONFIG_SND_KERNELDIR)/System.map))
+SYSTEM_MAP_OPT = -F $(CONFIG_SND_KERNELDIR)/System.map
+endif
+
+.PHONY: install-modules
+install-modules:
+ifeq ($(moddir_tree),y)
+	find $(DESTDIR)$(moddir) -name 'snd*.*o' | xargs rm -f
+	find $(DESTDIR)$(moddir) -name 'snd*.*o.gz' | xargs rm -f
+	find $(DESTDIR)$(moddir) -name 'ac97_bus.*o' | xargs rm -f
+	find $(DESTDIR)$(moddir) -name 'ac97_bus.*o.gz' | xargs rm -f
+else
+	rm -f $(DESTDIR)$(moddir)/snd*.*o $(DESTDIR)$(moddir)/persist.o $(DESTDIR)$(moddir)/isapnp.o
+	rm -f $(DESTDIR)$(moddir)/snd*.*o.gz $(DESTDIR)$(moddir)/persist.o.gz $(DESTDIR)$(moddir)/isapnp.o.gz
+endif
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d modules_install; then exit 1; fi; done
+ifeq ($(DESTDIR),)
+	-/sbin/depmod -a $(kaversion) $(SYSTEM_MAP_OPT)
+else
+	@echo "*** This is a \`staged' install using the prefix"
+	@echo "***	\"$(DESTDIR)\"."
+	@echo "***"
+	@echo "*** Once the modules have been moved to their final destination you must run the command"
+	@echo "***	\"/sbin/depmod -a $(kaversion) $(SYSTEM_MAP_OPT)\"."
+	@echo "***"
+	@echo "*** Alternatively, if you build a package (e.g. rpm), include the"
+	@echo "*** depmode command above in the post-(un)install procedure."
+endif
+
+.PHONY: install-scripts
+install-scripts:
+	@for d in /sbin/init.d /etc/rc.d/init.d /etc/init.d; do \
+	 if [ -d $(DESTDIR)$$d ]; then \
+	   if [ -f $(DESTDIR)$$d/alsasound ]; then \
+	     cmp -s utils/alsasound $(DESTDIR)$$d/alsasound || \
+	       install -m 755 -g $(IGROUP) -o $(IUSER) utils/alsasound $(DESTDIR)$$d/alsasound.new; \
+	     break; \
+	   fi; \
+	   install -m 755 -g $(IGROUP) -o $(IUSER) utils/alsasound $(DESTDIR)$$d/alsasound; \
+	   break; \
+	fi; done
+
+.PHONY: check-snd-prefix
+check-snd-prefix:
+	@ if [ x"$(DESTDIR)" = x -a -f /etc/modules.conf ]; then \
+	  if grep -s -q snd_ /etc/modules.conf; then \
+	    echo;\
+	    echo "             ===== WARNING =====";\
+	    echo;\
+	    echo "The options for ALSA modules on your system still include snd_ prefix,";\
+	    echo "which is obsoleted now.  Please fix /etc/modules.conf.";\
+	    echo "For convenience, you can use utils/module-options script to convert";\
+	    echo "the snd_ prefix automatically.";\
+	    echo;\
+	fi; fi
+
+.PHONY: clean1
+clean1:
+	rm -f .depend *.o snd.map*
+ifdef DEXPORT
+	rm -f $(DEXPORT)/*.ver
+endif
+	rm -f modules/*.o modules/*.ko
+
+.PHONY: clean
+clean: clean1
+ifdef NEW_KBUILD
+	rm -rf .tmp_versions
+endif
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d clean; then exit 1; fi; done
+	@for d in $(CSUBDIRS); do if ! $(MAKE) -C $$d clean; then exit 1; fi; done
+
+.PHONY: mrproper
+mrproper: clean1
+	@for d in $(SUBDIRS); do if ! $(MAKE) -C $$d mrproper; then exit 1; fi; done
+	@for d in $(CSUBDIRS); do if ! $(MAKE) -C $$d mrproper; then exit 1; fi; done
+	rm -f *~ out.txt *.orig *.rej .#* .gdb_history
+	rm -f doc/*~
+	-rm -f config.cache config.log config.status Makefile.conf
+	rm -f utils/alsa-driver.spec
+	rm -f `find alsa-kernel -name "*~"`
+	rm -f `find alsa-kernel -name "*.orig"`
+	rm -f `find alsa-kernel -name "*.rej"`
+	rm -f `find alsa-kernel -name ".#*"`
+	rm -f `find alsa-kernel -name "out.txt"`
+	rm -rf autom4te.cache
+
+.PHONY: cvsclean hgclean gitclean
+gitclean: mrproper
+	rm -f configure snddevices aclocal.m4 acinclude.m4 include/config.h include/config1.h \
+	  include/config1.h.in toplevel.config toplevel.config.in \
+	  sound
+	rm -rf include/linux alsa-kernel
+hgclean: gitclean
+cvsclean: gitclean
+
+.PHONY: pack
+pack: $(ALSAKERNELFILE) mrproper
+	chmod 755 utils/alsasound
+	# big note: use always '--bzip2 -p' where -p is fake argument
+	# it seems that some older tar has wrong getopt list
+	{ \
+		cd .. ; \
+		rm -rf alsa-driver/alsa-kernel ; \
+		mv alsa-kmirror alsa-driver/alsa-kernel ; \
+		mv alsa-driver alsa-driver-$(CONFIG_SND_VERSION) ; \
+		tar --exclude=CVS --exclude=kchanges --exclude=.cvsignore \
+                    --exclude='.hg*' --exclude=.gitignore \
+                    --owner=$(IGROUP) --group=$(IUSER) -cv --bzip2 -p \
+                    -f alsa-driver-$(CONFIG_SND_VERSION).tar.bz2 alsa-driver-$(CONFIG_SND_VERSION) ; \
+		mv alsa-driver-$(CONFIG_SND_VERSION) alsa-driver ; \
+	}
+
+.PHONY: uninstall
+uninstall:
+	-rm -rf $(DESTDIR)$(prefix)/include/sound
+ifeq ($(moddir_tree),y)
+	{ \
+		for i in core $(SUBDIRS) ; do \
+			rm -rf $(DESTDIR)$(moddir)/$$i ; \
+		done ; \
+	}
+else
+	rm -f $(DESTDIR)$(moddir)/snd*.o $(DESTDIR)$(moddir)/persist.o $(DESTDIR)$(moddir)/isapnp.o
+endif
+	rm -f $(DESTDIR)/sbin/init.d/alsasound
+	rm -f $(DESTDIR)/etc/rc.d/init.d/alsasound
+	rm -f $(DESTDIR)/etc/init.d/alsasound
+
+.PHONY: TAGS
+TAGS:
+	find . -name '*.[ch]' | etags -
+
+endif # call from 2.6 kernel build system
+
diff --git a/alsa/Makefile.conf.in b/alsa/Makefile.conf.in
new file mode 100644
index 0000000..c25f94b
--- /dev/null
+++ b/alsa/Makefile.conf.in
@@ -0,0 +1,80 @@
+#
+# Configuration Makefile for ALSA driver
+# Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>
+#
+
+NEW_KBUILD       = @NEW_KBUILD@
+
+mainsrcdir	= @srcdir@
+MAINSRCDIR	= @SRCDIR@
+ALSAKERNELDIR	?= @ALSAKERNELDIR@
+
+CROSS_COMPILE   ?= @CROSS_COMPILE@
+ARCH            ?= @ARCH@
+ifdef NEW_KBUILD
+CC		= $(CROSS_COMPILE)@CC@
+CPP		= $(CROSS_COMPILE)@CPP@
+export CROSS_COMPILE ARCH
+else
+AS		= $(CROSS_COMPILE)@AS@
+LD		= $(CROSS_COMPILE)@KLD@
+CC		= $(CROSS_COMPILE)@CC@
+CPP		= $(CROSS_COMPILE)@CPP@
+AR		= $(CROSS_COMPILE)@AR@
+MODFLAGS	= -DMODULE=1
+CFLAGS_KERNEL	=
+GENKSYMS	= @GENKSYMS@
+endif
+
+prefix		= @prefix@
+exec_prefix	= @exec_prefix@
+sysconfdir	= @sysconfdir@
+bindir		= @bindir@
+sbindir		= @sbindir@
+mandir		= @mandir@
+moddir		= @moddir@
+moddir_tree	= @moddir_tree@
+c_opts		= @c_opts@
+m_opts		= @m_opts@
+processor	= @processor@
+msmp		= @msmp@
+kaversion	= @kaversion@
+kversion	= @kversion@
+kpatchlevel	= @kpatchlevel@
+ksublevel	= @ksublevel@
+kextraversion	= @kextraversion@
+
+CONFIG_SND_VERSION	= @CONFIG_SND_VERSION@
+CONFIG_SND_KERNELDIR	= @CONFIG_SND_KERNELDIR@
+CONFIG_MODULES		= y
+CONFIG_SND_MVERSION	= @CONFIG_SND_MVERSION@
+CONFIG_ISAPNP_KERNEL	= @CONFIG_ISAPNP_KERNEL@
+CONFIG_PNP_KERNEL	= @CONFIG_PNP_KERNEL@
+CONFIG_PROC_FS		= @CONFIG_PROC_FS@
+CONFIG_PM		= @CONFIG_PM@
+CONFIG_AC97_BUS		= @CONFIG_AC97_BUS@
+CONFIG_HAS_DMA		= @CONFIG_HAS_DMA@
+
+ifndef NEW_KBUILD
+INCLUDE		= -I$(TOPDIR)/include @EXTRA_INCLUDES@ @KERNEL_INC@
+CFLAGS		= $(MODFLAGS) $(INCLUDE) $(c_opts) -Wall -Wstrict-prototypes \
+	-fomit-frame-pointer -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common \
+	-pipe -DALSA_BUILD -nostdinc -iwithprefix include
+ifdef CONFIG_SND_MVERSION
+CFLAGS += -DMODVERSIONS -include $(CONFIG_SND_KERNELDIR)/include/linux/modversions.h
+endif
+CPPFLAGS = $(MODFLAGS) $(INCLUDE) $(c_opts) -DALSA_BUILD -nostdinc -iwithprefix include
+MAKE		+= $(m_opts)
+SNDVERSIONS	= $(TOPDIR)/include/sndversions.h
+DEXPORT		= $(TOPDIR)/include/modules
+else
+# 2.6 kbuild
+EXTRA_CFLAGS += -DALSA_BUILD
+LINUXINCLUDE := -I$(MAINSRCDIR)/include $(LINUXINCLUDE)
+CPPFLAGS := -I$(MAINSRCDIR)/include $(CPPFLAGS)
+KBUILD_CPPFLAGS := -I$(MAINSRCDIR)/include $(KBUILD_CPPFLAGS)
+# 2.6.24 complains this override...
+# CFLAGS := -I$(MAINSRCDIR)/include $(CFLAGS)
+MAKE_ADDS = @MAKE_ADDS@
+endif
+
diff --git a/alsa/README b/alsa/README
new file mode 100644
index 0000000..01f5815
--- /dev/null
+++ b/alsa/README
@@ -0,0 +1,37 @@
+		Advanced Linux Sound Architecture (ALSA) - Driver
+		=================================================
+			 WWW: http://www.alsa-project.org
+
+
+Features
+========
+
+* general
+  - GPL license
+  - fully modularized architecture
+  - full proc filesystem support - /proc/asound
+  - SMP safe
+  - thread safe
+  - integrated to 2.6+ kernels
+  - moved all additional code (stream conversions etc.) outside the kernel
+* universal control API
+  - new enhanced and flexible API for applications
+  - support for unlimited number of controls
+  - support for mute (and hardware mute if hardware supports it)
+  - support for mixer events
+    - this allows two or more applications to be synchronized
+* digital audio (PCM)
+  - support for all types of hardware
+  - new enhanced API for applications
+  - full real duplex support
+  - stream start synchronization
+* sequencer
+  - support multiple event queues
+* hardware depedent API
+  - support hw specific things (like FX accelerated processing etc.)
+* OSS/Free kernel emulation
+  - mixer
+  - PCM (/dev/dsp) compatibility
+
+More information about the ALSA sound driver is located in alsa-driver/doc
+and alsa-kernel/Documentation directories.
diff --git a/alsa/Rules.make b/alsa/Rules.make
new file mode 100644
index 0000000..ba687b2
--- /dev/null
+++ b/alsa/Rules.make
@@ -0,0 +1,339 @@
+#
+# This file contains rules which are shared between multiple Makefiles.
+#
+# It's a stripped and modified version of /usr/src/linux/Rules.make. [--jk]
+#
+
+MODCURDIR = $(subst $(MAINSRCDIR)/,,$(shell /bin/pwd))
+
+ifdef NEW_KBUILD
+
+ifdef KBUILD_MODULES
+
+# clean obsolete definitions
+export-objs :=
+
+# apply patches beforehand
+.PHONY: cleanup
+cleanup:
+	rm -f *.[oas] *.ko .*.cmd .*.d .*.tmp *.mod.c $(clean-files)
+	@for d in $(patsubst %/,%,$(filter %/, $(obj-y))) \
+	          $(patsubst %/,%,$(filter %/, $(obj-m))) DUMMY; do \
+	 if [ $$d != DUMMY ]; then $(MAKE) -C $$d cleanup || exit 1; fi; \
+	done
+
+else # ! KBUILD_MODULES
+
+first_rule: modules
+
+include $(MAINSRCDIR)/Rules.make1
+
+%.c: %.patch
+	@SND_TOPDIR="$(MAINSRCDIR)" $(SND_TOPDIR)/utils/patch-alsa $@
+
+# apply patches beforehand
+.PHONY: prepare
+prepare: $(clean-files)
+	@for d in $(ALL_SUB_DIRS) DUMMY; do \
+	 if [ $$d != DUMMY ]; then $(MAKE) -C $$d prepare || exit 1; fi; \
+	done
+
+modules:
+	$(MAKE) prepare
+	$(MAKE) -C $(CONFIG_SND_KERNELDIR) SUBDIRS=$(MAINSRCDIR) $(MAKE_ADDS) SND_TOPDIR=$(MAINSRCDIR) modules
+	$(SND_TOPDIR)/utils/link-modules $(MODCURDIR)
+
+ALL_MOBJS := $(filter-out $(obj-y), $(obj-m))
+ALL_MOBJS := $(filter-out %/, $(ALL_MOBJS))
+modules_install:
+ifneq "$(strip $(ALL_MOBJS))" ""
+	mkdir -p $(DESTDIR)$(moddir)/$(MODCURDIR)
+	cp $(sort $(ALL_MOBJS:.o=.ko)) $(DESTDIR)$(moddir)/$(MODCURDIR)
+endif
+	@for d in $(ALL_SUB_DIRS) DUMMY; do \
+	 if [ $$d != DUMMY ]; then $(MAKE) -C $$d modules_install || exit 1; fi; \
+	done
+
+endif # KBUILD_MODULES
+
+else # ! NEW_KBUILD
+
+TOPDIR = $(MAINSRCDIR)
+
+comma = ,
+
+#
+# False targets.
+#
+.PHONY: dummy
+
+#
+# Get things started.
+#
+first_rule: modules
+
+include $(TOPDIR)/Rules.make1
+
+ifndef O_TARGET
+ifndef L_TARGET
+O_TARGET	:= built-in.o
+endif
+endif
+
+#
+# Common rules
+#
+
+%.s: %.c
+	$(CC) -D__KERNEL__ $(CFLAGS) $(EXTRA_CFLAGS)  -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
+
+%.i: %.c
+	$(CPP) -D__KERNEL__ $(CFLAGS) $(EXTRA_CFLAGS) -D"KBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $(CFLAGS_$@) $< > $@
+
+%.o: %.c
+	$(CC) -D__KERNEL__ $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $(CFLAGS_$@) -c -o $@ $<
+
+%.o: %.s
+	$(AS) -D__KERNEL__ $(AFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+
+# Old makefiles define their own rules for compiling .S files,
+# but these standard rules are available for any Makefile that
+# wants to use them.  Our plan is to incrementally convert all
+# the Makefiles to these standard rules.  -- rmk, mec
+ifdef USE_STANDARD_AS_RULE
+
+%.s: %.S
+	$(CPP) -D__KERNEL__ $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) $< > $@
+
+%.o: %.S
+	$(CC) -D__KERNEL__ $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $<
+
+endif
+
+%.c: %.patch
+	@xtmp=`echo $(MODCURDIR) | sed -e 's/^acore/core/'`/$@;\
+	echo "copying file alsa-kernel/$$xtmp";\
+	cp "$(TOPDIR)/alsa-kernel/$$xtmp" $@;\
+	patch -p0 -i $< || { rm $@; exit 1; }
+
+%.isapnp: %.c
+ifeq (y,$(CONFIG_ISAPNP))
+	$(CPP) -C -D__KERNEL__ $(CFLAGS) $(EXTRA_CFLAGS) -D__isapnp_now__ -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $(CFLAGS_$@) $< | awk -f $(TOPDIR)/utils/convert_isapnp_ids > $@
+else
+	rm -f $@
+	touch $@
+endif
+
+#
+#
+#
+all_targets: $(isapnp-files) $(O_TARGET) $(L_TARGET)
+
+#
+# Rule to compile a set of .o files into one .o file
+#
+ifdef O_TARGET
+$(O_TARGET): $(obj-y)
+	touch $@
+endif # O_TARGET
+
+#
+# Rule to compile a set of .o files into one .a file
+#
+ifdef L_TARGET
+$(L_TARGET): $(obj-y)
+	touch $@
+endif
+
+#
+# Rule to link composite objects
+#
+
+__obj-m = $(filter-out export.o,$(obj-m))
+ld-multi-used-m := $(sort $(foreach m,$(__obj-m),$(patsubst %,$(m),$($(basename $(m))-objs) $($(basename $(m))-y))))
+ld-multi-objs-m := $(foreach m, $(ld-multi-used-m), $($(basename $(m))-objs) $($(basename $(m))-y) $(extra-$(basename $(m))-objs))
+
+depend-objs	:= $(foreach m,$(__obj-m),$($(basename $(m))-objs) $($(basename $(m))-y))
+depend-files	:= $(patsubst %.o,%.c,$(depend-objs))
+
+$(ld-multi-used-m) : %.o: $(ld-multi-objs-m)
+	rm -f $@
+	$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(filter $($(basename $@)-objs) $($(basename $@)-y) $(extra-$(basename $@)-objs), $^)
+
+#
+# This make dependencies quickly
+#
+fastdep: $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) update-sndversions $(depend-files)
+ifneq "$(strip $(depend-files))" ""
+		$(CC) -M -D__KERNEL__ -D__isapnp_now__ $(CPPFLAGS) $(EXTRA_CFLAGS) $(depend-files) > .depend
+endif
+
+ifneq "$(strip $(ALL_SUB_DIRS))" ""
+$(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)):
+	$(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep
+endif
+
+#
+# A rule to make subdirectories
+#
+subdir-list = $(sort $(patsubst %,_subdir_%,$(SUB_DIRS)))
+sub_dirs: dummy $(subdir-list)
+
+ifdef SUB_DIRS
+$(subdir-list) : dummy
+	$(MAKE) -C $(patsubst _subdir_%,%,$@)
+endif
+
+#
+# A rule to make modules
+#
+ALL_MOBJS = $(filter-out $(obj-y), $(obj-m))
+
+MOD_DIRS := $(MOD_SUB_DIRS) $(MOD_IN_SUB_DIRS)
+ifneq "$(strip $(MOD_DIRS))" ""
+.PHONY: $(patsubst %,_modsubdir_%,$(MOD_DIRS))
+$(patsubst %,_modsubdir_%,$(MOD_DIRS)) : dummy
+	$(MAKE) -C $(patsubst _modsubdir_%,%,$@) modules
+
+.PHONY: $(patsubst %,_modinst_%,$(MOD_DIRS))
+$(patsubst %,_modinst_%,$(MOD_DIRS)) : dummy
+	$(MAKE) -C $(patsubst _modinst_%,%,$@) modules_install
+endif
+
+.PHONY: modules
+modules: $(isapnp-files) $(ALL_MOBJS) dummy \
+	 $(patsubst %,_modsubdir_%,$(MOD_DIRS))
+
+.PHONY: _modinst__
+_modinst__: dummy
+ifneq "$(strip $(ALL_MOBJS))" ""
+ifeq ($(moddir_tree),y)
+	mkdir -p $(DESTDIR)$(moddir)/$(MODCURDIR)
+	cp $(sort $(ALL_MOBJS)) $(DESTDIR)$(moddir)/$(MODCURDIR)
+else
+	mkdir -p $(DESTDIR)$(moddir)
+	cp $(sort $(ALL_MOBJS)) $(DESTDIR)$(moddir)
+endif
+endif
+
+.PHONY: modules_install
+modules_install: _modinst__ \
+	 $(patsubst %,_modinst_%,$(MOD_DIRS))
+
+#
+# This sets version suffixes on exported symbols
+# Separate the object into "normal" objects and "exporting" objects
+# Exporting objects are: all objects that define symbol tables
+#
+ifdef CONFIG_MODULES
+
+ifeq (y,$(CONFIG_SND_MVERSION))
+ifneq "$(strip $(export-objs))" ""
+
+MODINCL = $(TOPDIR)/include/modules
+MODPREFIX = $(subst /,-,$(MODCURDIR))__
+
+# The -w option (enable warnings) for genksyms will return here in 2.1
+# So where has it gone?
+#
+# Added the SMP separator to stop module accidents between uniprocessor
+# and SMP Intel boxes - AC - from bits by Michael Chastain
+#
+
+ifdef $(msmp)
+	genksyms_smp_prefix := -p smp_
+else
+	genksyms_smp_prefix := 
+endif
+
+$(MODINCL)/$(MODPREFIX)%.ver: %.c update-sndvers
+	@if [ ! -r $(MODINCL)/$(MODPREFIX)$*.stamp -o $(MODINCL)/$(MODPREFIX)$*.stamp -ot $< ]; then \
+		if [ ! -f $(CONFIG_SND_KERNELDIR)/include/linux/modules/$*.stamp ]; then \
+		echo '$(CC) -D__KERNEL__ $(CPPFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \
+		echo '| $(GENKSYMS) $(genksyms_smp_prefix) > $@.tmp'; \
+		$(CC) -D__KERNEL__ $(CPPFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \
+		| $(GENKSYMS) $(genksyms_smp_prefix) > $@.tmp; \
+		if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \
+		else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \
+		elif [ ! -r $@ ]; then touch $@; \
+		fi; \
+	fi; touch $(MODINCL)/$(MODPREFIX)$*.stamp
+
+$(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver)): $(TOPDIR)/include/config.h $(TOPDIR)/include/config1.h
+
+# updates .ver files but not modversions.h
+fastdep: $(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver))
+
+endif # export-objs 
+
+define update-sndvers
+	(tmpfile=`echo $(SNDVERSIONS).tmp`; \
+	(echo "#ifndef _LINUX_SNDVERSIONS_H"; \
+	  echo "#define _LINUX_SNDVERSIONS_H"; \
+	  echo "#include <linux/modsetver.h>"; \
+	  cd $(TOPDIR)/include/modules; \
+	  for f in *.ver; do \
+	    if [ -f $$f ]; then echo "#include \"modules/$${f}\""; fi; \
+	  done; \
+	  echo "#endif"; \
+	) > $${tmpfile}; \
+	if [ -r $(SNDVERSIONS) ] && cmp -s $(SNDVERSIONS) $${tmpfile}; then \
+		echo $(SNDVERSIONS) was not updated; \
+		rm -f $${tmpfile}; \
+	else \
+		echo $(SNDVERSIONS) was updated; \
+		mv -f $${tmpfile} $(SNDVERSIONS); \
+	fi)
+endef
+
+$(SNDVERSIONS):
+	$(update-sndvers)
+
+$(active-objs): $(SNDVERSIONS)
+
+else # !CONFIG_SND_MVERSION
+
+define update-sndvers
+	@echo "" > $(SNDVERSIONS)
+endef
+
+$(SNDVERSIONS):
+	$(update-sndvers)
+
+endif # CONFIG_SND_MVERSION
+
+$(ld-multi-used-m): $(addprefix $(TOPDIR)/modules/,$(ld-multi-used-m))
+
+$(TOPDIR)/modules/%.o: dummy
+	@if ! test -L $@; then \
+	    echo "ln -sf ../$(MODCURDIR)/$(notdir $@) $(TOPDIR)/modules/$(notdir $@)" ; \
+	    ln -sf ../$(MODCURDIR)/$(notdir $@) $(TOPDIR)/modules/$(notdir $@) ; \
+	fi
+
+.PHONY: update-sndversions
+update-sndversions: dummy
+	$(update-sndvers)
+
+ifneq "$(strip $(export-objs))" ""
+ifeq (y,$(CONFIG_SND_MVERSION))
+$(export-objs): $(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver)) $(export-objs:.o=.c)
+else
+$(export-objs): $(export-objs:.o=.c)
+endif
+	$(CC) -D__KERNEL__ $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
+endif
+
+endif # CONFIG_MODULES
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
+
+ifneq ($(wildcard $(TOPDIR)/.hdepend),)
+include $(TOPDIR)/.hdepend
+endif
+
+endif	# NEW_KBUILD
diff --git a/alsa/Rules.make1 b/alsa/Rules.make1
new file mode 100644
index 0000000..fcdf75d
--- /dev/null
+++ b/alsa/Rules.make1
@@ -0,0 +1,79 @@
+#
+# Shared rules
+#
+
+#
+# Parse directories
+#
+
+__subdir-y      := $(patsubst %/,%,$(filter %/, $(obj-y)))
+subdir-y        += $(__subdir-y)
+__subdir-m      := $(patsubst %/,%,$(filter %/, $(obj-m)))
+subdir-m        += $(__subdir-m) $(__subdir-y)
+__subdir-n      := $(patsubst %/,%,$(filter %/, $(obj-n)))
+subdir-n        += $(__subdir-n)
+__subdir-       := $(patsubst %/,%,$(filter %/, $(obj-)))
+subdir-         += $(__subdir-)
+obj-y           := $(patsubst %/, %/built-in.o, $(obj-y))
+obj-m           := $(filter-out %/, $(obj-m))
+
+#
+# ALSA hacks for extra code
+#
+
+subdir-y	+= $(extra-subdir-y)
+subdir-m	+= $(extra-subdir-m)
+subdir-n	+= $(extra-subdir-n)
+
+obj-y		+= $(extra-obj-y)
+obj-m		+= $(extra-obj-m)
+obj-n		+= $(extra-obj-n)
+
+#
+#
+#
+
+both-m          := $(filter $(mod-subdirs), $(subdir-y))
+SUB_DIRS	:= $(subdir-y)
+MOD_SUB_DIRS	:= $(sort $(subdir-m) $(both-m))
+ALL_SUB_DIRS	:= $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
+
+#
+#
+#
+
+#
+# A rule to do nothing
+#
+dummy:
+
+#
+# This is useful for testing
+#
+script:
+	$(SCRIPT)
+
+#
+#
+#
+
+.PHONY: clean1
+clean1:
+	rm -f .depend *.[oas] *.ko .*.cmd .*.tmp *.mod.c *.isapnp $(clean-files)
+
+.PHONY: clean
+clean: $(patsubst %,_sfclean_%,$(ALL_SUB_DIRS)) clean1
+
+.PHONY: mrproper
+mrproper: $(patsubst %,_sfmrproper_%,$(ALL_SUB_DIRS)) clean1
+	rm -f *~ out.txt *.orig *.rej .#* .gdb_history
+
+ifneq "$(strip $(ALL_SUB_DIRS))" ""
+$(patsubst %,_sfclean_%,$(ALL_SUB_DIRS)):
+	$(MAKE) -C $(patsubst _sfclean_%,%,$@) clean
+endif
+
+ifneq "$(strip $(ALL_SUB_DIRS))" ""
+$(patsubst %,_sfmrproper_%,$(ALL_SUB_DIRS)):
+	$(MAKE) -C $(patsubst _sfmrproper_%,%,$@) mrproper
+endif
diff --git a/alsa/SUPPORTED_KERNELS b/alsa/SUPPORTED_KERNELS
new file mode 100644
index 0000000..c3eb577
--- /dev/null
+++ b/alsa/SUPPORTED_KERNELS
@@ -0,0 +1,8 @@
+The alsa-drivers in this package are designed for the following kernels:
+
+ - Vanilla 2.6.29 or earlier
+ - Vanilla 2.4.31 or earlier
+ - Vanilla 2.2.26 or earlier
+
+It's not guaranteed that they work with any newer version than above
+or modified kernels by distributors.
diff --git a/alsa/TODO b/alsa/TODO
new file mode 100644
index 0000000..a2de145
--- /dev/null
+++ b/alsa/TODO
@@ -0,0 +1,24 @@
+- midlevel:
+H remove *fallback memory allocation functions once the hw_params stuff is finished
+H change defaults for Wave volume and DAC/ADC volume
+H add nonblock ioctl for rawmidi
+M add schedule call in all loop that may last more than 1 ms (search udelay/mdelay)
+M add master/divisor to timer
+M add configuration parser for OSS PCM (and perhaps mixer) emulation code
+M add the __setup code to all modules (including midlevel ones)
+L lock, grant and revoke ioctls (not available to application I propose)
+L nonblocking async mode (with requests queue)
+L check multithread safeness wrt at least read/write
+L extend the use of __init and __exit to all initialization code wherever it is
+L clean endianness stuff
+L add work_ptr (to think about)
+
+- lowlevel:
+M create an USB audio driver
+M reduce prepare path (a lot of stuff may be moved to hw_params) for faster xrun recovery
+L ICE1712 - fix consumer part PCM/AC'97 code - Hoontech Envy24 DSP (Jaroslav)
+L CS4236 - test the half duplex (one DMA) settings
+L rewrite CMI8330 PCM part
+L separate chip structure from pcm device
+L get rid of snd_pcm_lib_period_bytes and snd_pcm_lib_buffer_bytes
+L optimize lowlevel drivers for frame unit use
diff --git a/alsa/WARNING b/alsa/WARNING
new file mode 100644
index 0000000..ec38b1e
--- /dev/null
+++ b/alsa/WARNING
@@ -0,0 +1,5 @@
+
+WARNING!!! The mixer channels for the ALSA driver are muted by default!!!
+**************************************************************************
+You would use some ALSA or OSS mixer to set the appropriate volume.
+
diff --git a/alsa/acore/Kconfig b/alsa/acore/Kconfig
new file mode 100644
index 0000000..ffbb104
--- /dev/null
+++ b/alsa/acore/Kconfig
@@ -0,0 +1,27 @@
+# for backward compatibility
+
+if SND
+
+config SND_BIT32_EMUL
+	tristate
+
+config SND_DEBUG_MEMORY
+	bool "Debug memory"
+	depends on SND_DEBUG
+	help
+	  Say Y here to enable debugging of memory allocations.
+
+config SND_HPET
+	tristate "High Precision Event Timer support"
+	depends on HPET && BROKEN
+	select SND_TIMER
+	help
+	  Say Y here to enable HPET support for ALSA.  ALSA uses the
+	  HPE timers as a precise timing source and maps the HPE
+	  timers to ALSA's timer interface.  The ALSA sequencer code
+	  also can use this timing source.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-hpet.
+
+endif	# SND
\ No newline at end of file
diff --git a/alsa/acore/Makefile b/alsa/acore/Makefile
new file mode 100644
index 0000000..d0880be
--- /dev/null
+++ b/alsa/acore/Makefile
@@ -0,0 +1,41 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+clean-files := info.c pcm.c pcm_native.c control.c hwdep.c init.c rawmidi.c \
+	       sound.c timer.c memalloc.c misc.c hrtimer.c
+
+export-objs := control.o device.o info.o info_oss.o init.o isadma.o memory.o \
+	misc.o misc_driver.o sound.o sound_oss.o \
+	pcm.o pcm_lib.o pcm_memory.o pcm_misc.o pcm_native.o \
+	rawmidi.o timer.o hwdep.o memalloc.o vmaster.o wrappers.o
+
+include $(SND_TOPDIR)/alsa-kernel/core/Makefile
+
+snd-objs += wrappers.o misc_driver.o
+ifeq ($(CONFIG_SND_DEBUG_MEMORY),y)
+snd-objs += memory_debug.o
+endif
+snd-page-alloc-objs += memory_wrapper.o
+snd-hpet-objs := hpetimer.o
+
+obj-$(CONFIG_SND_HPET) += snd-hpet.o
+obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
+
+include $(SND_TOPDIR)/Rules.make
+
+info.c: info.inc info.patch $(SND_TOPDIR)/alsa-kernel/core/info.c
+pcm.c: pcm.patch $(SND_TOPDIR)/alsa-kernel/core/pcm.c
+pcm_native.c: pcm_native.patch $(SND_TOPDIR)/alsa-kernel/core/pcm_native.c
+control.c: control.patch $(SND_TOPDIR)/alsa-kernel/core/control.c
+hwdep.c: hwdep.patch $(SND_TOPDIR)/alsa-kernel/core/hwdep.c
+init.c: init.patch $(SND_TOPDIR)/alsa-kernel/core/init.c
+rawmidi.c: rawmidi.patch $(SND_TOPDIR)/alsa-kernel/core/rawmidi.c
+sound.c: sound.patch $(SND_TOPDIR)/alsa-kernel/core/sound.c
+timer.c: timer.patch $(SND_TOPDIR)/alsa-kernel/core/timer.c
+memalloc.c: memalloc.patch memalloc.inc memalloc.inc1 $(SND_TOPDIR)/alsa-kernel/core/memalloc.c
+misc.c: misc.patch $(SND_TOPDIR)/alsa-kernel/core/misc.c
+hrtimer.c: hrtimer.patch $(SND_TOPDIR)/alsa-kernel/core/hrtimer.c
diff --git a/alsa/acore/control.patch b/alsa/acore/control.patch
new file mode 100644
index 0000000..4b67090
--- /dev/null
+++ b/alsa/acore/control.patch
@@ -0,0 +1,84 @@
+--- ../alsa-kernel/core/control.c	2009-11-18 14:27:35.000000000 +0100
++++ control.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,5 @@
++#define __NO_VERSION__
++#include "adriver.h"
+ /*
+  *  Routines for driver control interface
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -21,6 +23,7 @@
+ 
+ #include <linux/threads.h>
+ #include <linux/interrupt.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/time.h>
+@@ -727,6 +730,10 @@
+ 	return result;
+ }
+ 
++#ifdef CONFIG_SND_BIT32_EMUL_MODULE
++EXPORT_SYMBOL(snd_ctl_elem_read);
++#endif
++
+ static int snd_ctl_elem_read_user(struct snd_card *card,
+ 				  struct snd_ctl_elem_value __user *_control)
+ {
+@@ -783,6 +790,10 @@
+ 	return result;
+ }
+ 
++#ifdef CONFIG_SND_BIT32_EMUL_MODULE
++EXPORT_SYMBOL(snd_ctl_elem_write);
++#endif
++
+ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+ 				   struct snd_ctl_elem_value __user *_control)
+ {
+@@ -1371,25 +1382,44 @@
+ /*
+  * ioctl32 compat
+  */
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "control_compat.c"
+ #else
+ #define snd_ctl_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_ctl_ioctl_old(struct inode *inode, struct file * file,
++			     unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_ctl_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /*
+  *  INIT PART
+  */
+ 
+ static const struct file_operations snd_ctl_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		snd_ctl_read,
+ 	.open =		snd_ctl_open,
+ 	.release =	snd_ctl_release,
+ 	.poll =		snd_ctl_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_ctl_ioctl,
+ 	.compat_ioctl =	snd_ctl_ioctl_compat,
++#else
++	.ioctl =	snd_ctl_ioctl_old,
++#endif
+ 	.fasync =	snd_ctl_fasync,
+ };
+ 
diff --git a/alsa/acore/control_compat.c b/alsa/acore/control_compat.c
new file mode 100644
index 0000000..d72dfa1
--- /dev/null
+++ b/alsa/acore/control_compat.c
@@ -0,0 +1 @@
+#include "../alsa-kernel/core/control_compat.c"
diff --git a/alsa/acore/device.c b/alsa/acore/device.c
new file mode 100644
index 0000000..c629d17
--- /dev/null
+++ b/alsa/acore/device.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/device.c"
diff --git a/alsa/acore/hpetimer.c b/alsa/acore/hpetimer.c
new file mode 100644
index 0000000..bcab50b
--- /dev/null
+++ b/alsa/acore/hpetimer.c
@@ -0,0 +1,130 @@
+/*
+ *  HPET based high-frequency timer
+ *
+ *  Copyright (c) 2005 Clemens Ladisch
+ *
+ *   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 "adriver.h"
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+#include <sound/info.h>
+#include <linux/hpet.h>
+
+static int frequency = 1024;
+static snd_timer_t *hpetimer;
+static struct hpet_task hpet_task;
+
+static int snd_hpet_open(snd_timer_t *timer)
+{
+	int err;
+
+	err = hpet_register(&hpet_task, 0);
+	if (err < 0)
+		return err;
+	hpet_control(&hpet_task, HPET_IRQFREQ, frequency);
+	timer->private_data = &hpet_task;
+	return 0;
+}
+
+static int snd_hpet_close(snd_timer_t *timer)
+{
+	hpet_unregister(&hpet_task);
+	hpet_task.ht_opaque = NULL;
+	return 0;
+}
+
+static int snd_hpet_start(snd_timer_t *timer)
+{
+	return hpet_control(&hpet_task, HPET_IE_ON, 0);
+}
+
+static int snd_hpet_stop(snd_timer_t *timer)
+{
+	return hpet_control(&hpet_task, HPET_IE_OFF, 0);
+}
+
+static void snd_hpet_task_func(void *private_data)
+{
+	snd_timer_interrupt((snd_timer_t *)private_data, 1);
+}
+
+static struct _snd_timer_hardware snd_hpet_hw = {
+	.flags = SNDRV_TIMER_HW_AUTO,
+	.ticks = 100000000,
+	.open = snd_hpet_open,
+	.close = snd_hpet_close,
+	.start = snd_hpet_start,
+	.stop = snd_hpet_stop,
+};
+
+static int __init hpetimer_init(void)
+{
+	int err;
+	snd_timer_t *timer;
+
+	if (frequency < 32 || frequency > 8192) {
+		snd_printk(KERN_ERR "invalid frequency %d\n", frequency);
+		return -EINVAL;
+	}
+
+	err = snd_timer_global_new("hpet", SNDRV_TIMER_GLOBAL_HPET, &timer);
+	if (err < 0)
+		return err;
+
+	timer->module = THIS_MODULE;
+	strcpy(timer->name, "high precision event timer");
+	timer->hw = snd_hpet_hw;
+	timer->hw.resolution = 1000000000 / frequency;
+
+	hpet_task.ht_func = snd_hpet_task_func;
+	hpet_task.ht_data = timer;
+
+	err = snd_timer_global_register(timer);
+	if (err < 0) {
+		snd_timer_global_free(timer);
+		return err;
+	}
+	hpetimer = timer;
+	return 0;
+}
+
+static void __exit hpetimer_exit(void)
+{
+	if (hpetimer)
+		snd_timer_global_unregister(hpetimer);
+}
+
+
+module_init(hpetimer_init)
+module_exit(hpetimer_exit)
+
+module_param(frequency, int, 0444);
+MODULE_PARM_DESC(frequency, "timer frequency in Hz");
+
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("High Precision Event Timer");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HPET));
+
+EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/hrtimer.patch b/alsa/acore/hrtimer.patch
new file mode 100644
index 0000000..8e7ab51
--- /dev/null
+++ b/alsa/acore/hrtimer.patch
@@ -0,0 +1,19 @@
+--- ../alsa-kernel/core/hrtimer.c	2009-12-11 14:40:22.000000000 +0100
++++ hrtimer.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  * ALSA timer back-end using hrtimer
+  * Copyright (C) 2008 Takashi Iwai
+@@ -65,6 +66,11 @@
+ 		return -ENOMEM;
+ 	hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ 	stime->timer = t;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
++	stime->hrt.cb_mode = HRTIMER_CB_IRQSAFE;
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) && defined(HRTIMER_STATE_PENDING)
++	stime->hrt.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
++#endif
+ 	stime->hrt.function = snd_hrtimer_callback;
+ 	atomic_set(&stime->running, 0);
+ 	t->private_data = stime;
diff --git a/alsa/acore/hwdep.patch b/alsa/acore/hwdep.patch
new file mode 100644
index 0000000..26ab2c6
--- /dev/null
+++ b/alsa/acore/hwdep.patch
@@ -0,0 +1,63 @@
+--- ../alsa-kernel/core/hwdep.c	2008-08-08 15:08:59.000000000 +0200
++++ hwdep.c	2008-08-08 15:10:26.000000000 +0200
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Hardware dependent layer
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -21,6 +22,7 @@
+ 
+ #include <linux/major.h>
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+ #include <linux/mutex.h>
+@@ -305,27 +307,46 @@
+ 	return -ENOIOCTLCMD;
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "hwdep_compat.c"
+ #else
+ #define snd_hwdep_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_hwdep_ioctl_old(struct inode *inode, struct file * file,
++			       unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_hwdep_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /*
+ 
+  */
+ 
+ static const struct file_operations snd_hwdep_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner = 	THIS_MODULE,
++#endif
+ 	.llseek =	snd_hwdep_llseek,
+ 	.read = 	snd_hwdep_read,
+ 	.write =	snd_hwdep_write,
+ 	.open =		snd_hwdep_open,
+ 	.release =	snd_hwdep_release,
+ 	.poll =		snd_hwdep_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_hwdep_ioctl,
+ 	.compat_ioctl =	snd_hwdep_ioctl_compat,
++#else
++	.ioctl =	snd_hwdep_ioctl_old,
++#endif
+ 	.mmap =		snd_hwdep_mmap,
+ };
+ 
diff --git a/alsa/acore/hwdep_compat.c b/alsa/acore/hwdep_compat.c
new file mode 100644
index 0000000..30b1c85
--- /dev/null
+++ b/alsa/acore/hwdep_compat.c
@@ -0,0 +1 @@
+#include "../alsa-kernel/core/hwdep_compat.c"
diff --git a/alsa/acore/info.inc b/alsa/acore/info.inc
new file mode 100644
index 0000000..80f4c95
--- /dev/null
+++ b/alsa/acore/info.inc
@@ -0,0 +1,148 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+#include <linux/utsrelease.h>
+#include <linux/proc_fs.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/version.h>
+
+static int snd_info_card_readlink(struct dentry *dentry,
+				  char *buffer, int buflen)
+{
+        char *s = PDE(dentry->d_inode)->data;
+	int len;
+	
+	if (s == NULL)
+		return -EIO;
+	len = strlen(s);
+	if (len > buflen)
+		len = buflen;
+	if (copy_to_user(buffer, s, len))
+		return -EFAULT;
+	return len;
+}
+
+static struct dentry *snd_info_card_followlink(struct dentry *dentry,
+					       struct dentry *base,
+					       unsigned int follow)
+{
+	char *s = PDE(dentry->d_inode)->data;
+	return lookup_dentry(s, base, follow);
+}
+
+static struct file_operations snd_info_card_link_operations =
+{
+	NULL
+};
+
+struct inode_operations snd_info_card_link_inode_operations =
+{
+	.default_file_ops =	&snd_info_card_link_operations,
+	.readlink =		snd_info_card_readlink,
+	.follow_link =		snd_info_card_followlink,
+};
+
+static struct proc_dir_entry *proc_symlink(const char *name,
+					   struct proc_dir_entry *parent,
+					   const char *dest)
+{
+	char *s = kstrdup(dest, GFP_KERNEL);
+	struct proc_dir_entry *p;
+
+	if (s == NULL)
+		return NULL;
+	p = create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
+ 	if (p == NULL) {
+		kfree(s);
+ 		return NULL;
+	}
+	p->data = s;
+	p->ops = &snd_info_card_link_inode_operations;
+	return p;
+}
+
+static void snd_info_fill_inode(struct inode *inode, int fill)
+{
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+}
+
+static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
+{
+	de->fill_inode = snd_info_fill_inode;
+}
+
+void snd_remove_proc_entry(struct proc_dir_entry *parent,
+			   struct proc_dir_entry *de)
+{
+	if (parent && de) {
+		if (S_ISLNK(de->mode) && de->data) {
+			kfree(de->data);
+			de->data = 0;
+		}
+		proc_unregister(parent, de->low_ino);
+	}
+}
+
+#else /* LINUX_VERSION_CODE < 2.4.0 */
+
+static void snd_remove_proc_entry(struct proc_dir_entry *parent,
+                                  struct proc_dir_entry *de)
+{
+	if (de)
+		remove_proc_entry(de->name, parent);
+}
+
+#endif
+
+#ifdef HAVE_PROCFS_OWNER
+static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
+{
+	de->owner = THIS_MODULE;
+}
+
+/**
+ * snd_create_proc_entry - create a procfs entry
+ * @name: the name of the proc file
+ * @mode: the file permission bits, S_Ixxx
+ * @parent: the parent proc-directory entry
+ *
+ * Creates a new proc file entry with the given name and permission
+ * on the given directory.
+ *
+ * Returns the pointer of new instance or NULL on failure.
+ */
+static struct proc_dir_entry *
+	snd_create_proc_entry(const char *name, mode_t mode,
+			      struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *p;
+	p = create_proc_entry(name, mode, parent);
+	if (p)
+		snd_info_entry_prepare(p);
+	return p;
+}
+static void snd_remove_proc_entry(struct proc_dir_entry *parent,
+                                  struct proc_dir_entry *de)
+{
+        if (de)
+                remove_proc_entry(de->name, parent);
+}
+#else
+static inline struct proc_dir_entry *
+	snd_create_proc_entry(const char *name, mode_t mode,
+			      struct proc_dir_entry *parent)
+{
+	return create_proc_entry(name, mode, parent);
+}
+#endif /* HAVE_PROCFS_OWNER */
diff --git a/alsa/acore/info.patch b/alsa/acore/info.patch
new file mode 100644
index 0000000..b0a58d4
--- /dev/null
+++ b/alsa/acore/info.patch
@@ -0,0 +1,177 @@
+--- ../alsa-kernel/core/info.c	2009-07-06 14:32:55.000000000 +0200
++++ info.c	2009-07-06 14:39:42.000000000 +0200
+@@ -1,3 +1,4 @@
++#include "info.inc"
+ /*
+  *  Information interface for ALSA driver
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -88,10 +89,18 @@
+ 	char *nbuf;
+ 
+ 	nsize = PAGE_ALIGN(nsize);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) || \
++	defined(CONFIG_SND_DEBUG_MEMORY)
++	nbuf = kmalloc(nsize, GFP_KERNEL);
++	if (!nbuf)
++		return -ENOMEM;
++	memcpy(nbuf, buffer->buffer, buffer->len);
++	kfree(buffer->buffer);
++#else	
+ 	nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
+ 	if (! nbuf)
+ 		return -ENOMEM;
+-
++#endif
+ 	buffer->buffer = nbuf;
+ 	buffer->len = nsize;
+ 	return 0;
+@@ -152,13 +161,6 @@
+ struct snd_info_entry *snd_oss_root;
+ #endif
+ 
+-static void snd_remove_proc_entry(struct proc_dir_entry *parent,
+-				  struct proc_dir_entry *de)
+-{
+-	if (de)
+-		remove_proc_entry(de->name, parent);
+-}
+-
+ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
+ {
+ 	struct snd_info_private_data *data;
+@@ -167,7 +169,9 @@
+ 
+ 	data = file->private_data;
+ 	entry = data->entry;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
+ 	lock_kernel();
++#endif
+ 	switch (entry->content) {
+ 	case SNDRV_INFO_CONTENT_TEXT:
+ 		switch (orig) {
+@@ -196,7 +200,9 @@
+ 	}
+ 	ret = -ENXIO;
+ out:
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
+ 	unlock_kernel();
++#endif
+ 	return ret;
+ }
+ 
+@@ -481,9 +487,26 @@
+ 	return -ENOTTY;
+ }
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_info_entry_ioctl_old(struct inode *inode, struct file * file,
++				    unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_info_entry_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	struct inode *inode = file->f_path.dentry->d_inode;
++#else
++	struct inode *inode = file->f_dentry->d_inode;
++#endif
+ 	struct snd_info_private_data *data;
+ 	struct snd_info_entry *entry;
+ 
+@@ -504,22 +527,35 @@
+ 
+ static const struct file_operations snd_info_entry_operations =
+ {
++#ifndef LINUX_2_2
+ 	.owner =		THIS_MODULE,
++#endif
+ 	.llseek =		snd_info_entry_llseek,
+ 	.read =			snd_info_entry_read,
+ 	.write =		snd_info_entry_write,
+ 	.poll =			snd_info_entry_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_info_entry_ioctl,
++#else
++	.ioctl =		snd_info_entry_ioctl_old,
++#endif
+ 	.mmap =			snd_info_entry_mmap,
+ 	.open =			snd_info_entry_open,
+ 	.release =		snd_info_entry_release,
+ };
+ 
++#ifdef LINUX_2_2
++static struct inode_operations snd_info_entry_inode_operations =
++{
++	&snd_info_entry_operations,	/* default sound info directory file-ops */
++}
++#endif
++
+ int __init snd_info_init(void)
+ {
+ 	struct proc_dir_entry *p;
+ 
+-	p = create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
++	p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+ 	if (p == NULL)
+ 		return -ENOMEM;
+ 	snd_proc_root = p;
+@@ -907,6 +943,7 @@
+ 
+ EXPORT_SYMBOL(snd_card_proc_new);
+ 
++
+ /**
+  * snd_info_free_entry - release the info entry
+  * @entry: the info entry
+@@ -946,13 +983,21 @@
+ 		return -ENXIO;
+ 	root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
+ 	mutex_lock(&info_mutex);
+-	p = create_proc_entry(entry->name, entry->mode, root);
++	p = snd_create_proc_entry(entry->name, entry->mode, root);
+ 	if (!p) {
+ 		mutex_unlock(&info_mutex);
+ 		return -ENOMEM;
+ 	}
+-	if (!S_ISDIR(entry->mode))
++#if defined(HAVE_PROCFS_OWNER) && defined(LINUX_2_2)
++	p->owner = entry->module;
++#endif
++	if (!S_ISDIR(entry->mode)) {
++#ifndef LINUX_2_2
+ 		p->proc_fops = &snd_info_entry_operations;
++#else
++		p->ops = &snd_info_entry_inode_operations;
++#endif
++	}
+ 	p->size = entry->size;
+ 	p->data = entry;
+ 	entry->p = p;
+@@ -972,9 +1017,19 @@
+ 
+ static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ {
++	static char *kernel_version = UTS_RELEASE;
++
+ 	snd_iprintf(buffer,
+ 		    "Advanced Linux Sound Architecture Driver Version "
+ 		    CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"
++		    "Compiled on " __DATE__ " for kernel %s"
++#ifdef CONFIG_SMP
++		    " (SMP)"
++#endif
++#ifdef MODVERSIONS
++		    " with versioned symbols"
++#endif
++		    ".\n", kernel_version
+ 		   );
+ }
+ 
diff --git a/alsa/acore/info_oss.c b/alsa/acore/info_oss.c
new file mode 100644
index 0000000..c7342c8
--- /dev/null
+++ b/alsa/acore/info_oss.c
@@ -0,0 +1,7 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include <linux/version.h>
+#ifndef CONFIG_HAVE_INIT_UTSNAME
+#define init_utsname()	(&system_utsname)
+#endif
+#include "../alsa-kernel/core/info_oss.c"
diff --git a/alsa/acore/init.patch b/alsa/acore/init.patch
new file mode 100644
index 0000000..fbd4796
--- /dev/null
+++ b/alsa/acore/init.patch
@@ -0,0 +1,90 @@
+--- ../alsa-kernel/core/init.c	2009-09-07 15:59:08.000000000 +0200
++++ init.c	2009-09-07 16:04:43.000000000 +0200
+@@ -1,3 +1,5 @@
++#define __NO_VERSION__
++#include "adriver.h"
+ /*
+  *  Initialization routines
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -296,11 +298,19 @@
+ 	return POLLERR | POLLNVAL;
+ }
+ 
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ static long snd_disconnect_ioctl(struct file *file,
+ 				 unsigned int cmd, unsigned long arg)
+ {
+ 	return -ENODEV;
+ }
++#else
++static int snd_disconnect_ioctl_old(struct inode *inode, struct file *file,
++				    unsigned int cmd, unsigned long arg)
++{
++	return -ENODEV;
++}
++#endif
+ 
+ static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+@@ -314,16 +324,22 @@
+ 
+ static const struct file_operations snd_shutdown_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner = 	THIS_MODULE,
++#endif
+ 	.llseek =	snd_disconnect_llseek,
+ 	.read = 	snd_disconnect_read,
+ 	.write =	snd_disconnect_write,
+ 	.release =	snd_disconnect_release,
+ 	.poll =		snd_disconnect_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl = snd_disconnect_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl = snd_disconnect_ioctl,
+ #endif
++#else
++	.ioctl =	snd_disconnect_ioctl_old,
++#endif
+ 	.mmap =		snd_disconnect_mmap,
+ 	.fasync =	snd_disconnect_fasync
+ };
+@@ -651,9 +667,21 @@
+ 		return -EINVAL;
+ #ifndef CONFIG_SYSFS_DEPRECATED
+ 	if (!card->card_dev) {
++#ifdef CONFIG_SND_HAS_DEVICE_CREATE_DRVDATA
++		card->card_dev = device_create_drvdata(sound_class, card->dev,
++						       MKDEV(0, 0), card,
++						       "card%i", card->number);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ 		card->card_dev = device_create(sound_class, card->dev,
+ 					       MKDEV(0, 0), card,
+ 					       "card%i", card->number);
++#else
++		card->card_dev = device_create(sound_class, card->dev,
++					       MKDEV(0, 0),
++					       "card%i", card->number);
++		if (card->card_dev && !IS_ERR(card->card_dev))
++			dev_set_drvdata(card->card_dev, card);
++#endif
+ 		if (IS_ERR(card->card_dev))
+ 			card->card_dev = NULL;
+ 	}
+@@ -945,3 +973,16 @@
+ 
+ EXPORT_SYMBOL(snd_power_wait);
+ #endif /* CONFIG_PM */
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
++/* just for old ABI compatibility */
++struct snd_card *snd_card_new(int idx, const char *id,
++			      struct module *module, int extra_size)
++{
++	struct snd_card *card;
++	if (snd_card_create(idx, id, module, extra_size, &card) < 0)
++		return NULL;
++	return card;
++}
++EXPORT_SYMBOL(snd_card_new);
++#endif
diff --git a/alsa/acore/ioctl32/Makefile b/alsa/acore/ioctl32/Makefile
new file mode 100644
index 0000000..8d10998
--- /dev/null
+++ b/alsa/acore/ioctl32/Makefile
@@ -0,0 +1,16 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
+ifneq ($(CONFIG_SND_SEQUENCER),n)
+  snd-ioctl32-objs += seq32.o
+endif
+
+obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
+
+include $(SND_TOPDIR)/Rules.make
+
diff --git a/alsa/acore/ioctl32/hwdep32.c b/alsa/acore/ioctl32/hwdep32.c
new file mode 100644
index 0000000..765577f
--- /dev/null
+++ b/alsa/acore/ioctl32/hwdep32.c
@@ -0,0 +1,18 @@
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "hwdep32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size);
+#define copy_in_user hack_copy_in_user
+#endif
+
+#include "hwdep32_new.c"
+
+#endif
diff --git a/alsa/acore/ioctl32/hwdep32_new.c b/alsa/acore/ioctl32/hwdep32_new.c
new file mode 100644
index 0000000..f8d533f
--- /dev/null
+++ b/alsa/acore/ioctl32/hwdep32_new.c
@@ -0,0 +1,73 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for hwdep API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/hwdep.h>
+#include <asm/uaccess.h>
+#include "ioctl32.h"
+
+struct snd_hwdep_dsp_image32 {
+	u32 index;
+	unsigned char name[64];
+	u32 image;	/* pointer */
+	u32 length;
+	u32 driver_data;
+} /* don't set packed attribute here */;
+
+static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_hwdep_dsp_image __user *data, *dst;
+	struct snd_hwdep_dsp_image32 __user *data32, *src;
+	compat_caddr_t ptr;
+
+	data32 = compat_ptr(arg);
+	data = compat_alloc_user_space(sizeof(*data));
+
+	/* index and name */
+	if (copy_in_user(data, data32, 4 + 64))
+		return -EFAULT;
+	if (__get_user(ptr, &data32->image) ||
+	    __put_user(compat_ptr(ptr), &data->image))
+		return -EFAULT;
+	src = data32;
+	dst = data;
+	COPY_CVT(length);
+	COPY_CVT(driver_data);
+	return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_HWDEP_IOCTL_DSP_LOAD32   = _IOW('H', 0x03, struct snd_hwdep_dsp_image32)
+};
+
+struct ioctl32_mapper hwdep_mappers[] = {
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
+	{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/hwdep32_old.c b/alsa/acore/ioctl32/hwdep32_old.c
new file mode 100644
index 0000000..31ea31f
--- /dev/null
+++ b/alsa/acore/ioctl32/hwdep32_old.c
@@ -0,0 +1,73 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for hwdep API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/hwdep.h>
+#include <asm/uaccess.h>
+#include "ioctl32_old.h"
+
+struct snd_hwdep_dsp_image32 {
+	u32 index;
+	unsigned char name[64];
+	u32 image;	/* pointer */
+	u32 length;
+	u32 driver_data;
+} /* don't set packed attribute here */;
+
+static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_hwdep_dsp_image data;
+	struct snd_hwdep_dsp_image32 data32;
+	mm_segment_t oldseg;
+	int err;
+
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	memset(&data, 0, sizeof(data));
+	data.index = data32.index;
+	memcpy(data.name, data32.name, sizeof(data.name));
+	data.image = compat_ptr(data32.image);
+	data.length = data32.length;
+	data.driver_data = data32.driver_data;
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+	set_fs(oldseg);
+	return err;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_HWDEP_IOCTL_DSP_LOAD32   = _IOW('H', 0x03, struct snd_hwdep_dsp_image32)
+};
+
+struct ioctl32_mapper hwdep_mappers[] = {
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
+	MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
+	{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/ioctl32.c b/alsa/acore/ioctl32/ioctl32.c
new file mode 100644
index 0000000..4bcfe9c
--- /dev/null
+++ b/alsa/acore/ioctl32/ioctl32.c
@@ -0,0 +1,30 @@
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "ioctl32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size)
+{
+	char tmp[64];
+	while (size) {
+		size_t s = sizeof(tmp) < size ? sizeof(tmp) : size;
+		if (copy_from_user(tmp, from, s) || copy_to_user(to, tmp, s))
+			break;
+		size -= s;
+		from += s;
+		to += s;
+	}
+	return size;
+}
+#define copy_in_user hack_copy_in_user
+#endif /* SPARC64 && < 2.6.8 */
+
+#include "ioctl32_new.c"
+
+#endif /* 2.6.0 */
+
diff --git a/alsa/acore/ioctl32/ioctl32.h b/alsa/acore/ioctl32/ioctl32.h
new file mode 100644
index 0000000..8a7ff9f
--- /dev/null
+++ b/alsa/acore/ioctl32/ioctl32.h
@@ -0,0 +1,102 @@
+/*
+ *   32bit -> 64bit ioctl helpers
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ *
+ * This file registers the converters from 32-bit ioctls to 64-bit ones.
+ * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
+ * macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
+ *
+ */
+
+#ifndef __ALSA_IOCTL32_H
+#define __ALSA_IOCTL32_H
+
+#include <linux/compat.h>
+
+#define COPY(x) \
+	do { \
+		if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
+			return -EFAULT; \
+	} while (0)
+
+#define COPY_ARRAY(x) \
+	do { \
+		if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
+			return -EFAULT; \
+	} while (0)
+
+#define COPY_CVT(x) \
+	do { \
+		__typeof__(src->x) __val_tmp; \
+		if (get_user(__val_tmp, &src->x) || \
+		    put_user(__val_tmp, &dst->x))\
+			return -EFAULT; \
+	} while (0)
+
+#define convert_from_32(type, dstp, srcp)\
+{\
+	struct snd_##type __user *dst = dstp;\
+	struct snd_##type##32 __user *src = srcp;\
+	CVT_##snd_##type();\
+}
+
+#define convert_to_32(type, dstp, srcp)\
+{\
+	struct snd_##type __user *src = srcp;\
+	struct snd_##type##32 __user *dst = dstp;\
+	CVT_##snd_##type();\
+}
+
+
+#define DEFINE_ALSA_IOCTL(type) \
+static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+{\
+	struct snd_##type##32 __user *data32;\
+	struct snd_##type __user *data;\
+	int err;\
+	data32 = compat_ptr(arg);\
+	data = compat_alloc_user_space(sizeof(*data));\
+	convert_from_32(type, data, data32);\
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
+	if (err < 0) \
+		return err;\
+	if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
+		convert_to_32(type, data32, data);\
+	}\
+	return 0;\
+}
+
+#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
+static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
+	return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
+}
+
+#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
+
+struct ioctl32_mapper {
+	unsigned int cmd;
+	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+	int registered;
+};
+
+int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
+
+int snd_ioctl32_register(struct ioctl32_mapper *mappers);
+void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
+
+#endif /* __ALSA_IOCTL32_H */
diff --git a/alsa/acore/ioctl32/ioctl32_new.c b/alsa/acore/ioctl32/ioctl32_new.c
new file mode 100644
index 0000000..4f245d2
--- /dev/null
+++ b/alsa/acore/ioctl32/ioctl32_new.c
@@ -0,0 +1,442 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for control API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/minors.h>
+#include <asm/uaccess.h>
+#include "ioctl32.h"
+
+
+/*
+ * register/unregister mappers
+ * exported for other modules
+ */
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("ioctl32 wrapper for ALSA");
+MODULE_LICENSE("GPL");
+
+int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
+int unregister_ioctl32_conversion(unsigned int cmd);
+
+
+int snd_ioctl32_register(struct ioctl32_mapper *mappers)
+{
+	int err;
+	struct ioctl32_mapper *m;
+
+	for (m = mappers; m->cmd; m++) {
+		err = register_ioctl32_conversion(m->cmd, m->handler);
+		if (err >= 0)
+			m->registered++;
+	}
+	return 0;
+}
+
+void snd_ioctl32_unregister(struct ioctl32_mapper *mappers)
+{
+	struct ioctl32_mapper *m;
+
+	for (m = mappers; m->cmd; m++) {
+		if (m->registered) {
+			unregister_ioctl32_conversion(m->cmd);
+			m->registered = 0;
+		}
+	}
+}
+
+
+/*
+ * compatible wrapper
+ */
+int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
+{
+	if (! filp->f_op || ! filp->f_op->ioctl)
+		return -ENOTTY;
+	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+}
+
+
+/*
+ * Controls
+ */
+
+struct snd_ctl_elem_list32 {
+	u32 offset;
+	u32 space;
+	u32 used;
+	u32 count;
+	u32 pids;
+	unsigned char reserved[50];
+} /* don't set packed attribute here */;
+
+static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_list32 __user *data32;
+	struct snd_ctl_elem_list __user *data;
+	compat_caddr_t ptr;
+	int err;
+
+	data32 = compat_ptr(arg);
+	data = compat_alloc_user_space(sizeof(*data));
+
+	/* offset, space, used, count */
+	if (copy_in_user(data, data32, 4 * sizeof(u32)))
+		return -EFAULT;
+	/* pids */
+	if (__get_user(ptr, &data32->pids) ||
+	    __put_user(compat_ptr(ptr), &data->pids))
+		return -EFAULT;
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	if (copy_in_user(data32, data, 4 * sizeof(u32)))
+		return -EFAULT;
+	return 0;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST);
+
+/*
+ * control element info
+ * it uses union, so the things are not easy..
+ */
+
+struct snd_ctl_elem_info32 {
+	struct snd_ctl_elem_id id; // the size of struct is same
+	s32 type;
+	u32 access;
+	u32 count;
+	s32 owner;
+	union {
+		struct {
+			s32 min;
+			s32 max;
+			s32 step;
+		} integer;
+		struct {
+			u64 min;
+			u64 max;
+			u64 step;
+		} integer64;
+		struct {
+			u32 items;
+			u32 item;
+			char name[64];
+		} enumerated;
+		unsigned char reserved[128];
+	} value;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_info __user *data, *src;
+	struct snd_ctl_elem_info32 __user *data32, *dst;
+	unsigned int type;
+	int err;
+
+	data32 = compat_ptr(arg);
+	data = compat_alloc_user_space(sizeof(*data));
+
+	/* copy id */
+	if (copy_in_user(&data->id, &data32->id, sizeof(data->id)))
+		return -EFAULT;
+	/* we need to copy the item index.
+	 * hope this doesn't break anything..
+	 */
+	if (copy_in_user(&data->value.enumerated.item,
+			 &data32->value.enumerated.item,
+			 sizeof(data->value.enumerated.item)))
+		return -EFAULT;
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	if (err < 0)
+		return err;
+	/* restore info to 32bit */
+	/* for COPY_CVT macro */
+	src = data;
+	dst = data32;
+	/* id, type, access, count */
+	if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) ||
+	    copy_in_user(&data32->type, &data->type, 3 * sizeof(u32)))
+		return -EFAULT;
+	COPY_CVT(owner);
+	__get_user(type, &data->type);
+	switch (type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		COPY_CVT(value.integer.min);
+		COPY_CVT(value.integer.max);
+		COPY_CVT(value.integer.step);
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+		if (copy_in_user(&data32->value.integer64,
+				 &data->value.integer64,
+				 sizeof(data->value.integer64)))
+			return -EFAULT;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+		if (copy_in_user(&data32->value.enumerated,
+				 &data->value.enumerated,
+				 sizeof(data->value.enumerated)))
+			return -EFAULT;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO);
+
+struct snd_ctl_elem_value32 {
+	struct snd_ctl_elem_id id;
+	unsigned int indirect;	/* bit-field causes misalignment */
+        union {
+		s32 integer[128];	/* integer and boolean need conversion */
+#ifndef CONFIG_X86_64
+		s64 integer64[64];	/* for alignment */
+#endif
+		unsigned char data[512];	/* others should be compatible */
+        } value;
+        unsigned char reserved[128];	/* not used */
+};
+
+
+/* hmm, it's so hard to retrieve the value type from the control id.. */
+static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id)
+{
+	struct snd_kcontrol *kctl;
+	struct snd_ctl_elem_info info;
+	int err;
+
+	down_read(&card->controls_rwsem);
+	kctl = snd_ctl_find_id(card, id);
+	if (! kctl) {
+		up_read(&card->controls_rwsem);
+		return -ENXIO;
+	}
+	info.id = *id;
+	snd_power_lock(card);
+	err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+	if (err >= 0)
+		err = kctl->info(kctl, &info);
+	snd_power_unlock(card);
+	up_read(&card->controls_rwsem);
+	if (err >= 0)
+		err = info.type;
+	return err;
+}
+
+static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_value *data;
+	struct snd_ctl_elem_value32 __user *data32;
+	struct snd_ctl_file *ctl;
+	struct snd_card *card;
+	int err, i, indirect;
+	int type;
+
+	/* sanity check */
+	if (imajor(file->f_dentry->d_inode) != snd_major ||
+	    !snd_lookup_minor_data(iminor(file->f_dentry->d_inode),
+				   SNDRV_DEVICE_TYPE_CONTROL))
+		return -ENOTTY;
+
+	if ((ctl = file->private_data) == NULL)
+		return -ENOTTY;
+
+	data32 = compat_ptr(arg);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) {
+		err = -EFAULT;
+		goto __end;
+	}
+	if (__get_user(indirect, &data32->indirect)) {
+		err = -EFAULT;
+		goto __end;
+	}
+	/* FIXME: indirect access is not supported */
+	if (indirect) {
+		err = -EINVAL;
+		goto __end;
+	}
+	card = ctl->card;
+	type = get_ctl_type(card, &data->id);
+	if (type < 0) {
+		err = type;
+		goto __end;
+	}
+
+	switch (type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		for (i = 0; i < 128; i++) {
+			int val;
+			if (__get_user(val, &data32->value.integer[i])) {
+				err = -EFAULT;
+				goto __end;
+			}
+			data->value.integer.value[i] = val;
+		}
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+	case SNDRV_CTL_ELEM_TYPE_BYTES:
+	case SNDRV_CTL_ELEM_TYPE_IEC958:
+		if (__copy_from_user(data->value.bytes.data,
+				     data32->value.data,
+				     sizeof(data32->value.data))) {
+			err = -EFAULT;
+			goto __end;
+		}
+		break;
+	default:
+		printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
+		err = -EINVAL;
+		goto __end;
+	}
+
+	snd_power_lock(card);
+	err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+	if (err >= 0) {
+		if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ)
+			err = snd_ctl_elem_read(card, data);
+		else
+			err = snd_ctl_elem_write(card, ctl, data);
+	}
+	snd_power_unlock(card);
+	if (err < 0)
+		goto __end;
+	/* restore info to 32bit */
+	switch (type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		for (i = 0; i < 128; i++) {
+			int val;
+			val = data->value.integer.value[i];
+			if (__put_user(val, &data32->value.integer[i])) {
+				err = -EFAULT;
+				goto __end;
+			}
+		}
+		break;
+	default:
+		if (__copy_to_user(data32->value.data,
+				   data->value.bytes.data,
+				   sizeof(data32->value.data))) {
+			err = -EFAULT;
+			goto __end;
+		}
+		break;
+	}
+	err = 0;
+      __end:
+	kfree(data);
+	return err;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE);
+
+/*
+ */
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32),
+	SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32),
+	SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32),
+	SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
+};
+
+static struct ioctl32_mapper control_mappers[] = {
+	/* controls (without rawmidi, hwdep, timer releated ones) */
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO),
+	{ SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) },
+	{ SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) },
+	{ SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) },
+	{ SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) },
+	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE),
+	{ 0 }
+};
+
+
+/*
+ */
+
+extern struct ioctl32_mapper pcm_mappers[];
+extern struct ioctl32_mapper rawmidi_mappers[];
+extern struct ioctl32_mapper timer_mappers[];
+extern struct ioctl32_mapper hwdep_mappers[];
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+extern struct ioctl32_mapper seq_mappers[];
+#endif
+
+static void snd_ioctl32_done(void)
+{
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+	snd_ioctl32_unregister(seq_mappers);
+#endif
+	snd_ioctl32_unregister(hwdep_mappers);
+	snd_ioctl32_unregister(timer_mappers);
+	snd_ioctl32_unregister(rawmidi_mappers);
+	snd_ioctl32_unregister(pcm_mappers);
+	snd_ioctl32_unregister(control_mappers);
+}
+
+static int __init snd_ioctl32_init(void)
+{
+	snd_ioctl32_register(control_mappers);
+	snd_ioctl32_register(pcm_mappers);
+	snd_ioctl32_register(rawmidi_mappers);
+	snd_ioctl32_register(timer_mappers);
+	snd_ioctl32_register(hwdep_mappers);
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+	snd_ioctl32_register(seq_mappers);
+#endif
+	return 0;
+}
+
+module_init(snd_ioctl32_init)
+module_exit(snd_ioctl32_done)
diff --git a/alsa/acore/ioctl32/ioctl32_old.c b/alsa/acore/ioctl32/ioctl32_old.c
new file mode 100644
index 0000000..485c472
--- /dev/null
+++ b/alsa/acore/ioctl32/ioctl32_old.c
@@ -0,0 +1,456 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for control API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <asm/uaccess.h>
+#include "ioctl32_old.h"
+
+/*
+ * register/unregister mappers
+ * exported for other modules
+ */
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("ioctl32 wrapper for ALSA");
+MODULE_LICENSE("GPL");
+
+int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
+int unregister_ioctl32_conversion(unsigned int cmd);
+
+
+int snd_ioctl32_register(struct ioctl32_mapper *mappers)
+{
+	int err;
+	struct ioctl32_mapper *m;
+
+	for (m = mappers; m->cmd; m++) {
+		err = register_ioctl32_conversion(m->cmd, m->handler);
+		if (err >= 0)
+			m->registered++;
+	}
+	return 0;
+}
+
+void snd_ioctl32_unregister(struct ioctl32_mapper *mappers)
+{
+	struct ioctl32_mapper *m;
+
+	for (m = mappers; m->cmd; m++) {
+		if (m->registered) {
+			unregister_ioctl32_conversion(m->cmd);
+			m->registered = 0;
+		}
+	}
+}
+
+
+/*
+ * compatible wrapper
+ */
+int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
+{
+	if (! filp->f_op || ! filp->f_op->ioctl)
+		return -ENOTTY;
+	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+}
+
+
+/*
+ * Controls
+ */
+
+struct snd_ctl_elem_list32 {
+	u32 offset;
+	u32 space;
+	u32 used;
+	u32 count;
+	u32 pids;
+	unsigned char reserved[50];
+} /* don't set packed attribute here */;
+
+#define CVT_snd_ctl_elem_list()\
+{\
+	COPY(offset);\
+	COPY(space);\
+	COPY(used);\
+	COPY(count);\
+	CPTR(pids);\
+}
+
+static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_list32 data32;
+	struct snd_ctl_elem_list data;
+	mm_segment_t oldseg;
+	int err;
+
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	memset(&data, 0, sizeof(data));
+	data.offset = data32.offset;
+	data.space = data32.space;
+	data.used = data32.used;
+	data.count = data32.count;
+	data.pids = compat_ptr(data32.pids);
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+	set_fs(oldseg);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	data32.offset = data.offset;
+	data32.space = data.space;
+	data32.used = data.used;
+	data32.count = data.count;
+	//data.pids = data.pids;
+	if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+		return -EFAULT;
+	return 0;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST);
+
+/*
+ * control element info
+ * it uses union, so the things are not easy..
+ */
+
+struct snd_ctl_elem_info32 {
+	struct snd_ctl_elem_id id; // the size of struct is same
+	s32 type;
+	u32 access;
+	u32 count;
+	s32 owner;
+	union {
+		struct {
+			s32 min;
+			s32 max;
+			s32 step;
+		} integer;
+		struct {
+			u64 min;
+			u64 max;
+			u64 step;
+		} integer64;
+		struct {
+			u32 items;
+			u32 item;
+			char name[64];
+		} enumerated;
+		unsigned char reserved[128];
+	} value;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_info data;
+	struct snd_ctl_elem_info32 data32;
+	int err;
+	mm_segment_t oldseg;
+
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	memset(&data, 0, sizeof(data));
+	data.id = data32.id;
+	/* we need to copy the item index.
+	 * hope this doesn't break anything..
+	 */
+	data.value.enumerated.item = data32.value.enumerated.item;
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+	set_fs(oldseg);
+	if (err < 0)
+		return err;
+	/* restore info to 32bit */
+	data32.id = data.id;
+	data32.type = data.type;
+	data32.access = data.access;
+	data32.count = data.count;
+	data32.owner = data.owner;
+	switch (data.type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		data32.value.integer.min = data.value.integer.min;
+		data32.value.integer.max = data.value.integer.max;
+		data32.value.integer.step = data.value.integer.step;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+		data32.value.integer64.min = data.value.integer64.min;
+		data32.value.integer64.max = data.value.integer64.max;
+		data32.value.integer64.step = data.value.integer64.step;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+		data32.value.enumerated.items = data.value.enumerated.items;
+		data32.value.enumerated.item = data.value.enumerated.item;
+		memcpy(data32.value.enumerated.name, data.value.enumerated.name,
+		       sizeof(data.value.enumerated.name));
+		break;
+	default:
+		break;
+	}
+	if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+		return -EFAULT;
+	return 0;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO);
+
+struct snd_ctl_elem_value32 {
+	struct snd_ctl_elem_id id;
+	unsigned int indirect;	/* bit-field causes misalignment */
+        union {
+		union {
+			s32 value[128];
+			u32 value_ptr;
+		} integer;
+		union {
+			s64 value[64];
+			u32 value_ptr;
+		} integer64;
+		union {
+			u32 item[128];
+			u32 item_ptr;
+		} enumerated;
+		union {
+			unsigned char data[512];
+			u32 data_ptr;
+		} bytes;
+		struct snd_aes_iec958 iec958;
+        } value;
+        unsigned char reserved[128];
+};
+
+
+/* hmm, it's so hard to retrieve the value type from the control id.. */
+static int get_ctl_type(struct file *file, struct snd_ctl_elem_id *id)
+{
+	struct snd_ctl_file *ctl;
+	struct snd_kcontrol *kctl;
+	struct snd_ctl_elem_info info;
+	int err;
+
+	ctl = file->private_data;
+
+	down_read(&ctl->card->controls_rwsem);
+	kctl = snd_ctl_find_id(ctl->card, id);
+	if (! kctl) {
+		up_read(&ctl->card->controls_rwsem);
+		return -ENXIO;
+	}
+	info.id = *id;
+	err = kctl->info(kctl, &info);
+	up_read(&ctl->card->controls_rwsem);
+	if (err >= 0)
+		err = info.type;
+	return err;
+}
+
+
+static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_ctl_elem_value *data;
+	struct snd_ctl_elem_value32 *data32;
+	int err, i;
+	int type;
+	mm_segment_t oldseg;
+
+	/* FIXME: check the sane ioctl.. */
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+	if (data == NULL || data32 == NULL) {
+		err = -ENOMEM;
+		goto __end;
+	}
+
+	if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+		err = -EFAULT;
+		goto __end;
+	}
+	memset(data, 0, sizeof(*data));
+	data->id = data32->id;
+	data->indirect = data32->indirect;
+	if (data->indirect) /* FIXME: this is not correct for long arrays */
+		data->value.integer.value_ptr = compat_ptr(data32->value.integer.value_ptr);
+	type = get_ctl_type(file, &data->id);
+	if (type < 0) {
+		err = type;
+		goto __end;
+	}
+	if (! data->indirect) {
+		switch (type) {
+		case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+		case SNDRV_CTL_ELEM_TYPE_INTEGER:
+			for (i = 0; i < 128; i++)
+				data->value.integer.value[i] = data32->value.integer.value[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+			for (i = 0; i < 64; i++)
+				data->value.integer64.value[i] = data32->value.integer64.value[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+			for (i = 0; i < 128; i++)
+				data->value.enumerated.item[i] = data32->value.enumerated.item[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_BYTES:
+			memcpy(data->value.bytes.data, data32->value.bytes.data,
+			       sizeof(data->value.bytes.data));
+			break;
+		case SNDRV_CTL_ELEM_TYPE_IEC958:
+			data->value.iec958 = data32->value.iec958;
+			break;
+		default:
+			printk("unknown type %d\n", type);
+			break;
+		}
+	}
+
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	set_fs(oldseg);
+	if (err < 0)
+		goto __end;
+	/* restore info to 32bit */
+	if (! data->indirect) {
+		switch (type) {
+		case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+		case SNDRV_CTL_ELEM_TYPE_INTEGER:
+			for (i = 0; i < 128; i++)
+				data32->value.integer.value[i] = data->value.integer.value[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+			for (i = 0; i < 64; i++)
+				data32->value.integer64.value[i] = data->value.integer64.value[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+			for (i = 0; i < 128; i++)
+				data32->value.enumerated.item[i] = data->value.enumerated.item[i];
+			break;
+		case SNDRV_CTL_ELEM_TYPE_BYTES:
+			memcpy(data32->value.bytes.data, data->value.bytes.data,
+			       sizeof(data->value.bytes.data));
+			break;
+		case SNDRV_CTL_ELEM_TYPE_IEC958:
+			data32->value.iec958 = data->value.iec958;
+			break;
+		default:
+			break;
+		}
+	}
+	err = 0;
+	if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+		err = -EFAULT;
+      __end:
+      	if (data32)
+      		kfree(data32);
+	if (data)
+		kfree(data);
+	return err;
+}
+
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
+DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE);
+
+/*
+ */
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32),
+	SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32),
+	SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32),
+	SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
+};
+
+static struct ioctl32_mapper control_mappers[] = {
+	/* controls (without rawmidi, hwdep, timer releated ones) */
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO),
+	{ SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) },
+	{ SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) },
+	{ SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) },
+	{ SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) },
+	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE),
+	{ 0 }
+};
+
+
+/*
+ */
+
+extern struct ioctl32_mapper pcm_mappers[];
+extern struct ioctl32_mapper rawmidi_mappers[];
+extern struct ioctl32_mapper timer_mappers[];
+extern struct ioctl32_mapper hwdep_mappers[];
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+extern struct ioctl32_mapper seq_mappers[];
+#endif
+
+static void snd_ioctl32_done(void)
+{
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+	snd_ioctl32_unregister(seq_mappers);
+#endif
+	snd_ioctl32_unregister(hwdep_mappers);
+	snd_ioctl32_unregister(timer_mappers);
+	snd_ioctl32_unregister(rawmidi_mappers);
+	snd_ioctl32_unregister(pcm_mappers);
+	snd_ioctl32_unregister(control_mappers);
+}
+
+static int __init snd_ioctl32_init(void)
+{
+	snd_ioctl32_register(control_mappers);
+	snd_ioctl32_register(pcm_mappers);
+	snd_ioctl32_register(rawmidi_mappers);
+	snd_ioctl32_register(timer_mappers);
+	snd_ioctl32_register(hwdep_mappers);
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+	snd_ioctl32_register(seq_mappers);
+#endif
+	return 0;
+}
+
+module_init(snd_ioctl32_init)
+module_exit(snd_ioctl32_done)
+
+EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/ioctl32/ioctl32_old.h b/alsa/acore/ioctl32/ioctl32_old.h
new file mode 100644
index 0000000..6f30abd
--- /dev/null
+++ b/alsa/acore/ioctl32/ioctl32_old.h
@@ -0,0 +1,131 @@
+/*
+ *   32bit -> 64bit ioctl helpers
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ *
+ * This file registers the converters from 32-bit ioctls to 64-bit ones.
+ * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
+ * macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
+ *
+ */
+
+#ifndef __ALSA_IOCTL32_H
+#define __ALSA_IOCTL32_H
+
+#include <linux/compat.h>
+
+#define COPY(x)  (dst->x = src->x)
+#define CPTR(x)	 (dst->x = compat_ptr(src->x))
+
+#define convert_from_32(type, dstp, srcp)\
+{\
+	struct snd_##type *dst = dstp;\
+	struct snd_##type##32 *src = srcp;\
+	CVT_##snd_##type();\
+}
+
+#define convert_to_32(type, dstp, srcp)\
+{\
+	struct snd_##type *src = srcp;\
+	struct snd_##type##32 *dst = dstp;\
+	CVT_##snd_##type();\
+}
+
+
+#define DEFINE_ALSA_IOCTL(type) \
+static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+{\
+	struct snd_##type##32 data32;\
+	struct snd_##type data;\
+	mm_segment_t oldseg;\
+	int err;\
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))\
+		return -EFAULT;\
+	memset(&data, 0, sizeof(data));\
+	convert_from_32(type, &data, &data32);\
+	oldseg = get_fs();\
+	set_fs(KERNEL_DS);\
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);\
+	set_fs(oldseg);\
+	if (err < 0) \
+		return err;\
+	if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
+		convert_to_32(type, &data32, &data);\
+		if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))\
+			return -EFAULT;\
+	}\
+	return 0;\
+}
+
+#define DEFINE_ALSA_IOCTL_BIG(type) \
+static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+{\
+	struct snd_##type##32 *data32;\
+	struct snd_##type *data;\
+	mm_segment_t oldseg;\
+	int err;\
+	data32 = kmalloc(sizeof(*data32), GFP_KERNEL); \
+	data = kmalloc(sizeof(*data), GFP_KERNEL); \
+	if (data32 == NULL || data == NULL) { \
+		err = -ENOMEM; \
+		goto __end; \
+	}\
+	if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) { \
+		err = -EFAULT; \
+		goto __end; \
+	}\
+	memset(data, 0, sizeof(*data));\
+	convert_from_32(type, data, data32);\
+	oldseg = get_fs();\
+	set_fs(KERNEL_DS);\
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
+	set_fs(oldseg);\
+	if (err < 0) \
+		goto __end;\
+	err = 0;\
+	if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
+		convert_to_32(type, data32, data);\
+		if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))\
+			err = -EFAULT;\
+	}\
+      __end:\
+      	if (data)\
+      		kfree(data);\
+      	if (data32)\
+      		kfree(data32);\
+	return err;\
+}
+
+#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
+static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
+	return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
+}
+
+#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
+
+struct ioctl32_mapper {
+	unsigned int cmd;
+	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+	int registered;
+};
+
+int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
+
+int snd_ioctl32_register(struct ioctl32_mapper *mappers);
+void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
+
+#endif /* __ALSA_IOCTL32_H */
diff --git a/alsa/acore/ioctl32/pcm32.c b/alsa/acore/ioctl32/pcm32.c
new file mode 100644
index 0000000..c3a70ac
--- /dev/null
+++ b/alsa/acore/ioctl32/pcm32.c
@@ -0,0 +1,18 @@
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "pcm32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size);
+#define copy_in_user hack_copy_in_user
+#endif
+
+#include "pcm32_new.c"
+
+#endif
diff --git a/alsa/acore/ioctl32/pcm32_new.c b/alsa/acore/ioctl32/pcm32_new.c
new file mode 100644
index 0000000..41a022c
--- /dev/null
+++ b/alsa/acore/ioctl32/pcm32_new.c
@@ -0,0 +1,467 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for PCM API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/minors.h>
+#include "ioctl32.h"
+
+
+/* wrapper for snd_pcm_[us]frames */
+struct snd_pcm_sframes_str {
+	snd_pcm_sframes_t val;
+};
+struct snd_pcm_sframes_str32 {
+	s32 val;
+};
+struct snd_pcm_uframes_str {
+	snd_pcm_uframes_t val;
+};
+struct snd_pcm_uframes_str32 {
+	u32 val;
+};
+
+#define CVT_snd_pcm_sframes_str() { COPY_CVT(val); }
+#define CVT_snd_pcm_uframes_str() { COPY_CVT(val); }
+
+
+struct snd_pcm_hw_params32 {
+	u32 flags;
+	struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
+	struct snd_mask mres[5];	/* reserved masks */
+	struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+	struct snd_interval ires[9];	/* reserved intervals */
+	u32 rmask;
+	u32 cmask;
+	u32 info;
+	u32 msbits;
+	u32 rate_num;
+	u32 rate_den;
+	u32 fifo_size;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+struct snd_pcm_sw_params32 {
+	s32 tstamp_mode;
+	u32 period_step;
+	u32 sleep_min;
+	u32 avail_min;
+	u32 xfer_align;
+	u32 start_threshold;
+	u32 stop_threshold;
+	u32 silence_threshold;
+	u32 silence_size;
+	u32 boundary;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+#define CVT_snd_pcm_sw_params()\
+{\
+	COPY(tstamp_mode);\
+	COPY(period_step);\
+	COPY(sleep_min);\
+	COPY_CVT(avail_min);\
+	COPY_CVT(xfer_align);\
+	COPY_CVT(start_threshold);\
+	COPY_CVT(stop_threshold);\
+	COPY_CVT(silence_threshold);\
+	COPY_CVT(silence_size);\
+	COPY_CVT(boundary);\
+}
+
+struct snd_pcm_channel_info32 {
+	u32 channel;
+	u32 offset;
+	u32 first;
+	u32 step;
+} __attribute__((packed));
+
+#define CVT_snd_pcm_channel_info()\
+{\
+	COPY(channel);\
+	COPY_CVT(offset);\
+	COPY(first);\
+	COPY(step);\
+}
+
+struct snd_pcm_status32 {
+	s32 state;
+	struct compat_timespec trigger_tstamp;
+	struct compat_timespec tstamp;
+	u32 appl_ptr;
+	u32 hw_ptr;
+	s32 delay;
+	u32 avail;
+	u32 avail_max;
+	u32 overrange;
+	s32 suspended_state;
+	unsigned char reserved[60];
+} __attribute__((packed));
+
+#define CVT_snd_pcm_status()\
+{\
+	COPY(state);\
+	COPY_CVT(trigger_tstamp.tv_sec);\
+	COPY_CVT(trigger_tstamp.tv_nsec);\
+	COPY_CVT(tstamp.tv_sec);\
+	COPY_CVT(tstamp.tv_nsec);\
+	COPY_CVT(appl_ptr);\
+	COPY_CVT(hw_ptr);\
+	COPY_CVT(delay);\
+	COPY_CVT(avail);\
+	COPY_CVT(avail_max);\
+	COPY_CVT(overrange);\
+	COPY(suspended_state);\
+}
+
+DEFINE_ALSA_IOCTL(pcm_uframes_str);
+DEFINE_ALSA_IOCTL(pcm_sframes_str);
+DEFINE_ALSA_IOCTL(pcm_sw_params);
+DEFINE_ALSA_IOCTL(pcm_channel_info);
+DEFINE_ALSA_IOCTL(pcm_status);
+
+/* sanity device check */
+static int sanity_check_pcm(struct file *file)
+{
+	unsigned int minor;
+
+	if (imajor(file->f_dentry->d_inode) != snd_major)
+		return -ENOTTY;
+	minor = iminor(file->f_dentry->d_inode);
+	if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
+	    !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE))
+		return -ENOTTY;
+	return 0;
+}
+
+/* recalcuate the boundary within 32bit */
+static void recalculate_boundary(struct snd_pcm_runtime *runtime)
+{
+	if (! runtime->buffer_size)
+		return;
+	runtime->boundary = runtime->buffer_size;
+	while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+		runtime->boundary *= 2;
+}
+
+int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+
+/* both for HW_PARAMS and HW_REFINE */
+static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_pcm_hw_params32 __user *data32;
+	struct snd_pcm_hw_params *data;
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+	int err;
+
+	if (sanity_check_pcm(file))
+		return -ENOTTY;
+	if (! (pcm_file = file->private_data))
+		return -ENOTTY;
+	if (! (substream = pcm_file->substream))
+		return -ENOTTY;
+	if (! (runtime = substream->runtime))
+		return -ENOTTY;
+
+	data32 = compat_ptr(arg);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	if (copy_from_user(data, data32, sizeof(*data32))) {
+		err = -EFAULT;
+		goto error;
+	}
+	if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE)
+		err = snd_pcm_hw_refine(substream, data);
+	else
+		err = snd_pcm_hw_params(substream, data);
+	if (err < 0)
+		goto error;
+	if (copy_to_user(data32, data, sizeof(*data32)) ||
+	    __put_user((u32)data->fifo_size, &data32->fifo_size)) {
+		err = -EFAULT;
+		goto error;
+	}
+
+	if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS)
+		recalculate_boundary(runtime);
+ error:
+	kfree(data);
+	return err;
+}
+
+
+/*
+ */
+struct snd_xferi32 {
+	s32 result;
+	u32 buf;
+	u32 frames;
+} __attribute__((packed));
+
+static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_xferi32 data32;
+	struct snd_xferi __user *data;
+	snd_pcm_sframes_t result;
+	int err;
+
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	data = compat_alloc_user_space(sizeof(*data));
+	if (put_user((snd_pcm_sframes_t)data32.result, &data->result) ||
+	    __put_user(compat_ptr(data32.buf), &data->buf) ||
+	    __put_user((snd_pcm_uframes_t)data32.frames, &data->frames))
+		return -EFAULT;
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	if (__get_user(result, &data->result))
+		return -EFAULT;
+	data32.result = result;
+	if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+		return -EFAULT;
+	return 0;
+}
+
+
+/* snd_xfern needs remapping of bufs */
+struct snd_xfern32 {
+	s32 result;
+	u32 bufs;  /* this is void **; */
+	u32 frames;
+} __attribute__((packed));
+
+/*
+ * xfern ioctl nees to copy (up to) 128 pointers on stack.
+ * although we may pass the copied pointers through f_op->ioctl, but the ioctl
+ * handler there expands again the same 128 pointers on stack, so it is better
+ * to handle the function (calling pcm_readv/writev) directly in this handler.
+ */
+static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	struct snd_xfern32 __user *srcptr = compat_ptr(arg);
+	struct snd_xfern32 data32;
+	void __user **bufs;
+	int err = 0, ch, i;
+	u32 __user *bufptr;
+
+	if (sanity_check_pcm(file))
+		return -ENOTTY;
+	if (! (pcm_file = file->private_data))
+		return -ENOTTY;
+	if (! (substream = pcm_file->substream))
+		return -ENOTTY;
+	if (! substream->runtime)
+		return -ENOTTY;
+
+	/* check validty of the command */
+	switch (native_ctl) {
+	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+		if (substream->stream  != SNDRV_PCM_STREAM_PLAYBACK)
+			return -EINVAL;
+		if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+			return -EBADFD;
+		break;
+	case SNDRV_PCM_IOCTL_READN_FRAMES:
+		if (substream->stream  != SNDRV_PCM_STREAM_CAPTURE)
+			return -EINVAL;
+		break;
+	}
+	if ((ch = substream->runtime->channels) > 128)
+		return -EINVAL;
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	bufptr = compat_ptr(data32.bufs);
+	bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
+	if (bufs == NULL)
+		return -ENOMEM;
+	for (i = 0; i < ch; i++) {
+		u32 ptr;
+		if (get_user(ptr, bufptr)) {
+			kfree(bufs);
+			return -EFAULT;
+		}
+		bufs[ch] = compat_ptr(ptr);
+		bufptr++;
+	}
+	switch (native_ctl) {
+	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+		err = snd_pcm_lib_writev(substream, bufs, data32.frames);
+		break;
+	case SNDRV_PCM_IOCTL_READN_FRAMES:
+		err = snd_pcm_lib_readv(substream, bufs, data32.frames);
+		break;
+	}
+	if (err >= 0) {
+		if (put_user(err, &srcptr->result))
+			err = -EFAULT;
+	}
+	kfree(bufs);
+	return err;
+}
+
+
+struct snd_pcm_mmap_status32 {
+	s32 state;
+	s32 pad1;
+	u32 hw_ptr;
+	struct compat_timespec tstamp;
+	s32 suspended_state;
+} __attribute__((packed));
+
+struct snd_pcm_mmap_control32 {
+	u32 appl_ptr;
+	u32 avail_min;
+} __attribute__((packed));
+
+struct snd_pcm_sync_ptr32 {
+	u32 flags;
+	union {
+		struct snd_pcm_mmap_status32 status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct snd_pcm_mmap_control32 control;
+		unsigned char reserved[64];
+	} c;
+} __attribute__((packed));
+
+#define CVT_snd_pcm_sync_ptr()\
+{\
+	COPY(flags);\
+	COPY(s.status.state);\
+	COPY(s.status.pad1);\
+	COPY_CVT(s.status.hw_ptr);\
+	COPY_CVT(s.status.tstamp.tv_sec);\
+	COPY_CVT(s.status.tstamp.tv_nsec);\
+	COPY(s.status.suspended_state);\
+	COPY_CVT(c.control.appl_ptr);\
+	COPY_CVT(c.control.avail_min);\
+}
+
+DEFINE_ALSA_IOCTL(pcm_sync_ptr);
+
+/*
+ */
+
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_forward, pcm_uframes_str, SNDRV_PCM_IOCTL_FORWARD);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
+
+
+/*
+ * When PCM is used on 32bit mode, we need to disable
+ * mmap of PCM status/control records because of the size
+ * incompatibility.
+ * 
+ * Since INFO ioctl is always called at first, we mark the
+ * mmap-disabling in this ioctl wrapper.
+ */
+static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
+{
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	if (! filp->f_op || ! filp->f_op->ioctl)
+		return -ENOTTY;
+	pcm_file = filp->private_data;
+	if (! pcm_file)
+		return -ENOTTY;
+	substream = pcm_file->substream;
+	if (! substream)
+		return -ENOTTY;
+	pcm_file->no_compat_mmap = 1;
+	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+}
+
+/*
+ */
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
+	SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
+	SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
+	SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
+	SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
+	SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
+	SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32),
+	SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
+	SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
+	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
+
+};
+
+struct ioctl32_mapper pcm_mappers[] = {
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
+	/* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */
+	{ SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_TTSTAMP),
+	{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
+	{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE),
+	{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
+	{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
+	{ SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
+	{ SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
+	{ SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_START),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_DROP),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE),
+	{ SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN),
+	{ SNDRV_PCM_IOCTL_FORWARD32, AP(pcm_forward) },
+	{ SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) },
+	{ SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) },
+	{ SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) },
+	{ SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_LINK),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK),
+
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/pcm32_old.c b/alsa/acore/ioctl32/pcm32_old.c
new file mode 100644
index 0000000..2b589b9
--- /dev/null
+++ b/alsa/acore/ioctl32/pcm32_old.c
@@ -0,0 +1,582 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for PCM API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include "ioctl32_old.h"
+
+
+/* wrapper for snd_pcm_[us]frames */
+struct snd_pcm_sframes_str {
+	snd_pcm_sframes_t val;
+};
+struct snd_pcm_sframes_str32 {
+	s32 val;
+};
+struct snd_pcm_uframes_str {
+	snd_pcm_uframes_t val;
+};
+struct snd_pcm_uframes_str32 {
+	u32 val;
+};
+
+#define CVT_snd_pcm_sframes_str() { COPY(val); }
+#define CVT_snd_pcm_uframes_str() { COPY(val); }
+
+
+struct snd_interval32 {
+	u32 min, max;
+	unsigned int openmin:1,
+		     openmax:1,
+		     integer:1,
+		     empty:1;
+};
+
+struct snd_pcm_hw_params32 {
+	u32 flags;
+	struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
+	struct snd_mask mres[5];	/* reserved masks */
+	struct snd_interval32 intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+	struct snd_interval ires[9];	/* reserved intervals */
+	u32 rmask;
+	u32 cmask;
+	u32 info;
+	u32 msbits;
+	u32 rate_num;
+	u32 rate_den;
+	u32 fifo_size;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+#define numberof(array) ARRAY_SIZE(array)
+
+#define CVT_snd_pcm_hw_params()\
+{\
+	unsigned int i;\
+	COPY(flags);\
+	for (i = 0; i < numberof(dst->masks); i++)\
+		COPY(masks[i]);\
+	for (i = 0; i < numberof(dst->intervals); i++) {\
+		COPY(intervals[i].min);\
+		COPY(intervals[i].max);\
+		COPY(intervals[i].openmin);\
+		COPY(intervals[i].openmax);\
+		COPY(intervals[i].integer);\
+		COPY(intervals[i].empty);\
+	}\
+	COPY(rmask);\
+	COPY(cmask);\
+	COPY(info);\
+	COPY(msbits);\
+	COPY(rate_num);\
+	COPY(rate_den);\
+	COPY(fifo_size);\
+}
+
+struct snd_pcm_sw_params32 {
+	s32 tstamp_mode;
+	u32 period_step;
+	u32 sleep_min;
+	u32 avail_min;
+	u32 xfer_align;
+	u32 start_threshold;
+	u32 stop_threshold;
+	u32 silence_threshold;
+	u32 silence_size;
+	u32 boundary;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+#define CVT_snd_pcm_sw_params()\
+{\
+	COPY(tstamp_mode);\
+	COPY(period_step);\
+	COPY(sleep_min);\
+	COPY(avail_min);\
+	COPY(xfer_align);\
+	COPY(start_threshold);\
+	COPY(stop_threshold);\
+	COPY(silence_threshold);\
+	COPY(silence_size);\
+	COPY(boundary);\
+}
+
+struct snd_pcm_channel_info32 {
+	u32 channel;
+	u32 offset;
+	u32 first;
+	u32 step;
+} __attribute__((packed));
+
+#define CVT_snd_pcm_channel_info()\
+{\
+	COPY(channel);\
+	COPY(offset);\
+	COPY(first);\
+	COPY(step);\
+}
+
+struct snd_pcm_status32 {
+	s32 state;
+	struct compat_timespec trigger_tstamp;
+	struct compat_timespec tstamp;
+	u32 appl_ptr;
+	u32 hw_ptr;
+	s32 delay;
+	u32 avail;
+	u32 avail_max;
+	u32 overrange;
+	s32 suspended_state;
+	unsigned char reserved[60];
+} __attribute__((packed));
+
+#define CVT_snd_pcm_status()\
+{\
+	COPY(state);\
+	COPY(trigger_tstamp.tv_sec);\
+	COPY(trigger_tstamp.tv_nsec);\
+	COPY(tstamp.tv_sec);\
+	COPY(tstamp.tv_nsec);\
+	COPY(appl_ptr);\
+	COPY(hw_ptr);\
+	COPY(delay);\
+	COPY(avail);\
+	COPY(avail_max);\
+	COPY(overrange);\
+	COPY(suspended_state);\
+}
+
+DEFINE_ALSA_IOCTL(pcm_uframes_str);
+DEFINE_ALSA_IOCTL(pcm_sframes_str);
+DEFINE_ALSA_IOCTL(pcm_sw_params);
+DEFINE_ALSA_IOCTL(pcm_channel_info);
+DEFINE_ALSA_IOCTL(pcm_status);
+
+/* recalcuate the boundary within 32bit */
+static void recalculate_boundary(struct file *file)
+{
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+
+	/* FIXME: need to check whether fop->ioctl is sane */
+	if (! (pcm_file = file->private_data))
+		return;
+	if (! (substream = pcm_file->substream))
+		return;
+	if (! (runtime = substream->runtime))
+		return;
+	runtime->boundary = runtime->buffer_size;
+	while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+		runtime->boundary *= 2;
+}
+
+static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_pcm_hw_params32 *data32;
+	struct snd_pcm_hw_params *data;
+	mm_segment_t oldseg;
+	int err;
+
+	data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (data32 == NULL || data == NULL) {
+		err = -ENOMEM;
+		goto __end;
+	}
+	if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+		err = -EFAULT;
+		goto __end;
+	}
+	memset(data, 0, sizeof(*data));
+	convert_from_32(pcm_hw_params, data, data32);
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	set_fs(oldseg);
+	if (err < 0)
+		goto __end;
+	err = 0;
+	convert_to_32(pcm_hw_params, data32, data);
+	if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+		err = -EFAULT;
+	else
+		recalculate_boundary(file);
+      __end:
+      	if (data)
+      		kfree(data);
+      	if (data32)
+      		kfree(data32);
+	return err;
+}
+
+
+/*
+ */
+struct snd_xferi32 {
+	s32 result;
+	u32 buf;
+	u32 frames;
+} __attribute__((packed));
+
+static inline int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_xferi32 data32;
+	struct snd_xferi data;
+	mm_segment_t oldseg;
+	int err;
+
+	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+		return -EFAULT;
+	memset(&data, 0, sizeof(data));
+	data.result = data32.result;
+	data.buf = compat_ptr(data32.buf);
+	data.frames = data32.frames;
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+	set_fs(oldseg);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	data32.result = data.result;
+	if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+		return -EFAULT;
+	return 0;
+}
+
+
+/* snd_xfern needs remapping of bufs */
+struct snd_xfern32 {
+	s32 result;
+	u32 bufs;  /* this is void **; */
+	u32 frames;
+} __attribute__((packed));
+
+/*
+ * xfern ioctl nees to copy (up to) 128 pointers on stack.
+ * although we may pass the copied pointers through f_op->ioctl, but the ioctl
+ * handler there expands again the same 128 pointers on stack, so it is better
+ * to handle the function (calling pcm_readv/writev) directly in this handler.
+ */
+static inline int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	struct snd_xfern32 data32;
+	struct snd_xfern32 __user *srcptr = (void __user *)arg;
+	void __user **bufs = NULL;
+	int err = 0, ch, i;
+	u32 __user *bufptr;
+	mm_segment_t oldseg;
+
+	/* FIXME: need to check whether fop->ioctl is sane */
+
+	pcm_file = file->private_data;
+	substream = pcm_file->substream;
+	if (PCM_RUNTIME_CHECK(substream))
+		return -ENXIO;
+
+	/* check validty of the command */
+	switch (native_ctl) {
+	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+		if (substream->stream  != SNDRV_PCM_STREAM_PLAYBACK)
+			return -EINVAL;
+		if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+			return -EBADFD;
+		break;
+	case SNDRV_PCM_IOCTL_READN_FRAMES:
+		if (substream->stream  != SNDRV_PCM_STREAM_CAPTURE)
+			return -EINVAL;
+		break;
+	}
+	if ((ch = substream->runtime->channels) > 128)
+		return -EINVAL;
+	if (get_user(data32.frames, &srcptr->frames))
+		return -EFAULT;
+	__get_user(data32.bufs, &srcptr->bufs);
+	bufptr = compat_ptr(data32.bufs);
+	bufs = kmalloc(sizeof(void *) * 128, GFP_KERNEL);
+	if (bufs == NULL)
+		return -ENOMEM;
+	for (i = 0; i < ch; i++) {
+		u32 ptr;
+		if (get_user(ptr, bufptr))
+			return -EFAULT;
+		bufs[ch] = compat_ptr(ptr);
+		bufptr++;
+	}
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	switch (native_ctl) {
+	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+		err = snd_pcm_lib_writev(substream, bufs, data32.frames);
+		break;
+	case SNDRV_PCM_IOCTL_READN_FRAMES:
+		err = snd_pcm_lib_readv(substream, bufs, data32.frames);
+		break;
+	}
+	set_fs(oldseg);
+	if (err >= 0) {
+		if (put_user(err, &srcptr->result))
+			err = -EFAULT;
+	}
+	kfree(bufs);
+	return 0;
+}
+
+
+struct snd_pcm_hw_params_old32 {
+	u32 flags;
+	u32 masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
+			   SNDRV_PCM_HW_PARAM_ACCESS + 1];
+	struct snd_interval32 intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
+					SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
+	u32 rmask;
+	u32 cmask;
+	u32 info;
+	u32 msbits;
+	u32 rate_num;
+	u32 rate_den;
+	u32 fifo_size;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
+#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
+
+static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params, struct snd_pcm_hw_params_old32 *oparams)
+{
+	unsigned int i;
+
+	memset(params, 0, sizeof(*params));
+	params->flags = oparams->flags;
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
+		params->masks[i].bits[0] = oparams->masks[i];
+	memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
+	params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
+	params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
+	params->info = oparams->info;
+	params->msbits = oparams->msbits;
+	params->rate_num = oparams->rate_num;
+	params->rate_den = oparams->rate_den;
+	params->fifo_size = oparams->fifo_size;
+}
+
+static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old32 *oparams, struct snd_pcm_hw_params *params)
+{
+	unsigned int i;
+
+	memset(oparams, 0, sizeof(*oparams));
+	oparams->flags = params->flags;
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
+		oparams->masks[i] = params->masks[i].bits[0];
+	memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
+	oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
+	oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
+	oparams->info = params->info;
+	oparams->msbits = params->msbits;
+	oparams->rate_num = params->rate_num;
+	oparams->rate_den = params->rate_den;
+	oparams->fifo_size = params->fifo_size;
+}
+
+static inline int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct snd_pcm_hw_params_old32 *data32;
+	struct snd_pcm_hw_params *data;
+	mm_segment_t oldseg;
+	int err;
+
+	data32 = kzalloc(sizeof(*data32), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (data32 == NULL || data == NULL) {
+		err = -ENOMEM;
+		goto __end;
+	}
+	if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+		err = -EFAULT;
+		goto __end;
+	}
+	snd_pcm_hw_convert_from_old_params(data, data32);
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	set_fs(oldseg);
+	if (err < 0)
+		goto __end;
+	snd_pcm_hw_convert_to_old_params(data32, data);
+	err = 0;
+	if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+		err = -EFAULT;
+	else
+		recalculate_boundary(file);
+      __end:
+      	if (data)
+      		kfree(data);
+      	if (data32)
+      		kfree(data32);
+	return err;
+}
+
+struct snd_pcm_mmap_status32 {
+	s32 state;
+	s32 pad1;
+	u32 hw_ptr;
+	struct compat_timespec tstamp;
+	s32 suspended_state;
+} __attribute__((packed));
+
+struct snd_pcm_mmap_control32 {
+	u32 appl_ptr;
+	u32 avail_min;
+} __attribute__((packed));
+
+struct snd_pcm_sync_ptr32 {
+	u32 flags;
+	union {
+		struct snd_pcm_mmap_status32 status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct snd_pcm_mmap_control32 control;
+		unsigned char reserved[64];
+	} c;
+} __attribute__((packed));
+
+#define CVT_snd_pcm_sync_ptr()\
+{\
+	COPY(flags);\
+	COPY(s.status.state);\
+	COPY(s.status.pad1);\
+	COPY(s.status.hw_ptr);\
+	COPY(s.status.tstamp.tv_sec);\
+	COPY(s.status.tstamp.tv_nsec);\
+	COPY(s.status.suspended_state);\
+	COPY(c.control.appl_ptr);\
+	COPY(c.control.avail_min);\
+}
+
+DEFINE_ALSA_IOCTL_BIG(pcm_sync_ptr);
+
+/*
+ */
+
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_REFINE);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
+
+
+/*
+ * When PCM is used on 32bit mode, we need to disable
+ * mmap of PCM status/control records because of the size
+ * incompatibility.
+ * 
+ * Since INFO ioctl is always called at first, we mark the
+ * mmap-disabling in this ioctl wrapper.
+ */
+static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
+{
+	struct snd_pcm_file *pcm_file;
+	struct snd_pcm_substream *substream;
+	if (! filp->f_op || ! filp->f_op->ioctl)
+		return -ENOTTY;
+	pcm_file = filp->private_data;
+	if (! pcm_file)
+		return -ENOTTY;
+	substream = pcm_file->substream;
+	if (! substream)
+		return -ENOTTY;
+	pcm_file->no_compat_mmap = 1;
+	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+}
+
+/*
+ */
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
+	SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
+	SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
+	SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
+	SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
+	SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32),
+	SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
+	SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
+	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
+	SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct snd_pcm_hw_params_old32),
+	SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct snd_pcm_hw_params_old32),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
+
+};
+
+struct ioctl32_mapper pcm_mappers[] = {
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
+	/* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */
+	{ SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_TTSTAMP),
+	{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
+	{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
+	{ SNDRV_PCM_IOCTL_HW_REFINE_OLD32, AP(pcm_hw_refine_old) },
+	{ SNDRV_PCM_IOCTL_HW_PARAMS_OLD32, AP(pcm_hw_params_old) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE),
+	{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
+	{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
+	{ SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
+	{ SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
+	{ SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_START),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_DROP),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE),
+	{ SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN),
+	{ SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) },
+	{ SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) },
+	{ SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) },
+	{ SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_LINK),
+	MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK),
+
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/rawmidi32.c b/alsa/acore/ioctl32/rawmidi32.c
new file mode 100644
index 0000000..d9bc2d4
--- /dev/null
+++ b/alsa/acore/ioctl32/rawmidi32.c
@@ -0,0 +1,18 @@
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "rawmidi32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size);
+#define copy_in_user hack_copy_in_user
+#endif
+
+#include "rawmidi32_new.c"
+
+#endif
diff --git a/alsa/acore/ioctl32/rawmidi32_new.c b/alsa/acore/ioctl32/rawmidi32_new.c
new file mode 100644
index 0000000..e60be6a
--- /dev/null
+++ b/alsa/acore/ioctl32/rawmidi32_new.c
@@ -0,0 +1,91 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for raw MIDI API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/rawmidi.h>
+#include <asm/uaccess.h>
+#include "ioctl32.h"
+
+struct snd_rawmidi_params32 {
+	s32 stream;
+	u32 buffer_size;
+	u32 avail_min;
+	unsigned int no_active_sensing; /* avoid bit-field */
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+#define CVT_snd_rawmidi_params()\
+{\
+	COPY(stream);\
+	COPY_CVT(buffer_size);\
+	COPY_CVT(avail_min);\
+	if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\
+			 ((size_t __user *)&src->avail_min + 1), 4)) \
+		return -EFAULT;\
+}
+
+struct snd_rawmidi_status32 {
+	s32 stream;
+	struct compat_timespec tstamp;
+	u32 avail;
+	u32 xruns;
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+#define CVT_snd_rawmidi_status()\
+{\
+	COPY(stream);\
+	COPY_CVT(tstamp.tv_sec);\
+	COPY_CVT(tstamp.tv_nsec);\
+	COPY_CVT(avail);\
+	COPY_CVT(xruns);\
+}
+
+DEFINE_ALSA_IOCTL(rawmidi_params);
+DEFINE_ALSA_IOCTL(rawmidi_status);
+
+DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS);
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
+	SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+};
+
+struct ioctl32_mapper rawmidi_mappers[] = {
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO),
+	{ SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) },
+	{ SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) },
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP),
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN),
+
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE),
+
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/rawmidi32_old.c b/alsa/acore/ioctl32/rawmidi32_old.c
new file mode 100644
index 0000000..20087c9
--- /dev/null
+++ b/alsa/acore/ioctl32/rawmidi32_old.c
@@ -0,0 +1,89 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for raw MIDI API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/rawmidi.h>
+#include <asm/uaccess.h>
+#include "ioctl32_old.h"
+
+struct snd_rawmidi_params32 {
+	s32 stream;
+	u32 buffer_size;
+	u32 avail_min;
+	unsigned int no_active_sensing; /* avoid bit-field */
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+#define CVT_snd_rawmidi_params()\
+{\
+	COPY(stream);\
+	COPY(buffer_size);\
+	COPY(avail_min);\
+	COPY(no_active_sensing);\
+}
+
+struct snd_rawmidi_status32 {
+	s32 stream;
+	struct compat_timespec tstamp;
+	u32 avail;
+	u32 xruns;
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+#define CVT_snd_rawmidi_status()\
+{\
+	COPY(stream);\
+	COPY(tstamp.tv_sec);\
+	COPY(tstamp.tv_nsec);\
+	COPY(avail);\
+	COPY(xruns);\
+}
+
+DEFINE_ALSA_IOCTL(rawmidi_params);
+DEFINE_ALSA_IOCTL(rawmidi_status);
+
+DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS);
+DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS);
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
+	SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+};
+
+struct ioctl32_mapper rawmidi_mappers[] = {
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO),
+	{ SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) },
+	{ SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) },
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP),
+	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN),
+
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO),
+	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE),
+
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/seq32.c b/alsa/acore/ioctl32/seq32.c
new file mode 100644
index 0000000..2585ee0
--- /dev/null
+++ b/alsa/acore/ioctl32/seq32.c
@@ -0,0 +1,18 @@
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "seq32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size);
+#define copy_in_user hack_copy_in_user
+#endif
+
+#include "seq32_new.c"
+
+#endif
diff --git a/alsa/acore/ioctl32/seq32_new.c b/alsa/acore/ioctl32/seq32_new.c
new file mode 100644
index 0000000..91ca983
--- /dev/null
+++ b/alsa/acore/ioctl32/seq32_new.c
@@ -0,0 +1,117 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for sequencer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+#include <asm/uaccess.h>
+#include <sound/asequencer.h>
+#include "ioctl32.h"
+
+struct snd_seq_port_info32 {
+	struct snd_seq_addr addr;	/* client/port numbers */
+	char name[64];			/* port name */
+
+	u32 capability;	/* port capability bits */
+	u32 type;		/* port type bits */
+	s32 midi_channels;		/* channels per MIDI port */
+	s32 midi_voices;		/* voices per MIDI port */
+	s32 synth_voices;		/* voices per SYNTH port */
+
+	s32 read_use;			/* R/O: subscribers for output (from this port) */
+	s32 write_use;			/* R/O: subscribers for input (to this port) */
+
+	u32 kernel;			/* reserved for kernel use (must be NULL) */
+	u32 flags;		/* misc. conditioning */
+	unsigned char time_queue;	/* queue # for timestamping */
+	char reserved[59];		/* for future use */
+};
+
+#define CVT_snd_seq_port_info()\
+{\
+	COPY(addr);\
+	COPY_ARRAY(name);\
+	COPY(capability);\
+	COPY(type);\
+	COPY(midi_channels);\
+	COPY(midi_voices);\
+	COPY(synth_voices);\
+	COPY(read_use);\
+	COPY(write_use);\
+	COPY(flags);\
+	COPY(time_queue);\
+	dst->kernel = 0;\
+}
+
+DEFINE_ALSA_IOCTL(seq_port_info);
+DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT);
+DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT);
+DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT);
+
+/*
+ */
+#define AP(x) snd_ioctl32_##x
+
+enum {
+  SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32),
+};
+
+struct ioctl32_mapper seq_mappers[] = {
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO),
+	{ SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) },
+	{ SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) },
+	{ SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) },
+	{ SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) },
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT),
+	{ SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) },
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE),
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/seq32_old.c b/alsa/acore/ioctl32/seq32_old.c
new file mode 100644
index 0000000..cef50b2
--- /dev/null
+++ b/alsa/acore/ioctl32/seq32_old.c
@@ -0,0 +1,117 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for sequencer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+#include <asm/uaccess.h>
+#include <sound/asequencer.h>
+#include "ioctl32_old.h"
+
+struct snd_seq_port_info32 {
+	struct snd_seq_addr addr;	/* client/port numbers */
+	char name[64];			/* port name */
+
+	u32 capability;	/* port capability bits */
+	u32 type;		/* port type bits */
+	s32 midi_channels;		/* channels per MIDI port */
+	s32 midi_voices;		/* voices per MIDI port */
+	s32 synth_voices;		/* voices per SYNTH port */
+
+	s32 read_use;			/* R/O: subscribers for output (from this port) */
+	s32 write_use;			/* R/O: subscribers for input (to this port) */
+
+	u32 kernel;			/* reserved for kernel use (must be NULL) */
+	u32 flags;		/* misc. conditioning */
+	unsigned char time_queue;	/* queue # for timestamping */
+	char reserved[59];		/* for future use */
+};
+
+#define CVT_snd_seq_port_info()\
+{\
+	COPY(addr);\
+	memcpy(dst->name, src->name, sizeof(dst->name));\
+	COPY(capability);\
+	COPY(type);\
+	COPY(midi_channels);\
+	COPY(midi_voices);\
+	COPY(synth_voices);\
+	COPY(read_use);\
+	COPY(write_use);\
+	COPY(flags);\
+	COPY(time_queue);\
+	dst->kernel = 0;\
+}
+
+DEFINE_ALSA_IOCTL(seq_port_info);
+DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT);
+DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT);
+DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT);
+
+/*
+ */
+#define AP(x) snd_ioctl32_##x
+
+enum {
+  SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32),
+  SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32),
+};
+
+struct ioctl32_mapper seq_mappers[] = {
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO),
+	{ SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) },
+	{ SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) },
+	{ SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) },
+	{ SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) },
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION),
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT),
+	{ SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) },
+	MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE),
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/timer32.c b/alsa/acore/ioctl32/timer32.c
new file mode 100644
index 0000000..2ccc6c8
--- /dev/null
+++ b/alsa/acore/ioctl32/timer32.c
@@ -0,0 +1,18 @@
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "timer32_old.c"
+#else
+
+#if defined(CONFIG_SPARC64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+#ifdef copy_in_user
+#undef copy_in_user
+#endif
+size_t hack_copy_in_user(void __user *to, const void __user *from, size_t size);
+#define copy_in_user hack_copy_in_user
+#endif
+
+#include "timer32_new.c"
+
+#endif
diff --git a/alsa/acore/ioctl32/timer32_new.c b/alsa/acore/ioctl32/timer32_new.c
new file mode 100644
index 0000000..5ae7166
--- /dev/null
+++ b/alsa/acore/ioctl32/timer32_new.c
@@ -0,0 +1,98 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for timer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+#include <asm/uaccess.h>
+#include "ioctl32.h"
+
+struct snd_timer_info32 {
+	u32 flags;
+	s32 card;
+	unsigned char id[64];
+	unsigned char name[80];
+	u32 reserved0;
+	u32 resolution;
+	unsigned char reserved[64];
+};
+
+#define CVT_snd_timer_info()\
+{\
+	COPY(flags);\
+	COPY(card);\
+	COPY_ARRAY(id);\
+	COPY_ARRAY(name);\
+	COPY_CVT(resolution);\
+}
+
+struct snd_timer_status32 {
+	struct compat_timespec tstamp;
+	u32 resolution;
+	u32 lost;
+	u32 overrun;
+	u32 queue;
+	unsigned char reserved[64];
+};
+
+#define CVT_snd_timer_status()\
+{\
+	COPY_CVT(tstamp.tv_sec);\
+	COPY_CVT(tstamp.tv_nsec);\
+	COPY(resolution);\
+	COPY(lost);\
+	COPY(overrun);\
+	COPY(queue);\
+}
+
+DEFINE_ALSA_IOCTL(timer_info);
+DEFINE_ALSA_IOCTL(timer_status);
+
+DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS);
+
+/*
+ */
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
+	SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
+};
+
+struct ioctl32_mapper timer_mappers[] = {
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT),
+	{ SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) },
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS),
+	{ SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) },
+	/* The ioctls are changed, so we can enable them again */
+	/* The old ioctls conflict with TIOC_* */
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_START),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE),
+	{ 0 },
+};
diff --git a/alsa/acore/ioctl32/timer32_old.c b/alsa/acore/ioctl32/timer32_old.c
new file mode 100644
index 0000000..229a065
--- /dev/null
+++ b/alsa/acore/ioctl32/timer32_old.c
@@ -0,0 +1,98 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for timer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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 "adriver.h"
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+#include <asm/uaccess.h>
+#include "ioctl32_old.h"
+
+struct snd_timer_info32 {
+	u32 flags;
+	s32 card;
+	unsigned char id[64];
+	unsigned char name[80];
+	u32 reserved0;
+	u32 resolution;
+	unsigned char reserved[64];
+};
+
+#define CVT_snd_timer_info()\
+{\
+	COPY(flags);\
+	COPY(card);\
+	memcpy(dst->id, src->id, sizeof(src->id));\
+	memcpy(dst->name, src->name, sizeof(src->name));\
+	COPY(resolution);\
+}
+
+struct snd_timer_status32 {
+	struct compat_timespec tstamp;
+	u32 resolution;
+	u32 lost;
+	u32 overrun;
+	u32 queue;
+	unsigned char reserved[64];
+};
+
+#define CVT_snd_timer_status()\
+{\
+	COPY(tstamp.tv_sec);\
+	COPY(tstamp.tv_nsec);\
+	COPY(resolution);\
+	COPY(lost);\
+	COPY(overrun);\
+	COPY(queue);\
+}
+
+DEFINE_ALSA_IOCTL(timer_info);
+DEFINE_ALSA_IOCTL(timer_status);
+
+DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO);
+DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS);
+
+/*
+ */
+
+#define AP(x) snd_ioctl32_##x
+
+enum {
+	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
+	SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
+};
+
+struct ioctl32_mapper timer_mappers[] = {
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT),
+	{ SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) },
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS),
+	{ SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) },
+	/* The ioctls are changed, so we can enable them again */
+	/* The old ioctls conflict with TIOC_* */
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_START),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE),
+	MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE),
+	{ 0 },
+};
diff --git a/alsa/acore/isadma.c b/alsa/acore/isadma.c
new file mode 100644
index 0000000..2a5cfdd
--- /dev/null
+++ b/alsa/acore/isadma.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/isadma.c"
diff --git a/alsa/acore/jack.c b/alsa/acore/jack.c
new file mode 100644
index 0000000..a19ab51
--- /dev/null
+++ b/alsa/acore/jack.c
@@ -0,0 +1,13 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include <linux/input.h>
+#ifndef SW_LINEOUT_INSERT
+#define SW_LINEOUT_INSERT	0x06  /* set = inserted */
+#endif
+#ifndef SW_JACK_PHYSICAL_INSERT
+#define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
+#endif
+#ifndef SW_VIDEOOUT_INSERT
+#define SW_VIDEOOUT_INSERT	0x08  /* set = inserted */
+#endif
+#include "../alsa-kernel/core/jack.c"
diff --git a/alsa/acore/memalloc.inc b/alsa/acore/memalloc.inc
new file mode 100644
index 0000000..a8dbcd2
--- /dev/null
+++ b/alsa/acore/memalloc.inc
@@ -0,0 +1,51 @@
+#include "config.h"
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__) && !defined(__DEPEND__)
+#include "sndversions.h"
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+#define CONFIG_HAS_DMA 1
+#endif
+
+#include <linux/pci.h>
+#define SKIP_HIDDEN_MALLOCS 1
+#include "adriver.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_PROC_FS)
+#include <linux/proc_fs.h>
+static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+	mode_t mode, struct proc_dir_entry *base, 
+	read_proc_t *read_proc, void * data)
+{
+	struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+	if (res) {
+		res->read_proc=read_proc;
+		res->data=data;
+	}
+	return res;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#undef WARN_ON
+#define WARN_ON(condition) ({						\
+	int __ret_warn_on = !!(condition);				\
+	if (unlikely(__ret_warn_on)) {					\
+		printk("BUG: warning at %s:%d/%s()\n", __FILE__,	\
+			__LINE__, __FUNCTION__);       			\
+		dump_stack();	  					\
+	}								\
+	unlikely(__ret_warn_on);					\
+})
+#endif
+
+// vim: ft=c
diff --git a/alsa/acore/memalloc.inc1 b/alsa/acore/memalloc.inc1
new file mode 100644
index 0000000..bd9165e
--- /dev/null
+++ b/alsa/acore/memalloc.inc1
@@ -0,0 +1,42 @@
+/* compatible functions */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+EXPORT_SYMBOL(snd_pci_compat_alloc_consistent);
+EXPORT_SYMBOL(snd_pci_compat_free_consistent);
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(snd_pci_compat_match_device);
+EXPORT_SYMBOL(snd_pci_compat_register_driver);
+EXPORT_SYMBOL(snd_pci_compat_unregister_driver);
+EXPORT_SYMBOL(snd_pci_compat_get_size);
+EXPORT_SYMBOL(snd_pci_compat_get_flags);
+EXPORT_SYMBOL(snd_pci_compat_set_power_state);
+EXPORT_SYMBOL(snd_pci_compat_enable_device);
+EXPORT_SYMBOL(snd_pci_compat_disable_device);
+EXPORT_SYMBOL(snd_pci_compat_find_capability);
+EXPORT_SYMBOL(snd_pci_compat_dma_supported);
+EXPORT_SYMBOL(snd_pci_compat_get_dma_mask);
+EXPORT_SYMBOL(snd_pci_compat_set_dma_mask);
+EXPORT_SYMBOL(snd_pci_compat_get_driver_data);
+EXPORT_SYMBOL(snd_pci_compat_set_driver_data);
+EXPORT_SYMBOL(snd_pci_compat_get_pci_driver);
+EXPORT_SYMBOL(snd_pci_compat_request_region);
+EXPORT_SYMBOL(snd_pci_compat_release_region);
+EXPORT_SYMBOL(snd_pci_compat_request_regions);
+EXPORT_SYMBOL(snd_pci_compat_release_regions);
+EXPORT_SYMBOL(snd_pci_compat_save_state);
+EXPORT_SYMBOL(snd_pci_compat_restore_state);
+#endif
+#endif
+
+#ifndef CONFIG_HAVE_STRLCPY
+EXPORT_SYMBOL(snd_compat_strlcpy);
+#endif
+#ifndef CONFIG_HAVE_SNPRINTF
+EXPORT_SYMBOL(snd_compat_snprintf);
+#endif
+#ifndef CONFIG_HAVE_VSNPRINTF
+EXPORT_SYMBOL(snd_compat_vsnprintf);
+#endif
+
+#ifndef CONFIG_HAVE_VMALLOC_TO_PAGE
+EXPORT_SYMBOL(snd_compat_vmalloc_to_page);
+#endif
diff --git a/alsa/acore/memalloc.patch b/alsa/acore/memalloc.patch
new file mode 100644
index 0000000..55bc0d8
--- /dev/null
+++ b/alsa/acore/memalloc.patch
@@ -0,0 +1,257 @@
+--- ../alsa-kernel/core/memalloc.c	2009-09-21 15:57:35.000000000 +0200
++++ memalloc.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "memalloc.inc"
+ /*
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+  *                   Takashi Iwai <tiwai@suse.de>
+@@ -57,6 +58,138 @@
+ #define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
+ 
+ /*
++ *  Hacks
++ */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
++static void *snd_dma_alloc_coherent1(struct device *dev, size_t size,
++				     dma_addr_t *dma_handle, int flags)
++{
++	if (dev)
++		return dma_alloc_coherent(dev, size, dma_handle, flags);
++	else /* FIXME: dma_alloc_coherent does't always accept dev=NULL */
++		return pci_alloc_consistent(NULL, size, dma_handle);
++}
++
++static void snd_dma_free_coherent1(struct device *dev, size_t size, void *dma_addr,
++				   dma_addr_t dma_handle)
++{
++	if (dev)
++		return dma_free_coherent(dev, size, dma_addr, dma_handle);
++	else
++		return pci_free_consistent(NULL, size, dma_addr, dma_handle);
++}
++
++#undef dma_alloc_coherent
++#define dma_alloc_coherent snd_dma_alloc_coherent1
++#undef dma_free_coherent
++#define dma_free_coherent snd_dma_free_coherent1
++#endif /* < 2.6.5 */
++
++#else
++
++/* for 2.2/2.4 kernels */
++#if defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(__i386__)
++#define dma_alloc_coherent(dev,size,addr,flags) pci_alloc_consistent((struct pci_dev *)(dev),size,addr)
++#define dma_free_coherent(dev,size,ptr,addr) pci_free_consistent((struct pci_dev *)(dev),size,ptr,addr)
++#elif CONFIG_SBUS
++#define dma_alloc_coherent(dev,size,addr,flags) sbus_alloc_consistent((struct sbus_dev *)(dev),size,addr)
++#define dma_free_coherent(dev,size,ptr,addr) sbus_free_consistent((struct sbus_dev *)(dev),size,ptr,addr)
++#else
++#error "Need a bus for dma_alloc_coherent()"
++#endif
++
++#endif /* >= 2.6.0 */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && \
++	LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
++#if defined(__i386__) || defined(__ppc__) || defined(__x86_64__)
++
++/*
++ * A hack to allocate large buffers via dma_alloc_coherent()
++ *
++ * since dma_alloc_coherent always tries GFP_DMA when the requested
++ * pci memory region is below 32bit, it happens quite often that even
++ * 2 order of pages cannot be allocated.
++ *
++ * so in the following, we allocate at first without dma_mask, so that
++ * allocation will be done without GFP_DMA.  if the area doesn't match
++ * with the requested region, then realloate with the original dma_mask
++ * again.
++ *
++ * Really, we want to move this type of thing into dma_alloc_coherent()
++ * so dma_mask doesn't have to be messed with.
++ */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#define VALID_DMA_MASK(dev)	(dev)->dma_mask
++#define GET_DMA_MASK(dev)	*(dev)->dma_mask
++#define SET_DMA_MASK(dev,val)	(*(dev)->dma_mask = (val))
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 5)
++#define GET_COHERENT_DMA_MASK(dev)	(dev)->coherent_dma_mask
++#define SET_COHERENT_DMA_MASK(dev,val)	((dev)->coherent_dma_mask = (val))
++#else
++#define GET_COHERENT_DMA_MASK(dev)	0 /* dummy */
++#define SET_COHERENT_DMA_MASK(dev,val)
++#endif
++#else /* 2.4.x */
++#define VALID_DMA_MASK(dev)	1
++#define GET_DMA_MASK(dev)	((struct pci_dev *)(dev))->dma_mask
++#define SET_DMA_MASK(dev,val)	(((struct pci_dev *)(dev))->dma_mask = (val))
++#ifdef CONFIG_HAVE_PCI_CONSISTENT_DMA_MASK
++#define GET_COHERENT_DMA_MASK(dev)	((struct pci_dev *)(dev))->consistent_dma_mask
++#define SET_COHERENT_DMA_MASK(dev,val)	(((struct pci_dev *)(dev))->consistent_dma_mask = (val))
++#else
++#define GET_COHERENT_DMA_MASK(dev)	0 /* dummy */
++#define SET_COHERENT_DMA_MASK(dev,val)
++#endif
++#endif
++
++static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
++					 dma_addr_t *dma_handle,
++					 gfp_t flags)
++{
++	void *ret;
++	u64 dma_mask, coherent_dma_mask;
++
++	if (dev == NULL || !VALID_DMA_MASK(dev))
++		return dma_alloc_coherent(dev, size, dma_handle, flags);
++	dma_mask = GET_DMA_MASK(dev);
++	coherent_dma_mask = GET_COHERENT_DMA_MASK(dev);
++	SET_DMA_MASK(dev, 0xffffffff); 	/* do without masking */
++	SET_COHERENT_DMA_MASK(dev, 0xffffffff); 	/* do without masking */
++	ret = dma_alloc_coherent(dev, size, dma_handle, flags);
++	SET_DMA_MASK(dev, dma_mask);	/* restore */
++	SET_COHERENT_DMA_MASK(dev, coherent_dma_mask)	/* restore */;
++	if (ret) {
++		/* obtained address is out of range? */
++		if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) {
++			/* reallocate with the proper mask */
++			dma_free_coherent(dev, size, ret, *dma_handle);
++			ret = dma_alloc_coherent(dev, size, dma_handle, flags);
++		}
++	} else {
++		/* wish to success now with the proper mask... */
++		if (dma_mask != 0xffffffffUL) {
++			/* allocation with GFP_ATOMIC to avoid the long stall */
++			flags &= ~GFP_KERNEL;
++			flags |= GFP_ATOMIC;
++			ret = dma_alloc_coherent(dev, size, dma_handle, flags);
++		}
++	}
++	return ret;
++}
++
++/* redefine dma_alloc_coherent for some architectures */
++#undef dma_alloc_coherent
++#define dma_alloc_coherent snd_dma_hack_alloc_coherent
++
++#endif /* arch */
++#endif /* >= 2.4.0 && < 2.6.26 */
++
++
++/*
+  *
+  *  Generic memory allocators
+  *
+@@ -74,6 +207,24 @@
+ 	snd_allocated_pages -= 1 << order;
+ }
+ 
++static void mark_pages(struct page *page, int order)
++{
++#if ! defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
++	struct page *last_page = page + (1 << order);
++	while (page < last_page)
++		SetPageReserved(page++);
++#endif
++}
++
++static void unmark_pages(struct page *page, int order)
++{
++#if ! defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
++	struct page *last_page = page + (1 << order);
++	while (page < last_page)
++		ClearPageReserved(page++);
++#endif
++}
++
+ /**
+  * snd_malloc_pages - allocate pages with the given size
+  * @size: the size to allocate in bytes
+@@ -94,8 +245,10 @@
+ 		return NULL;
+ 	gfp_flags |= __GFP_COMP;	/* compound page lets parts be mapped */
+ 	pg = get_order(size);
+-	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
++	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
++		mark_pages(virt_to_page(res), pg);
+ 		inc_snd_pages(pg);
++	}
+ 	return res;
+ }
+ 
+@@ -114,6 +267,7 @@
+ 		return;
+ 	pg = get_order(size);
+ 	dec_snd_pages(pg);
++	unmark_pages(virt_to_page(ptr), pg);
+ 	free_pages((unsigned long) ptr, pg);
+ }
+ 
+@@ -139,8 +293,10 @@
+ 		| __GFP_NORETRY /* don't trigger OOM-killer */
+ 		| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
+ 	res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
+-	if (res != NULL)
++	if (res != NULL) {
++		mark_pages(virt_to_page(res), pg);
+ 		inc_snd_pages(pg);
++	}
+ 
+ 	return res;
+ }
+@@ -155,6 +311,7 @@
+ 		return;
+ 	pg = get_order(size);
+ 	dec_snd_pages(pg);
++	unmark_pages(virt_to_page(ptr), pg);
+ 	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
+ }
+ #endif /* CONFIG_HAS_DMA */
+@@ -366,6 +523,7 @@
+ 
+ 
+ #ifdef CONFIG_PROC_FS
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ /*
+  * proc file interface
+  */
+@@ -504,6 +662,7 @@
+ 	.release	= single_release,
+ };
+ 
++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) */
+ #endif /* CONFIG_PROC_FS */
+ 
+ /*
+@@ -513,15 +672,23 @@
+ static int __init snd_mem_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ 	snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
+ 				   &snd_mem_proc_fops);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++	snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
++	if (snd_mem_proc)
++		snd_mem_proc->proc_fops = &snd_mem_proc_fops;
++#endif
+ #endif
+ 	return 0;
+ }
+ 
+ static void __exit snd_mem_exit(void)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ 	remove_proc_entry(SND_MEM_PROC_FILE, NULL);
++#endif
+ 	free_all_reserved_pages();
+ 	if (snd_allocated_pages > 0)
+ 		printk(KERN_ERR "snd-malloc: Memory leak?  pages not freed = %li\n", snd_allocated_pages);
+@@ -544,3 +711,5 @@
+ 
+ EXPORT_SYMBOL(snd_malloc_pages);
+ EXPORT_SYMBOL(snd_free_pages);
++
++#include "memalloc.inc1"
diff --git a/alsa/acore/memory.c b/alsa/acore/memory.c
new file mode 100644
index 0000000..e2d1176
--- /dev/null
+++ b/alsa/acore/memory.c
@@ -0,0 +1,38 @@
+#include "config.h"
+#define __NO_VERSION__
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+#include <linux/compiler.h>
+#ifndef __iomem
+#define __iomem
+#endif
+#ifndef __user
+#define __user
+#endif
+#ifndef __kernel
+#define __kernel
+#endif
+#ifndef __nocast
+#define __nocast
+#endif
+#ifndef __force
+#define __force
+#endif
+#ifndef __safe
+#define __safe
+#endif
+#ifndef __bitwise
+#define __bitwise
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "adriver.h"
+#endif /* KERNEL < 2.6.0 */
+
+#include "../alsa-kernel/core/memory.c"
diff --git a/alsa/acore/memory_debug.c b/alsa/acore/memory_debug.c
new file mode 100644
index 0000000..4527378
--- /dev/null
+++ b/alsa/acore/memory_debug.c
@@ -0,0 +1,193 @@
+#define __NO_VERSION__
+/*
+ *  Memory allocation helpers.
+ *
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ *   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 "adriver.h"
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/info.h>
+
+
+/*
+ *  memory allocation helpers and debug routines
+ */
+
+struct snd_alloc_track {
+	unsigned long magic;
+	void *caller;
+	size_t size;
+	struct list_head list;
+	long data[0];
+};
+
+#define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data)
+
+static long snd_alloc_kmalloc;
+static LIST_HEAD(snd_alloc_kmalloc_list);
+static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
+#define KMALLOC_MAGIC 0x87654321
+
+void snd_memory_done(void)
+{
+	struct list_head *head;
+	struct snd_alloc_track *t;
+
+	if (snd_alloc_kmalloc > 0)
+		printk(KERN_ERR "snd: Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
+	list_for_each_prev(head, &snd_alloc_kmalloc_list) {
+		t = list_entry(head, struct snd_alloc_track, list);
+		if (t->magic != KMALLOC_MAGIC) {
+			printk(KERN_ERR "snd: Corrupted kmalloc\n");
+			break;
+		}
+		printk(KERN_ERR "snd: kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
+	}
+}
+
+static void *__snd_kmalloc(size_t size, gfp_t gfp_flags, void *caller)
+{
+	unsigned long flags;
+	struct snd_alloc_track *t;
+	void *ptr;
+	
+	ptr = snd_wrapper_kmalloc(size + sizeof(struct snd_alloc_track), gfp_flags);
+	if (ptr != NULL) {
+		t = (struct snd_alloc_track *)ptr;
+		t->magic = KMALLOC_MAGIC;
+		t->caller = caller;
+		spin_lock_irqsave(&snd_alloc_kmalloc_lock, flags);
+		list_add_tail(&t->list, &snd_alloc_kmalloc_list);
+		spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, flags);
+		t->size = size;
+		snd_alloc_kmalloc += size;
+		ptr = t->data;
+	}
+	return ptr;
+}
+
+#define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0));
+void *snd_hidden_kmalloc(size_t size, gfp_t gfp_flags)
+{
+	return _snd_kmalloc(size, gfp_flags);
+}
+
+void *snd_hidden_kzalloc(size_t size, gfp_t gfp_flags)
+{
+	void *ret = _snd_kmalloc(size, gfp_flags);
+	if (ret)
+		memset(ret, 0, size);
+	return ret;
+}
+
+void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t gfp_flags)
+{
+	void *ret = NULL;
+	if (n != 0 && size > INT_MAX / n)
+		return ret;
+	return snd_hidden_kzalloc(n * size, gfp_flags);
+}
+
+void snd_hidden_kfree(const void *obj)
+{
+	unsigned long flags;
+	struct snd_alloc_track *t;
+	if (obj == NULL)
+		return;
+	t = snd_alloc_track_entry(obj);
+	if (t->magic != KMALLOC_MAGIC) {
+		printk(KERN_WARNING "snd: bad kfree (called from %p)\n", __builtin_return_address(0));
+		dump_stack();
+		return;
+	}
+	spin_lock_irqsave(&snd_alloc_kmalloc_lock, flags);
+	list_del(&t->list);
+	spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, flags);
+	t->magic = 0;
+	snd_alloc_kmalloc -= t->size;
+	obj = t;
+	snd_wrapper_kfree(obj);
+}
+
+char *snd_hidden_kstrdup(const char *s, gfp_t gfp_flags)
+{
+	int len;
+	char *buf;
+
+	if (!s) return NULL;
+
+	len = strlen(s) + 1;
+	buf = _snd_kmalloc(len, gfp_flags);
+	if (buf)
+		memcpy(buf, s, len);
+	return buf;
+}
+
+char *snd_hidden_kstrndup(const char *s, size_t maxlen, gfp_t gfp_flags)
+{
+	int len;
+	char *buf;
+
+	if (!s) return NULL;
+
+	len = strlen(s);
+	if (len > maxlen)
+		len = maxlen;
+	buf = _snd_kmalloc(len + 1, gfp_flags);
+	if (buf) {
+		memcpy(buf, s, len);
+		buf[len] = 0;
+	}
+	return buf;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct snd_info_entry *snd_memory_info_entry;
+
+static void snd_memory_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+{
+	snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc);
+}
+
+#define PROC_FILE_NAME	"driver/snd-memory-debug"
+
+int __init snd_memory_info_init(void)
+{
+	struct snd_info_entry *entry;
+
+	entry = snd_info_create_module_entry(THIS_MODULE, "meminfo", NULL);
+	if (entry) {
+		entry->c.text.read = snd_memory_info_read;
+		if (snd_info_register(entry) < 0) {
+			snd_info_free_entry(entry);
+			entry = NULL;
+		}
+	}
+	snd_memory_info_entry = entry;
+	return 0;
+}
+
+void __exit snd_memory_info_done(void)
+{
+	snd_info_free_entry(snd_memory_info_entry);
+}
+#endif
diff --git a/alsa/acore/memory_wrapper.c b/alsa/acore/memory_wrapper.c
new file mode 100644
index 0000000..963aa77
--- /dev/null
+++ b/alsa/acore/memory_wrapper.c
@@ -0,0 +1,444 @@
+#include "config.h"
+#define __NO_VERSION__
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__) && !defined(__DEPEND__)
+#include "sndversions.h"
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#include <linux/ioport.h>
+static inline void snd_memory_wrapper_request_region(unsigned long from, unsigned long extent, const char *name)
+{
+	request_region(from, extent, name);
+}
+#endif
+
+#undef CONFIG_SND_DEBUG_MEMORY
+#include "adriver.h"
+#include <linux/mm.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#include <sound/memalloc.h>
+#include "pci_compat_22.c"
+#endif
+
+/* vmalloc_to_page wrapper */
+#ifndef CONFIG_HAVE_VMALLOC_TO_PAGE
+#include <linux/highmem.h>
+struct page *snd_compat_vmalloc_to_page(void *pageptr)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long lpage;
+	struct page *page;
+
+	lpage = VMALLOC_VMADDR(pageptr);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	spin_lock(&init_mm.page_table_lock);
+#endif
+	pgd = pgd_offset(&init_mm, lpage);
+	pmd = pmd_offset(pgd, lpage);
+	pte = pte_offset(pmd, lpage);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+	page = virt_to_page(pte_page(*pte));
+#else
+	page = pte_page(*pte);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	spin_unlock(&init_mm.page_table_lock);
+#endif
+
+	return page;
+}    
+#endif
+
+#ifndef CONFIG_HAVE_STRLCPY
+size_t snd_compat_strlcpy(char *dest, const char *src, size_t size)
+{
+	size_t ret = strlen(src);
+
+	if (size) {
+		size_t len = (ret >= size) ? size-1 : ret;
+		memcpy(dest, src, len);
+		dest[len] = '\0';
+	}
+	return ret;
+}
+#endif
+
+#ifndef CONFIG_HAVE_VSNPRINTF
+/* copied from lib/vsprintf.c from recent kernel tree */
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#undef SPECIAL
+#define SPECIAL	32		/* 0x */
+#undef LARGE
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+/* we use this so that we can do without the ctype library */
+#undef isdigit
+#define isdigit(c)	((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+	int i=0;
+
+	while (isdigit(**s))
+		i = i*10 + *((*s)++) - '0';
+	return i;
+}
+
+static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
+{
+	char c,sign,tmp[66];
+	const char *digits;
+	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	int i;
+
+	digits = (type & LARGE) ? large_digits : small_digits;
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+		return NULL;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if ((signed long long) num < 0) {
+			sign = '-';
+			num = - (signed long long) num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++]='0';
+	else while (num != 0)
+		tmp[i++] = digits[do_div(num,base)];
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type&(ZEROPAD+LEFT))) {
+		while(size-->0) {
+			if (buf < end)
+				*buf = ' ';
+			++buf;
+		}
+	}
+	if (sign) {
+		if (buf < end)
+			*buf = sign;
+		++buf;
+	}
+	if (type & SPECIAL) {
+		if (base==8) {
+			if (buf < end)
+				*buf = '0';
+			++buf;
+		} else if (base==16) {
+			if (buf < end)
+				*buf = '0';
+			++buf;
+			if (buf < end)
+				*buf = digits[33];
+			++buf;
+		}
+	}
+	if (!(type & LEFT)) {
+		while (size-- > 0) {
+			if (buf < end)
+				*buf = c;
+			++buf;
+		}
+	}
+	while (i < precision--) {
+		if (buf < end)
+			*buf = '0';
+		++buf;
+	}
+	while (i-- > 0) {
+		if (buf < end)
+			*buf = tmp[i];
+		++buf;
+	}
+	while (size-- > 0) {
+		if (buf < end)
+			*buf = ' ';
+		++buf;
+	}
+	return buf;
+}
+
+int snd_compat_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long long num;
+	int i, base;
+	char *str, *end, c;
+	const char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+				/* 'z' support added 23/7/1999 S.H.    */
+				/* 'z' changed to 'Z' --davidm 1/25/99 */
+				/* 't' added for ptrdiff_t */
+
+	/* Reject out-of-range values early.  Large positive sizes are
+	   used for unknown buffer sizes. */
+	if (unlikely((int) size < 0))
+		return 0;
+
+	str = buf;
+	end = buf + size;
+
+	/* Make sure end is always >= buf */
+	if (end < buf) {
+		end = ((void *)-1);
+		size = end - buf;
+	}
+
+	for (; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			if (str < end)
+				*str = *fmt;
+			++str;
+			continue;
+		}
+
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+			}
+
+		/* get field width */
+		field_width = -1;
+		if (isdigit(*fmt))
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;	
+			if (isdigit(*fmt))
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+		    *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
+			qualifier = *fmt;
+			++fmt;
+			if (qualifier == 'l' && *fmt == 'l') {
+				qualifier = 'L';
+				++fmt;
+			}
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+			case 'c':
+				if (!(flags & LEFT)) {
+					while (--field_width > 0) {
+						if (str < end)
+							*str = ' ';
+						++str;
+					}
+				}
+				c = (unsigned char) va_arg(args, int);
+				if (str < end)
+					*str = c;
+				++str;
+				while (--field_width > 0) {
+					if (str < end)
+						*str = ' ';
+					++str;
+				}
+				continue;
+
+			case 's':
+				s = va_arg(args, char *);
+				if ((unsigned long)s < PAGE_SIZE)
+					s = "<NULL>";
+
+				len = strnlen(s, precision);
+
+				if (!(flags & LEFT)) {
+					while (len < field_width--) {
+						if (str < end)
+							*str = ' ';
+						++str;
+					}
+				}
+				for (i = 0; i < len; ++i) {
+					if (str < end)
+						*str = *s;
+					++str; ++s;
+				}
+				while (len < field_width--) {
+					if (str < end)
+						*str = ' ';
+					++str;
+				}
+				continue;
+
+			case 'p':
+				if (field_width == -1) {
+					field_width = 2*sizeof(void *);
+					flags |= ZEROPAD;
+				}
+				str = number(str, end,
+						(unsigned long) va_arg(args, void *),
+						16, field_width, precision, flags);
+				continue;
+
+
+			case 'n':
+				/* FIXME:
+				* What does C99 say about the overflow case here? */
+				if (qualifier == 'l') {
+					long * ip = va_arg(args, long *);
+					*ip = (str - buf);
+				} else if (qualifier == 'Z' || qualifier == 'z') {
+					size_t * ip = va_arg(args, size_t *);
+					*ip = (str - buf);
+				} else {
+					int * ip = va_arg(args, int *);
+					*ip = (str - buf);
+				}
+				continue;
+
+			case '%':
+				if (str < end)
+					*str = '%';
+				++str;
+				continue;
+
+				/* integer number formats - set up the flags and "break" */
+			case 'o':
+				base = 8;
+				break;
+
+			case 'X':
+				flags |= LARGE;
+			case 'x':
+				base = 16;
+				break;
+
+			case 'd':
+			case 'i':
+				flags |= SIGN;
+			case 'u':
+				break;
+
+			default:
+				if (str < end)
+					*str = '%';
+				++str;
+				if (*fmt) {
+					if (str < end)
+						*str = *fmt;
+					++str;
+				} else {
+					--fmt;
+				}
+				continue;
+		}
+		if (qualifier == 'L')
+			num = va_arg(args, long long);
+		else if (qualifier == 'l') {
+			num = va_arg(args, unsigned long);
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'Z' || qualifier == 'z') {
+			num = va_arg(args, size_t);
+		} else if (qualifier == 't') {
+			num = va_arg(args, ptrdiff_t);
+		} else if (qualifier == 'h') {
+			num = (unsigned short) va_arg(args, int);
+			if (flags & SIGN)
+				num = (signed short) num;
+		} else {
+			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
+		str = number(str, end, num, base,
+				field_width, precision, flags);
+	}
+	if (size > 0) {
+		if (str < end)
+			*str = '\0';
+		else
+			end[-1] = '\0';
+	}
+	/* the trailing null byte doesn't count towards the total */
+	return str-buf;
+}
+#endif
+
+#ifndef CONFIG_HAVE_SNPRINTF
+int snd_compat_snprintf(char *buf, size_t size, const char * fmt, ...)
+{
+	int res;
+	va_list args;
+
+	va_start(args, fmt);
+	res = vsnprintf(buf, size, fmt, args);
+	va_end(args);
+	return res;
+}
+#endif
diff --git a/alsa/acore/misc.patch b/alsa/acore/misc.patch
new file mode 100644
index 0000000..befbb7b
--- /dev/null
+++ b/alsa/acore/misc.patch
@@ -0,0 +1,71 @@
+--- ../alsa-kernel/core/misc.c	2009-08-27 17:44:33.000000000 +0200
++++ misc.c	2009-09-01 08:28:18.000000000 +0200
+@@ -1,3 +1,9 @@
++#define __NO_VERSION__
++#include "adriver.h"
++#ifndef KERN_DEFAULT
++#define KERN_DEFAULT	""
++#endif
++
+ /*
+  *  Misc and compatibility things
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -42,7 +48,7 @@
+ {
+ 	if (res) {
+ 		release_resource(res);
+-		kfree(res);
++		kfree_nocheck(res);
+ 	}
+ }
+ 
+@@ -115,15 +121,47 @@
+ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
+ {
+ 	const struct snd_pci_quirk *q;
++	unsigned short subsystem_vendor, subsystem_device;
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 0)
++	subsystem_vendor = pci->subsystem_vendor;
++	subsystem_device = pci->subsystem_device;
++#else
++	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
++	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
++#endif
+ 	for (q = list; q->subvendor; q++) {
+-		if (q->subvendor != pci->subsystem_vendor)
++		if (q->subvendor != subsystem_vendor)
+ 			continue;
+ 		if (!q->subdevice ||
+-		    (pci->subsystem_device & q->subdevice_mask) == q->subdevice)
++		    (subsystem_device & q->subdevice_mask) == q->subdevice)
+ 			return q;
+ 	}
+ 	return NULL;
+ }
+ EXPORT_SYMBOL(snd_pci_quirk_lookup);
+ #endif
++
++/* just for compatibility reason */
++void snd_verbose_printk(const char *file, int line, const char *format, ...)
++{
++	va_list args;
++	va_start(args, format);
++	if (print_snd_pfx(0, file, line, format))
++		format += 3; /* skip the printk level-prefix */
++	vprintk(format, args);
++	va_end(args);
++}
++EXPORT_SYMBOL(snd_verbose_printk);
++
++void snd_verbose_printd(const char *file, int line, const char *format, ...)
++{
++	va_list args;
++	va_start(args, format);
++	if (print_snd_pfx(1, file, line, format))
++		format += 3; /* skip the printk level-prefix */
++	vprintk(format, args);
++	va_end(args);
++
++}
++EXPORT_SYMBOL(snd_verbose_printd);
diff --git a/alsa/acore/misc_driver.c b/alsa/acore/misc_driver.c
new file mode 100644
index 0000000..89a5e3f
--- /dev/null
+++ b/alsa/acore/misc_driver.c
@@ -0,0 +1,1136 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+
+/*
+ * platform_device wrapper
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+static LIST_HEAD(snd_driver_list);
+
+struct bus_type snd_platform_bus_type;
+EXPORT_SYMBOL(snd_platform_bus_type);
+
+/* for platform_device only! */
+int snd_compat_driver_register(struct device_driver *driver)
+{
+	list_add(&driver->list, &snd_driver_list);
+	INIT_LIST_HEAD(&driver->device_list);
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_driver_register);
+
+void snd_compat_driver_unregister(struct device_driver *driver)
+{
+	struct list_head *p, *n;
+
+	list_del(&driver->list);
+	list_for_each_safe(p, n, &driver->device_list) {
+		struct platform_device *dev = list_entry(p, struct platform_device, list);
+		list_del(p);
+		if (driver->remove)
+			driver->remove((struct device *)dev);
+		kfree(dev);
+	}
+}
+EXPORT_SYMBOL(snd_compat_driver_unregister);
+
+#ifdef CONFIG_PM
+static int snd_device_pm_callback(struct pm_dev *pm_dev, pm_request_t rqst, void *data)
+{
+	struct device *dev = data;
+	switch (rqst) {
+	case PM_SUSPEND:
+		if (dev->driver->suspend)
+			dev->driver->suspend(dev, PMSG_SUSPEND);
+		break;
+	case PM_RESUME:
+		if (dev->driver->resume)
+			dev->driver->resume(dev);
+		break;
+	}
+	return 0;
+}
+#endif
+
+struct platform_device *
+snd_platform_device_register_simple(const char *name, int id,
+				    struct resource *res, int nres)
+{
+	struct list_head *p;
+	struct platform_device *dev;
+	int err;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (! dev)
+		return ERR_PTR(-ENOMEM);
+	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "%s.%d", name, id);
+
+	list_for_each(p, &snd_driver_list) {
+		struct device_driver *driver = list_entry(p, struct device_driver, list);
+		if (! strcmp(driver->name, name)) {
+			dev->name = name;
+			dev->id = id;
+			dev->dev.driver = driver;
+			err = driver->probe((struct device *)dev);
+			if (err < 0) {
+				kfree(dev);
+				return ERR_PTR(err);
+			}
+#ifdef CONFIG_PM
+			dev->dev.pm_dev = pm_register(PM_UNKNOWN_DEV, 0,
+						      snd_device_pm_callback);
+			if (dev->dev.pm_dev)
+				dev->dev.pm_dev->data = dev;
+#endif
+			list_add(&dev->list, &driver->device_list);
+			return dev;
+		}
+	}
+	kfree(dev);
+	return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(snd_platform_device_register_simple);
+#endif /* < 2.6.0 */
+
+
+/*
+ * pci_save/restore_config wrapper
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#ifdef CONFIG_PCI
+#ifndef CONFIG_HAVE_NEW_PCI_SAVE_STATE
+#ifdef CONFIG_HAVE_PCI_SAVED_CONFIG
+int snd_pci_compat_save_state(struct pci_dev *pci)
+{
+	return snd_pci_orig_save_state(pci, pci->saved_config_space);
+}
+EXPORT_SYMBOL(snd_pci_compat_save_state);
+int snd_pci_compat_restore_state(struct pci_dev *pci)
+{
+	return snd_pci_orig_restore_state(pci, pci->saved_config_space);
+}
+EXPORT_SYMBOL(snd_pci_compat_restore_state);
+#else /* !CONFIG_HAVE_PCI_SAVED_CONFIG */
+struct saved_config_tbl {
+	struct pci_dev *pci;
+	u32 config[16];
+};
+static struct saved_config_tbl saved_tbl[16];
+
+int snd_pci_compat_save_state(struct pci_dev *pci)
+{
+	int i;
+	/* FIXME: mutex needed for race? */
+	for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
+		if (! saved_tbl[i].pci) {
+			saved_tbl[i].pci = pci;
+			snd_pci_orig_save_state(pci, saved_tbl[i].config);
+			return 0;
+		}
+	}
+	printk(KERN_DEBUG "snd: no pci config space found!\n");
+	return 1;
+}
+EXPORT_SYMBOL(snd_pci_compat_save_state);
+
+int snd_pci_compat_restore_state(struct pci_dev *pci)
+{
+	int i;
+	/* FIXME: mutex needed for race? */
+	for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
+		if (saved_tbl[i].pci == pci) {
+			saved_tbl[i].pci = NULL;
+			snd_pci_orig_restore_state(pci, saved_tbl[i].config);
+			return 0;
+		}
+	}
+	printk(KERN_DEBUG "snd: no saved pci config!\n");
+	return 1;
+}
+EXPORT_SYMBOL(snd_pci_compat_restore_state);
+#endif /* CONFIG_HAVE_PCI_SAVED_CONFIG */
+#endif /* ! CONFIG_HAVE_NEW_PCI_SAVE_STATE */
+#endif
+#endif /* >= 2.4.0 */
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+
+#include <linux/slab.h>
+#include <asm/io.h>
+
+int try_inc_mod_count(struct module *module)
+{
+	__MOD_INC_USE_COUNT(module);
+	return 1;
+}
+EXPORT_SYMBOL(try_inc_mod_count);
+
+struct resource *snd_compat_request_region(unsigned long start, unsigned long size, const char *name, int is_memory)
+{
+	struct resource *resource;
+
+#ifdef CONFIG_SND_DEBUG_MEMORY
+	/* DON'T use kmalloc here; the allocated resource is released
+	 * by kfree without wrapper in each driver
+	 */
+	resource = snd_wrapper_kmalloc(sizeof(struct resource), GFP_KERNEL);
+#else
+	resource = kmalloc(sizeof(struct resource), GFP_KERNEL);
+#endif
+	if (resource == NULL)
+		return NULL;
+	if (! is_memory) {
+		if (check_region(start, size)) {
+			kfree_nocheck(resource);
+			return NULL;
+		}
+		snd_wrapper_request_region(start, size, name);
+	}
+	memset(resource, 0, sizeof(struct resource));
+	resource->name = name;
+	resource->start = start;
+	resource->end = start + size - 1;
+	resource->flags = is_memory ? IORESOURCE_MEM : IORESOURCE_IO;
+	return resource;
+}
+EXPORT_SYMBOL(snd_compat_request_region);
+
+int snd_compat_release_resource(struct resource *resource)
+{
+	if (!resource)
+		return -EINVAL;
+	if (resource->flags & IORESOURCE_MEM)
+		return 0;
+	release_region(resource->start, (resource->end - resource->start) + 1);
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_release_resource);
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
+
+#include <linux/apm_bios.h>
+
+static spinlock_t pm_devs_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(pm_devs);
+
+#ifdef CONFIG_PCI
+static struct pm_dev *pci_compat_pm_dev;
+static int pci_compat_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
+{
+	struct pci_dev *dev;
+	switch (rqst) {
+	case PM_SUSPEND:
+		pci_for_each_dev(dev) {
+			struct pci_driver *drv = snd_pci_compat_get_pci_driver(dev);
+			if (drv && drv->suspend)
+				drv->suspend(dev, PMSG_SUSPEND);
+		}
+		break;
+	case PM_RESUME:
+		pci_for_each_dev(dev) {
+			struct pci_driver *drv = snd_pci_compat_get_pci_driver(dev);
+			if (drv && drv->resume)
+				drv->resume(dev);
+		}
+		break;
+	}	
+	return 0;
+}
+#endif
+
+static int snd_apm_callback(apm_event_t ev)
+{
+	struct list_head *entry;
+	pm_request_t rqst;
+	void *data;
+	int status;
+	
+	switch (ev) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+	case APM_CRITICAL_SUSPEND:
+		rqst = PM_SUSPEND;
+		data = (void *)3;
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+	case APM_STANDBY_RESUME:		/* ??? */
+		rqst = PM_RESUME;
+		data = (void *)0;
+		break;
+	default:
+		return 0;
+	}
+	list_for_each(entry, &pm_devs) {
+		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+		if ((status = pm_send(dev, rqst, data)))
+			return status;
+	}
+	/* platform_device */
+	list_for_each(entry, &snd_driver_list) {
+		struct device_driver *driver = list_entry(entry, struct device_driver, list);
+		struct list_head *p;
+		if (rqst == PM_SUSPEND) {
+			if (! driver->suspend)
+				continue;
+		} else {
+			if (! driver->resume)
+				continue;
+		}
+		list_for_each(p, &driver->device_list) {
+			struct platform_device *dev = list_entry(p, struct platform_device, list);
+			if (rqst == PM_SUSPEND)
+				driver->suspend((struct device *)dev, PMSG_SUSPEND);
+			else
+				driver->resume((struct device *)dev);
+		}
+	}
+
+	return 0;
+}
+
+int __init pm_init(void)
+{
+	if (apm_register_callback(snd_apm_callback))
+		snd_printk(KERN_ERR "apm_register_callback failure!\n");
+#ifdef CONFIG_PCI
+	pci_compat_pm_dev = pm_register(PM_PCI_DEV, 0, pci_compat_pm_callback);
+#endif
+	return 0;
+}
+
+void __exit pm_done(void)
+{
+#ifdef CONFIG_PCI
+	if (pci_compat_pm_dev)
+		pm_unregister(pci_compat_pm_dev);
+#endif
+	apm_unregister_callback(snd_apm_callback);
+}
+
+struct pm_dev *pm_register(pm_dev_t type,
+			   unsigned long id,
+			   pm_callback callback)
+{
+	struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+
+	if (dev) {
+		unsigned long flags;
+		
+		memset(dev, 0, sizeof(*dev));
+		dev->type = type;
+		dev->id = id;
+		dev->callback = callback;
+		
+		spin_lock_irqsave(&pm_devs_lock, flags);
+		list_add(&dev->entry, &pm_devs);
+		spin_unlock_irqrestore(&pm_devs_lock, flags);
+	}
+	return dev;
+}
+EXPORT_SYMBOL(pm_register);
+
+void pm_unregister(struct pm_dev *dev)
+{
+	if (dev) {
+		unsigned long flags;
+		
+		spin_lock_irqsave(&pm_devs_lock, flags);
+		list_del(&dev->entry);
+		spin_unlock_irqrestore(&pm_devs_lock, flags);
+
+		kfree(dev);
+	}
+}
+EXPORT_SYMBOL(pm_unregister);
+
+int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	int status = 0;
+	int prev_state, next_state;
+	
+	switch (rqst) {
+	case PM_SUSPEND:
+	case PM_RESUME:
+		prev_state = dev->state;
+		next_state = (int) data;
+		if (prev_state != next_state) {
+			if (dev->callback)
+				status = (*dev->callback)(dev, rqst, data);
+			if (!status) {
+				dev->state = next_state;
+				dev->prev_state = prev_state;
+			}
+		} else {
+			dev->prev_state = prev_state;
+		}
+		break;
+	default:
+		if (dev->callback)
+			status = (*dev->callback)(dev, rqst, data);
+		break;
+	}
+	return status;
+}
+EXPORT_SYMBOL(pm_send);
+
+#endif /* kernel version < 2.3.0 && CONFIG_APM */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 7)
+/* wait-for-completion handler emulation */
+
+/* we know this is used below exactly once for at most one waiter */
+struct completion {
+	int done;
+	wait_queue_head_t wait;
+};
+
+static inline void init_completion(struct completion *comp)
+{
+	comp->done = 0;
+	init_waitqueue_head(&comp->wait);
+}
+
+static void wait_for_completion(struct completion *comp)
+{
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&comp->wait, &wait);
+	for (;;) {
+		mb();
+		if (comp->done)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule();
+		set_current_state(TASK_RUNNING);
+	}
+	remove_wait_queue(&comp->wait, &wait);
+}
+
+static void complete_and_exit(struct completion *comp, long code)
+{
+	comp->done = 1;
+	wmb();
+	wake_up(&comp->wait);
+	/*do_exit(code);*/ /* FIXME: not exported from the kernel */
+}
+
+#else
+#include <linux/completion.h>
+#endif /* kernel version < 2.3.0 */
+
+/* workqueue-alike; 2.5.45 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 45)
+
+static int work_caller(void *data)
+{
+	struct work_struct *works = data;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+	lock_kernel();
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 18)
+	daemonize();
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
+	reparent_to_init();
+#endif
+	strcpy(current->comm, "snd"); /* FIXME: different names? */
+
+	works->func(works->data);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+	unlock_kernel();
+#endif
+
+	return 0;
+}
+
+int snd_compat_schedule_work(struct work_struct *works)
+{
+	return kernel_thread(work_caller, works, 0) >= 0;
+}
+EXPORT_SYMBOL(snd_compat_schedule_work);
+
+struct workqueue_struct {
+	spinlock_t lock;
+	const char *name;
+	struct list_head worklist;
+	int task_pid;
+	struct task_struct *task;
+	wait_queue_head_t more_work;
+	wait_queue_head_t work_done;
+	struct completion thread_exited;
+};
+
+static void run_workqueue(struct workqueue_struct *wq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wq->lock, flags);
+	while (!list_empty(&wq->worklist)) {
+		struct work_struct *work = list_entry(wq->worklist.next,
+						      struct work_struct, entry);
+		void (*f) (void *) = work->func;
+		void *data = work->data;
+
+		list_del_init(wq->worklist.next);
+		spin_unlock_irqrestore(&wq->lock, flags);
+		clear_bit(0, &work->pending);
+		f(data);
+		spin_lock_irqsave(&wq->lock, flags);
+		wake_up(&wq->work_done);
+	}
+	spin_unlock_irqrestore(&wq->lock, flags);
+}
+
+void snd_compat_flush_workqueue(struct workqueue_struct *wq)
+{
+	if (wq->task == current) {
+		run_workqueue(wq);
+	} else {
+		wait_queue_t wait;
+
+		init_waitqueue_entry(&wait, current);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		spin_lock_irq(&wq->lock);
+		add_wait_queue(&wq->work_done, &wait);
+		while (!list_empty(&wq->worklist)) {
+			spin_unlock_irq(&wq->lock);
+			schedule();
+			spin_lock_irq(&wq->lock);
+		}
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&wq->work_done, &wait);
+		spin_unlock_irq(&wq->lock);
+	}
+}
+EXPORT_SYMBOL(snd_compat_flush_workqueue);
+
+void snd_compat_destroy_workqueue(struct workqueue_struct *wq)
+{
+	snd_compat_flush_workqueue(wq);
+	kill_proc(wq->task_pid, SIGKILL, 1);
+	if (wq->task_pid >= 0)
+		wait_for_completion(&wq->thread_exited);
+	kfree(wq);
+}
+EXPORT_SYMBOL(snd_compat_destroy_workqueue);
+
+static int xworker_thread(void *data)
+{
+	struct workqueue_struct *wq = data;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+	lock_kernel();
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 18)
+	daemonize();
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
+	reparent_to_init();
+#endif
+	strcpy(current->comm, wq->name);
+
+	do {
+		run_workqueue(wq);
+		wait_event_interruptible(wq->more_work, !list_empty(&wq->worklist));
+	} while (!signal_pending(current));
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+	unlock_kernel();
+#endif
+	complete_and_exit(&wq->thread_exited, 0);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+	return 0;
+#endif
+}
+
+struct workqueue_struct *snd_compat_create_workqueue(const char *name)
+{
+	struct workqueue_struct *wq;
+	
+	BUG_ON(strlen(name) > 10);
+	
+	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
+	if (!wq)
+		return NULL;
+	memset(wq, 0, sizeof(*wq));
+	
+	spin_lock_init(&wq->lock);
+	INIT_LIST_HEAD(&wq->worklist);
+	init_waitqueue_head(&wq->more_work);
+	init_waitqueue_head(&wq->work_done);
+	init_completion(&wq->thread_exited);
+	wq->name = name;
+	wq->task_pid = kernel_thread(xworker_thread, wq, 0);
+	if (wq->task_pid < 0) {
+		printk(KERN_ERR "snd: failed to start thread %s\n", name);
+		snd_compat_destroy_workqueue(wq);
+		wq = NULL;
+	}
+	wq->task = find_task_by_pid(wq->task_pid);
+	return wq;
+}
+EXPORT_SYMBOL(snd_compat_create_workqueue);
+
+static void __x_queue_work(struct workqueue_struct *wq, struct work_struct *work)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wq->lock, flags);
+	work->wq_data = wq;
+	list_add_tail(&work->entry, &wq->worklist);
+	wake_up(&wq->more_work);
+	spin_unlock_irqrestore(&wq->lock, flags);
+}
+
+int snd_compat_queue_work(struct workqueue_struct *wq, struct work_struct *work)
+{
+	if (!test_and_set_bit(0, &work->pending)) {
+		__x_queue_work(wq, work);
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_queue_work);
+
+static void delayed_work_timer_fn(unsigned long __data)
+{
+	struct work_struct *work = (struct work_struct *)__data;
+	struct workqueue_struct *wq = work->wq_data;
+	
+	if (wq)
+		__x_queue_work(wq, work);
+	else
+		snd_compat_schedule_work(work);
+}
+
+int snd_compat_queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay)
+{
+	struct work_struct *work = &dwork->work;
+	struct timer_list *timer = &work->timer;
+
+	if (!test_and_set_bit(0, &work->pending)) {
+		work->wq_data = wq;
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)work;
+		timer->function = delayed_work_timer_fn;
+		add_timer(timer);
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_queue_delayed_work);
+
+int snd_compat_cancel_delayed_work(struct delayed_work *dwork)
+{
+	struct work_struct *work = &dwork->work;
+	int ret;
+
+	ret = del_timer_sync(&work->timer);
+	if (ret)
+		clear_bit(0, &work->pending);
+	return ret;
+}
+EXPORT_SYMBOL(snd_compat_cancel_delayed_work);
+
+#endif
+
+#ifndef CONFIG_HAVE_KZALLOC
+#ifndef CONFIG_SND_DEBUG_MEMORY
+/* Don't put this to wrappers.c.  We need to call the kmalloc wrapper here. */
+void *snd_compat_kzalloc(size_t size, unsigned int __nocast flags)
+{
+	void *ret;
+	ret = kmalloc(size, flags);
+	if (ret)
+		memset(ret, 0, size);
+	return ret;
+}
+EXPORT_SYMBOL(snd_compat_kzalloc);
+#endif
+#endif
+
+#ifndef CONFIG_HAVE_KCALLOC
+#ifndef CONFIG_SND_DEBUG_MEMORY
+/* Don't put this to wrappers.c.  We need to call the kmalloc wrapper here. */
+void *snd_compat_kcalloc(size_t n, size_t size, unsigned int __nocast flags)
+{
+	if (n != 0 && size > INT_MAX / n)
+		return NULL;
+	return snd_compat_kzalloc(n * size, flags);
+}
+EXPORT_SYMBOL(snd_compat_kcalloc);
+#endif
+#endif
+
+#ifndef CONFIG_HAVE_KSTRDUP
+#ifndef CONFIG_SND_DEBUG_MEMORY
+char *snd_compat_kstrdup(const char *s, unsigned int __nocast gfp_flags)
+{
+	int len;
+	char *buf;
+
+	if (!s) return NULL;
+
+	len = strlen(s) + 1;
+	buf = kmalloc(len, gfp_flags);
+	if (buf)
+		memcpy(buf, s, len);
+	return buf;
+}
+EXPORT_SYMBOL(snd_compat_kstrdup);
+#endif
+#endif
+
+#ifndef CONFIG_HAVE_KSTRNDUP
+#ifndef CONFIG_SND_DEBUG_MEMORY
+char *snd_compat_kstrndup(const char *s, size_t maxlen,
+			  unsigned int __nocast gfp_flags)
+{
+	int len;
+	char *buf;
+
+	if (!s) return NULL;
+
+	len = strlen(s);
+	if (len >= maxlen)
+		len = maxlen;
+	buf = kmalloc(len + 1, gfp_flags);
+	if (buf) {
+		memcpy(buf, s, len);
+		buf[len] = 0;
+	}
+	return buf;
+}
+EXPORT_SYMBOL(snd_compat_kstrndup);
+#endif
+#endif
+
+#ifdef CONFIG_CREATE_WORKQUEUE_FLAGS
+
+#include <linux/workqueue.h>
+
+struct workqueue_struct *snd_compat_create_workqueue2(const char *name)
+{
+	return create_workqueue(name, 0);
+}
+EXPORT_SYMBOL(snd_compat_create_workqueue2);
+
+#endif
+
+
+/*
+ * PnP suspend/resume wrapper
+ */
+#if defined(CONFIG_PNP) && defined(CONFIG_PM)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+#ifndef CONFIG_HAVE_PNP_SUSPEND
+
+#include <linux/pm.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
+#include <linux/pm_legacy.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) || defined(CONFIG_PM_LEGACY)
+#define SUPPORT_PM
+#endif
+
+#ifdef SUPPORT_PM
+struct snd_pnp_pm_devs {
+	void *dev;
+	void *driver;
+	struct pm_dev *pm;
+};
+
+static struct snd_pnp_pm_devs snd_pm_devs[16]; /* FIXME */
+
+static void register_pnp_pm_callback(void *dev, void *driver, pm_callback callback)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(snd_pm_devs); i++) {
+		if (snd_pm_devs[i].dev)
+			continue;
+		snd_pm_devs[i].pm = pm_register(PM_ISA_DEV, 0, callback);
+		if (snd_pm_devs[i].pm) {
+			snd_pm_devs[i].dev = dev;
+			snd_pm_devs[i].driver = driver;
+			snd_pm_devs[i].pm->data = &snd_pm_devs[i];
+		}
+		return;
+	}
+}
+
+static void unregister_pnp_pm_callback(void *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(snd_pm_devs); i++) {
+		if (snd_pm_devs[i].dev == dev) {
+			snd_pm_devs[i].dev = NULL;
+			snd_pm_devs[i].driver = NULL;
+			if (snd_pm_devs[i].pm) {
+				pm_unregister(snd_pm_devs[i].pm);
+				snd_pm_devs[i].pm = NULL;
+			}
+			return;
+		}
+	}
+}
+
+static int snd_pnp_dev_pm_callback(struct pm_dev *dev, pm_request_t req, void *data)
+{
+	struct snd_pnp_pm_devs *pm = dev->data;
+	struct pnp_dev *pdev = pm->dev;
+	struct snd_pnp_driver *driver = pm->driver;
+
+	switch (req) {
+	case PM_SUSPEND:
+		driver->suspend(pdev, PMSG_SUSPEND);
+		break;
+	case PM_RESUME:
+		driver->resume(pdev);
+		break;
+	}
+	return 0;
+}
+
+static int snd_pnp_dev_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+{
+	struct snd_pnp_driver *driver = (struct snd_pnp_driver *)dev->driver;
+	int err = driver->probe(dev, dev_id);
+	if (err >= 0)
+		register_pnp_pm_callback(dev, driver, snd_pnp_dev_pm_callback);
+	return err;
+}
+
+static void snd_pnp_dev_remove(struct pnp_dev *dev)
+{
+	struct snd_pnp_driver *driver = (struct snd_pnp_driver *)dev->driver;
+	unregister_pnp_pm_callback(dev);
+	driver->remove(dev);
+}
+#endif /* SUPPORT_PM */
+
+#undef pnp_register_driver
+
+int snd_pnp_register_driver(struct snd_pnp_driver *driver)
+{
+	driver->real_driver.name = driver->name;
+	driver->real_driver.id_table = driver->id_table;
+	driver->real_driver.flags = driver->flags;
+#ifdef SUPPORT_PM
+	if (driver->suspend || driver->resume) {
+		driver->real_driver.probe = snd_pnp_dev_probe;
+		driver->real_driver.remove = snd_pnp_dev_remove;
+	} else
+#endif
+	{
+		driver->real_driver.probe = driver->probe;
+		driver->real_driver.remove = driver->remove;
+	}
+	return pnp_register_driver(&driver->real_driver);
+}
+EXPORT_SYMBOL(snd_pnp_register_driver);
+
+#ifdef SUPPORT_PM
+/*
+ * for card
+ */
+static int snd_pnp_card_pm_callback(struct pm_dev *dev, pm_request_t req, void *data)
+{
+	struct snd_pnp_pm_devs *pm = dev->data;
+	struct pnp_card_link *pdev = pm->dev;
+	struct snd_pnp_card_driver *driver = pm->driver;
+
+	switch (req) {
+	case PM_SUSPEND:
+		driver->suspend(pdev, PMSG_SUSPEND);
+		break;
+	case PM_RESUME:
+		driver->resume(pdev);
+		break;
+	}
+	return 0;
+}
+
+static int snd_pnp_card_probe(struct pnp_card_link *dev, const struct pnp_card_device_id *dev_id)
+{
+	struct snd_pnp_card_driver *driver = (struct snd_pnp_card_driver *)dev->driver;
+	int err = driver->probe(dev, dev_id);
+	if (err >= 0)
+		register_pnp_pm_callback(dev, driver, snd_pnp_card_pm_callback);
+	return err;
+}
+
+static void snd_pnp_card_remove(struct pnp_card_link *dev)
+{
+	struct snd_pnp_card_driver *driver = (struct snd_pnp_card_driver *)dev->driver;
+	unregister_pnp_pm_callback(dev);
+	driver->remove(dev);
+}
+#endif /* SUPPORT_PM */
+
+#undef pnp_register_card_driver
+
+int snd_pnp_register_card_driver(struct snd_pnp_card_driver *driver)
+{
+	driver->real_driver.name = driver->name;
+	driver->real_driver.id_table = driver->id_table;
+	driver->real_driver.flags = driver->flags;
+#ifdef SUPPORT_PM
+	if (driver->suspend || driver->resume) {
+		driver->real_driver.probe = snd_pnp_card_probe;
+		driver->real_driver.remove = snd_pnp_card_remove;
+	} else
+#endif
+	{
+		driver->real_driver.probe = driver->probe;
+		driver->real_driver.remove = driver->remove;
+	}
+	return pnp_register_card_driver(&driver->real_driver);
+}
+EXPORT_SYMBOL(snd_pnp_register_card_driver);
+
+#endif /* ! CONFIG_HAVE_PNP_SUSPEND */
+#endif /* 2.6 */
+#endif /* PNP && PM */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#include <linux/firmware.h>
+#ifdef NEEDS_COMPAT_FW_LOADER
+
+extern int mod_firmware_load(const char *fn, char **fp);
+
+static int snd_try_load_firmware(const char *path, const char *name,
+				 struct firmware *firmware)
+{
+	char filename[30 + FIRMWARE_NAME_MAX];
+
+	sprintf(filename, "%s/%s", path, name);
+	firmware->size = mod_firmware_load(filename, (char **)&firmware->data);
+	if (firmware->size)
+		printk(KERN_INFO "Loaded '%s'.", filename);
+	return firmware->size;
+}
+
+int snd_compat_request_firmware(const struct firmware **fw, const char *name)
+{
+	struct firmware *firmware;
+
+	*fw = NULL;
+	firmware = kmalloc(sizeof *firmware, GFP_KERNEL);
+	if (!firmware)
+		return -ENOMEM;
+	if (!snd_try_load_firmware("/lib/firmware", name, firmware) &&
+	    !snd_try_load_firmware("/lib/hotplug/firmware", name, firmware) &&
+	    !snd_try_load_firmware("/usr/lib/hotplug/firmware", name, firmware)) {
+		kfree(firmware);
+		return -EIO;
+	}
+	*fw = firmware;
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_request_firmware);
+
+void snd_compat_release_firmware(const struct firmware *fw)
+{
+	if (fw) {
+		vfree(fw->data);
+		kfree(fw);
+	}
+}
+EXPORT_SYMBOL(snd_compat_release_firmware);
+
+#endif /* NEEDS_COMPAT_FW_LOADER */
+#endif /* !2.6 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+void snd_compat_print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+				     const void *buf, size_t len)
+{
+	size_t off;
+	unsigned int i;
+
+	for (off = 0; off < len; off += 16) {
+		printk(KERN_DEBUG "%s", prefix_str);
+		if (prefix_type == DUMP_PREFIX_OFFSET)
+			printk(" %.4x:", (unsigned int)off);
+		for (i = 0; i < 16 && off + i < len; ++i)
+			printk(" %02x", ((const u8*)buf)[off + i]);
+		printk("\n");
+	}
+}
+EXPORT_SYMBOL(snd_compat_print_hex_dump_bytes);
+#endif
+
+/* ISA drivers */
+#ifdef CONFIG_ISA
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <linux/device.h>
+#include <linux/isa.h>
+#ifdef HAVE_DUMMY_SND_ISA_WRAPPER
+#include <linux/list.h>
+#include <linux/err.h>
+
+#define MAX_ISA_NUMS	8
+
+struct isa_platform_link {
+	struct platform_driver platform;
+	struct isa_driver *isa;
+	unsigned int cards;
+	struct platform_device *pdevs[MAX_ISA_NUMS];
+	struct list_head list;
+};
+	
+static LIST_HEAD(snd_isa_link_list);
+
+static struct isa_platform_link *get_isa_link(struct isa_driver *driver)
+{
+	struct isa_platform_link *p;
+	list_for_each_entry(p, &snd_isa_link_list, list) {
+		if (p->isa == driver)
+			return p;
+	}
+	return NULL;
+}
+
+static struct isa_platform_link *get_pdev_link(struct platform_device *pdev)
+{
+	struct platform_driver *pdrv = container_of(pdev->dev.driver,
+						    struct platform_driver,
+						    driver);
+	return (struct isa_platform_link *)pdrv;
+}
+
+
+static int snd_isa_platform_probe(struct platform_device *pdev)
+{
+	struct isa_platform_link *p = get_pdev_link(pdev);
+	int n = pdev->id;
+
+	if (!p)
+		return -EINVAL;
+	p = get_pdev_link(pdev);
+	if (p->isa->match)
+		if (!p->isa->match(&pdev->dev, n))
+			return -EINVAL;
+	return p->isa->probe(&pdev->dev, n);
+}
+
+static int snd_isa_platform_remove(struct platform_device *pdev)
+{
+	struct isa_platform_link *p = get_pdev_link(pdev);
+	int n = pdev->id;
+
+	if (!p)
+		return 0;
+	p->isa->remove(&pdev->dev, n);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_isa_platform_suspend(struct platform_device *pdev,
+				    pm_message_t state)
+{
+	struct isa_platform_link *p = get_pdev_link(pdev);
+	int n = pdev->id;
+
+	if (!p)
+		return -EINVAL;
+	return p->isa->suspend(&pdev->dev, n, state);
+}
+
+static int snd_isa_platform_resume(struct platform_device *pdev)
+{
+	struct isa_platform_link *p = get_pdev_link(pdev);
+	int n = pdev->id;
+
+	if (!p)
+		return -EINVAL;
+	return p->isa->resume(&pdev->dev, n);
+}
+#endif
+
+int snd_isa_register_driver(struct isa_driver *driver, unsigned int nums)
+{
+	int i, cards, err;
+	struct isa_platform_link *p;
+
+	if (nums >= MAX_ISA_NUMS)
+		return -EINVAL;
+
+	if (get_isa_link(driver))
+		return -EBUSY;
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&p->list);
+	p->isa = driver;
+	p->platform.probe = snd_isa_platform_probe;
+	p->platform.driver.name = driver->driver.name;
+	if (driver->remove)
+		p->platform.remove = snd_isa_platform_remove;
+#ifdef CONFIG_PM
+	if (driver->suspend)
+		p->platform.suspend = snd_isa_platform_suspend;
+	if (driver->resume)
+		p->platform.resume = snd_isa_platform_resume;
+#endif
+	err = platform_driver_register(&p->platform);
+	if (err < 0) {
+		kfree(p);
+		return err;
+	}
+	list_add(&p->list, &snd_isa_link_list);
+
+	cards = 0;
+	for (i = 0; i < nums; i++) {
+		struct platform_device *device;
+		device = platform_device_register_simple((char *)
+							 driver->driver.name,
+							 i, NULL, 0);
+		if (IS_ERR(device))
+			continue;
+		p->pdevs[i] = device;
+		cards++;
+	}
+	if (!cards) {
+		snd_isa_unregister_driver(driver);
+		return -ENODEV;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(snd_isa_register_driver);
+
+void snd_isa_unregister_driver(struct isa_driver *driver)
+{
+	struct isa_platform_link *p = get_isa_link(driver);
+	int i;
+
+	if (!p)
+		return;
+	for (i = 0; i < MAX_ISA_NUMS; i++)
+		if (p->pdevs[i])
+			platform_device_unregister(p->pdevs[i]);
+	platform_driver_unregister(&p->platform);
+	list_del(&p->list);
+	kfree(p);
+}
+EXPORT_SYMBOL(snd_isa_unregister_driver);
+
+#endif /* HAVE_DUMMY_SND_ISA_WRAPPER */
+#endif /* < 2.6.18 */
+#endif /* CONFIG_ISA */
diff --git a/alsa/acore/oss/Makefile b/alsa/acore/oss/Makefile
new file mode 100644
index 0000000..8cceefd
--- /dev/null
+++ b/alsa/acore/oss/Makefile
@@ -0,0 +1,22 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+clean-files := mixer_oss.c pcm_oss.c
+
+export-objs  := mixer_oss.o
+
+include $(SND_TOPDIR)/alsa-kernel/core/oss/Makefile
+
+EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/core/oss
+# avoid oops due to the compiler bug (?) of old gcc
+EXTRA_CFLAGS += -fno-omit-frame-pointer
+
+include $(SND_TOPDIR)/Rules.make
+
+mixer_oss.c: mixer_oss.patch $(SND_TOPDIR)/alsa-kernel/core/oss/mixer_oss.c
+pcm_oss.c: pcm_oss.patch $(SND_TOPDIR)/alsa-kernel/core/oss/pcm_oss.c
+
diff --git a/alsa/acore/oss/copy.c b/alsa/acore/oss/copy.c
new file mode 100644
index 0000000..ef5f37f
--- /dev/null
+++ b/alsa/acore/oss/copy.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/copy.c"
diff --git a/alsa/acore/oss/io.c b/alsa/acore/oss/io.c
new file mode 100644
index 0000000..f7e0a1c
--- /dev/null
+++ b/alsa/acore/oss/io.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/io.c"
diff --git a/alsa/acore/oss/linear.c b/alsa/acore/oss/linear.c
new file mode 100644
index 0000000..2f28404
--- /dev/null
+++ b/alsa/acore/oss/linear.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/linear.c"
diff --git a/alsa/acore/oss/mixer_oss.patch b/alsa/acore/oss/mixer_oss.patch
new file mode 100644
index 0000000..46825b5
--- /dev/null
+++ b/alsa/acore/oss/mixer_oss.patch
@@ -0,0 +1,60 @@
+--- ../../alsa-kernel/core/oss/mixer_oss.c	2007-12-20 10:19:01.000000000 +0100
++++ mixer_oss.c	2007-12-20 10:45:48.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  OSS emulation layer for the mixer interface
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -20,6 +21,7 @@
+  */
+ 
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+ #include <linux/string.h>
+@@ -377,24 +379,43 @@
+ 	return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ /* all compatible */
+ #define snd_mixer_oss_ioctl_compat	snd_mixer_oss_ioctl
+ #else
+ #define snd_mixer_oss_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_mixer_oss_ioctl_old(struct inode *inode, struct file * file,
++				   unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_mixer_oss_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /*
+  *  REGISTRATION PART
+  */
+ 
+ static const struct file_operations snd_mixer_oss_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.open =		snd_mixer_oss_open,
+ 	.release =	snd_mixer_oss_release,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_mixer_oss_ioctl,
+ 	.compat_ioctl =	snd_mixer_oss_ioctl_compat,
++#else
++	.ioctl =	snd_mixer_oss_ioctl_old,
++#endif	
+ };
+ 
+ /*
diff --git a/alsa/acore/oss/mulaw.c b/alsa/acore/oss/mulaw.c
new file mode 100644
index 0000000..1a929f1
--- /dev/null
+++ b/alsa/acore/oss/mulaw.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/mulaw.c"
diff --git a/alsa/acore/oss/pcm_oss.patch b/alsa/acore/oss/pcm_oss.patch
new file mode 100644
index 0000000..ea2b5d2
--- /dev/null
+++ b/alsa/acore/oss/pcm_oss.patch
@@ -0,0 +1,111 @@
+--- ../../../alsa-kmirror/core/oss/pcm_oss.c	2009-04-08 12:30:58.000000000 +0200
++++ pcm_oss.c	2009-04-08 16:08:18.000000000 +0200
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Digital Audio (PCM) abstract layer / OSS compatible
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -27,6 +28,7 @@
+ #endif
+ 
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+ #include <linux/vmalloc.h>
+@@ -1903,9 +1905,13 @@ static int snd_pcm_oss_set_fragment(stru
+ 
+ static int snd_pcm_oss_nonblock(struct file * file)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ 	spin_lock(&file->f_lock);
++#endif
+ 	file->f_flags |= O_NONBLOCK;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ 	spin_unlock(&file->f_lock);
++#endif
+ 	return 0;
+ }
+ 
+@@ -2617,13 +2623,26 @@ static long snd_pcm_oss_ioctl(struct fil
+ 	return -EINVAL;
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ /* all compatible */
+ #define snd_pcm_oss_ioctl_compat	snd_pcm_oss_ioctl
+ #else
+ #define snd_pcm_oss_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_pcm_oss_ioctl_old(struct inode *inode, struct file * file,
++				 unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_pcm_oss_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
+ {
+ 	struct snd_pcm_oss_file *pcm_oss_file;
+@@ -2656,8 +2675,14 @@ static ssize_t snd_pcm_oss_write(struct
+ 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
+ 	if (substream == NULL)
+ 		return -ENXIO;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
++	up(&file->f_dentry->d_inode->i_sem);
++#endif
+ 	substream->f_flags = file->f_flags & O_NONBLOCK;
+ 	result = snd_pcm_oss_write1(substream, buf, count);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
++	down(&file->f_dentry->d_inode->i_sem);
++#endif
+ #ifdef OSS_DEBUG
+ 	printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
+ 	       (long)count, (long)result);
+@@ -2774,7 +2799,11 @@ static int snd_pcm_oss_mmap(struct file
+ 		return -EIO;
+ #endif
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
+ 	if (area->vm_pgoff != 0)
++#else
++	if (area->vm_offset != 0)
++#endif
+ 		return -EINVAL;
+ 
+ 	err = snd_pcm_mmap_data(substream, file, area);
+@@ -2954,14 +2983,20 @@ static void snd_pcm_oss_proc_done(struct
+ 
+ static const struct file_operations snd_pcm_oss_f_reg =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		snd_pcm_oss_read,
+ 	.write =	snd_pcm_oss_write,
+ 	.open =		snd_pcm_oss_open,
+ 	.release =	snd_pcm_oss_release,
+ 	.poll =		snd_pcm_oss_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_pcm_oss_ioctl,
+ 	.compat_ioctl =	snd_pcm_oss_ioctl_compat,
++#else
++	.ioctl =	snd_pcm_oss_ioctl_old,
++#endif
+ 	.mmap =		snd_pcm_oss_mmap,
+ };
+ 
+@@ -3075,3 +3110,5 @@ static void __exit alsa_pcm_oss_exit(voi
+ 
+ module_init(alsa_pcm_oss_init)
+ module_exit(alsa_pcm_oss_exit)
++
++EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/oss/pcm_plugin.c b/alsa/acore/oss/pcm_plugin.c
new file mode 100644
index 0000000..ef5f56f
--- /dev/null
+++ b/alsa/acore/oss/pcm_plugin.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/pcm_plugin.c"
diff --git a/alsa/acore/oss/rate.c b/alsa/acore/oss/rate.c
new file mode 100644
index 0000000..53a292a
--- /dev/null
+++ b/alsa/acore/oss/rate.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/rate.c"
diff --git a/alsa/acore/oss/route.c b/alsa/acore/oss/route.c
new file mode 100644
index 0000000..51b954d
--- /dev/null
+++ b/alsa/acore/oss/route.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/oss/route.c"
diff --git a/alsa/acore/pci_compat_22.c b/alsa/acore/pci_compat_22.c
new file mode 100644
index 0000000..d9a5eed
--- /dev/null
+++ b/alsa/acore/pci_compat_22.c
@@ -0,0 +1,445 @@
+/*
+ * PCI-compatible layer for 2.2 kernels
+ */
+
+#ifdef CONFIG_PCI
+
+static LIST_HEAD(pci_drivers);
+
+struct pci_driver_mapping {
+	struct pci_dev *dev;
+	struct pci_driver *drv;
+	unsigned long dma_mask;
+	void *driver_data;
+	u32 saved_config[16];
+};
+
+#define PCI_MAX_MAPPINGS 64
+static struct pci_driver_mapping drvmap [PCI_MAX_MAPPINGS] = { { NULL, } , };
+
+
+static struct pci_driver_mapping *get_pci_driver_mapping(struct pci_dev *dev)
+{
+	int i;
+	
+	for (i = 0; i < PCI_MAX_MAPPINGS; i++)
+		if (drvmap[i].dev == dev)
+			return &drvmap[i];
+	return NULL;
+}
+
+struct pci_driver *snd_pci_compat_get_pci_driver(struct pci_dev *dev)
+{
+	struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+	if (map)
+		return map->drv;
+	return NULL;
+}
+
+void * snd_pci_compat_get_driver_data (struct pci_dev *dev)
+{
+	struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+	if (map)
+		return map->driver_data;
+	return NULL;
+}
+
+
+void snd_pci_compat_set_driver_data (struct pci_dev *dev, void *driver_data)
+{
+	struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+	if (map)
+		map->driver_data = driver_data;
+}
+
+
+unsigned long snd_pci_compat_get_dma_mask (struct pci_dev *dev)
+{
+	if (dev) {
+		struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+		if (map)
+			return map->dma_mask;
+		return 0;
+	} else
+		return 0xffffff; /* ISA - 16MB */
+}
+
+
+int snd_pci_compat_set_dma_mask (struct pci_dev *dev, unsigned long mask)
+{
+	if (dev) {
+		struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+		if (map)
+			map->dma_mask = mask;
+	}
+	return 0;
+}
+
+
+const struct pci_device_id * snd_pci_compat_match_device(const struct pci_device_id *ids, struct pci_dev *dev)
+{
+	u16 subsystem_vendor, subsystem_device;
+
+	pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+	pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &subsystem_device);
+
+	while (ids->vendor || ids->subvendor || ids->class_mask) {
+		if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) &&
+		    (ids->device == PCI_ANY_ID || ids->device == dev->device) &&
+		    (ids->subvendor == PCI_ANY_ID || ids->subvendor == subsystem_vendor) &&
+		    (ids->subdevice == PCI_ANY_ID || ids->subdevice == subsystem_device) &&
+		    !((ids->class ^ dev->class) & ids->class_mask))
+			return ids;
+		ids++;
+	}
+	return NULL;
+}
+
+static int snd_pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
+{
+        int i;
+	const struct pci_device_id *id;
+
+	if (drv->id_table) {
+		id = snd_pci_compat_match_device(drv->id_table, dev);
+		if (!id)
+			return 0;
+	} else {
+		id = NULL;
+	}
+        for (i = 0; i < PCI_MAX_MAPPINGS; i++) {
+	        if (drvmap[i].dev == NULL) {
+	                drvmap[i].dev = dev;
+	                drvmap[i].drv = drv;
+			drvmap[i].dma_mask = ~0UL;
+	                break;
+	        }
+        }
+        if (i >= PCI_MAX_MAPPINGS)
+		return 0;
+	if (drv->probe(dev, id) < 0) {
+                 drvmap[i].dev = NULL;
+	         return 0;
+	}
+	return 1;
+}
+
+int snd_pci_compat_register_driver(struct pci_driver *drv)
+{
+	struct pci_dev *dev;
+	int count = 0;
+
+	list_add_tail(&drv->node, &pci_drivers);
+	pci_for_each_dev(dev) {
+		struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+		if (! map)
+			count += snd_pci_announce_device(drv, dev);
+	}
+	if (! count)
+		return -ENODEV;
+	return 0;
+}
+
+void snd_pci_compat_unregister_driver(struct pci_driver *drv)
+{
+	struct pci_dev *dev;
+
+	list_del(&drv->node);
+	pci_for_each_dev(dev) {
+		struct pci_driver_mapping *map = get_pci_driver_mapping(dev);
+		if (map && map->drv == drv) {
+			if (drv->remove)
+				drv->remove(dev);
+			map->dev = NULL;
+			map->drv = NULL;
+	        }
+	}
+}
+
+unsigned long snd_pci_compat_get_size (struct pci_dev *dev, int n_base)
+{
+	u32 l, sz;
+	int reg = PCI_BASE_ADDRESS_0 + (n_base << 2);
+
+	pci_read_config_dword (dev, reg, &l);
+	if (l == 0xffffffff)
+		return 0;
+
+	pci_write_config_dword (dev, reg, ~0);
+	pci_read_config_dword (dev, reg, &sz);
+	pci_write_config_dword (dev, reg, l);
+
+	if (!sz || sz == 0xffffffff)
+		return 0;
+	if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
+		sz = ~(sz & PCI_BASE_ADDRESS_MEM_MASK);
+	} else {
+		sz = ~(sz & PCI_BASE_ADDRESS_IO_MASK) & 0xffff;
+	}
+	
+	return sz;
+}
+
+/* hack, hack, hack - why 2.2 kernels are so broken? */
+static struct broken_addr {
+	u16 vendor;
+	u16 device;
+	u32 flags;
+} broken_addr[] = {
+	{ 0x8086, 0x2415, IORESOURCE_IO },		/* 82801AA */
+	{ 0x8086, 0x2425, IORESOURCE_IO },		/* 82901AB */
+	{ 0x8086, 0x2445, IORESOURCE_IO },		/* 82801BA */
+	{ 0x8086, 0x2485, IORESOURCE_IO },		/* ICH3 */
+	{ 0x8086, 0x7195, IORESOURCE_IO },		/* 440MX */
+	{ 0, 0, 0 }
+};
+
+int snd_pci_compat_get_flags (struct pci_dev *dev, int n_base)
+{
+	unsigned long foo;
+	int flags = 0;
+
+	for (foo = 0; broken_addr[foo].vendor; foo++)
+		if (dev->vendor == broken_addr[foo].vendor &&
+		    dev->device == broken_addr[foo].device)
+		    	return broken_addr[foo].flags;
+	
+	foo = dev->base_address[n_base] & PCI_BASE_ADDRESS_SPACE;
+	if (foo & 1)
+		flags |= IORESOURCE_IO;
+	else
+		flags |= IORESOURCE_MEM;
+
+	return flags;
+}
+
+/*
+ *  Set power management state of a device.  For transitions from state D3
+ *  it isn't as straightforward as one could assume since many devices forget
+ *  their configuration space during wakeup.  Returns old power state.
+ */
+int snd_pci_compat_set_power_state(struct pci_dev *dev, int new_state)
+{
+	u32 base[5], romaddr;
+	u16 pci_command, pwr_command;
+	u8  pci_latency, pci_cacheline;
+	int i, old_state;
+	int pm = snd_pci_compat_find_capability(dev, PCI_CAP_ID_PM);
+
+	if (!pm)
+		return 0;
+	pci_read_config_word(dev, pm + PCI_PM_CTRL, &pwr_command);
+	old_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+	if (old_state == new_state)
+		return old_state;
+	if (old_state == 3) {
+		pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+		pci_write_config_word(dev, PCI_COMMAND, pci_command & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+		for (i = 0; i < 5; i++)
+			pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, &base[i]);
+		pci_read_config_dword(dev, PCI_ROM_ADDRESS, &romaddr);
+		pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+		pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+		pci_write_config_word(dev, pm + PCI_PM_CTRL, new_state);
+		for (i = 0; i < 5; i++)
+			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, base[i]);
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, romaddr);
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cacheline);
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, pci_latency);
+		pci_write_config_word(dev, PCI_COMMAND, pci_command);
+	} else
+		pci_write_config_word(dev, pm + PCI_PM_CTRL, (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | new_state);
+	return old_state;
+}
+
+/*
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O and memory. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int snd_pci_compat_enable_device(struct pci_dev *dev)
+{
+	u16 pci_command;
+
+	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+	pci_write_config_word(dev, PCI_COMMAND, pci_command | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+	snd_pci_compat_set_power_state(dev, 0);
+	return 0;
+}
+
+void snd_pci_compat_disable_device(struct pci_dev *dev)
+{
+	u16 pci_command;
+
+	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+	if (pci_command & PCI_COMMAND_MASTER) {
+		pci_command &= ~PCI_COMMAND_MASTER;
+		pci_write_config_word(dev, PCI_COMMAND, pci_command);
+	}
+}
+
+int snd_pci_compat_find_capability(struct pci_dev *dev, int cap)
+{
+	u16 status;
+	u8 pos, id;
+	int ttl = 48;
+
+	pci_read_config_word(dev, PCI_STATUS, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+	pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
+	while (ttl-- && pos >= 0x40) {
+		pos &= ~3;
+		pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
+	}
+	return 0;
+}
+
+int snd_pci_compat_dma_supported(struct pci_dev *dev, dma_addr_t mask)
+{
+	return 1;
+}
+
+/*
+ */
+int snd_pci_compat_request_region(struct pci_dev *pdev, int bar, char *res_name)
+{
+	int flags;
+
+	if (pci_resource_len(pdev, bar) == 0)
+		return 0;
+	flags = snd_pci_compat_get_flags(pdev, bar);
+	if (flags & IORESOURCE_IO) {
+		if (check_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)))
+			goto err_out;
+		snd_memory_wrapper_request_region(pci_resource_start(pdev, bar),
+						  pci_resource_len(pdev, bar), res_name);
+	}
+	return 0;
+
+err_out:
+	printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
+		flags & IORESOURCE_IO ? "I/O" : "mem",
+		bar + 1, /* PCI BAR # */
+		pci_resource_len(pdev, bar), pci_resource_start(pdev, bar),
+		res_name);
+	return -EBUSY;
+}
+
+void snd_pci_compat_release_region(struct pci_dev *pdev, int bar)
+{
+	int flags;
+
+	if (pci_resource_len(pdev, bar) == 0)
+		return;
+	flags = snd_pci_compat_get_flags(pdev, bar);
+	if (flags & IORESOURCE_IO) {
+		release_region(pci_resource_start(pdev, bar),
+			       pci_resource_len(pdev, bar));
+	}
+}
+
+int snd_pci_compat_request_regions(struct pci_dev *pdev, char *res_name)
+{
+	int i;
+	
+	for (i = 0; i < 6; i++)
+		if (pci_request_region(pdev, i, res_name))
+			goto err;
+	return 0;
+ err:
+	while (--i >= 0)
+		snd_pci_compat_release_region(pdev, i);
+	return -EBUSY;
+}
+
+void snd_pci_compat_release_regions(struct pci_dev *pdev)
+{
+	int i;
+	for (i = 0; i < 6; i++)
+		snd_pci_compat_release_region(pdev, i);
+}
+
+int snd_pci_compat_save_state(struct pci_dev *pdev)
+{
+	struct pci_driver_mapping *map = get_pci_driver_mapping(pdev);
+
+	if (map) {
+		int i;
+		u32 *buffer = map->saved_config;
+		for (i = 0; i < 16; i++, buffer++)
+			pci_read_config_dword(pdev, i * 4, buffer);
+	}
+	return 0;
+}
+
+int snd_pci_compat_restore_state(struct pci_dev *pdev)
+{
+	struct pci_driver_mapping *map = get_pci_driver_mapping(pdev);
+
+	if (map) {
+		int i;
+		u32 *buffer = map->saved_config;
+		for (i = 0; i < 16; i++, buffer++)
+			pci_write_config_dword(pdev, i * 4, *buffer);
+	}
+	return 0;
+}
+
+#endif /* CONFIG_PCI */
+
+/* these functions are outside of CONFIG_PCI */
+
+static void *snd_pci_compat_alloc_consistent1(unsigned long dma_mask,
+					      unsigned long size,
+					      int hop)
+{
+	void *res;
+
+	if (++hop > 10)
+		return NULL;
+	res = snd_malloc_pages(size, GFP_KERNEL | (dma_mask <= 0x00ffffff ? GFP_DMA : 0));
+	if (res == NULL)
+		return NULL;
+	if ((virt_to_bus(res) & ~dma_mask) ||
+	    ((virt_to_bus(res) + size - 1) & ~dma_mask)) {
+		void *res1 = snd_pci_compat_alloc_consistent1(dma_mask, size, hop);
+		snd_free_pages(res, size);
+		return res1;
+	}
+	return res;
+}
+
+void *snd_pci_compat_alloc_consistent(struct pci_dev *dev,
+				      long size,
+				      dma_addr_t *dmaaddr)
+{
+	unsigned long dma_mask;
+	void *res;
+
+#ifdef CONFIG_PCI
+	dma_mask = snd_pci_compat_get_dma_mask(dev);
+#else
+	dma_mask = 0xffffff; /* ISA - 16MB */
+#endif
+	res = snd_pci_compat_alloc_consistent1(dma_mask, size, 0);
+	if (res != NULL)
+		*dmaaddr = (dma_addr_t)virt_to_bus(res);
+	return res;
+}
+
+void snd_pci_compat_free_consistent(struct pci_dev *dev, long size, void *ptr, dma_addr_t dmaaddr)
+{
+	if (bus_to_virt(dmaaddr) != ptr) {
+		printk(KERN_ERR "invalid address given %p != %lx to snd_pci_compat_free_consistent\n", ptr, (unsigned long)dmaaddr);
+		return;
+	}
+	snd_free_pages(ptr, size);
+}
+
diff --git a/alsa/acore/pcm.patch b/alsa/acore/pcm.patch
new file mode 100644
index 0000000..84058ee
--- /dev/null
+++ b/alsa/acore/pcm.patch
@@ -0,0 +1,53 @@
+--- ../alsa-kernel/core/pcm.c	2009-11-10 18:21:52.000000000 +0100
++++ pcm.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Digital Audio (PCM) abstract layer
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -928,8 +929,12 @@
+ 	substream->pstr->substream_opened--;
+ }
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ static ssize_t show_pcm_class(struct device *dev,
+ 			      struct device_attribute *attr, char *buf)
++#else
++static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
++#endif
+ {
+ 	struct snd_pcm *pcm;
+ 	const char *str;
+@@ -940,7 +945,11 @@
+ 		[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
+ 	};
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	if (! (pcm = dev_get_drvdata(dev)) ||
++#else
++	if (! (pcm = class_get_devdata(class_device)) ||
++#endif
+ 	    pcm->dev_class > SNDRV_PCM_CLASS_LAST)
+ 		str = "none";
+ 	else
+@@ -948,7 +957,11 @@
+         return snprintf(buf, PAGE_SIZE, "%s\n", str);
+ }
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ static struct device_attribute pcm_attrs =
++#else
++static struct class_device_attribute pcm_attrs =
++#endif
+ 	__ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
+ 
+ static int snd_pcm_dev_register(struct snd_device *device)
+@@ -1000,7 +1013,7 @@
+ 			return err;
+ 		}
+ 		snd_add_device_sysfs_file(devtype, pcm->card, pcm->device,
+-					  &pcm_attrs);
++					  (struct device_attribute *)&pcm_attrs);
+ 		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
+ 			snd_pcm_timer_init(substream);
+ 	}
diff --git a/alsa/acore/pcm_compat.c b/alsa/acore/pcm_compat.c
new file mode 100644
index 0000000..a8362aa
--- /dev/null
+++ b/alsa/acore/pcm_compat.c
@@ -0,0 +1 @@
+#include "../alsa-kernel/core/pcm_compat.c"
diff --git a/alsa/acore/pcm_lib.c b/alsa/acore/pcm_lib.c
new file mode 100644
index 0000000..d901943
--- /dev/null
+++ b/alsa/acore/pcm_lib.c
@@ -0,0 +1,9 @@
+#define __NO_VERSION__
+#include "adriver.h"
+
+#include "../alsa-kernel/core/pcm_lib.c"
+
+#ifdef CONFIG_SND_BIT32_EMUL_MODULE
+int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+EXPORT_SYMBOL(snd_pcm_hw_params);
+#endif
diff --git a/alsa/acore/pcm_memory.c b/alsa/acore/pcm_memory.c
new file mode 100644
index 0000000..2fb902b
--- /dev/null
+++ b/alsa/acore/pcm_memory.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/pcm_memory.c"
diff --git a/alsa/acore/pcm_misc.c b/alsa/acore/pcm_misc.c
new file mode 100644
index 0000000..bf277ac
--- /dev/null
+++ b/alsa/acore/pcm_misc.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/pcm_misc.c"
diff --git a/alsa/acore/pcm_native.patch b/alsa/acore/pcm_native.patch
new file mode 100644
index 0000000..99191ee
--- /dev/null
+++ b/alsa/acore/pcm_native.patch
@@ -0,0 +1,551 @@
+--- ../alsa-kernel/core/pcm_native.c	2009-11-27 11:25:09.000000000 +0100
++++ pcm_native.c	2009-11-27 11:46:27.000000000 +0100
+@@ -1,3 +1,5 @@
++#define __NO_VERSION__
++#include "adriver.h"
+ /*
+  *  Digital Audio (PCM) abstract layer
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -20,9 +22,9 @@
+  */
+ 
+ #include <linux/mm.h>
++#include <linux/smp_lock.h>
+ #include <linux/file.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/time.h>
+ #include <linux/pm_qos_params.h>
+ #include <linux/uio.h>
+@@ -366,7 +368,10 @@ static int period_to_usecs(struct snd_pc
+ 	return usecs;
+ }
+ 
+-static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
++#ifndef CONFIG_SND_BIT32_EMUL_MODULE
++static
++#endif
++int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ 			     struct snd_pcm_hw_params *params)
+ {
+ 	struct snd_pcm_runtime *runtime;
+@@ -1539,7 +1544,11 @@ static struct file *snd_pcm_file_fd(int
+ 	file = fget(fd);
+ 	if (!file)
+ 		return NULL;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	inode = file->f_path.dentry->d_inode;
++#else
++	inode = file->f_dentry->d_inode;
++#endif
+ 	if (!S_ISCHR(inode->i_mode) ||
+ 	    imajor(inode) != snd_major) {
+ 		fput(file);
+@@ -2792,25 +2801,50 @@ static ssize_t snd_pcm_write(struct file
+ 	struct snd_pcm_runtime *runtime;
+ 	snd_pcm_sframes_t result;
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
++	up(&file->f_dentry->d_inode->i_sem);
++#endif
+ 	pcm_file = file->private_data;
+ 	substream = pcm_file->substream;
+-	if (PCM_RUNTIME_CHECK(substream))
+-		return -ENXIO;
++	if (PCM_RUNTIME_CHECK(substream)) {
++		result = -ENXIO;
++		goto end;
++	}
+ 	runtime = substream->runtime;
+-	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+-		return -EBADFD;
+-	if (!frame_aligned(runtime, count))
+-		return -EINVAL;
++	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
++		result = -EBADFD;
++		goto end;
++	}
++	if (!frame_aligned(runtime, count)) {
++		result = -EINVAL;
++		goto end;
++	}
+ 	count = bytes_to_frames(runtime, count);
+ 	result = snd_pcm_lib_write(substream, buf, count);
+ 	if (result > 0)
+ 		result = frames_to_bytes(runtime, result);
++ end:
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
++	down(&file->f_dentry->d_inode->i_sem);
++#endif
+ 	return result;
+ }
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 44)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++#define SND_PCM_USE_AIO
++#else
++#define SND_PCM_USE_READV
++#endif
++
++#ifdef SND_PCM_USE_AIO
+ static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ 			     unsigned long nr_segs, loff_t pos)
+-
++#else
++static ssize_t snd_pcm_readv(struct file *file, const struct iovec *iov,
++			     unsigned long nr_segs, loff_t * offset)
++#endif
+ {
+ 	struct snd_pcm_file *pcm_file;
+ 	struct snd_pcm_substream *substream;
+@@ -2820,7 +2854,11 @@ static ssize_t snd_pcm_aio_read(struct k
+ 	void __user **bufs;
+ 	snd_pcm_uframes_t frames;
+ 
++#ifdef SND_PCM_USE_AIO
+ 	pcm_file = iocb->ki_filp->private_data;
++#else
++	pcm_file = file->private_data;
++#endif
+ 	substream = pcm_file->substream;
+ 	if (PCM_RUNTIME_CHECK(substream))
+ 		return -ENXIO;
+@@ -2844,8 +2882,13 @@ static ssize_t snd_pcm_aio_read(struct k
+ 	return result;
+ }
+ 
++#ifdef SND_PCM_USE_AIO
+ static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ 			      unsigned long nr_segs, loff_t pos)
++#else
++static ssize_t snd_pcm_writev(struct file *file, const struct iovec *iov,
++			      unsigned long nr_segs, loff_t * offset)
++#endif
+ {
+ 	struct snd_pcm_file *pcm_file;
+ 	struct snd_pcm_substream *substream;
+@@ -2855,7 +2898,11 @@ static ssize_t snd_pcm_aio_write(struct
+ 	void __user **bufs;
+ 	snd_pcm_uframes_t frames;
+ 
++#ifdef SND_PCM_USE_AIO
+ 	pcm_file = iocb->ki_filp->private_data;
++#else
++	pcm_file = file->private_data;
++#endif
+ 	substream = pcm_file->substream;
+ 	if (PCM_RUNTIME_CHECK(substream))
+ 		return -ENXIO;
+@@ -2877,6 +2924,7 @@ static ssize_t snd_pcm_aio_write(struct
+ 	kfree(bufs);
+ 	return result;
+ }
++#endif /* >= 2.3.44 */
+ 
+ static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
+ {
+@@ -2964,6 +3012,22 @@ static unsigned int snd_pcm_capture_poll
+  * mmap support
+  */
+ 
++#ifndef VM_RESERVED
++#define USE_MMAP_SWAPOUT
++#define VM_RESERVED	0	/* dummy */
++#endif
++
++#ifdef USE_MMAP_SWAPOUT
++#ifndef LINUX_2_2
++static int snd_pcm_mmap_swapout(struct page * page, struct file * file)
++#else
++static int snd_pcm_mmap_swapout(struct vm_area_struct * area, struct page * page)
++#endif
++{
++	return 0;
++}
++#endif
++
+ /*
+  * Only on coherent architectures, we can mmap the status and the control records
+  * for effcient data transfer.  On others, we have to use HWSYNC ioctl...
+@@ -2972,6 +3036,7 @@ static unsigned int snd_pcm_capture_poll
+ /*
+  * mmap status record
+  */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
+ 						struct vm_fault *vmf)
+ {
+@@ -2985,10 +3050,49 @@ static int snd_pcm_mmap_status_fault(str
+ 	get_page(vmf->page);
+ 	return 0;
+ }
++#else /* 2.6.24 */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
++						unsigned long address, int *type)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
++						unsigned long address, int no_share)
++#else
++static unsigned long snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
++						unsigned long address, int no_share)
++#endif
++{
++	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data;
++	struct snd_pcm_runtime *runtime;
++	struct page * page;
++	
++	if (substream == NULL)
++		return NOPAGE_SIGBUS;
++	runtime = substream->runtime;
++	page = virt_to_page(runtime->status);
++#ifndef CONFIG_SND_REMOVE_PAGE_RESERVE
++	if (!PageReserved(page))
++#endif
++	get_page(page);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++	if (type)
++		*type = VM_FAULT_MINOR;
++#endif
++#ifndef LINUX_2_2
++	return page;
++#else
++	return page_address(page);
++#endif
++}
++#endif /* >= 2.6.24 */
+ 
+ static const struct vm_operations_struct snd_pcm_vm_ops_status =
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ 	.fault =	snd_pcm_mmap_status_fault,
++#else
++	.nopage =	snd_pcm_mmap_status_nopage,
++#endif
+ };
+ 
+ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
+@@ -3003,7 +3107,11 @@ static int snd_pcm_mmap_status(struct sn
+ 	if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
+ 		return -EINVAL;
+ 	area->vm_ops = &snd_pcm_vm_ops_status;
++#ifndef LINUX_2_2
+ 	area->vm_private_data = substream;
++#else
++	area->vm_private_data = (long)substream;
++#endif
+ 	area->vm_flags |= VM_RESERVED;
+ 	return 0;
+ }
+@@ -3011,6 +3119,7 @@ static int snd_pcm_mmap_status(struct sn
+ /*
+  * mmap control record
+  */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
+ 						struct vm_fault *vmf)
+ {
+@@ -3024,10 +3133,50 @@ static int snd_pcm_mmap_control_fault(st
+ 	get_page(vmf->page);
+ 	return 0;
+ }
++#else /* 2.6.24 */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
++					unsigned long address, int *type)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
++					unsigned long address, int no_share)
++#else
++static unsigned long snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
++					unsigned long address, int no_share)
++#endif
++{
++	struct snd_pcm_substream *substream =
++		(struct snd_pcm_substream *)area->vm_private_data;
++	struct snd_pcm_runtime *runtime;
++	struct page * page;
++	
++	if (substream == NULL)
++		return NOPAGE_SIGBUS;
++	runtime = substream->runtime;
++	page = virt_to_page(runtime->control);
++#ifndef CONFIG_SND_REMOVE_PAGE_RESERVE
++	if (!PageReserved(page))
++#endif
++	get_page(page);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++	if (type)
++		*type = VM_FAULT_MINOR;
++#endif
++#ifndef LINUX_2_2
++	return page;
++#else
++	return page_address(page);
++#endif
++}
++#endif /* >= 2.6.24 */
+ 
+ static const struct vm_operations_struct snd_pcm_vm_ops_control =
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ 	.fault =	snd_pcm_mmap_control_fault,
++#else
++	.nopage =	snd_pcm_mmap_control_nopage,
++#endif
+ };
+ 
+ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
+@@ -3042,7 +3191,11 @@ static int snd_pcm_mmap_control(struct s
+ 	if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
+ 		return -EINVAL;
+ 	area->vm_ops = &snd_pcm_vm_ops_control;
++#ifndef LINUX_2_2
+ 	area->vm_private_data = substream;
++#else
++	area->vm_private_data = (long)substream;
++#endif
+ 	area->vm_flags |= VM_RESERVED;
+ 	return 0;
+ }
+@@ -3083,9 +3236,16 @@ snd_pcm_default_page_ops(struct snd_pcm_
+ 	return virt_to_page(vaddr);
+ }
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
++#define get_vm_area_offset(area)	((area)->vm_pgoff << PAGE_SHIFT)
++#else
++#define get_vm_area_offset(area)	(area)->vm_offset
++#endif
++
+ /*
+  * fault callback for mmapping a RAM page
+  */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
+ 						struct vm_fault *vmf)
+ {
+@@ -3112,6 +3272,59 @@ static int snd_pcm_mmap_data_fault(struc
+ 	vmf->page = page;
+ 	return 0;
+ }
++#else /* 2.6.24 */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
++					     unsigned long address, int *type)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
++					unsigned long address, int no_share)
++#else
++static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
++					unsigned long address, int no_share)
++#endif
++{
++	struct snd_pcm_substream *substream =
++		(struct snd_pcm_substream *)area->vm_private_data;
++	struct snd_pcm_runtime *runtime;
++	unsigned long offset;
++	struct page * page;
++	void *vaddr;
++	size_t dma_bytes;
++	
++	if (substream == NULL)
++		return NOPAGE_SIGBUS;
++	runtime = substream->runtime;
++	offset = get_vm_area_offset(area);
++	offset += address - area->vm_start;
++	if (snd_BUG_ON(offset % PAGE_SIZE))
++		return NOPAGE_SIGBUS;
++	dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
++	if (offset > dma_bytes - PAGE_SIZE)
++		return NOPAGE_SIGBUS;
++	if (substream->ops->page) {
++		page = substream->ops->page(substream, offset);
++		if (! page)
++			return NOPAGE_OOM; /* XXX: is this really due to OOM? */
++	} else {
++		vaddr = runtime->dma_area + offset;
++		page = virt_to_page(vaddr);
++	}
++#ifndef CONFIG_SND_REMOVE_PAGE_RESERVE
++	if (!PageReserved(page))
++#endif
++	get_page(page);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++	if (type)
++		*type = VM_FAULT_MINOR;
++#endif
++#ifndef LINUX_2_2
++	return page;
++#else
++	return page_address(page);
++#endif
++}
++#endif /* >= 2.6.24 */
+ 
+ static const struct vm_operations_struct snd_pcm_vm_ops_data = {
+ 	.open =		snd_pcm_mmap_data_open,
+@@ -3121,7 +3334,14 @@ static const struct vm_operations_struct
+ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
+ 	.open =		snd_pcm_mmap_data_open,
+ 	.close =	snd_pcm_mmap_data_close,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ 	.fault =	snd_pcm_mmap_data_fault,
++#else
++	.nopage =	snd_pcm_mmap_data_nopage,
++#ifdef USE_MMAP_SWAPOUT
++	.swapout =	snd_pcm_mmap_swapout,
++#endif
++#endif
+ };
+ 
+ #ifndef ARCH_HAS_DMA_MMAP_COHERENT
+@@ -3167,11 +3387,26 @@ int snd_pcm_lib_mmap_iomem(struct snd_pc
+ #endif
+ 	area->vm_flags |= VM_IO;
+ 	size = area->vm_end - area->vm_start;
+-	offset = area->vm_pgoff << PAGE_SHIFT;
++  	offset = get_vm_area_offset(area);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
++#define io_remap_page_range remap_page_range
++#endif
++#ifdef CONFIG_HAVE_IO_REMAP_PFN_RANGE
+ 	if (io_remap_pfn_range(area, area->vm_start,
+ 				(substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
+ 				size, area->vm_page_prot))
+ 		return -EAGAIN;
++#elif defined(CONFIG_OLD_IO_REMAP_PAGE_RANGE)
++	if (io_remap_page_range(area->vm_start,
++				substream->runtime->dma_addr + offset,
++				size, area->vm_page_prot))
++		return -EAGAIN;
++#else
++	if (io_remap_page_range(area, area->vm_start,
++				substream->runtime->dma_addr + offset,
++				size, area->vm_page_prot))
++		return -EAGAIN;
++#endif
+ 	return 0;
+ }
+ 
+@@ -3206,7 +3441,7 @@ int snd_pcm_mmap_data(struct snd_pcm_sub
+ 	    runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ 		return -EINVAL;
+ 	size = area->vm_end - area->vm_start;
+-	offset = area->vm_pgoff << PAGE_SHIFT;
++	offset = get_vm_area_offset(area);
+ 	dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
+ 	if ((size_t)size > dma_bytes)
+ 		return -EINVAL;
+@@ -3214,7 +3449,11 @@ int snd_pcm_mmap_data(struct snd_pcm_sub
+ 		return -EINVAL;
+ 
+ 	area->vm_ops = &snd_pcm_vm_ops_data;
++#ifndef LINUX_2_2
+ 	area->vm_private_data = substream;
++#else
++	area->vm_private_data = (long)substream;
++#endif
+ 	if (substream->ops->mmap)
+ 		err = substream->ops->mmap(substream, area);
+ 	else
+@@ -3237,7 +3476,7 @@ static int snd_pcm_mmap(struct file *fil
+ 	if (PCM_RUNTIME_CHECK(substream))
+ 		return -ENXIO;
+ 
+-	offset = area->vm_pgoff << PAGE_SHIFT;
++	offset = get_vm_area_offset(area);
+ 	switch (offset) {
+ 	case SNDRV_PCM_MMAP_OFFSET_STATUS:
+ 		if (pcm_file->no_compat_mmap)
+@@ -3275,12 +3514,34 @@ out:
+ /*
+  * ioctl32 compat
+  */
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "pcm_compat.c"
+ #else
+ #define snd_pcm_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_pcm_playback_ioctl_old(struct inode *inode, struct file * file,
++				      unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_pcm_playback_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++static int snd_pcm_capture_ioctl_old(struct inode *inode, struct file * file,
++				      unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_pcm_capture_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /*
+  *  To be removed helpers to keep binary compatibility
+  */
+@@ -3405,29 +3666,53 @@ unsigned long dummy_get_unmapped_area(st
+ 
+ const struct file_operations snd_pcm_f_ops[2] = {
+ 	{
++#ifndef LINUX_2_2
+ 		.owner =		THIS_MODULE,
++#endif
+ 		.write =		snd_pcm_write,
++#ifdef SND_PCM_USE_AIO
+ 		.aio_write =		snd_pcm_aio_write,
++#elif defined(SND_PCM_USE_READV)
++		.writev =		snd_pcm_writev,
++#endif
+ 		.open =			snd_pcm_playback_open,
+ 		.release =		snd_pcm_release,
+ 		.poll =			snd_pcm_playback_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 		.unlocked_ioctl =	snd_pcm_playback_ioctl,
+ 		.compat_ioctl = 	snd_pcm_ioctl_compat,
++#else
++		.ioctl =		snd_pcm_playback_ioctl_old,
++#endif
+ 		.mmap =			snd_pcm_mmap,
+ 		.fasync =		snd_pcm_fasync,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ 		.get_unmapped_area =	dummy_get_unmapped_area,
++#endif
+ 	},
+ 	{
++#ifndef LINUX_2_2
+ 		.owner =		THIS_MODULE,
++#endif
+ 		.read =			snd_pcm_read,
++#ifdef SND_PCM_USE_AIO
+ 		.aio_read =		snd_pcm_aio_read,
++#elif defined(SND_PCM_USE_READV)
++		.readv =		snd_pcm_readv,
++#endif
+ 		.open =			snd_pcm_capture_open,
+ 		.release =		snd_pcm_release,
+ 		.poll =			snd_pcm_capture_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 		.unlocked_ioctl =	snd_pcm_capture_ioctl,
+ 		.compat_ioctl = 	snd_pcm_ioctl_compat,
++#else
++		.ioctl =		snd_pcm_capture_ioctl_old,
++#endif
+ 		.mmap =			snd_pcm_mmap,
+ 		.fasync =		snd_pcm_fasync,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ 		.get_unmapped_area =	dummy_get_unmapped_area,
++#endif
+ 	}
+ };
diff --git a/alsa/acore/pcm_timer.c b/alsa/acore/pcm_timer.c
new file mode 100644
index 0000000..e9d7ed6
--- /dev/null
+++ b/alsa/acore/pcm_timer.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/pcm_timer.c"
diff --git a/alsa/acore/rawmidi.patch b/alsa/acore/rawmidi.patch
new file mode 100644
index 0000000..ffe716c
--- /dev/null
+++ b/alsa/acore/rawmidi.patch
@@ -0,0 +1,73 @@
+--- ../alsa-kernel/core/rawmidi.c	2009-12-15 22:08:58.000000000 +0100
++++ rawmidi.c	2009-12-15 22:25:55.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Abstract layer for MIDI v1.0 stream
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -22,6 +23,7 @@
+ #include <sound/core.h>
+ #include <linux/major.h>
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+@@ -1257,6 +1259,9 @@
+ 			break;
+ 		count -= count1;
+ 	}
++#ifndef O_DSYNC
++#define O_DSYNC O_SYNC
++#endif
+ 	if (file->f_flags & O_DSYNC) {
+ 		spin_lock_irq(&runtime->lock);
+ 		while (runtime->avail != runtime->buffer_size) {
+@@ -1309,12 +1314,25 @@
+ 
+ /*
+  */
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "rawmidi_compat.c"
+ #else
+ #define snd_rawmidi_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_rawmidi_ioctl_old(struct inode *inode, struct file * file,
++				 unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_rawmidi_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /*
+ 
+  */
+@@ -1386,14 +1404,20 @@
+ 
+ static const struct file_operations snd_rawmidi_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		snd_rawmidi_read,
+ 	.write =	snd_rawmidi_write,
+ 	.open =		snd_rawmidi_open,
+ 	.release =	snd_rawmidi_release,
+ 	.poll =		snd_rawmidi_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_rawmidi_ioctl,
+ 	.compat_ioctl =	snd_rawmidi_ioctl_compat,
++#else
++	.ioctl =	snd_rawmidi_ioctl_old,
++#endif
+ };
+ 
+ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
diff --git a/alsa/acore/rawmidi_compat.c b/alsa/acore/rawmidi_compat.c
new file mode 100644
index 0000000..fa61a7e
--- /dev/null
+++ b/alsa/acore/rawmidi_compat.c
@@ -0,0 +1 @@
+#include "../alsa-kernel/core/rawmidi_compat.c"
diff --git a/alsa/acore/rtctimer.c b/alsa/acore/rtctimer.c
new file mode 100644
index 0000000..a96c3bd
--- /dev/null
+++ b/alsa/acore/rtctimer.c
@@ -0,0 +1,3 @@
+#include "adriver.h"
+#include "../alsa-kernel/core/rtctimer.c"
+EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/seq/CHANGES b/alsa/acore/seq/CHANGES
new file mode 100644
index 0000000..c03a779
--- /dev/null
+++ b/alsa/acore/seq/CHANGES
@@ -0,0 +1,100 @@
+19990604	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Event pool is assigned to each client instead of each queue.
+ - Input FIFO is allocated only for user client.
+ - Write select and blocking mode are implemented.
+ - Events with subscription and broadcast queue are dispatched
+   immediately.  Scheduled subscription events should contain
+   SND_SEQ_ADDRESS_SUBSCRIBERS in client number with the proper
+   queue number.
+
+19990609	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - EVENT_NOTE is decomposed to NOTEON and NOTEOFF events before
+   queued.  seq_midi.c and seq_midi_emul.c don't need to process
+   this event.
+
+19990615	Jaroslav Kysela <perex@perex.cz>
+ - Changed threshold_output name to output_room.
+
+19990616	Steve Ratcliffe <steve@parabola.demon.co.uk>
+ - Spinlock bugs are fixed.
+
+199906017	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Write pool is allocated on demand.  As default, no pool is assigned
+   to kernel clients.  They need to be allocated explicitly by using
+   SET_CLIENT_POOL ioctl.
+ - GET_CLIENT_POOL ioctl refers client field in the record.
+
+19990701	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Add snd-seq-device module.  This module supports for plug-in table
+   of sequencer devices.
+
+19990815	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Allow subscription from the "third client".  You only need to call
+   SUBSCRIBE_PORT ioctl with two connecting port addresses.  The
+   sender and receiver queues must be valid and identical, although
+   the client doesn't have to own or use specified queues.
+   If PORT_CAP_NO_EXPORT_ROUTE is set in one of subscribed ports,
+   the subscription is refused.
+ - The port which receives any events must have CAP_OUT flag.
+   Otherwise events are ignored.
+ - PORT_CAP_SUBSCRIPTION is divided to CAP_SUBS_IN and CAP_SUBS_OUT
+   for input and output, respectively.  PORT_CAP_SUBSCRIPTION defines
+   both input and output.
+ - Add GET_SUBSCRIPTION ioctl.  This checks the presence of the given
+   subscription (connection).
+ - Event dispatcher checks the number of events delivered.
+   snd_seq_dispatch_event() returns the number of delivered events
+   (in the case of broadcast or subscribers, this may be more than
+   one!).
+ - ADDRESS_BROADCAST can be set as port address.  Events are delivered
+   to all ports in the specified client.
+ - QUERY_NEXT_CLIENT and QUERY_NEXT_PORT ioctls  (hey, not tested!)
+   The query scheme should be more discussed..
+
+19990820	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Add group and group permissions to ports:
+   group (string) is added to client_info and port_info.
+   The standard group names are defined in asequencer.h.
+   A group name is used to help the query of clients/ports and
+   restrict access permissions to ports.
+   The access to a port from ports of the same group is checked by
+   looking at permissions in cap_group field in port_info_t.   
+ - Add num_ports in client_info_t.
+ - Bug fix of QUERY_NEXT_PORT ioctl.
+
+19990824	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Delivery path is checked.  It avoids hang up when a kernel client
+   dispatches events in an infinite loop.  Two arguments (atomic and
+   path_len) are added to event_input callback.  path_len argument
+   is added to snd_seq_kerne_client_dispatch() and _enqueue().
+ - QUERY_SUBSCRIPTION ioctl is added.
+
+19990826	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Add convert_time field in snd_seq_port_subscribe_t.
+   The timestamp is no longer converted unless this flag is true.
+ - Simplify subscription code; subscribe and use callbacks are invoked 
+   always for both sender and receiver ports (even to the client
+   itself that is calling ioctl).  However, NOTIFY events are not sent
+   to the calling client.
+   READ_TRACK and WRITE_TRACK were removed from query_subscription.
+ - Event from non-existing port is also accepted, but client group is
+   checked for security.
+ - Event priority is checked (seq_prioq.c).
+   The event is inserted at the head of the same time slice if
+   SND_SEQ_EVENT_PRIORITY_HIGH is specified.
+
+19990827	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Fix: auto-loading bugs in seq_device.c.
+ - Add a dummy sequencer client module: snd-seq-dummy.o.
+
+19991113	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Queue are allocated dynamically; see seq_queue.c for details.
+
+19991116	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - active_list in seq_queue.c is removed.
+
+19991127	Takashi Iwai <iwai@ww.uni-erlangen.de>
+ - Use reference counter for copying buffers allocated via
+   snd_seq_ext_malloc to avoid unnecessary malloc/copy/free.
+   snd_seq_ext_ref() simply increases the counter.
+
diff --git a/alsa/acore/seq/Makefile b/alsa/acore/seq/Makefile
new file mode 100644
index 0000000..04cc283
--- /dev/null
+++ b/alsa/acore/seq/Makefile
@@ -0,0 +1,21 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+clean-files := seq.c seq_clientmgr.c seq_memory.c
+
+export-objs  := seq_device.o seq_clientmgr.o seq_lock.o seq_memory.o \
+	seq_ports.o seq_midi_emul.o seq_midi_event.o seq_virmidi.o
+
+include $(SND_TOPDIR)/alsa-kernel/core/seq/Makefile
+
+EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/core/seq
+
+include $(SND_TOPDIR)/Rules.make
+
+seq.c: seq.patch $(SND_TOPDIR)/alsa-kernel/core/seq/seq.c
+seq_clientmgr.c: seq_clientmgr.patch $(SND_TOPDIR)/alsa-kernel/core/seq/seq_clientmgr.c
+seq_memory.c: seq_memory.patch $(SND_TOPDIR)/alsa-kernel/core/seq/seq_memory.c
diff --git a/alsa/acore/seq/old/instr/Makefile b/alsa/acore/seq/old/instr/Makefile
new file mode 100644
index 0000000..6089603
--- /dev/null
+++ b/alsa/acore/seq/old/instr/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for ALSA
+# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+#
+
+snd-ainstr-fm-objs := ainstr_fm.o
+snd-ainstr-simple-objs := ainstr_simple.o
+snd-ainstr-gf1-objs := ainstr_gf1.o
+snd-ainstr-iw-objs := ainstr_iw.o
+
+#
+# this function returns:
+#   "m" - CONFIG_SND_SEQUENCER is m
+#   <empty string> - CONFIG_SND_SEQUENCER is undefined
+#   otherwise parameter #1 value
+#
+sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
+
+# Toplevel Module Dependency
+obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o
+obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
diff --git a/alsa/acore/seq/old/instr/ainstr_fm.c b/alsa/acore/seq/old/instr/ainstr_fm.c
new file mode 100644
index 0000000..f80fab8
--- /dev/null
+++ b/alsa/acore/seq/old/instr/ainstr_fm.c
@@ -0,0 +1,155 @@
+/*
+ *  FM (OPL2/3) Instrument routines
+ *  Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include <sound/ainstr_fm.h>
+#include <sound/initval.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
+MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
+MODULE_LICENSE("GPL");
+
+static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr,
+			  char __user *instr_data, long len, int atomic, int cmd)
+{
+	struct fm_instrument *ip;
+	struct fm_xinstrument ix;
+	int idx;
+
+	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
+		return -EINVAL;
+	/* copy instrument data */
+	if (len < (long)sizeof(ix))
+		return -EINVAL;
+	if (copy_from_user(&ix, instr_data, sizeof(ix)))
+		return -EFAULT;
+	if (ix.stype != FM_STRU_INSTR)
+		return -EINVAL;
+	ip = (struct fm_instrument *)KINSTR_DATA(instr);
+	ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
+	ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
+	ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
+	ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
+	ip->type = ix.type;
+	for (idx = 0; idx < 4; idx++) {
+		ip->op[idx].am_vib = ix.op[idx].am_vib;
+		ip->op[idx].ksl_level = ix.op[idx].ksl_level;
+		ip->op[idx].attack_decay = ix.op[idx].attack_decay;
+		ip->op[idx].sustain_release = ix.op[idx].sustain_release;
+		ip->op[idx].wave_select = ix.op[idx].wave_select;
+	}
+	for (idx = 0; idx < 2; idx++) {
+		ip->feedback_connection[idx] = ix.feedback_connection[idx];
+	}
+	ip->echo_delay = ix.echo_delay;
+	ip->echo_atten = ix.echo_atten;
+	ip->chorus_spread = ix.chorus_spread;
+	ip->trnsps = ix.trnsps;
+	ip->fix_dur = ix.fix_dur;
+	ip->modes = ix.modes;
+	ip->fix_key = ix.fix_key;
+	return 0;
+}
+
+static int snd_seq_fm_get(void *private_data, struct snd_seq_kinstr *instr,
+			  char __user *instr_data, long len, int atomic,
+			  int cmd)
+{
+	struct fm_instrument *ip;
+	struct fm_xinstrument ix;
+	int idx;
+	
+	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
+		return -EINVAL;
+	if (len < (long)sizeof(ix))
+		return -ENOMEM;
+	memset(&ix, 0, sizeof(ix));
+	ip = (struct fm_instrument *)KINSTR_DATA(instr);
+	ix.stype = FM_STRU_INSTR;
+	ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
+	ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
+	ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
+	ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
+	ix.type = ip->type;
+	for (idx = 0; idx < 4; idx++) {
+		ix.op[idx].am_vib = ip->op[idx].am_vib;
+		ix.op[idx].ksl_level = ip->op[idx].ksl_level;
+		ix.op[idx].attack_decay = ip->op[idx].attack_decay;
+		ix.op[idx].sustain_release = ip->op[idx].sustain_release;
+		ix.op[idx].wave_select = ip->op[idx].wave_select;
+	}
+	for (idx = 0; idx < 2; idx++) {
+		ix.feedback_connection[idx] = ip->feedback_connection[idx];
+	}
+	if (copy_to_user(instr_data, &ix, sizeof(ix)))
+		return -EFAULT;
+	ix.echo_delay = ip->echo_delay;
+	ix.echo_atten = ip->echo_atten;
+	ix.chorus_spread = ip->chorus_spread;
+	ix.trnsps = ip->trnsps;
+	ix.fix_dur = ip->fix_dur;
+	ix.modes = ip->modes;
+	ix.fix_key = ip->fix_key;
+	return 0;
+}
+
+static int snd_seq_fm_get_size(void *private_data, struct snd_seq_kinstr *instr,
+			       long *size)
+{
+	*size = sizeof(struct fm_xinstrument);
+	return 0;
+}
+
+int snd_seq_fm_init(struct snd_seq_kinstr_ops *ops,
+		    struct snd_seq_kinstr_ops *next)
+{
+	memset(ops, 0, sizeof(*ops));
+	// ops->private_data = private_data;
+	ops->add_len = sizeof(struct fm_instrument);
+	ops->instr_type = SNDRV_SEQ_INSTR_ID_OPL2_3;
+	ops->put = snd_seq_fm_put;
+	ops->get = snd_seq_fm_get;
+	ops->get_size = snd_seq_fm_get_size;
+	// ops->remove = snd_seq_fm_remove;
+	// ops->notify = snd_seq_fm_notify;
+	ops->next = next;
+	return 0;
+}
+
+/*
+ *  Init part
+ */
+
+static int __init alsa_ainstr_fm_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_ainstr_fm_exit(void)
+{
+}
+
+module_init(alsa_ainstr_fm_init)
+module_exit(alsa_ainstr_fm_exit)
+
+EXPORT_SYMBOL(snd_seq_fm_init);
diff --git a/alsa/acore/seq/old/instr/ainstr_gf1.c b/alsa/acore/seq/old/instr/ainstr_gf1.c
new file mode 100644
index 0000000..4940026
--- /dev/null
+++ b/alsa/acore/seq/old/instr/ainstr_gf1.c
@@ -0,0 +1,359 @@
+/*
+ *   GF1 (GUS) Patch - Instrument routines
+ *   Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/ainstr_gf1.h>
+#include <sound/initval.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
+MODULE_LICENSE("GPL");
+
+static unsigned int snd_seq_gf1_size(unsigned int size, unsigned int format)
+{
+	unsigned int result = size;
+	
+	if (format & GF1_WAVE_16BIT)
+		result <<= 1;
+	if (format & GF1_WAVE_STEREO)
+		result <<= 1;
+	return format;
+}
+
+static int snd_seq_gf1_copy_wave_from_stream(struct snd_gf1_ops *ops,
+					     struct gf1_instrument *ip,
+					     char __user **data,
+					     long *len,
+					     int atomic)
+{
+	struct gf1_wave *wp, *prev;
+	struct gf1_xwave xp;
+	int err;
+	gfp_t gfp_mask;
+	unsigned int real_size;
+	
+	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
+	if (*len < (long)sizeof(xp))
+		return -EINVAL;
+	if (copy_from_user(&xp, *data, sizeof(xp)))
+		return -EFAULT;
+	*data += sizeof(xp);
+	*len -= sizeof(xp);
+	wp = kzalloc(sizeof(*wp), gfp_mask);
+	if (wp == NULL)
+		return -ENOMEM;
+	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
+	wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
+	wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
+	wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
+	wp->format = le32_to_cpu(xp.format);
+	wp->size = le32_to_cpu(xp.size);
+	wp->start = le32_to_cpu(xp.start);
+	wp->loop_start = le32_to_cpu(xp.loop_start);
+	wp->loop_end = le32_to_cpu(xp.loop_end);
+	wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
+	wp->flags = xp.flags;
+	wp->sample_rate = le32_to_cpu(xp.sample_rate);
+	wp->low_frequency = le32_to_cpu(xp.low_frequency);
+	wp->high_frequency = le32_to_cpu(xp.high_frequency);
+	wp->root_frequency = le32_to_cpu(xp.root_frequency);
+	wp->tune = le16_to_cpu(xp.tune);
+	wp->balance = xp.balance;
+	memcpy(wp->envelope_rate, xp.envelope_rate, 6);
+	memcpy(wp->envelope_offset, xp.envelope_offset, 6);
+	wp->tremolo_sweep = xp.tremolo_sweep;
+	wp->tremolo_rate = xp.tremolo_rate;
+	wp->tremolo_depth = xp.tremolo_depth;
+	wp->vibrato_sweep = xp.vibrato_sweep;
+	wp->vibrato_rate = xp.vibrato_rate;
+	wp->vibrato_depth = xp.vibrato_depth;
+	wp->scale_frequency = le16_to_cpu(xp.scale_frequency);
+	wp->scale_factor = le16_to_cpu(xp.scale_factor);
+	real_size = snd_seq_gf1_size(wp->size, wp->format);
+	if ((long)real_size > *len) {
+		kfree(wp);
+		return -ENOMEM;
+	}
+	if (ops->put_sample) {
+		err = ops->put_sample(ops->private_data, wp,
+				      *data, real_size, atomic);
+		if (err < 0) {
+			kfree(wp);
+			return err;
+		}
+	}
+	*data += real_size;
+	*len -= real_size;
+	prev = ip->wave;
+	if (prev) {
+		while (prev->next) prev = prev->next;
+		prev->next = wp;
+	} else {
+		ip->wave = wp;
+	}
+	return 0;
+}
+
+static void snd_seq_gf1_wave_free(struct snd_gf1_ops *ops,
+				  struct gf1_wave *wave,
+				  int atomic)
+{
+	if (ops->remove_sample)
+		ops->remove_sample(ops->private_data, wave, atomic);
+	kfree(wave);
+}
+
+static void snd_seq_gf1_instr_free(struct snd_gf1_ops *ops,
+				   struct gf1_instrument *ip,
+				   int atomic)
+{
+	struct gf1_wave *wave;
+	
+	while ((wave = ip->wave) != NULL) {
+		ip->wave = wave->next;
+		snd_seq_gf1_wave_free(ops, wave, atomic);
+	}
+}
+
+static int snd_seq_gf1_put(void *private_data, struct snd_seq_kinstr *instr,
+			   char __user *instr_data, long len, int atomic,
+			   int cmd)
+{
+	struct snd_gf1_ops *ops = private_data;
+	struct gf1_instrument *ip;
+	struct gf1_xinstrument ix;
+	int err;
+	gfp_t gfp_mask;
+
+	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
+		return -EINVAL;
+	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
+	/* copy instrument data */
+	if (len < (long)sizeof(ix))
+		return -EINVAL;
+	if (copy_from_user(&ix, instr_data, sizeof(ix)))
+		return -EFAULT;
+	if (ix.stype != GF1_STRU_INSTR)
+		return -EINVAL;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	ip = (struct gf1_instrument *)KINSTR_DATA(instr);
+	ip->exclusion = le16_to_cpu(ix.exclusion);
+	ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
+	ip->effect1 = ix.effect1;
+	ip->effect1_depth = ix.effect1_depth;
+	ip->effect2 = ix.effect2;
+	ip->effect2_depth = ix.effect2_depth;
+	/* copy layers */
+	while (len > (long)sizeof(__u32)) {
+		__u32 stype;
+
+		if (copy_from_user(&stype, instr_data, sizeof(stype)))
+			return -EFAULT;
+		if (stype != GF1_STRU_WAVE) {
+			snd_seq_gf1_instr_free(ops, ip, atomic);
+			return -EINVAL;
+		}
+		err = snd_seq_gf1_copy_wave_from_stream(ops,
+							ip,
+							&instr_data,
+							&len,
+							atomic);
+		if (err < 0) {
+			snd_seq_gf1_instr_free(ops, ip, atomic);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int snd_seq_gf1_copy_wave_to_stream(struct snd_gf1_ops *ops,
+					   struct gf1_instrument *ip,
+					   char __user **data,
+					   long *len,
+					   int atomic)
+{
+	struct gf1_wave *wp;
+	struct gf1_xwave xp;
+	int err;
+	unsigned int real_size;
+	
+	for (wp = ip->wave; wp; wp = wp->next) {
+		if (*len < (long)sizeof(xp))
+			return -ENOMEM;
+		memset(&xp, 0, sizeof(xp));
+		xp.stype = GF1_STRU_WAVE;
+		xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
+		xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
+		xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
+		xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
+		xp.format = cpu_to_le32(wp->format);
+		xp.size = cpu_to_le32(wp->size);
+		xp.start = cpu_to_le32(wp->start);
+		xp.loop_start = cpu_to_le32(wp->loop_start);
+		xp.loop_end = cpu_to_le32(wp->loop_end);
+		xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
+		xp.flags = wp->flags;
+		xp.sample_rate = cpu_to_le32(wp->sample_rate);
+		xp.low_frequency = cpu_to_le32(wp->low_frequency);
+		xp.high_frequency = cpu_to_le32(wp->high_frequency);
+		xp.root_frequency = cpu_to_le32(wp->root_frequency);
+		xp.tune = cpu_to_le16(wp->tune);
+		xp.balance = wp->balance;
+		memcpy(xp.envelope_rate, wp->envelope_rate, 6);
+		memcpy(xp.envelope_offset, wp->envelope_offset, 6);
+		xp.tremolo_sweep = wp->tremolo_sweep;
+		xp.tremolo_rate = wp->tremolo_rate;
+		xp.tremolo_depth = wp->tremolo_depth;
+		xp.vibrato_sweep = wp->vibrato_sweep;
+		xp.vibrato_rate = wp->vibrato_rate;
+		xp.vibrato_depth = wp->vibrato_depth;
+		xp.scale_frequency = cpu_to_le16(wp->scale_frequency);
+		xp.scale_factor = cpu_to_le16(wp->scale_factor);
+		if (copy_to_user(*data, &xp, sizeof(xp)))
+			return -EFAULT;
+		*data += sizeof(xp);
+		*len -= sizeof(xp);
+		real_size = snd_seq_gf1_size(wp->size, wp->format);
+		if (*len < (long)real_size)
+			return -ENOMEM;
+		if (ops->get_sample) {
+			err = ops->get_sample(ops->private_data, wp,
+					      *data, real_size, atomic);
+			if (err < 0)
+				return err;
+		}
+		*data += wp->size;
+		*len -= wp->size;
+	}
+	return 0;
+}
+
+static int snd_seq_gf1_get(void *private_data, struct snd_seq_kinstr *instr,
+			   char __user *instr_data, long len, int atomic,
+			   int cmd)
+{
+	struct snd_gf1_ops *ops = private_data;
+	struct gf1_instrument *ip;
+	struct gf1_xinstrument ix;
+	
+	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
+		return -EINVAL;
+	if (len < (long)sizeof(ix))
+		return -ENOMEM;
+	memset(&ix, 0, sizeof(ix));
+	ip = (struct gf1_instrument *)KINSTR_DATA(instr);
+	ix.stype = GF1_STRU_INSTR;
+	ix.exclusion = cpu_to_le16(ip->exclusion);
+	ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
+	ix.effect1 = cpu_to_le16(ip->effect1);
+	ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
+	ix.effect2 = ip->effect2;
+	ix.effect2_depth = ip->effect2_depth;
+	if (copy_to_user(instr_data, &ix, sizeof(ix)))
+		return -EFAULT;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	return snd_seq_gf1_copy_wave_to_stream(ops,
+					       ip,
+					       &instr_data,
+					       &len,
+					       atomic);
+}
+
+static int snd_seq_gf1_get_size(void *private_data, struct snd_seq_kinstr *instr,
+				long *size)
+{
+	long result;
+	struct gf1_instrument *ip;
+	struct gf1_wave *wp;
+
+	*size = 0;
+	ip = (struct gf1_instrument *)KINSTR_DATA(instr);
+	result = sizeof(struct gf1_xinstrument);
+	for (wp = ip->wave; wp; wp = wp->next) {
+		result += sizeof(struct gf1_xwave);
+		result += wp->size;
+	}
+	*size = result;
+	return 0;
+}
+
+static int snd_seq_gf1_remove(void *private_data,
+			      struct snd_seq_kinstr *instr,
+                              int atomic)
+{
+	struct snd_gf1_ops *ops = private_data;
+	struct gf1_instrument *ip;
+
+	ip = (struct gf1_instrument *)KINSTR_DATA(instr);
+	snd_seq_gf1_instr_free(ops, ip, atomic);
+	return 0;
+}
+
+static void snd_seq_gf1_notify(void *private_data,
+			       struct snd_seq_kinstr *instr,
+			       int what)
+{
+	struct snd_gf1_ops *ops = private_data;
+
+	if (ops->notify)
+		ops->notify(ops->private_data, instr, what);
+}
+
+int snd_seq_gf1_init(struct snd_gf1_ops *ops,
+		     void *private_data,
+		     struct snd_seq_kinstr_ops *next)
+{
+	memset(ops, 0, sizeof(*ops));
+	ops->private_data = private_data;
+	ops->kops.private_data = ops;
+	ops->kops.add_len = sizeof(struct gf1_instrument);
+	ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
+	ops->kops.put = snd_seq_gf1_put;
+	ops->kops.get = snd_seq_gf1_get;
+	ops->kops.get_size = snd_seq_gf1_get_size;
+	ops->kops.remove = snd_seq_gf1_remove;
+	ops->kops.notify = snd_seq_gf1_notify;
+	ops->kops.next = next;
+	return 0;
+}
+
+/*
+ *  Init part
+ */
+
+static int __init alsa_ainstr_gf1_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_ainstr_gf1_exit(void)
+{
+}
+
+module_init(alsa_ainstr_gf1_init)
+module_exit(alsa_ainstr_gf1_exit)
+
+EXPORT_SYMBOL(snd_seq_gf1_init);
diff --git a/alsa/acore/seq/old/instr/ainstr_iw.c b/alsa/acore/seq/old/instr/ainstr_iw.c
new file mode 100644
index 0000000..6c40eb7
--- /dev/null
+++ b/alsa/acore/seq/old/instr/ainstr_iw.c
@@ -0,0 +1,623 @@
+/*
+ *   IWFFFF - AMD InterWave (tm) - Instrument routines
+ *   Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/ainstr_iw.h>
+#include <sound/initval.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
+MODULE_LICENSE("GPL");
+
+static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format)
+{
+	unsigned int result = size;
+	
+	if (format & IWFFFF_WAVE_16BIT)
+		result <<= 1;
+	if (format & IWFFFF_WAVE_STEREO)
+		result <<= 1;
+	return result;
+}
+
+static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp,
+						struct iwffff_xlfo *fx)
+{
+	fp->freq = le16_to_cpu(fx->freq);
+	fp->depth = le16_to_cpu(fx->depth);
+	fp->sweep = le16_to_cpu(fx->sweep);
+	fp->shape = fx->shape;
+	fp->delay = fx->delay;
+}
+
+static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
+					       struct iwffff_layer *lp,
+					       struct iwffff_env *ep,
+					       struct iwffff_xenv *ex,
+					       char __user **data,
+					       long *len,
+					       gfp_t gfp_mask)
+{
+	__u32 stype;
+	struct iwffff_env_record *rp, *rp_last;
+	struct iwffff_xenv_record rx;
+	struct iwffff_env_point *pp;
+	struct iwffff_xenv_point px;
+	int points_size, idx;
+
+	ep->flags = ex->flags;
+	ep->mode = ex->mode;
+	ep->index = ex->index;
+	rp_last = NULL;
+	while (1) {
+		if (*len < (long)sizeof(__u32))
+			return -EINVAL;
+		if (copy_from_user(&stype, *data, sizeof(stype)))
+			return -EFAULT;
+		if (stype == IWFFFF_STRU_WAVE)
+			return 0;
+		if (req_stype != stype) {
+			if (stype == IWFFFF_STRU_ENV_RECP ||
+			    stype == IWFFFF_STRU_ENV_RECV)
+				return 0;
+		}
+		if (*len < (long)sizeof(rx))
+			return -EINVAL;
+		if (copy_from_user(&rx, *data, sizeof(rx)))
+			return -EFAULT;
+		*data += sizeof(rx);
+		*len -= sizeof(rx);
+		points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
+		if (points_size > *len)
+			return -EINVAL;
+		rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
+		if (rp == NULL)
+			return -ENOMEM;
+		rp->nattack = le16_to_cpu(rx.nattack);
+		rp->nrelease = le16_to_cpu(rx.nrelease);
+		rp->sustain_offset = le16_to_cpu(rx.sustain_offset);
+		rp->sustain_rate = le16_to_cpu(rx.sustain_rate);
+		rp->release_rate = le16_to_cpu(rx.release_rate);
+		rp->hirange = rx.hirange;
+		pp = (struct iwffff_env_point *)(rp + 1);
+		for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
+			if (copy_from_user(&px, *data, sizeof(px)))
+				return -EFAULT;
+			*data += sizeof(px);
+			*len -= sizeof(px);
+			pp->offset = le16_to_cpu(px.offset);
+			pp->rate = le16_to_cpu(px.rate);
+		}
+		if (ep->record == NULL) {
+			ep->record = rp;
+		} else {
+			rp_last = rp;
+		}
+		rp_last = rp;
+	}
+	return 0;
+}
+
+static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops,
+						struct iwffff_layer *lp,
+					        char __user **data,
+					        long *len,
+					        int atomic)
+{
+	struct iwffff_wave *wp, *prev;
+	struct iwffff_xwave xp;
+	int err;
+	gfp_t gfp_mask;
+	unsigned int real_size;
+	
+	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
+	if (*len < (long)sizeof(xp))
+		return -EINVAL;
+	if (copy_from_user(&xp, *data, sizeof(xp)))
+		return -EFAULT;
+	*data += sizeof(xp);
+	*len -= sizeof(xp);
+	wp = kzalloc(sizeof(*wp), gfp_mask);
+	if (wp == NULL)
+		return -ENOMEM;
+	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
+	wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
+	wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
+	wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
+	wp->format = le32_to_cpu(xp.format);
+	wp->address.memory = le32_to_cpu(xp.offset);
+	wp->size = le32_to_cpu(xp.size);
+	wp->start = le32_to_cpu(xp.start);
+	wp->loop_start = le32_to_cpu(xp.loop_start);
+	wp->loop_end = le32_to_cpu(xp.loop_end);
+	wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
+	wp->sample_ratio = le32_to_cpu(xp.sample_ratio);
+	wp->attenuation = xp.attenuation;
+	wp->low_note = xp.low_note;
+	wp->high_note = xp.high_note;
+	real_size = snd_seq_iwffff_size(wp->size, wp->format);
+	if (!(wp->format & IWFFFF_WAVE_ROM)) {
+		if ((long)real_size > *len) {
+			kfree(wp);
+			return -ENOMEM;
+		}
+	}
+	if (ops->put_sample) {
+		err = ops->put_sample(ops->private_data, wp,
+				      *data, real_size, atomic);
+		if (err < 0) {
+			kfree(wp);
+			return err;
+		}
+	}
+	if (!(wp->format & IWFFFF_WAVE_ROM)) {
+		*data += real_size;
+		*len -= real_size;
+	}
+	prev = lp->wave;
+	if (prev) {
+		while (prev->next) prev = prev->next;
+		prev->next = wp;
+	} else {
+		lp->wave = wp;
+	}
+	return 0;
+}
+
+static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops,
+				    struct iwffff_env *env,
+				    int atomic)
+{
+	struct iwffff_env_record *rec;
+	
+	while ((rec = env->record) != NULL) {
+		env->record = rec->next;
+		kfree(rec);
+	}
+}
+				    
+static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops,
+				     struct iwffff_wave *wave,
+				     int atomic)
+{
+	if (ops->remove_sample)
+		ops->remove_sample(ops->private_data, wave, atomic);
+	kfree(wave);
+}
+
+static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops,
+                                      struct iwffff_instrument *ip,
+                                      int atomic)
+{
+	struct iwffff_layer *layer;
+	struct iwffff_wave *wave;
+	
+	while ((layer = ip->layer) != NULL) {
+		ip->layer = layer->next;
+		snd_seq_iwffff_env_free(ops, &layer->penv, atomic);
+		snd_seq_iwffff_env_free(ops, &layer->venv, atomic);
+		while ((wave = layer->wave) != NULL) {
+			layer->wave = wave->next;
+			snd_seq_iwffff_wave_free(ops, wave, atomic);
+		}
+		kfree(layer);
+	}
+}
+
+static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr,
+			      char __user *instr_data, long len, int atomic,
+			      int cmd)
+{
+	struct snd_iwffff_ops *ops = private_data;
+	struct iwffff_instrument *ip;
+	struct iwffff_xinstrument ix;
+	struct iwffff_layer *lp, *prev_lp;
+	struct iwffff_xlayer lx;
+	int err;
+	gfp_t gfp_mask;
+
+	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
+		return -EINVAL;
+	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
+	/* copy instrument data */
+	if (len < (long)sizeof(ix))
+		return -EINVAL;
+	if (copy_from_user(&ix, instr_data, sizeof(ix)))
+		return -EFAULT;
+	if (ix.stype != IWFFFF_STRU_INSTR)
+		return -EINVAL;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
+	ip->exclusion = le16_to_cpu(ix.exclusion);
+	ip->layer_type = le16_to_cpu(ix.layer_type);
+	ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
+	ip->effect1 = ix.effect1;
+	ip->effect1_depth = ix.effect1_depth;
+	ip->effect2 = ix.effect2;
+	ip->effect2_depth = ix.effect2_depth;
+	/* copy layers */
+	prev_lp = NULL;
+	while (len > 0) {
+		if (len < (long)sizeof(struct iwffff_xlayer)) {
+			snd_seq_iwffff_instr_free(ops, ip, atomic);
+			return -EINVAL;
+		}
+		if (copy_from_user(&lx, instr_data, sizeof(lx)))
+			return -EFAULT;
+		instr_data += sizeof(lx);
+		len -= sizeof(lx);
+		if (lx.stype != IWFFFF_STRU_LAYER) {
+			snd_seq_iwffff_instr_free(ops, ip, atomic);
+			return -EINVAL;
+		}
+		lp = kzalloc(sizeof(*lp), gfp_mask);
+		if (lp == NULL) {
+			snd_seq_iwffff_instr_free(ops, ip, atomic);
+			return -ENOMEM;
+		}
+		if (prev_lp) {
+			prev_lp->next = lp;
+		} else {
+			ip->layer = lp;
+		}
+		prev_lp = lp;
+		lp->flags = lx.flags;
+		lp->velocity_mode = lx.velocity_mode;
+		lp->layer_event = lx.layer_event;
+		lp->low_range = lx.low_range;
+		lp->high_range = lx.high_range;
+		lp->pan = lx.pan;
+		lp->pan_freq_scale = lx.pan_freq_scale;
+		lp->attenuation = lx.attenuation;
+		snd_seq_iwffff_copy_lfo_from_stream(&lp->tremolo, &lx.tremolo);
+		snd_seq_iwffff_copy_lfo_from_stream(&lp->vibrato, &lx.vibrato);
+		lp->freq_scale = le16_to_cpu(lx.freq_scale);
+		lp->freq_center = lx.freq_center;
+		err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP,
+							  lp,
+							  &lp->penv, &lx.penv,
+						          &instr_data, &len,
+						          gfp_mask);
+		if (err < 0) {
+			snd_seq_iwffff_instr_free(ops, ip, atomic);
+			return err;
+		}
+		err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV,
+							  lp,
+							  &lp->venv, &lx.venv,
+						          &instr_data, &len,
+						          gfp_mask);
+		if (err < 0) {
+			snd_seq_iwffff_instr_free(ops, ip, atomic);
+			return err;
+		}
+		while (len > (long)sizeof(__u32)) {
+			__u32 stype;
+
+			if (copy_from_user(&stype, instr_data, sizeof(stype)))
+				return -EFAULT;
+			if (stype != IWFFFF_STRU_WAVE)
+				break;
+			err = snd_seq_iwffff_copy_wave_from_stream(ops,
+								   lp,
+							    	   &instr_data,
+								   &len,
+								   atomic);
+			if (err < 0) {
+				snd_seq_iwffff_instr_free(ops, ip, atomic);
+				return err;
+			}
+		}
+	}
+	return 0;
+}
+
+static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx,
+					      struct iwffff_lfo *fp)
+{
+	fx->freq = cpu_to_le16(fp->freq);
+	fx->depth = cpu_to_le16(fp->depth);
+	fx->sweep = cpu_to_le16(fp->sweep);
+	fp->shape = fx->shape;
+	fp->delay = fx->delay;
+}
+
+static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
+					     struct iwffff_layer *lp,
+					     struct iwffff_xenv *ex,
+					     struct iwffff_env *ep,
+					     char __user **data,
+					     long *len)
+{
+	struct iwffff_env_record *rp;
+	struct iwffff_xenv_record rx;
+	struct iwffff_env_point *pp;
+	struct iwffff_xenv_point px;
+	int points_size, idx;
+
+	ex->flags = ep->flags;
+	ex->mode = ep->mode;
+	ex->index = ep->index;
+	for (rp = ep->record; rp; rp = rp->next) {
+		if (*len < (long)sizeof(rx))
+			return -ENOMEM;
+		memset(&rx, 0, sizeof(rx));
+		rx.stype = req_stype;
+		rx.nattack = cpu_to_le16(rp->nattack);
+		rx.nrelease = cpu_to_le16(rp->nrelease);
+		rx.sustain_offset = cpu_to_le16(rp->sustain_offset);
+		rx.sustain_rate = cpu_to_le16(rp->sustain_rate);
+		rx.release_rate = cpu_to_le16(rp->release_rate);
+		rx.hirange = cpu_to_le16(rp->hirange);
+		if (copy_to_user(*data, &rx, sizeof(rx)))
+			return -EFAULT;
+		*data += sizeof(rx);
+		*len -= sizeof(rx);
+		points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
+		if (*len < points_size)
+			return -ENOMEM;
+		pp = (struct iwffff_env_point *)(rp + 1);
+		for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
+			px.offset = cpu_to_le16(pp->offset);
+			px.rate = cpu_to_le16(pp->rate);
+			if (copy_to_user(*data, &px, sizeof(px)))
+				return -EFAULT;
+			*data += sizeof(px);
+			*len -= sizeof(px);
+		}
+	}
+	return 0;
+}
+
+static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops,
+					      struct iwffff_layer *lp,
+					      char __user **data,
+					      long *len,
+					      int atomic)
+{
+	struct iwffff_wave *wp;
+	struct iwffff_xwave xp;
+	int err;
+	unsigned int real_size;
+	
+	for (wp = lp->wave; wp; wp = wp->next) {
+		if (*len < (long)sizeof(xp))
+			return -ENOMEM;
+		memset(&xp, 0, sizeof(xp));
+		xp.stype = IWFFFF_STRU_WAVE;
+		xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
+		xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
+		xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
+		xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
+		xp.format = cpu_to_le32(wp->format);
+		if (wp->format & IWFFFF_WAVE_ROM)
+			xp.offset = cpu_to_le32(wp->address.memory);
+		xp.size = cpu_to_le32(wp->size);
+		xp.start = cpu_to_le32(wp->start);
+		xp.loop_start = cpu_to_le32(wp->loop_start);
+		xp.loop_end = cpu_to_le32(wp->loop_end);
+		xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
+		xp.sample_ratio = cpu_to_le32(wp->sample_ratio);
+		xp.attenuation = wp->attenuation;
+		xp.low_note = wp->low_note;
+		xp.high_note = wp->high_note;
+		if (copy_to_user(*data, &xp, sizeof(xp)))
+			return -EFAULT;
+		*data += sizeof(xp);
+		*len -= sizeof(xp);
+		real_size = snd_seq_iwffff_size(wp->size, wp->format);
+		if (!(wp->format & IWFFFF_WAVE_ROM)) {
+			if (*len < (long)real_size)
+				return -ENOMEM;
+		}
+		if (ops->get_sample) {
+			err = ops->get_sample(ops->private_data, wp,
+					      *data, real_size, atomic);
+			if (err < 0)
+				return err;
+		}
+		if (!(wp->format & IWFFFF_WAVE_ROM)) {
+			*data += real_size;
+			*len -= real_size;
+		}
+	}
+	return 0;
+}
+
+static int snd_seq_iwffff_get(void *private_data, struct snd_seq_kinstr *instr,
+			      char __user *instr_data, long len, int atomic, int cmd)
+{
+	struct snd_iwffff_ops *ops = private_data;
+	struct iwffff_instrument *ip;
+	struct iwffff_xinstrument ix;
+	struct iwffff_layer *lp;
+	struct iwffff_xlayer lx;
+	char __user *layer_instr_data;
+	int err;
+	
+	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
+		return -EINVAL;
+	if (len < (long)sizeof(ix))
+		return -ENOMEM;
+	memset(&ix, 0, sizeof(ix));
+	ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
+	ix.stype = IWFFFF_STRU_INSTR;
+	ix.exclusion = cpu_to_le16(ip->exclusion);
+	ix.layer_type = cpu_to_le16(ip->layer_type);
+	ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
+	ix.effect1 = cpu_to_le16(ip->effect1);
+	ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
+	ix.effect2 = ip->effect2;
+	ix.effect2_depth = ip->effect2_depth;
+	if (copy_to_user(instr_data, &ix, sizeof(ix)))
+		return -EFAULT;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	for (lp = ip->layer; lp; lp = lp->next) {
+		if (len < (long)sizeof(lx))
+			return -ENOMEM;
+		memset(&lx, 0, sizeof(lx));
+		lx.stype = IWFFFF_STRU_LAYER;
+		lx.flags = lp->flags;
+		lx.velocity_mode = lp->velocity_mode;
+		lx.layer_event = lp->layer_event;
+		lx.low_range = lp->low_range;
+		lx.high_range = lp->high_range;
+		lx.pan = lp->pan;
+		lx.pan_freq_scale = lp->pan_freq_scale;
+		lx.attenuation = lp->attenuation;
+		snd_seq_iwffff_copy_lfo_to_stream(&lx.tremolo, &lp->tremolo);
+		snd_seq_iwffff_copy_lfo_to_stream(&lx.vibrato, &lp->vibrato);
+		layer_instr_data = instr_data;
+		instr_data += sizeof(lx);
+		len -= sizeof(lx);
+		err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP,
+							lp,
+							&lx.penv, &lp->penv,
+						        &instr_data, &len);
+		if (err < 0)
+			return err;
+		err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV,
+							lp,
+							&lx.venv, &lp->venv,
+						        &instr_data, &len);
+		if (err < 0)
+			return err;
+		/* layer structure updating is now finished */
+		if (copy_to_user(layer_instr_data, &lx, sizeof(lx)))
+			return -EFAULT;
+		err = snd_seq_iwffff_copy_wave_to_stream(ops,
+							 lp,
+							 &instr_data,
+							 &len,
+							 atomic);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep)
+{
+	long result = 0;
+	struct iwffff_env_record *rp;
+
+	for (rp = ep->record; rp; rp = rp->next) {
+		result += sizeof(struct iwffff_xenv_record);
+		result += (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
+	}
+	return 0;
+}
+
+static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp)
+{
+	long result = 0;
+	struct iwffff_wave *wp;
+	
+	for (wp = lp->wave; wp; wp = wp->next) {
+		result += sizeof(struct iwffff_xwave);
+		if (!(wp->format & IWFFFF_WAVE_ROM))
+			result += wp->size;
+	}
+	return result;
+}
+
+static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr,
+				   long *size)
+{
+	long result;
+	struct iwffff_instrument *ip;
+	struct iwffff_layer *lp;
+
+	*size = 0;
+	ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
+	result = sizeof(struct iwffff_xinstrument);
+	for (lp = ip->layer; lp; lp = lp->next) {
+		result += sizeof(struct iwffff_xlayer);
+		result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
+		result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
+		result += snd_seq_iwffff_wave_size_in_stream(lp);
+	}
+	*size = result;
+	return 0;
+}
+
+static int snd_seq_iwffff_remove(void *private_data,
+				 struct snd_seq_kinstr *instr,
+                                 int atomic)
+{
+	struct snd_iwffff_ops *ops = private_data;
+	struct iwffff_instrument *ip;
+
+	ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
+	snd_seq_iwffff_instr_free(ops, ip, atomic);
+	return 0;
+}
+
+static void snd_seq_iwffff_notify(void *private_data,
+				  struct snd_seq_kinstr *instr,
+                                  int what)
+{
+	struct snd_iwffff_ops *ops = private_data;
+
+	if (ops->notify)
+		ops->notify(ops->private_data, instr, what);
+}
+
+int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
+			void *private_data,
+			struct snd_seq_kinstr_ops *next)
+{
+	memset(ops, 0, sizeof(*ops));
+	ops->private_data = private_data;
+	ops->kops.private_data = ops;
+	ops->kops.add_len = sizeof(struct iwffff_instrument);
+	ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_INTERWAVE;
+	ops->kops.put = snd_seq_iwffff_put;
+	ops->kops.get = snd_seq_iwffff_get;
+	ops->kops.get_size = snd_seq_iwffff_get_size;
+	ops->kops.remove = snd_seq_iwffff_remove;
+	ops->kops.notify = snd_seq_iwffff_notify;
+	ops->kops.next = next;
+	return 0;
+}
+
+/*
+ *  Init part
+ */
+
+static int __init alsa_ainstr_iw_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_ainstr_iw_exit(void)
+{
+}
+
+module_init(alsa_ainstr_iw_init)
+module_exit(alsa_ainstr_iw_exit)
+
+EXPORT_SYMBOL(snd_seq_iwffff_init);
diff --git a/alsa/acore/seq/old/instr/ainstr_simple.c b/alsa/acore/seq/old/instr/ainstr_simple.c
new file mode 100644
index 0000000..78f68be
--- /dev/null
+++ b/alsa/acore/seq/old/instr/ainstr_simple.c
@@ -0,0 +1,215 @@
+/*
+ *   Simple (MOD player) - Instrument routines
+ *   Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/ainstr_simple.h>
+#include <sound/initval.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
+MODULE_LICENSE("GPL");
+
+static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
+{
+	unsigned int result = size;
+	
+	if (format & SIMPLE_WAVE_16BIT)
+		result <<= 1;
+	if (format & SIMPLE_WAVE_STEREO)
+		result <<= 1;
+	return result;
+}
+
+static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
+				      struct simple_instrument *ip,
+				      int atomic)
+{
+	if (ops->remove_sample)
+		ops->remove_sample(ops->private_data, ip, atomic);
+}
+
+static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
+			      char __user *instr_data, long len,
+			      int atomic, int cmd)
+{
+	struct snd_simple_ops *ops = private_data;
+	struct simple_instrument *ip;
+	struct simple_xinstrument ix;
+	int err;
+	gfp_t gfp_mask;
+	unsigned int real_size;
+
+	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
+		return -EINVAL;
+	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
+	/* copy instrument data */
+	if (len < (long)sizeof(ix))
+		return -EINVAL;
+	if (copy_from_user(&ix, instr_data, sizeof(ix)))
+		return -EFAULT;
+	if (ix.stype != SIMPLE_STRU_INSTR)
+		return -EINVAL;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	ip = (struct simple_instrument *)KINSTR_DATA(instr);
+	ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
+	ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
+	ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
+	ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
+	ip->format = le32_to_cpu(ix.format);
+	ip->size = le32_to_cpu(ix.size);
+	ip->start = le32_to_cpu(ix.start);
+	ip->loop_start = le32_to_cpu(ix.loop_start);
+	ip->loop_end = le32_to_cpu(ix.loop_end);
+	ip->loop_repeat = le16_to_cpu(ix.loop_repeat);
+	ip->effect1 = ix.effect1;
+	ip->effect1_depth = ix.effect1_depth;
+	ip->effect2 = ix.effect2;
+	ip->effect2_depth = ix.effect2_depth;
+	real_size = snd_seq_simple_size(ip->size, ip->format);
+	if (len < (long)real_size)
+		return -EINVAL;
+	if (ops->put_sample) {
+		err = ops->put_sample(ops->private_data, ip,
+				      instr_data, real_size, atomic);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
+			      char __user *instr_data, long len,
+			      int atomic, int cmd)
+{
+	struct snd_simple_ops *ops = private_data;
+	struct simple_instrument *ip;
+	struct simple_xinstrument ix;
+	int err;
+	unsigned int real_size;
+	
+	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
+		return -EINVAL;
+	if (len < (long)sizeof(ix))
+		return -ENOMEM;
+	memset(&ix, 0, sizeof(ix));
+	ip = (struct simple_instrument *)KINSTR_DATA(instr);
+	ix.stype = SIMPLE_STRU_INSTR;
+	ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
+	ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
+	ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
+	ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
+	ix.format = cpu_to_le32(ip->format);
+	ix.size = cpu_to_le32(ip->size);
+	ix.start = cpu_to_le32(ip->start);
+	ix.loop_start = cpu_to_le32(ip->loop_start);
+	ix.loop_end = cpu_to_le32(ip->loop_end);
+	ix.loop_repeat = cpu_to_le32(ip->loop_repeat);
+	ix.effect1 = cpu_to_le16(ip->effect1);
+	ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
+	ix.effect2 = ip->effect2;
+	ix.effect2_depth = ip->effect2_depth;
+	if (copy_to_user(instr_data, &ix, sizeof(ix)))
+		return -EFAULT;
+	instr_data += sizeof(ix);
+	len -= sizeof(ix);
+	real_size = snd_seq_simple_size(ip->size, ip->format);
+	if (len < (long)real_size)
+		return -ENOMEM;
+	if (ops->get_sample) {
+		err = ops->get_sample(ops->private_data, ip,
+				      instr_data, real_size, atomic);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
+				   long *size)
+{
+	struct simple_instrument *ip;
+
+	ip = (struct simple_instrument *)KINSTR_DATA(instr);
+	*size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
+	return 0;
+}
+
+static int snd_seq_simple_remove(void *private_data,
+			         struct snd_seq_kinstr *instr,
+                                 int atomic)
+{
+	struct snd_simple_ops *ops = private_data;
+	struct simple_instrument *ip;
+
+	ip = (struct simple_instrument *)KINSTR_DATA(instr);
+	snd_seq_simple_instr_free(ops, ip, atomic);
+	return 0;
+}
+
+static void snd_seq_simple_notify(void *private_data,
+			          struct snd_seq_kinstr *instr,
+                                  int what)
+{
+	struct snd_simple_ops *ops = private_data;
+
+	if (ops->notify)
+		ops->notify(ops->private_data, instr, what);
+}
+
+int snd_seq_simple_init(struct snd_simple_ops *ops,
+		        void *private_data,
+		        struct snd_seq_kinstr_ops *next)
+{
+	memset(ops, 0, sizeof(*ops));
+	ops->private_data = private_data;
+	ops->kops.private_data = ops;
+	ops->kops.add_len = sizeof(struct simple_instrument);
+	ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
+	ops->kops.put = snd_seq_simple_put;
+	ops->kops.get = snd_seq_simple_get;
+	ops->kops.get_size = snd_seq_simple_get_size;
+	ops->kops.remove = snd_seq_simple_remove;
+	ops->kops.notify = snd_seq_simple_notify;
+	ops->kops.next = next;
+	return 0;
+}
+
+/*
+ *  Init part
+ */
+
+static int __init alsa_ainstr_simple_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_ainstr_simple_exit(void)
+{
+}
+
+module_init(alsa_ainstr_simple_init)
+module_exit(alsa_ainstr_simple_exit)
+
+EXPORT_SYMBOL(snd_seq_simple_init);
diff --git a/alsa/acore/seq/old/seq_instr.c b/alsa/acore/seq/old/seq_instr.c
new file mode 100644
index 0000000..9a6fd56
--- /dev/null
+++ b/alsa/acore/seq/old/seq_instr.c
@@ -0,0 +1,655 @@
+/*
+ *   Generic Instrument routines for ALSA sequencer
+ *   Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include "seq_clientmgr.h"
+#include <sound/seq_instr.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
+MODULE_LICENSE("GPL");
+
+
+static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list)
+{
+	if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
+		spin_lock_irqsave(&list->ops_lock, list->ops_flags);
+	} else {
+		mutex_lock(&list->ops_mutex);
+	}
+}
+
+static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list)
+{
+	if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
+		spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);
+	} else {
+		mutex_unlock(&list->ops_mutex);
+	}
+}
+
+static struct snd_seq_kinstr *snd_seq_instr_new(int add_len, int atomic)
+{
+	struct snd_seq_kinstr *instr;
+	
+	instr = kzalloc(sizeof(struct snd_seq_kinstr) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+	if (instr == NULL)
+		return NULL;
+	instr->add_len = add_len;
+	return instr;
+}
+
+static int snd_seq_instr_free(struct snd_seq_kinstr *instr, int atomic)
+{
+	int result = 0;
+
+	if (instr == NULL)
+		return -EINVAL;
+	if (instr->ops && instr->ops->remove)
+		result = instr->ops->remove(instr->ops->private_data, instr, 1);
+	if (!result)
+		kfree(instr);
+	return result;
+}
+
+struct snd_seq_kinstr_list *snd_seq_instr_list_new(void)
+{
+	struct snd_seq_kinstr_list *list;
+
+	list = kzalloc(sizeof(struct snd_seq_kinstr_list), GFP_KERNEL);
+	if (list == NULL)
+		return NULL;
+	spin_lock_init(&list->lock);
+	spin_lock_init(&list->ops_lock);
+	mutex_init(&list->ops_mutex);
+	list->owner = -1;
+	return list;
+}
+
+void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
+{
+	struct snd_seq_kinstr_list *list;
+	struct snd_seq_kinstr *instr;
+	struct snd_seq_kcluster *cluster;
+	int idx;
+	unsigned long flags;
+
+	if (list_ptr == NULL)
+		return;
+	list = *list_ptr;
+	*list_ptr = NULL;
+	if (list == NULL)
+		return;
+	
+	for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {		
+		while ((instr = list->hash[idx]) != NULL) {
+			list->hash[idx] = instr->next;
+			list->count--;
+			spin_lock_irqsave(&list->lock, flags);
+			while (instr->use) {
+				spin_unlock_irqrestore(&list->lock, flags);
+				schedule_timeout_uninterruptible(1);
+				spin_lock_irqsave(&list->lock, flags);
+			}				
+			spin_unlock_irqrestore(&list->lock, flags);
+			if (snd_seq_instr_free(instr, 0)<0)
+				snd_printk(KERN_WARNING "instrument free problem\n");
+		}
+		while ((cluster = list->chash[idx]) != NULL) {
+			list->chash[idx] = cluster->next;
+			list->ccount--;
+			kfree(cluster);
+		}
+	}
+	kfree(list);
+}
+
+static int instr_free_compare(struct snd_seq_kinstr *instr,
+			      struct snd_seq_instr_header *ifree,
+			      unsigned int client)
+{
+	switch (ifree->cmd) {
+	case SNDRV_SEQ_INSTR_FREE_CMD_ALL:
+		/* all, except private for other clients */
+		if ((instr->instr.std & 0xff000000) == 0)
+			return 0;
+		if (((instr->instr.std >> 24) & 0xff) == client)
+			return 0;
+		return 1;
+	case SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE:
+		/* all my private instruments */
+		if ((instr->instr.std & 0xff000000) == 0)
+			return 1;
+		if (((instr->instr.std >> 24) & 0xff) == client)
+			return 0;
+		return 1;
+	case SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER:
+		/* all my private instruments */
+		if ((instr->instr.std & 0xff000000) == 0) {
+			if (instr->instr.cluster == ifree->id.cluster)
+				return 0;
+			return 1;
+		}
+		if (((instr->instr.std >> 24) & 0xff) == client) {
+			if (instr->instr.cluster == ifree->id.cluster)
+				return 0;
+		}
+		return 1;
+	}
+	return 1;
+}
+
+int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
+			         struct snd_seq_instr_header *ifree,
+			         int client,
+			         int atomic)
+{
+	struct snd_seq_kinstr *instr, *prev, *next, *flist;
+	int idx;
+	unsigned long flags;
+
+	snd_instr_lock_ops(list);
+	for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {
+		spin_lock_irqsave(&list->lock, flags);
+		instr = list->hash[idx];
+		prev = flist = NULL;
+		while (instr) {
+			while (instr && instr_free_compare(instr, ifree, (unsigned int)client)) {
+				prev = instr;
+				instr = instr->next;
+			}
+			if (instr == NULL)
+				continue;
+			if (instr->ops && instr->ops->notify)
+				instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
+			next = instr->next;
+			if (prev == NULL) {
+				list->hash[idx] = next;
+			} else {
+				prev->next = next;
+			}
+			list->count--;
+			instr->next = flist;
+			flist = instr;
+			instr = next;
+		}
+		spin_unlock_irqrestore(&list->lock, flags);
+		while (flist) {
+			instr = flist;
+			flist = instr->next;
+			while (instr->use) {
+				schedule_timeout_uninterruptible(1);
+				barrier();
+			}
+			if (snd_seq_instr_free(instr, atomic)<0)
+				snd_printk(KERN_WARNING "instrument free problem\n");
+			instr = next;
+		}
+	}
+	snd_instr_unlock_ops(list);
+	return 0;	
+}
+
+static int compute_hash_instr_key(struct snd_seq_instr *instr)
+{
+	int result;
+	
+	result = instr->bank | (instr->prg << 16);
+	result += result >> 24;
+	result += result >> 16;
+	result += result >> 8;
+	return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
+}
+
+#if 0
+static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster)
+{
+	int result;
+	
+	result = cluster;
+	result += result >> 24;
+	result += result >> 16;
+	result += result >> 8;
+	return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
+}
+#endif
+
+static int compare_instr(struct snd_seq_instr *i1, struct snd_seq_instr *i2, int exact)
+{
+	if (exact) {
+		if (i1->cluster != i2->cluster ||
+		    i1->bank != i2->bank ||
+		    i1->prg != i2->prg)
+			return 1;
+		if ((i1->std & 0xff000000) != (i2->std & 0xff000000))
+			return 1;
+		if (!(i1->std & i2->std))
+			return 1;
+		return 0;
+	} else {
+		unsigned int client_check;
+		
+		if (i2->cluster && i1->cluster != i2->cluster)
+			return 1;
+		client_check = i2->std & 0xff000000;
+		if (client_check) {
+			if ((i1->std & 0xff000000) != client_check)
+				return 1;
+		} else {
+			if ((i1->std & i2->std) != i2->std)
+				return 1;
+		}
+		return i1->bank != i2->bank || i1->prg != i2->prg;
+	}
+}
+
+struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
+					  struct snd_seq_instr *instr,
+					  int exact,
+					  int follow_alias)
+{
+	unsigned long flags;
+	int depth = 0;
+	struct snd_seq_kinstr *result;
+
+	if (list == NULL || instr == NULL)
+		return NULL;
+	spin_lock_irqsave(&list->lock, flags);
+      __again:
+	result = list->hash[compute_hash_instr_key(instr)];
+	while (result) {
+		if (!compare_instr(&result->instr, instr, exact)) {
+			if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) {
+				instr = (struct snd_seq_instr *)KINSTR_DATA(result);
+				if (++depth > 10)
+					goto __not_found;
+				goto __again;
+			}
+			result->use++;
+			spin_unlock_irqrestore(&list->lock, flags);
+			return result;
+		}
+		result = result->next;
+	}
+      __not_found:
+	spin_unlock_irqrestore(&list->lock, flags);
+	return NULL;
+}
+
+void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
+			    struct snd_seq_kinstr *instr)
+{
+	unsigned long flags;
+
+	if (list == NULL || instr == NULL)
+		return;
+	spin_lock_irqsave(&list->lock, flags);
+	if (instr->use <= 0) {
+		snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);
+	} else {
+		instr->use--;
+	}
+	spin_unlock_irqrestore(&list->lock, flags);
+}
+
+static struct snd_seq_kinstr_ops *instr_ops(struct snd_seq_kinstr_ops *ops,
+					    char *instr_type)
+{
+	while (ops) {
+		if (!strcmp(ops->instr_type, instr_type))
+			return ops;
+		ops = ops->next;
+	}
+	return NULL;
+}
+
+static int instr_result(struct snd_seq_event *ev,
+			int type, int result,
+			int atomic)
+{
+	struct snd_seq_event sev;
+	
+	memset(&sev, 0, sizeof(sev));
+	sev.type = SNDRV_SEQ_EVENT_RESULT;
+	sev.flags = SNDRV_SEQ_TIME_STAMP_REAL | SNDRV_SEQ_EVENT_LENGTH_FIXED |
+	            SNDRV_SEQ_PRIORITY_NORMAL;
+	sev.source = ev->dest;
+	sev.dest = ev->source;
+	sev.data.result.event = type;
+	sev.data.result.result = result;
+#if 0
+	printk("instr result - type = %i, result = %i, queue = %i, source.client:port = %i:%i, dest.client:port = %i:%i\n",
+				type, result,
+				sev.queue,
+				sev.source.client, sev.source.port,
+				sev.dest.client, sev.dest.port);
+#endif
+	return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0);
+}
+
+static int instr_begin(struct snd_seq_kinstr_ops *ops,
+		       struct snd_seq_kinstr_list *list,
+		       struct snd_seq_event *ev,
+		       int atomic, int hop)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&list->lock, flags);
+	if (list->owner >= 0 && list->owner != ev->source.client) {
+		spin_unlock_irqrestore(&list->lock, flags);
+		return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, -EBUSY, atomic);
+	}
+	list->owner = ev->source.client;
+	spin_unlock_irqrestore(&list->lock, flags);
+	return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic);
+}
+
+static int instr_end(struct snd_seq_kinstr_ops *ops,
+		     struct snd_seq_kinstr_list *list,
+		     struct snd_seq_event *ev,
+		     int atomic, int hop)
+{
+	unsigned long flags;
+
+	/* TODO: timeout handling */
+	spin_lock_irqsave(&list->lock, flags);
+	if (list->owner == ev->source.client) {
+		list->owner = -1;
+		spin_unlock_irqrestore(&list->lock, flags);
+		return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, 0, atomic);
+	}
+	spin_unlock_irqrestore(&list->lock, flags);
+	return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic);
+}
+
+static int instr_info(struct snd_seq_kinstr_ops *ops,
+		      struct snd_seq_kinstr_list *list,
+		      struct snd_seq_event *ev,
+		      int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_format_info(struct snd_seq_kinstr_ops *ops,
+			     struct snd_seq_kinstr_list *list,
+			     struct snd_seq_event *ev,
+			     int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_reset(struct snd_seq_kinstr_ops *ops,
+		       struct snd_seq_kinstr_list *list,
+		       struct snd_seq_event *ev,
+		       int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_status(struct snd_seq_kinstr_ops *ops,
+			struct snd_seq_kinstr_list *list,
+			struct snd_seq_event *ev,
+			int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_put(struct snd_seq_kinstr_ops *ops,
+		     struct snd_seq_kinstr_list *list,
+		     struct snd_seq_event *ev,
+		     int atomic, int hop)
+{
+	unsigned long flags;
+	struct snd_seq_instr_header put;
+	struct snd_seq_kinstr *instr;
+	int result = -EINVAL, len, key;
+
+	if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
+		goto __return;
+
+	if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
+		goto __return;
+	if (copy_from_user(&put, (void __user *)ev->data.ext.ptr,
+			   sizeof(struct snd_seq_instr_header))) {
+		result = -EFAULT;
+		goto __return;
+	}
+	snd_instr_lock_ops(list);
+	if (put.id.instr.std & 0xff000000) {	/* private instrument */
+		put.id.instr.std &= 0x00ffffff;
+		put.id.instr.std |= (unsigned int)ev->source.client << 24;
+	}
+	if ((instr = snd_seq_instr_find(list, &put.id.instr, 1, 0))) {
+		snd_seq_instr_free_use(list, instr);
+		snd_instr_unlock_ops(list);
+		result = -EBUSY;
+		goto __return;
+	}
+	ops = instr_ops(ops, put.data.data.format);
+	if (ops == NULL) {
+		snd_instr_unlock_ops(list);
+		goto __return;
+	}
+	len = ops->add_len;
+	if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)
+		len = sizeof(struct snd_seq_instr);
+	instr = snd_seq_instr_new(len, atomic);
+	if (instr == NULL) {
+		snd_instr_unlock_ops(list);
+		result = -ENOMEM;
+		goto __return;
+	}
+	instr->ops = ops;
+	instr->instr = put.id.instr;
+	strlcpy(instr->name, put.data.name, sizeof(instr->name));
+	instr->type = put.data.type;
+	if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
+		result = ops->put(ops->private_data,
+				  instr,
+				  (void __user *)ev->data.ext.ptr + sizeof(struct snd_seq_instr_header),
+				  ev->data.ext.len - sizeof(struct snd_seq_instr_header),
+				  atomic,
+				  put.cmd);
+		if (result < 0) {
+			snd_seq_instr_free(instr, atomic);
+			snd_instr_unlock_ops(list);
+			goto __return;
+		}
+	}
+	key = compute_hash_instr_key(&instr->instr);
+	spin_lock_irqsave(&list->lock, flags);
+	instr->next = list->hash[key];
+	list->hash[key] = instr;
+	list->count++;
+	spin_unlock_irqrestore(&list->lock, flags);
+	snd_instr_unlock_ops(list);
+	result = 0;
+      __return:
+	instr_result(ev, SNDRV_SEQ_EVENT_INSTR_PUT, result, atomic);
+	return result;
+}
+
+static int instr_get(struct snd_seq_kinstr_ops *ops,
+		     struct snd_seq_kinstr_list *list,
+		     struct snd_seq_event *ev,
+		     int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_free(struct snd_seq_kinstr_ops *ops,
+		      struct snd_seq_kinstr_list *list,
+		      struct snd_seq_event *ev,
+		      int atomic, int hop)
+{
+	struct snd_seq_instr_header ifree;
+	struct snd_seq_kinstr *instr, *prev;
+	int result = -EINVAL;
+	unsigned long flags;
+	unsigned int hash;
+
+	if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
+		goto __return;
+
+	if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
+		goto __return;
+	if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr,
+			   sizeof(struct snd_seq_instr_header))) {
+		result = -EFAULT;
+		goto __return;
+	}
+	if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_ALL ||
+	    ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE ||
+	    ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER) {
+	    	result = snd_seq_instr_list_free_cond(list, &ifree, ev->dest.client, atomic);
+	    	goto __return;
+	}
+	if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_SINGLE) {
+		if (ifree.id.instr.std & 0xff000000) {
+			ifree.id.instr.std &= 0x00ffffff;
+			ifree.id.instr.std |= (unsigned int)ev->source.client << 24;
+		}
+		hash = compute_hash_instr_key(&ifree.id.instr);
+		snd_instr_lock_ops(list);
+		spin_lock_irqsave(&list->lock, flags);
+		instr = list->hash[hash];
+		prev = NULL;
+		while (instr) {
+			if (!compare_instr(&instr->instr, &ifree.id.instr, 1))
+				goto __free_single;
+			prev = instr;
+			instr = instr->next;
+		}
+		result = -ENOENT;
+		spin_unlock_irqrestore(&list->lock, flags);
+		snd_instr_unlock_ops(list);
+		goto __return;
+		
+	      __free_single:
+		if (prev) {
+			prev->next = instr->next;
+		} else {
+			list->hash[hash] = instr->next;
+		}
+		if (instr->ops && instr->ops->notify)
+			instr->ops->notify(instr->ops->private_data, instr,
+					   SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
+		while (instr->use) {
+			spin_unlock_irqrestore(&list->lock, flags);
+			schedule_timeout_uninterruptible(1);
+			spin_lock_irqsave(&list->lock, flags);
+		}				
+		spin_unlock_irqrestore(&list->lock, flags);
+		result = snd_seq_instr_free(instr, atomic);
+		snd_instr_unlock_ops(list);
+		goto __return;
+	}
+
+      __return:
+	instr_result(ev, SNDRV_SEQ_EVENT_INSTR_FREE, result, atomic);
+	return result;
+}
+
+static int instr_list(struct snd_seq_kinstr_ops *ops,
+		      struct snd_seq_kinstr_list *list,
+		      struct snd_seq_event *ev,
+		      int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+static int instr_cluster(struct snd_seq_kinstr_ops *ops,
+			 struct snd_seq_kinstr_list *list,
+			 struct snd_seq_event *ev,
+			 int atomic, int hop)
+{
+	return -ENXIO;
+}
+
+int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
+			struct snd_seq_kinstr_list *list,
+			struct snd_seq_event *ev,
+			int client,
+			int atomic,
+			int hop)
+{
+	int direct = 0;
+
+	snd_assert(ops != NULL && list != NULL && ev != NULL, return -EINVAL);
+	if (snd_seq_ev_is_direct(ev)) {
+		direct = 1;
+		switch (ev->type) {
+		case SNDRV_SEQ_EVENT_INSTR_BEGIN:
+			return instr_begin(ops, list, ev, atomic, hop);
+		case SNDRV_SEQ_EVENT_INSTR_END:
+			return instr_end(ops, list, ev, atomic, hop);
+		}
+	}
+	if ((list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT) && !direct)
+		return -EINVAL;
+	switch (ev->type) {
+	case SNDRV_SEQ_EVENT_INSTR_INFO:
+		return instr_info(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_FINFO:
+		return instr_format_info(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_RESET:
+		return instr_reset(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_STATUS:
+		return instr_status(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_PUT:
+		return instr_put(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_GET:
+		return instr_get(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_FREE:
+		return instr_free(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_LIST:
+		return instr_list(ops, list, ev, atomic, hop);
+	case SNDRV_SEQ_EVENT_INSTR_CLUSTER:
+		return instr_cluster(ops, list, ev, atomic, hop);
+	}
+	return -EINVAL;
+}
+			
+/*
+ *  Init part
+ */
+
+static int __init alsa_seq_instr_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_seq_instr_exit(void)
+{
+}
+
+module_init(alsa_seq_instr_init)
+module_exit(alsa_seq_instr_exit)
+
+EXPORT_SYMBOL(snd_seq_instr_list_new);
+EXPORT_SYMBOL(snd_seq_instr_list_free);
+EXPORT_SYMBOL(snd_seq_instr_list_free_cond);
+EXPORT_SYMBOL(snd_seq_instr_find);
+EXPORT_SYMBOL(snd_seq_instr_free_use);
+EXPORT_SYMBOL(snd_seq_instr_event);
diff --git a/alsa/acore/seq/old/seq_instr_missing.diff b/alsa/acore/seq/old/seq_instr_missing.diff
new file mode 100644
index 0000000..8e695b1
--- /dev/null
+++ b/alsa/acore/seq/old/seq_instr_missing.diff
@@ -0,0 +1,348 @@
+diff -ru alsa-kernel/include/asequencer.h new-kernel/include/asequencer.h
+--- alsa-kernel/include/asequencer.h	2007-10-30 12:01:55.000000000 +0100
++++ new-kernel/include/asequencer.h	2007-10-15 11:25:08.000000000 +0200
+@@ -110,7 +110,18 @@
+ #define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED	66	/* ports connected */
+ #define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67	/* ports disconnected */
+ 
+-/* 70-89:  synthesizer events - obsoleted */
++/** synthesizer events
++ * event data type = snd_seq_eve_sample_control
++ */
++#define SNDRV_SEQ_EVENT_SAMPLE		70	/* sample select */
++#define SNDRV_SEQ_EVENT_SAMPLE_CLUSTER	71	/* sample cluster select */
++#define SNDRV_SEQ_EVENT_SAMPLE_START	72	/* voice start */
++#define SNDRV_SEQ_EVENT_SAMPLE_STOP	73	/* voice stop */
++#define SNDRV_SEQ_EVENT_SAMPLE_FREQ	74	/* playback frequency */
++#define SNDRV_SEQ_EVENT_SAMPLE_VOLUME	75	/* volume and balance */
++#define SNDRV_SEQ_EVENT_SAMPLE_LOOP	76	/* sample loop */
++#define SNDRV_SEQ_EVENT_SAMPLE_POSITION	77	/* sample position */
++#define SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1	78	/* private (hardware dependent) event */
+ 
+ /** user-defined events with fixed length
+  * event data type = any
+@@ -126,7 +137,28 @@
+ #define SNDRV_SEQ_EVENT_USR8		98
+ #define SNDRV_SEQ_EVENT_USR9		99
+ 
+-/* 100-118: instrument layer - obsoleted */
++/** instrument layer
++ * variable length data can be passed directly to the driver
++ */
++#define SNDRV_SEQ_EVENT_INSTR_BEGIN	100	/* begin of instrument management */
++#define SNDRV_SEQ_EVENT_INSTR_END	101	/* end of instrument management */
++#define SNDRV_SEQ_EVENT_INSTR_INFO	102	/* instrument interface info */
++#define SNDRV_SEQ_EVENT_INSTR_INFO_RESULT 103	/* result */
++#define SNDRV_SEQ_EVENT_INSTR_FINFO	104	/* get format info */
++#define SNDRV_SEQ_EVENT_INSTR_FINFO_RESULT 105	/* get format info */
++#define SNDRV_SEQ_EVENT_INSTR_RESET	106	/* reset instrument memory */
++#define SNDRV_SEQ_EVENT_INSTR_STATUS	107	/* instrument interface status */
++#define SNDRV_SEQ_EVENT_INSTR_STATUS_RESULT 108	/* result */
++#define SNDRV_SEQ_EVENT_INSTR_PUT	109	/* put instrument to port */
++#define SNDRV_SEQ_EVENT_INSTR_GET	110	/* get instrument from port */
++#define SNDRV_SEQ_EVENT_INSTR_GET_RESULT 111	/* result */
++#define SNDRV_SEQ_EVENT_INSTR_FREE	112	/* free instrument(s) */
++#define SNDRV_SEQ_EVENT_INSTR_LIST	113	/* instrument list */
++#define SNDRV_SEQ_EVENT_INSTR_LIST_RESULT 114	/* result */
++#define SNDRV_SEQ_EVENT_INSTR_CLUSTER	115	/* cluster parameters */
++#define SNDRV_SEQ_EVENT_INSTR_CLUSTER_GET 116	/* get cluster parameters */
++#define SNDRV_SEQ_EVENT_INSTR_CLUSTER_RESULT 117 /* result */
++#define SNDRV_SEQ_EVENT_INSTR_CHANGE	118	/* instrument change */
+ /* 119-129: reserved */
+ 
+ /* 130-139: variable length events
+@@ -226,6 +258,78 @@
+ 	void *ptr;		/* pointer to data (note: maybe 64-bit) */
+ } __attribute__((packed));
+ 
++/* Instrument cluster type */
++typedef unsigned int snd_seq_instr_cluster_t;
++
++/* Instrument type */
++struct snd_seq_instr {
++	snd_seq_instr_cluster_t cluster;
++	unsigned int std;		/* the upper byte means a private instrument (owner - client #) */
++	unsigned short bank;
++	unsigned short prg;
++};
++
++	/* sample number */
++struct snd_seq_ev_sample {
++	unsigned int std;
++	unsigned short bank;
++	unsigned short prg;
++};
++
++	/* sample cluster */
++struct snd_seq_ev_cluster {
++	snd_seq_instr_cluster_t cluster;
++};
++
++	/* sample position */
++typedef unsigned int snd_seq_position_t; /* playback position (in samples) * 16 */
++
++	/* sample stop mode */
++enum {
++	SAMPLE_STOP_IMMEDIATELY = 0,	/* terminate playing immediately */
++	SAMPLE_STOP_VENVELOPE = 1,	/* finish volume envelope */
++	SAMPLE_STOP_LOOP = 2		/* terminate loop and finish wave */
++};
++
++	/* sample frequency */
++typedef int snd_seq_frequency_t; /* playback frequency in HZ * 16 */
++
++	/* sample volume control; if any value is set to -1 == do not change */
++struct snd_seq_ev_volume {
++	signed short volume;	/* range: 0-16383 */
++	signed short lr;	/* left-right balance; range: 0-16383 */
++	signed short fr;	/* front-rear balance; range: 0-16383 */
++	signed short du;	/* down-up balance; range: 0-16383 */
++};
++
++	/* simple loop redefinition */
++struct snd_seq_ev_loop {
++	unsigned int start;	/* loop start (in samples) * 16 */
++	unsigned int end;	/* loop end (in samples) * 16 */
++};
++
++struct snd_seq_ev_sample_control {
++	unsigned char channel;
++	unsigned char unused1, unused2, unused3;	/* pad */
++	union {
++		struct snd_seq_ev_sample sample;
++		struct snd_seq_ev_cluster cluster;
++		snd_seq_position_t position;
++		int stop_mode;
++		snd_seq_frequency_t frequency;
++		struct snd_seq_ev_volume volume;
++		struct snd_seq_ev_loop loop;
++		unsigned char raw8[8];
++	} param;
++};
++
++
++
++/* INSTR_BEGIN event */
++struct snd_seq_ev_instr_begin {
++	int timeout;		/* zero = forever, otherwise timeout in ms */
++};
++
+ struct snd_seq_result {
+ 	int event;		/* processed event type */
+ 	int result;
+@@ -295,6 +399,8 @@
+ 		struct snd_seq_addr addr;
+ 		struct snd_seq_connect connect;
+ 		struct snd_seq_result result;
++		struct snd_seq_ev_instr_begin instr_begin;
++		struct snd_seq_ev_sample_control sample;
+ 		struct snd_seq_ev_quote quote;
+ 	} data;
+ };
+@@ -335,6 +441,8 @@
+ #define snd_seq_ev_is_user_type(ev)	((ev)->type >= 90 && (ev)->type < 99)
+ /* fixed length events: 0-99 */
+ #define snd_seq_ev_is_fixed_type(ev)	((ev)->type < 100)
++/* instrument layer events: 100-129 */
++#define snd_seq_ev_is_instr_type(ev)	((ev)->type >= 100 && (ev)->type < 130)
+ /* variable length events: 130-139 */
+ #define snd_seq_ev_is_variable_type(ev)	((ev)->type >= 130 && (ev)->type < 140)
+ /* reserved for kernel */
+@@ -630,6 +738,136 @@
+ 
+ 
+ /*
++ *  Instrument abstraction layer
++ *     - based on events
++ */
++
++/* instrument types */
++#define SNDRV_SEQ_INSTR_ATYPE_DATA	0	/* instrument data */
++#define SNDRV_SEQ_INSTR_ATYPE_ALIAS	1	/* instrument alias */
++
++/* instrument ASCII identifiers */
++#define SNDRV_SEQ_INSTR_ID_DLS1		"DLS1"
++#define SNDRV_SEQ_INSTR_ID_DLS2		"DLS2"
++#define SNDRV_SEQ_INSTR_ID_SIMPLE	"Simple Wave"
++#define SNDRV_SEQ_INSTR_ID_SOUNDFONT	"SoundFont"
++#define SNDRV_SEQ_INSTR_ID_GUS_PATCH	"GUS Patch"
++#define SNDRV_SEQ_INSTR_ID_INTERWAVE	"InterWave FFFF"
++#define SNDRV_SEQ_INSTR_ID_OPL2_3	"OPL2/3 FM"
++#define SNDRV_SEQ_INSTR_ID_OPL4		"OPL4"
++
++/* instrument types */
++#define SNDRV_SEQ_INSTR_TYPE0_DLS1	(1<<0)	/* MIDI DLS v1 */
++#define SNDRV_SEQ_INSTR_TYPE0_DLS2	(1<<1)	/* MIDI DLS v2 */
++#define SNDRV_SEQ_INSTR_TYPE1_SIMPLE	(1<<0)	/* Simple Wave */
++#define SNDRV_SEQ_INSTR_TYPE1_SOUNDFONT	(1<<1)	/* EMU SoundFont */
++#define SNDRV_SEQ_INSTR_TYPE1_GUS_PATCH	(1<<2)	/* Gravis UltraSound Patch */
++#define SNDRV_SEQ_INSTR_TYPE1_INTERWAVE	(1<<3)	/* InterWave FFFF */
++#define SNDRV_SEQ_INSTR_TYPE2_OPL2_3	(1<<0)	/* Yamaha OPL2/3 FM */
++#define SNDRV_SEQ_INSTR_TYPE2_OPL4	(1<<1)	/* Yamaha OPL4 */
++
++/* put commands */
++#define SNDRV_SEQ_INSTR_PUT_CMD_CREATE	0
++#define SNDRV_SEQ_INSTR_PUT_CMD_REPLACE	1
++#define SNDRV_SEQ_INSTR_PUT_CMD_MODIFY	2
++#define SNDRV_SEQ_INSTR_PUT_CMD_ADD	3
++#define SNDRV_SEQ_INSTR_PUT_CMD_REMOVE	4
++
++/* get commands */
++#define SNDRV_SEQ_INSTR_GET_CMD_FULL	0
++#define SNDRV_SEQ_INSTR_GET_CMD_PARTIAL	1
++
++/* query flags */
++#define SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS (1<<0)
++
++/* free commands */
++#define SNDRV_SEQ_INSTR_FREE_CMD_ALL		0
++#define SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE	1
++#define SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER	2
++#define SNDRV_SEQ_INSTR_FREE_CMD_SINGLE		3
++
++/* size of ROM/RAM */
++typedef unsigned int snd_seq_instr_size_t;
++
++/* INSTR_INFO */
++
++struct snd_seq_instr_info {
++	int result;			/* operation result */
++	unsigned int formats[8];	/* bitmap of supported formats */
++	int ram_count;			/* count of RAM banks */
++	snd_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */
++	int rom_count;			/* count of ROM banks */
++	snd_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */
++	char reserved[128];
++};
++
++/* INSTR_STATUS */
++
++struct snd_seq_instr_status {
++	int result;			/* operation result */
++	snd_seq_instr_size_t free_ram[16]; /* free RAM in banks */
++	int instrument_count;		/* count of downloaded instruments */
++	char reserved[128];
++};
++
++/* INSTR_FORMAT_INFO */
++
++struct snd_seq_instr_format_info {
++	char format[16];		/* format identifier - SNDRV_SEQ_INSTR_ID_* */	
++	unsigned int len;		/* max data length (without this structure) */
++};
++
++struct snd_seq_instr_format_info_result {
++	int result;			/* operation result */
++	char format[16];		/* format identifier */
++	unsigned int len;		/* filled data length (without this structure) */
++};
++
++/* instrument data */
++struct snd_seq_instr_data {
++	char name[32];			/* instrument name */
++	char reserved[16];		/* for the future use */
++	int type;			/* instrument type */
++	union {
++		char format[16];	/* format identifier */
++		struct snd_seq_instr alias;
++	} data;
++};
++
++/* INSTR_PUT/GET, data are stored in one block (extended), header + data */
++
++struct snd_seq_instr_header {
++	union {
++		struct snd_seq_instr instr;
++		snd_seq_instr_cluster_t cluster;
++	} id;				/* instrument identifier */
++	unsigned int cmd;		/* get/put/free command */
++	unsigned int flags;		/* query flags (only for get) */
++	unsigned int len;		/* real instrument data length (without header) */
++	int result;			/* operation result */
++	char reserved[16];		/* for the future */
++	struct snd_seq_instr_data data; /* instrument data (for put/get result) */
++};
++
++/* INSTR_CLUSTER_SET */
++
++struct snd_seq_instr_cluster_set {
++	snd_seq_instr_cluster_t cluster; /* cluster identifier */
++	char name[32];			/* cluster name */
++	int priority;			/* cluster priority */
++	char reserved[64];		/* for the future use */
++};
++
++/* INSTR_CLUSTER_GET */
++
++struct snd_seq_instr_cluster_get {
++	snd_seq_instr_cluster_t cluster; /* cluster identifier */
++	char name[32];			/* cluster name */
++	int priority;			/* cluster priority */
++	char reserved[64];		/* for the future use */
++};
++
++/*
+  *  IOCTL commands
+  */
+ 
+diff -ru alsa-kernel/core/seq/Makefile new-kernel/core/seq/Makefile
+--- alsa-kernel/core/seq/Makefile	2007-10-30 12:01:55.000000000 +0100
++++ new-kernel/core/seq/Makefile	2007-10-15 11:25:07.000000000 +0200
+@@ -3,6 +3,7 @@
+ # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
+ #
+ 
++obj-$(CONFIG_SND) += instr/
+ ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
+   obj-$(CONFIG_SND_SEQUENCER) += oss/
+ endif
+@@ -14,6 +15,7 @@
+ snd-seq-midi-objs := seq_midi.o
+ snd-seq-midi-emul-objs := seq_midi_emul.o
+ snd-seq-midi-event-objs := seq_midi_event.o
++snd-seq-instr-objs := seq_instr.o
+ snd-seq-dummy-objs := seq_dummy.o
+ snd-seq-virmidi-objs := seq_virmidi.o
+ 
+@@ -34,7 +36,9 @@
+ # Toplevel Module Dependency
+ obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
+ obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
+-obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
+-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
++obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
++obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
++obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o
+ obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+ obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
++obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o
+diff -ru alsa-kernel/core/seq/seq_clientmgr.c new-kernel/core/seq/seq_clientmgr.c
+--- alsa-kernel/core/seq/seq_clientmgr.c	2007-10-30 12:01:55.000000000 +0100
++++ new-kernel/core/seq/seq_clientmgr.c	2007-10-26 17:50:55.000000000 +0200
+@@ -966,7 +966,8 @@
+ 			return -EINVAL;
+ 		break;
+ 	case SNDRV_SEQ_EVENT_LENGTH_VARUSR:
+-		if (! snd_seq_ev_is_direct(ev))
++		if (! snd_seq_ev_is_instr_type(ev) ||
++		    ! snd_seq_ev_is_direct(ev))
+ 			return -EINVAL;
+ 		break;
+ 	}
+diff -ru alsa-kernel/core/seq/seq_midi_emul.c new-kernel/core/seq/seq_midi_emul.c
+--- alsa-kernel/core/seq/seq_midi_emul.c	2007-10-30 12:01:55.000000000 +0100
++++ new-kernel/core/seq/seq_midi_emul.c	2007-05-11 17:53:34.000000000 +0200
+@@ -229,6 +229,13 @@
+ 	case SNDRV_SEQ_EVENT_PORT_START:
+ 	case SNDRV_SEQ_EVENT_PORT_EXIT:
+ 	case SNDRV_SEQ_EVENT_PORT_CHANGE:
++	case SNDRV_SEQ_EVENT_SAMPLE:
++	case SNDRV_SEQ_EVENT_SAMPLE_START:
++	case SNDRV_SEQ_EVENT_SAMPLE_STOP:
++	case SNDRV_SEQ_EVENT_SAMPLE_FREQ:
++	case SNDRV_SEQ_EVENT_SAMPLE_VOLUME:
++	case SNDRV_SEQ_EVENT_SAMPLE_LOOP:
++	case SNDRV_SEQ_EVENT_SAMPLE_POSITION:
+ 	case SNDRV_SEQ_EVENT_ECHO:
+ 	not_yet:
+ 	default:
diff --git a/alsa/acore/seq/oss/Makefile b/alsa/acore/seq/oss/Makefile
new file mode 100644
index 0000000..612e1a7
--- /dev/null
+++ b/alsa/acore/seq/oss/Makefile
@@ -0,0 +1,16 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+clean-files := seq_oss.c
+
+include $(SND_TOPDIR)/alsa-kernel/core/seq/oss/Makefile
+
+EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/core/seq/oss
+
+include $(SND_TOPDIR)/Rules.make
+
+seq_oss.c: seq_oss.patch $(SND_TOPDIR)/alsa-kernel/core/seq/oss/seq_oss.c
diff --git a/alsa/acore/seq/oss/seq_oss.patch b/alsa/acore/seq/oss/seq_oss.patch
new file mode 100644
index 0000000..adef3aa
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss.patch
@@ -0,0 +1,69 @@
+--- ../../../alsa-kernel/core/seq/oss/seq_oss.c	2007-12-20 10:19:26.000000000 +0100
++++ seq_oss.c	2007-12-20 10:54:07.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  * OSS compatible sequencer driver
+  *
+@@ -21,6 +22,7 @@
+  */
+ 
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/moduleparam.h>
+ #include <linux/mutex.h>
+ #include <sound/core.h>
+@@ -187,12 +189,25 @@
+ 	return snd_seq_oss_ioctl(dp, cmd, arg);
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #define odev_ioctl_compat	odev_ioctl
+ #else
+ #define odev_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int odev_ioctl_old(struct inode *inode, struct file * file,
++			  unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = odev_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ static unsigned int
+ odev_poll(struct file *file, poll_table * wait)
+ {
+@@ -208,14 +223,20 @@
+ 
+ static const struct file_operations seq_oss_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		odev_read,
+ 	.write =	odev_write,
+ 	.open =		odev_open,
+ 	.release =	odev_release,
+ 	.poll =		odev_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	odev_ioctl,
+ 	.compat_ioctl =	odev_ioctl_compat,
++#else
++	.ioctl =	odev_ioctl_old,
++#endif
+ };
+ 
+ static int __init
+@@ -305,3 +326,5 @@
+ 	info_entry = NULL;
+ }
+ #endif /* CONFIG_PROC_FS */
++
++EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/seq/oss/seq_oss_event.c b/alsa/acore/seq/oss/seq_oss_event.c
new file mode 100644
index 0000000..05ac343
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_event.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_event.c"
diff --git a/alsa/acore/seq/oss/seq_oss_init.c b/alsa/acore/seq/oss/seq_oss_init.c
new file mode 100644
index 0000000..861f534
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_init.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_init.c"
diff --git a/alsa/acore/seq/oss/seq_oss_ioctl.c b/alsa/acore/seq/oss/seq_oss_ioctl.c
new file mode 100644
index 0000000..e65fa53
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_ioctl.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_ioctl.c"
diff --git a/alsa/acore/seq/oss/seq_oss_midi.c b/alsa/acore/seq/oss/seq_oss_midi.c
new file mode 100644
index 0000000..1d63db7
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_midi.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_midi.c"
diff --git a/alsa/acore/seq/oss/seq_oss_misc.c b/alsa/acore/seq/oss/seq_oss_misc.c
new file mode 100644
index 0000000..4a49ef2
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_misc.c
@@ -0,0 +1 @@
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_misc.c"
diff --git a/alsa/acore/seq/oss/seq_oss_readq.c b/alsa/acore/seq/oss/seq_oss_readq.c
new file mode 100644
index 0000000..2770b57
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_readq.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_readq.c"
diff --git a/alsa/acore/seq/oss/seq_oss_rw.c b/alsa/acore/seq/oss/seq_oss_rw.c
new file mode 100644
index 0000000..cdbc8eb
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_rw.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_rw.c"
diff --git a/alsa/acore/seq/oss/seq_oss_synth.c b/alsa/acore/seq/oss/seq_oss_synth.c
new file mode 100644
index 0000000..22321d1
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_synth.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_synth.c"
diff --git a/alsa/acore/seq/oss/seq_oss_timer.c b/alsa/acore/seq/oss/seq_oss_timer.c
new file mode 100644
index 0000000..cca9be9
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_timer.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_timer.c"
diff --git a/alsa/acore/seq/oss/seq_oss_writeq.c b/alsa/acore/seq/oss/seq_oss_writeq.c
new file mode 100644
index 0000000..8e09df8
--- /dev/null
+++ b/alsa/acore/seq/oss/seq_oss_writeq.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../../alsa-kernel/core/seq/oss/seq_oss_writeq.c"
diff --git a/alsa/acore/seq/seq.patch b/alsa/acore/seq/seq.patch
new file mode 100644
index 0000000..2e93335
--- /dev/null
+++ b/alsa/acore/seq/seq.patch
@@ -0,0 +1,19 @@
+--- ../../alsa-kernel/core/seq/seq.c	2007-12-20 10:19:22.000000000 +0100
++++ seq.c	2007-12-20 10:51:11.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  ALSA sequencer main module
+  *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+@@ -56,7 +57,11 @@
+ MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer.");
+ MODULE_LICENSE("GPL");
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
++MODULE_PARM(seq_client_load, "1-64i");
++#else
+ module_param_array(seq_client_load, int, NULL, 0444);
++#endif
+ MODULE_PARM_DESC(seq_client_load, "The numbers of global (system) clients to load through kmod.");
+ module_param(seq_default_timer_class, int, 0644);
+ MODULE_PARM_DESC(seq_default_timer_class, "The default timer class.");
diff --git a/alsa/acore/seq/seq_clientmgr.patch b/alsa/acore/seq/seq_clientmgr.patch
new file mode 100644
index 0000000..f03506d
--- /dev/null
+++ b/alsa/acore/seq/seq_clientmgr.patch
@@ -0,0 +1,64 @@
+--- ../../alsa-kernel/core/seq/seq_clientmgr.c	2007-12-20 10:19:43.000000000 +0100
++++ seq_clientmgr.c	2007-12-20 10:51:34.000000000 +0100
+@@ -1,3 +1,5 @@
++#define __NO_VERSION__
++#include "adriver.h"
+ /*
+  *  ALSA sequencer Client Manager
+  *  Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl>
+@@ -22,6 +24,7 @@
+  */
+ 
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
+ #include <sound/minors.h>
+@@ -2200,12 +2203,25 @@
+ 	return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "seq_compat.c"
+ #else
+ #define snd_seq_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_seq_ioctl_old(struct inode *inode, struct file * file,
++			     unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_seq_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ /* -------------------------------------------------------- */
+ 
+ 
+@@ -2535,14 +2551,20 @@
+ 
+ static const struct file_operations snd_seq_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		snd_seq_read,
+ 	.write =	snd_seq_write,
+ 	.open =		snd_seq_open,
+ 	.release =	snd_seq_release,
+ 	.poll =		snd_seq_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_seq_ioctl,
+ 	.compat_ioctl =	snd_seq_ioctl_compat,
++#else
++	.ioctl =	snd_seq_ioctl_old,
++#endif
+ };
+ 
+ /* 
diff --git a/alsa/acore/seq/seq_compat.c b/alsa/acore/seq/seq_compat.c
new file mode 100644
index 0000000..8f8120c
--- /dev/null
+++ b/alsa/acore/seq/seq_compat.c
@@ -0,0 +1 @@
+#include "../../alsa-kernel/core/seq/seq_compat.c"
diff --git a/alsa/acore/seq/seq_device.c b/alsa/acore/seq/seq_device.c
new file mode 100644
index 0000000..580693b
--- /dev/null
+++ b/alsa/acore/seq/seq_device.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_device.c"
diff --git a/alsa/acore/seq/seq_dummy.c b/alsa/acore/seq/seq_dummy.c
new file mode 100644
index 0000000..d2a9672
--- /dev/null
+++ b/alsa/acore/seq/seq_dummy.c
@@ -0,0 +1,3 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_dummy.c"
+EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/seq/seq_fifo.c b/alsa/acore/seq/seq_fifo.c
new file mode 100644
index 0000000..7d3711a
--- /dev/null
+++ b/alsa/acore/seq/seq_fifo.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_fifo.c"
diff --git a/alsa/acore/seq/seq_info.c b/alsa/acore/seq/seq_info.c
new file mode 100644
index 0000000..1ab0212
--- /dev/null
+++ b/alsa/acore/seq/seq_info.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_info.c"
diff --git a/alsa/acore/seq/seq_lock.c b/alsa/acore/seq/seq_lock.c
new file mode 100644
index 0000000..4663541
--- /dev/null
+++ b/alsa/acore/seq/seq_lock.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_lock.c"
diff --git a/alsa/acore/seq/seq_memory.patch b/alsa/acore/seq/seq_memory.patch
new file mode 100644
index 0000000..d01418d
--- /dev/null
+++ b/alsa/acore/seq/seq_memory.patch
@@ -0,0 +1,38 @@
+--- ../../alsa-kernel/core/seq/seq_memory.c	2007-12-20 10:19:32.000000000 +0100
++++ seq_memory.c	2007-12-20 10:52:18.000000000 +0100
+@@ -1,3 +1,5 @@
++#define __NO_VERSION__
++#include "adriver.h"
+ /*
+  *  ALSA sequencer Memory Manager
+  *  Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
+@@ -31,6 +33,10 @@
+ #include "seq_info.h"
+ #include "seq_lock.h"
+ 
++/* semaphore in struct file record */
++#define semaphore_of(fp)	((fp)->f_dentry->d_inode->i_sem)
++
++
+ static inline int snd_seq_pool_available(struct snd_seq_pool *pool)
+ {
+ 	return pool->total_elements - atomic_read(&pool->counter);
+@@ -242,7 +248,18 @@
+ 		set_current_state(TASK_INTERRUPTIBLE);
+ 		add_wait_queue(&pool->output_sleep, &wait);
+ 		spin_unlock_irq(&pool->lock);
++#ifdef LINUX_2_2
++		/* change semaphore to allow other clients
++		   to access device file */
++		if (file)
++			up(&semaphore_of(file));
++#endif
+ 		schedule();
++#ifdef LINUX_2_2
++		/* restore semaphore again */
++		if (file)
++			down(&semaphore_of(file));
++#endif
+ 		spin_lock_irq(&pool->lock);
+ 		remove_wait_queue(&pool->output_sleep, &wait);
+ 		/* interrupted? */
diff --git a/alsa/acore/seq/seq_midi.c b/alsa/acore/seq/seq_midi.c
new file mode 100644
index 0000000..3ebb44a
--- /dev/null
+++ b/alsa/acore/seq/seq_midi.c
@@ -0,0 +1,3 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_midi.c"
+EXPORT_NO_SYMBOLS;
diff --git a/alsa/acore/seq/seq_midi_emul.c b/alsa/acore/seq/seq_midi_emul.c
new file mode 100644
index 0000000..2c8ef11
--- /dev/null
+++ b/alsa/acore/seq/seq_midi_emul.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_midi_emul.c"
diff --git a/alsa/acore/seq/seq_midi_event.c b/alsa/acore/seq/seq_midi_event.c
new file mode 100644
index 0000000..9b3dc42
--- /dev/null
+++ b/alsa/acore/seq/seq_midi_event.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_midi_event.c"
diff --git a/alsa/acore/seq/seq_ports.c b/alsa/acore/seq/seq_ports.c
new file mode 100644
index 0000000..7f5be2c
--- /dev/null
+++ b/alsa/acore/seq/seq_ports.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_ports.c"
diff --git a/alsa/acore/seq/seq_prioq.c b/alsa/acore/seq/seq_prioq.c
new file mode 100644
index 0000000..ab887f2
--- /dev/null
+++ b/alsa/acore/seq/seq_prioq.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_prioq.c"
diff --git a/alsa/acore/seq/seq_queue.c b/alsa/acore/seq/seq_queue.c
new file mode 100644
index 0000000..157fe02
--- /dev/null
+++ b/alsa/acore/seq/seq_queue.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_queue.c"
diff --git a/alsa/acore/seq/seq_system.c b/alsa/acore/seq/seq_system.c
new file mode 100644
index 0000000..3138ec2
--- /dev/null
+++ b/alsa/acore/seq/seq_system.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_system.c"
diff --git a/alsa/acore/seq/seq_timer.c b/alsa/acore/seq/seq_timer.c
new file mode 100644
index 0000000..e666a78
--- /dev/null
+++ b/alsa/acore/seq/seq_timer.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_timer.c"
diff --git a/alsa/acore/seq/seq_virmidi.c b/alsa/acore/seq/seq_virmidi.c
new file mode 100644
index 0000000..9d606e4
--- /dev/null
+++ b/alsa/acore/seq/seq_virmidi.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/core/seq/seq_virmidi.c"
diff --git a/alsa/acore/sgbuf.c b/alsa/acore/sgbuf.c
new file mode 100644
index 0000000..1dbc524
--- /dev/null
+++ b/alsa/acore/sgbuf.c
@@ -0,0 +1,184 @@
+#include "config.h"
+#define __NO_VERSION__
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__) && !defined(__DEPEND__)
+#include "sndversions.h"
+#endif
+#endif
+
+#define SKIP_HIDDEN_MALLOCS
+#include "adriver.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+#define CONFIG_HAS_DMA 1
+#endif
+#include "../alsa-kernel/core/sgbuf.c"
+#else
+
+/*
+ * we don't have vmap/vunmap, so use vmalloc_32 and vmalloc_dma instead
+ */
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <sound/memalloc.h>
+
+/* table entries are align to 32 */
+#define SGBUF_TBL_ALIGN		32
+#define sgbuf_align_table(tbl)	((((tbl) + SGBUF_TBL_ALIGN - 1) / SGBUF_TBL_ALIGN) * SGBUF_TBL_ALIGN)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+/* get the virtual address of the given vmalloc'ed pointer */
+static void *get_vmalloc_addr(void *pageptr)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long lpage;
+
+	lpage = VMALLOC_VMADDR(pageptr);
+	pgd = pgd_offset_k(lpage);
+	pmd = pmd_offset(pgd, lpage);
+	pte = pte_offset(pmd, lpage);
+	return (void *)pte_page(*pte);
+}    
+#endif
+
+/* set up the page table from the given vmalloc'ed buffer pointer.
+ * return a negative error if the page is out of the pci address mask.
+ */
+static int store_page_tables(struct snd_sg_buf *sgbuf, void *vmaddr, unsigned int pages)
+{
+	unsigned int i;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+	unsigned long rmask;
+	struct pci_dev *pci = (struct pci_dev *)sgbuf->dev;
+	rmask = pci->dma_mask;
+	if (rmask)
+		rmask = ~rmask;
+	else
+		rmask = ~0xffffffUL;
+#endif
+
+	sgbuf->pages = 0;
+	for (i = 0; i < pages; i++) {
+		struct page *page;
+		void *ptr;
+		dma_addr_t addr;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+		page = vmalloc_to_page(vmaddr + (i << PAGE_SHIFT));
+		ptr = page_address(page);
+		addr = virt_to_bus(ptr);
+		if (addr & rmask)
+			return -EINVAL;
+#else
+		ptr = get_vmalloc_addr(vmaddr + (i << PAGE_SHIFT));
+		addr = virt_to_bus(ptr);
+		page = virt_to_page(ptr);
+#endif
+		sgbuf->table[i].buf = ptr;
+		sgbuf->table[i].addr = addr;
+		sgbuf->page_table[i] = page;
+		SetPageReserved(page);
+		sgbuf->pages++;
+	}
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#define vmalloc_32(x) vmalloc(x)
+#endif
+
+/* remove all vmalloced pages */
+static void release_vm_buffer(struct snd_sg_buf *sgbuf, void *vmaddr)
+{
+	int i;
+
+	for (i = 0; i < sgbuf->pages; i++)
+		if (sgbuf->page_table[i]) {
+			ClearPageReserved(sgbuf->page_table[i]);
+			sgbuf->page_table[i] = NULL;
+		}
+	sgbuf->pages = 0;
+	if (vmaddr)
+		vfree(vmaddr); /* don't use wrapper */
+}
+
+int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
+{
+	struct snd_sg_buf *sgbuf = dmab->private_data;
+
+	if (dmab->area)
+		release_vm_buffer(sgbuf, dmab->area);
+	dmab->area = NULL;
+	if (sgbuf->table)
+		kfree(sgbuf->table);
+	sgbuf->table = NULL;
+	if (sgbuf->page_table)
+		kfree(sgbuf->page_table);
+	kfree(sgbuf);
+	dmab->private_data = NULL;
+	
+	return 0;
+}
+
+void *snd_malloc_sgbuf_pages(struct device *dev,
+			     size_t size, struct snd_dma_buffer *dmab,
+			     size_t *res_size)
+{
+	struct snd_sg_buf *sgbuf;
+	unsigned int pages;
+
+	dmab->area = NULL;
+	dmab->addr = 0;
+	dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL);
+	if (! sgbuf)
+		return NULL;
+	memset(sgbuf, 0, sizeof(*sgbuf));
+	sgbuf->dev = dev;
+	pages = snd_sgbuf_aligned_pages(size);
+	sgbuf->tblsize = sgbuf_align_table(pages);
+	sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
+	if (! sgbuf->table)
+		goto _failed;
+	memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize);
+	sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize, GFP_KERNEL);
+	if (! sgbuf->page_table)
+		goto _failed;
+	memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize);
+
+	sgbuf->size = size;
+	dmab->area = vmalloc_32(pages << PAGE_SHIFT);
+	if (! dmab->area || store_page_tables(sgbuf, dmab->area, pages) < 0) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+		/* reallocate with DMA flag */
+		release_vm_buffer(sgbuf, dmab->area);
+		dmab->area = vmalloc_dma(pages << PAGE_SHIFT);
+		if (! dmab->area || store_page_tables(sgbuf, dmab->area, pages) < 0)
+			goto _failed;
+		
+#else
+		goto _failed;
+#endif
+	}
+
+	memset(dmab->area, 0, size);
+	return dmab->area;
+
+ _failed:
+	snd_free_sgbuf_pages(dmab); /* free the table */
+	return NULL;
+}
+
+#endif /* < 2.5.0 */
diff --git a/alsa/acore/sound.inc b/alsa/acore/sound.inc
new file mode 100644
index 0000000..a79755e
--- /dev/null
+++ b/alsa/acore/sound.inc
@@ -0,0 +1,9 @@
+  /* wrappers */
+#ifdef CONFIG_SND_DEBUG_MEMORY
+EXPORT_SYMBOL(snd_hidden_kmalloc);
+EXPORT_SYMBOL(snd_hidden_kzalloc);
+EXPORT_SYMBOL(snd_hidden_kcalloc);
+EXPORT_SYMBOL(snd_hidden_kfree);
+EXPORT_SYMBOL(snd_hidden_kstrdup);
+EXPORT_SYMBOL(snd_hidden_kstrndup);
+#endif
diff --git a/alsa/acore/sound.patch b/alsa/acore/sound.patch
new file mode 100644
index 0000000..fd15928
--- /dev/null
+++ b/alsa/acore/sound.patch
@@ -0,0 +1,249 @@
+--- ../alsa-kernel/core/sound.c	2009-09-21 15:57:35.000000000 +0200
++++ sound.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Advanced Linux Sound Architecture
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -39,6 +40,9 @@
+ EXPORT_SYMBOL(snd_major);
+ 
+ static int cards_limit = 1;
++#ifdef CONFIG_DEVFS_FS
++static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
++#endif
+ 
+ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+ MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
+@@ -47,6 +51,10 @@
+ MODULE_PARM_DESC(major, "Major # for sound driver.");
+ module_param(cards_limit, int, 0444);
+ MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
++#ifdef CONFIG_DEVFS_FS
++module_param(device_mode, int, 0444);
++MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
++#endif
+ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
+ 
+ /* this one holds the actual max. card number currently available.
+@@ -180,7 +188,9 @@
+ 
+ static const struct file_operations snd_fops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.open =		snd_open
+ };
+ 
+@@ -256,7 +266,11 @@
+ 
+ 	if (snd_BUG_ON(!name))
+ 		return -EINVAL;
++#ifdef CONFIG_DEVFS_FS
++	preg = kmalloc(sizeof(*preg) + strlen(name) + 1, GFP_KERNEL);
++#else
+ 	preg = kmalloc(sizeof *preg, GFP_KERNEL);
++#endif
+ 	if (preg == NULL)
+ 		return -ENOMEM;
+ 	preg->type = type;
+@@ -264,6 +278,9 @@
+ 	preg->device = dev;
+ 	preg->f_ops = f_ops;
+ 	preg->private_data = private_data;
++#ifdef CONFIG_DEVFS_FS
++	strcpy((char *)(preg + 1), name);
++#endif
+ 	mutex_lock(&sound_mutex);
+ #ifdef CONFIG_SND_DYNAMIC_MINORS
+ 	minor = snd_find_free_minor();
+@@ -278,8 +295,23 @@
+ 		return minor;
+ 	}
+ 	snd_minors[minor] = preg;
++#ifdef CONFIG_DEVFS_FS
++	if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit)
++		devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode,
++			      "snd/%s", name);
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
++#ifdef CONFIG_SND_HAS_DEVICE_CREATE_DRVDATA
++	preg->dev = device_create_drvdata(sound_class, device,
++					  MKDEV(major, minor),
++					  private_data, "%s", name);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ 	preg->dev = device_create(sound_class, device, MKDEV(major, minor),
+ 				  private_data, "%s", name);
++#else
++  	preg->dev = device_create(sound_class, device, MKDEV(major, minor),
++  				  "%s", name);
++#endif /* SND_HAS_DEVICE_CREATE_DRVDATA */
+ 	if (IS_ERR(preg->dev)) {
+ 		snd_minors[minor] = NULL;
+ 		mutex_unlock(&sound_mutex);
+@@ -287,6 +319,22 @@
+ 		kfree(preg);
+ 		return minor;
+ 	}
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) && \
++	!defined(CONFIG_SND_HAS_DEVICE_CREATE_DRVDATA)
++  	if (preg->dev)
++  		dev_set_drvdata(preg->dev, private_data);
++#endif
++
++#elif defined(CONFIG_SND_HAVE_CLASS_SIMPLE)
++	class_simple_device_add((struct class_simple *)sound_class,
++				MKDEV(major, minor), device, name);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
++	preg->dev = (struct device *)class_device_create(sound_class, NULL,
++							 MKDEV(major, minor),
++						         device, "%s", name);
++	if (preg->dev)
++		class_set_devdata((struct class_device *)preg->dev, private_data);
++#endif /* 2.6.20 */
+ 
+ 	mutex_unlock(&sound_mutex);
+ 	return 0;
+@@ -326,6 +374,9 @@
+ int snd_unregister_device(int type, struct snd_card *card, int dev)
+ {
+ 	int minor;
++#ifdef CONFIG_DEVFS_FS
++	struct snd_minor *mptr;
++#endif
+ 
+ 	mutex_lock(&sound_mutex);
+ 	minor = find_snd_minor(type, card, dev);
+@@ -334,7 +385,20 @@
+ 		return -EINVAL;
+ 	}
+ 
++#ifdef CONFIG_DEVFS_FS
++	mptr = snd_minors[minor];
++	if (mptr->type != SNDRV_DEVICE_TYPE_CONTROL ||
++	    mptr->card >= cards_limit) /* created in sound.c */
++		devfs_remove("snd/%s", (char *)(mptr + 1));
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	device_destroy(sound_class, MKDEV(major, minor));
++#elif defined(CONFIG_SND_HAVE_CLASS_SIMPLE)
++	class_simple_device_remove(MKDEV(major, minor));
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
++	class_device_destroy(sound_class, MKDEV(major, minor));
++#endif
+ 
+ 	kfree(snd_minors[minor]);
+ 	snd_minors[minor] = NULL;
+@@ -347,16 +411,28 @@
+ int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
+ 			      struct device_attribute *attr)
+ {
++#if defined(CONFIG_SND_HAVE_CLASS_SIMPLE) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 2)
++	return -EINVAL;
++#else
+ 	int minor, ret = -EINVAL;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	struct device *d;
++#else
++	struct class_device *d;
++#endif
+ 
+ 	mutex_lock(&sound_mutex);
+ 	minor = find_snd_minor(type, card, dev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ 	if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
+ 		ret = device_create_file(d, attr);
++#else
++	if (minor >= 0 && (d = (struct class_device *)snd_minors[minor]->dev) != NULL)
++		ret = class_device_create_file(d, (const struct class_device_attribute *)attr);
++#endif
+ 	mutex_unlock(&sound_mutex);
+ 	return ret;
+-
++#endif
+ }
+ 
+ EXPORT_SYMBOL(snd_add_device_sysfs_file);
+@@ -442,31 +518,80 @@
+  *  INIT PART
+  */
+ 
++#ifdef CONFIG_SND_DEBUG_MEMORY
++extern void snd_memory_done(void);
++#else
++#define snd_memory_done()
++#endif
++#if defined(CONFIG_SND_DEBUG_MEMORY) && defined(CONFIG_PROC_FS)
++extern int snd_memory_info_init(void);
++extern void snd_memory_info_done(void);
++#else
++#define snd_memory_info_init()
++#define snd_memory_info_done()
++#endif
++
+ static int __init alsa_sound_init(void)
+ {
+ 	snd_major = major;
+ 	snd_ecards_limit = cards_limit;
++#ifdef CONFIG_DEVFS_FS
++	devfs_mk_dir("snd");
++#endif
+ 	if (register_chrdev(major, "alsa", &snd_fops)) {
+ 		snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
++#ifdef CONFIG_DEVFS_FS
++		devfs_remove("snd");
++#endif
+ 		return -EIO;
+ 	}
+ 	if (snd_info_init() < 0) {
+ 		unregister_chrdev(major, "alsa");
++		snd_memory_done();
+ 		return -ENOMEM;
+ 	}
++	snd_memory_info_init();
+ 	snd_info_minor_register();
++#ifdef CONFIG_DEVFS_FS
++	{
++		short controlnum;
++		for (controlnum = 0; controlnum < cards_limit; controlnum++)
++			devfs_mk_cdev(MKDEV(major, controlnum<<5),
++				      S_IFCHR | device_mode ,
++				      "snd/controlC%d", controlnum);
++	}
++#endif
+ #ifndef MODULE
+ 	printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
+ #endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
++	pm_init();
++#endif
+ 	return 0;
+ }
+ 
+ static void __exit alsa_sound_exit(void)
+ {
++#ifdef CONFIG_DEVFS_FS
++	short controlnum;
++	for (controlnum = 0; controlnum < cards_limit; controlnum++)
++		devfs_remove("snd/controlC%d", controlnum);
++#endif
++
+ 	snd_info_minor_unregister();
++	snd_memory_info_done();
+ 	snd_info_done();
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
++	pm_done();
++#endif
+ 	unregister_chrdev(major, "alsa");
++	snd_memory_done();
++#ifdef CONFIG_DEVFS_FS
++	devfs_remove("snd");
++#endif
+ }
+ 
+ module_init(alsa_sound_init)
+ module_exit(alsa_sound_exit)
++
++#include "sound.inc"
diff --git a/alsa/acore/sound_oss.c b/alsa/acore/sound_oss.c
new file mode 100644
index 0000000..f2a3c53
--- /dev/null
+++ b/alsa/acore/sound_oss.c
@@ -0,0 +1,6 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#ifndef CONFIG_HAVE_REGISTER_SOUND_SPECIAL_DEVICE
+#define register_sound_special_device(ops,unit,dev) register_sound_special(ops,unit)
+#endif
+#include "../alsa-kernel/core/sound_oss.c"
diff --git a/alsa/acore/timer.patch b/alsa/acore/timer.patch
new file mode 100644
index 0000000..049bfc9
--- /dev/null
+++ b/alsa/acore/timer.patch
@@ -0,0 +1,74 @@
+--- ../alsa-kernel/core/timer.c	2009-09-21 15:57:35.000000000 +0200
++++ timer.c	2009-12-15 22:17:50.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "adriver.h"
+ /*
+  *  Timers abstract layer
+  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+@@ -21,6 +22,7 @@
+ 
+ #include <linux/delay.h>
+ #include <linux/init.h>
++#include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+ #include <linux/mutex.h>
+@@ -995,7 +997,7 @@
+ static struct snd_timer_hardware snd_timer_system =
+ {
+ 	.flags =	SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
+-	.resolution =	1000000000L / HZ,
++	// .resolution =	1000000000L / HZ,
+ 	.ticks =	10000000L,
+ 	.start =	snd_timer_s_start,
+ 	.stop =		snd_timer_s_stop
+@@ -1909,21 +1911,40 @@
+ 	return mask;
+ }
+ 
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) && defined(CONFIG_SND_HAVE_NEW_IOCTL)
+ #include "timer_compat.c"
+ #else
+ #define snd_timer_user_ioctl_compat	NULL
+ #endif
+ 
++#ifndef CONFIG_SND_HAVE_NEW_IOCTL
++/* need to unlock BKL to allow preemption */
++static int snd_timer_user_ioctl_old(struct inode *inode, struct file * file,
++				    unsigned int cmd, unsigned long arg)
++{
++	int err;
++	unlock_kernel();
++	err = snd_timer_user_ioctl(file, cmd, arg);
++	lock_kernel();
++	return err;
++}
++#endif
++
+ static const struct file_operations snd_timer_f_ops =
+ {
++#ifndef LINUX_2_2
+ 	.owner =	THIS_MODULE,
++#endif
+ 	.read =		snd_timer_user_read,
+ 	.open =		snd_timer_user_open,
+ 	.release =	snd_timer_user_release,
+ 	.poll =		snd_timer_user_poll,
++#ifdef CONFIG_SND_HAVE_NEW_IOCTL
+ 	.unlocked_ioctl =	snd_timer_user_ioctl,
+ 	.compat_ioctl =	snd_timer_user_ioctl_compat,
++#else
++	.ioctl =	snd_timer_user_ioctl_old,
++#endif
+ 	.fasync = 	snd_timer_user_fasync,
+ };
+ 
+@@ -1935,6 +1956,7 @@
+ {
+ 	int err;
+ 
++	snd_timer_system.resolution = 1000000000L / HZ;
+ #ifdef SNDRV_OSS_INFO_DEV_TIMERS
+ 	snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
+ 			      "system timer");
diff --git a/alsa/acore/timer_compat.c b/alsa/acore/timer_compat.c
new file mode 100644
index 0000000..2ba9f98
--- /dev/null
+++ b/alsa/acore/timer_compat.c
@@ -0,0 +1 @@
+#include "../alsa-kernel/core/timer_compat.c"
diff --git a/alsa/acore/vmaster.c b/alsa/acore/vmaster.c
new file mode 100644
index 0000000..802512c
--- /dev/null
+++ b/alsa/acore/vmaster.c
@@ -0,0 +1,3 @@
+#define __NO_VERSION__
+#include "adriver.h"
+#include "../alsa-kernel/core/vmaster.c"
diff --git a/alsa/acore/wrappers.c b/alsa/acore/wrappers.c
new file mode 100644
index 0000000..ac45870
--- /dev/null
+++ b/alsa/acore/wrappers.c
@@ -0,0 +1,340 @@
+#define __NO_VERSION__
+#include "config.h"
+
+#include <linux/version.h>
+#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H
+#include <linux/autoconf.h>
+#else
+#include <linux/config.h>
+#endif
+#include <linux/string.h>
+#include <linux/sched.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__) && !defined(__DEPEND__)
+#include "sndversions.h"
+#endif
+#endif
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/devfs_fs_kernel.h>
+
+/* defined in adriver.h but we don't include it... */
+#include <linux/compiler.h>
+#ifndef __nocast
+#define __nocast
+#endif
+
+#ifndef CONFIG_HAVE_STRLCPY
+#define strlcat snd_compat_strlcat
+#ifndef BUG_ON
+#define BUG_ON(x) /* nothing */
+#endif
+size_t snd_compat_strlcat(char *dest, const char *src, size_t count)
+{
+	size_t dsize = strlen(dest);
+	size_t len = strlen(src);
+	size_t res = dsize + len;
+
+	/* This would be a bug */
+	BUG_ON(dsize >= count);
+
+	dest += dsize;
+	count -= dsize;
+	if (len >= count)
+		len = count-1;
+	memcpy(dest, src, len);
+	dest[len] = 0;
+	return res;
+}
+EXPORT_SYMBOL(snd_compat_strlcat);
+#endif
+
+#ifndef CONFIG_HAVE_VSNPRINTF
+#define vsnprintf snd_compat_vsnprintf
+int snd_compat_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+#endif
+
+#ifndef CONFIG_HAVE_SSCANF
+#include <linux/ctype.h>
+
+/* this function supports any format as long as it's %x  :-) */
+int snd_compat_vsscanf(const char *buf, const char *fmt, va_list args)
+{
+	const char *str = buf;
+	char *next;
+	int num = 0;
+	unsigned int *p;
+
+	while (*fmt && *str) {
+		while (isspace(*fmt))
+			++fmt;
+
+		if (!*fmt)
+			break;
+
+		if (fmt[0] != '%' || fmt[1] != 'x') {
+			printk(KERN_ERR "snd_compat_vsscanf: format isn't %%x\n");
+			return 0;
+		}
+		fmt += 2;
+
+		while (isspace(*str))
+			++str;
+
+		if (!*str || !isxdigit(*str))
+			break;
+
+		p = (unsigned int*) va_arg(args, unsigned int*);
+		*p = (unsigned int) simple_strtoul(str, &next, 0x10);
+		++num;
+
+		if (!next)
+			break;
+		str = next;
+	}
+	return num;
+}
+EXPORT_SYMBOL(snd_compat_vsscanf);
+
+int snd_compat_sscanf(const char *buf, const char *fmt, ...)
+{
+	int res;
+	va_list args;
+
+	va_start(args, fmt);
+	res = snd_compat_vsscanf(buf, fmt, args);
+	va_end(args);
+	return res;
+}
+EXPORT_SYMBOL(snd_compat_sscanf);
+#endif
+
+#ifdef CONFIG_HAVE_OLD_REQUEST_MODULE
+void snd_compat_request_module(const char *fmt, ...)
+{
+	char buf[64];
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n < 64 && buf[0])
+		request_module(buf);
+	va_end(args);
+}
+EXPORT_SYMBOL(snd_compat_request_module);
+#endif
+
+#if defined(CONFIG_DEVFS_FS)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 29)
+
+void snd_compat_devfs_remove(const char *fmt, ...)
+{
+	char buf[64];
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n < 64 && buf[0]) {
+		devfs_handle_t de = devfs_get_handle(NULL, buf, 0, 0, 0, 0);
+		devfs_unregister(de);
+		devfs_put(de);
+	}
+	va_end(args);
+}
+EXPORT_SYMBOL(snd_compat_devfs_remove);
+
+#endif /* 2.5.29 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 67)
+
+int snd_compat_devfs_mk_dir(const char *dir, ...)
+{
+	char buf[64];
+	va_list args;
+	int n;
+
+	va_start(args, dir);
+	n = vsnprintf(buf, 64, dir, args);
+	va_end(args);
+	if (n < 64 && buf[0]) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+		return devfs_mk_dir(NULL, buf, strlen(dir), NULL) ? -EIO : 0;
+#else
+		return devfs_mk_dir(NULL, buf, NULL) ? -EIO : 0;
+#endif
+	}
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_devfs_mk_dir);
+
+extern struct file_operations snd_fops;
+int snd_compat_devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	char buf[64];
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	va_end(args);
+	if (n < 64 && buf[0]) {
+		devfs_register(NULL, buf, DEVFS_FL_DEFAULT,
+			       major(dev), minor(dev), mode,
+			       &snd_fops, NULL);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(snd_compat_devfs_mk_cdev);
+
+#endif /* 2.5.67 */
+
+#endif /* CONFIG_DEVFS_FS */
+
+#ifndef CONFIG_HAVE_PCI_DEV_PRESENT
+#include <linux/pci.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+/* for pci_device_id compatibility layer */
+#include "compat_22.h"
+#endif
+int snd_pci_dev_present(const struct pci_device_id *ids)
+{
+	while (ids->vendor || ids->subvendor) {
+		if (pci_find_device(ids->vendor, ids->subvendor, NULL))
+			return 1;
+		ids++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(snd_pci_dev_present);
+#endif
+
+/*
+ * msleep wrapper
+ */
+#ifndef CONFIG_HAVE_MSLEEP
+#include <linux/delay.h>
+void snd_compat_msleep(unsigned int msecs)
+{
+	unsigned long timeout = ((msecs) * HZ + 999) / 1000;
+
+	while (timeout) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+	}
+}
+EXPORT_SYMBOL(snd_compat_msleep);
+#endif
+
+#ifndef CONFIG_HAVE_MSLEEP_INTERRUPTIBLE
+#include <linux/delay.h>
+unsigned long snd_compat_msleep_interruptible(unsigned int msecs)
+{
+	unsigned long timeout = ((msecs) * HZ + 999) / 1000;
+
+	while (timeout && !signal_pending(current)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+	}
+	return (timeout * 1000) / HZ;
+}
+EXPORT_SYMBOL(snd_compat_msleep_interruptible);
+#endif /* < 2.6.6 */
+
+/* wrapper for new irq handler type */
+#ifndef CONFIG_SND_NEW_IRQ_HANDLER
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+typedef int (*snd_irq_handler_t)(int, void *);
+struct irq_list {
+	snd_irq_handler_t handler;
+	int irq;
+	void *data;
+	struct list_head list;
+};
+	
+struct pt_regs *snd_irq_regs;
+EXPORT_SYMBOL(snd_irq_regs);
+
+#if defined(IRQ_NONE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static irqreturn_t irq_redirect(int irq, void *data, struct pt_regs *reg)
+{
+	struct irq_list *list = data;
+	irqreturn_t val;
+	snd_irq_regs = reg;
+	val = list->handler(irq, list->data);
+	snd_irq_regs = NULL;
+	return val;
+}
+#else
+static void irq_redirect(int irq, void *data, struct pt_regs *reg)
+{
+	struct irq_list *list = data;
+	snd_irq_regs = reg;
+	list->handler(irq, list->data);
+	snd_irq_regs = NULL;
+}
+#endif
+
+static LIST_HEAD(irq_list_head);
+static DEFINE_MUTEX(irq_list_mutex);
+
+int snd_request_irq(unsigned int irq, snd_irq_handler_t handler,
+		    unsigned long irq_flags, const char *str, void *data)
+{
+	struct irq_list *list = kmalloc(sizeof(*list), GFP_KERNEL);
+	int err;
+
+	if (!list)
+		return -ENOMEM;
+	list->handler = handler;
+	list->irq = irq;
+	list->data = data;
+	err = request_irq(irq, irq_redirect, irq_flags, str, list);
+	if (err) {
+		kfree(list);
+		return err;
+	}
+	mutex_lock(&irq_list_mutex);
+	list_add(&list->list, &irq_list_head);
+	mutex_unlock(&irq_list_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(snd_request_irq);
+
+void snd_free_irq(unsigned int irq, void *data)
+{
+	struct list_head *p;
+
+	mutex_lock(&irq_list_mutex);
+	list_for_each(p, &irq_list_head) {
+		struct irq_list *list = list_entry(p, struct irq_list, list);
+		if (list->irq == irq && list->data == data) {
+			free_irq(irq, list);
+			list_del(p);
+			kfree(list);
+			break;
+		}
+	}
+	mutex_unlock(&irq_list_mutex);
+}
+EXPORT_SYMBOL(snd_free_irq);
+#endif /* !CONFIG_SND_NEW_IRQ_HANDLER */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+#include <linux/ctype.h>
+
+char *compat_skip_spaces(const char *str)
+{
+	while (isspace(*str))
+		++str;
+	return (char *)str;
+}
+EXPORT_SYMBOL(compat_skip_spaces);
+#endif /* < 2.6.33 */
diff --git a/alsa/aoa/Makefile b/alsa/aoa/Makefile
new file mode 100644
index 0000000..a2c766a
--- /dev/null
+++ b/alsa/aoa/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/codecs/Makefile b/alsa/aoa/codecs/Makefile
new file mode 100644
index 0000000..b9f801b
--- /dev/null
+++ b/alsa/aoa/codecs/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/codecs/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/codecs/onyx.c b/alsa/aoa/codecs/onyx.c
new file mode 100644
index 0000000..68a7d32
--- /dev/null
+++ b/alsa/aoa/codecs/onyx.c
@@ -0,0 +1,6 @@
+#include "ppc-prom-hack.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+#include "onyx_old_i2c.c"
+#else
+#include "../../alsa-kernel/aoa/codecs/onyx.c"
+#endif
diff --git a/alsa/aoa/codecs/onyx_old_i2c.c b/alsa/aoa/codecs/onyx_old_i2c.c
new file mode 100644
index 0000000..b600925
--- /dev/null
+++ b/alsa/aoa/codecs/onyx_old_i2c.c
@@ -0,0 +1,1118 @@
+/*
+ * Apple Onboard Audio driver for Onyx codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This is a driver for the pcm3052 codec chip (codenamed Onyx)
+ * that is present in newer Apple hardware (with digital output).
+ *
+ * The Onyx codec has the following connections (listed by the bit
+ * to be used in aoa_codec.connected):
+ *  0: analog output
+ *  1: digital output
+ *  2: line input
+ *  3: microphone input
+ * Note that even though I know of no machine that has for example
+ * the digital output connected but not the analog, I have handled
+ * all the different cases in the code so that this driver may serve
+ * as a good example of what to do.
+ *
+ * NOTE: This driver assumes that there's at most one chip to be
+ * 	 used with one alsa card, in form of creating all kinds
+ *	 of mixer elements without regard for their existence.
+ *	 But snd-aoa assumes that there's at most one card, so
+ *	 this means you can only have one onyx on a system. This
+ *	 should probably be fixed by changing the assumption of
+ *	 having just a single card on a system, and making the
+ *	 'card' pointer accessible to anyone who needs it instead
+ *	 of hiding it in the aoa_snd_* functions...
+ *
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
+
+#include "../../alsa-kernel/aoa/codecs/onyx.h"
+#include "../../alsa-kernel/aoa/aoa.h"
+#include "../../alsa-kernel/aoa/soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-onyx: "
+
+struct onyx {
+	/* cache registers 65 to 80, they are write-only! */
+	u8			cache[16];
+	struct i2c_client	i2c;
+	struct aoa_codec	codec;
+	u32			initialised:1,
+				spdif_locked:1,
+				analog_locked:1,
+				original_mute:2;
+	int			open_count;
+	struct codec_info	*codec_info;
+
+	/* mutex serializes concurrent access to the device
+	 * and this structure.
+	 */
+	struct mutex mutex;
+};
+#define codec_to_onyx(c) container_of(c, struct onyx, codec)
+
+/* both return 0 if all ok, else on error */
+static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
+{
+	s32 v;
+
+	if (reg != ONYX_REG_CONTROL) {
+		*value = onyx->cache[reg-FIRSTREGISTER];
+		return 0;
+	}
+	v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
+	if (v < 0)
+		return -1;
+	*value = (u8)v;
+	onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
+	return 0;
+}
+
+static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
+{
+	int result;
+
+	result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
+	if (!result)
+		onyx->cache[reg-FIRSTREGISTER] = value;
+	return result;
+}
+
+/* alsa stuff */
+
+static int onyx_dev_register(struct snd_device *dev)
+{
+	return 0;
+}
+
+static struct snd_device_ops ops = {
+	.dev_register = onyx_dev_register,
+};
+
+/* this is necessary because most alsa mixer programs
+ * can't properly handle the negative range */
+#define VOLUME_RANGE_SHIFT	128
+
+static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
+	uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
+	return 0;
+}
+
+static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 l, r;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
+	ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
+
+	return 0;
+}
+
+static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 l, r;
+
+	if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT ||
+	    ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT)
+		return -EINVAL;
+	if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT ||
+	    ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)
+		return -EINVAL;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+
+	if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
+	    r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
+		mutex_unlock(&onyx->mutex);
+		return 0;
+	}
+
+	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
+			    ucontrol->value.integer.value[0]
+			     - VOLUME_RANGE_SHIFT);
+	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
+			    ucontrol->value.integer.value[1]
+			     - VOLUME_RANGE_SHIFT);
+	mutex_unlock(&onyx->mutex);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_vol_info,
+	.get = onyx_snd_vol_get,
+	.put = onyx_snd_vol_put,
+};
+
+/* like above, this is necessary because a lot
+ * of alsa mixer programs don't handle ranges
+ * that don't start at 0 properly.
+ * even alsamixer is one of them... */
+#define INPUTGAIN_RANGE_SHIFT	(-3)
+
+static int onyx_snd_inputgain_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 = 3 + INPUTGAIN_RANGE_SHIFT;
+	uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
+	return 0;
+}
+
+static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 ig;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] =
+		(ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
+
+	return 0;
+}
+
+static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v, n;
+
+	if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT ||
+	    ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT)
+		return -EINVAL;
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	n = v;
+	n &= ~ONYX_ADC_PGA_GAIN_MASK;
+	n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
+		& ONYX_ADC_PGA_GAIN_MASK;
+	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
+	mutex_unlock(&onyx->mutex);
+
+	return n != v;
+}
+
+static struct snd_kcontrol_new inputgain_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Capture Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_inputgain_info,
+	.get = onyx_snd_inputgain_get,
+	.put = onyx_snd_inputgain_put,
+};
+
+static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Line-In", "Microphone" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
+
+	return 0;
+}
+
+static void onyx_set_capture_source(struct onyx *onyx, int mic)
+{
+	s8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	v &= ~ONYX_ADC_INPUT_MIC;
+	if (mic)
+		v |= ONYX_ADC_INPUT_MIC;
+	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
+	mutex_unlock(&onyx->mutex);
+}
+
+static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	if (ucontrol->value.enumerated.item[0] > 1)
+		return -EINVAL;
+	onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
+				ucontrol->value.enumerated.item[0]);
+	return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* If we name this 'Input Source', it properly shows up in
+	 * alsamixer as a selection, * but it's shown under the
+	 * 'Playback' category.
+	 * If I name it 'Capture Source', it shows up in strange
+	 * ways (two bools of which one can be selected at a
+	 * time) but at least it's shown in the 'Capture'
+	 * category.
+	 * I was told that this was due to backward compatibility,
+	 * but I don't understand then why the mangling is *not*
+	 * done when I name it "Input Source".....
+	 */
+	.name = "Capture Source",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_capture_source_info,
+	.get = onyx_snd_capture_source_get,
+	.put = onyx_snd_capture_source_put,
+};
+
+#define onyx_snd_mute_info	snd_ctl_boolean_stereo_info
+
+static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 c;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
+	ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
+
+	return 0;
+}
+
+static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v = 0, c = 0;
+	int err = -EBUSY;
+
+	mutex_lock(&onyx->mutex);
+	if (onyx->analog_locked)
+		goto out_unlock;
+
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+	c = v;
+	c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
+	if (!ucontrol->value.integer.value[0])
+		c |= ONYX_MUTE_LEFT;
+	if (!ucontrol->value.integer.value[1])
+		c |= ONYX_MUTE_RIGHT;
+	err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return !err ? (v != c) : err;
+}
+
+static struct snd_kcontrol_new mute_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Switch",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_mute_info,
+	.get = onyx_snd_mute_get,
+	.put = onyx_snd_mute_put,
+};
+
+
+#define onyx_snd_single_bit_info	snd_ctl_boolean_mono_info
+
+#define FLAG_POLARITY_INVERT	1
+#define FLAG_SPDIFLOCK		2
+
+static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 c;
+	long int pv = kcontrol->private_value;
+	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+	u8 address = (pv >> 8) & 0xff;
+	u8 mask = pv & 0xff;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, address, &c);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
+
+	return 0;
+}
+
+static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v = 0, c = 0;
+	int err;
+	long int pv = kcontrol->private_value;
+	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+	u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
+	u8 address = (pv >> 8) & 0xff;
+	u8 mask = pv & 0xff;
+
+	mutex_lock(&onyx->mutex);
+	if (spdiflock && onyx->spdif_locked) {
+		/* even if alsamixer doesn't care.. */
+		err = -EBUSY;
+		goto out_unlock;
+	}
+	onyx_read_register(onyx, address, &v);
+	c = v;
+	c &= ~(mask);
+	if (!!ucontrol->value.integer.value[0] ^ polarity)
+		c |= mask;
+	err = onyx_write_register(onyx, address, c);
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return !err ? (v != c) : err;
+}
+
+#define SINGLE_BIT(n, type, description, address, mask, flags)	 	\
+static struct snd_kcontrol_new n##_control = {				\
+	.iface = SNDRV_CTL_ELEM_IFACE_##type,				\
+	.name = description,						\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,			\
+	.info = onyx_snd_single_bit_info,				\
+	.get = onyx_snd_single_bit_get,					\
+	.put = onyx_snd_single_bit_put,					\
+	.private_value = (flags << 16) | (address << 8) | mask		\
+}
+
+SINGLE_BIT(spdif,
+	   MIXER,
+	   SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
+	   ONYX_REG_DIG_INFO4,
+	   ONYX_SPDIF_ENABLE,
+	   FLAG_SPDIFLOCK);
+SINGLE_BIT(ovr1,
+	   MIXER,
+	   "Oversampling Rate",
+	   ONYX_REG_DAC_CONTROL,
+	   ONYX_OVR1,
+	   0);
+SINGLE_BIT(flt0,
+	   MIXER,
+	   "Fast Digital Filter Rolloff",
+	   ONYX_REG_DAC_FILTER,
+	   ONYX_ROLLOFF_FAST,
+	   FLAG_POLARITY_INVERT);
+SINGLE_BIT(hpf,
+	   MIXER,
+	   "Highpass Filter",
+	   ONYX_REG_ADC_HPF_BYPASS,
+	   ONYX_HPF_DISABLE,
+	   FLAG_POLARITY_INVERT);
+SINGLE_BIT(dm12,
+	   MIXER,
+	   "Digital De-Emphasis",
+	   ONYX_REG_DAC_DEEMPH,
+	   ONYX_DIGDEEMPH_CTRL,
+	   0);
+
+static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	/* datasheet page 30, all others are 0 */
+	ucontrol->value.iec958.status[0] = 0x3e;
+	ucontrol->value.iec958.status[1] = 0xff;
+
+	ucontrol->value.iec958.status[3] = 0x3f;
+	ucontrol->value.iec958.status[4] = 0x0f;
+
+	return 0;
+}
+
+static struct snd_kcontrol_new onyx_spdif_mask = {
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+	.info =		onyx_spdif_info,
+	.get =		onyx_spdif_mask_get,
+};
+
+static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+	ucontrol->value.iec958.status[0] = v & 0x3e;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
+	ucontrol->value.iec958.status[1] = v;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+	ucontrol->value.iec958.status[3] = v & 0x3f;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	ucontrol->value.iec958.status[4] = v & 0x0f;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+	v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
+
+	v = ucontrol->value.iec958.status[1];
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+	v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+	mutex_unlock(&onyx->mutex);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new onyx_spdif_ctrl = {
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+	.info =		onyx_spdif_info,
+	.get =		onyx_spdif_get,
+	.put =		onyx_spdif_put,
+};
+
+/* our registers */
+
+static u8 register_map[] = {
+	ONYX_REG_DAC_ATTEN_LEFT,
+	ONYX_REG_DAC_ATTEN_RIGHT,
+	ONYX_REG_CONTROL,
+	ONYX_REG_DAC_CONTROL,
+	ONYX_REG_DAC_DEEMPH,
+	ONYX_REG_DAC_FILTER,
+	ONYX_REG_DAC_OUTPHASE,
+	ONYX_REG_ADC_CONTROL,
+	ONYX_REG_ADC_HPF_BYPASS,
+	ONYX_REG_DIG_INFO1,
+	ONYX_REG_DIG_INFO2,
+	ONYX_REG_DIG_INFO3,
+	ONYX_REG_DIG_INFO4
+};
+
+static u8 initial_values[ARRAY_SIZE(register_map)] = {
+	0x80, 0x80, /* muted */
+	ONYX_MRST | ONYX_SRST, /* but handled specially! */
+	ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
+	0, /* no deemphasis */
+	ONYX_DAC_FILTER_ALWAYS,
+	ONYX_OUTPHASE_INVERTED,
+	(-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
+	ONYX_ADC_HPF_ALWAYS,
+	(1<<2),	/* pcm audio */
+	2,	/* category: pcm coder */
+	0,	/* sampling frequency 44.1 kHz, clock accuracy level II */
+	1	/* 24 bit depth */
+};
+
+/* reset registers of chip, either to initial or to previous values */
+static int onyx_register_init(struct onyx *onyx)
+{
+	int i;
+	u8 val;
+	u8 regs[sizeof(initial_values)];
+
+	if (!onyx->initialised) {
+		memcpy(regs, initial_values, sizeof(initial_values));
+		if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
+			return -1;
+		val &= ~ONYX_SILICONVERSION;
+		val |= initial_values[3];
+		regs[3] = val;
+	} else {
+		for (i=0; i<sizeof(register_map); i++)
+			regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
+	}
+
+	for (i=0; i<sizeof(register_map); i++) {
+		if (onyx_write_register(onyx, register_map[i], regs[i]))
+			return -1;
+	}
+	onyx->initialised = 1;
+	return 0;
+}
+
+static struct transfer_info onyx_transfers[] = {
+	/* this is first so we can skip it if no input is present...
+	 * No hardware exists with that, but it's here as an example
+	 * of what to do :) */
+	{
+		/* analog input */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.transfer_in = 1,
+		.must_be_clock_source = 0,
+		.tag = 0,
+	},
+	{
+		/* if analog and digital are currently off, anything should go,
+		 * so this entry describes everything we can do... */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+			   | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+#endif
+		,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.tag = 0,
+	},
+	{
+		/* analog output */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.transfer_in = 0,
+		.must_be_clock_source = 0,
+		.tag = 1,
+	},
+	{
+		/* digital pcm output, also possible for analog out */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000,
+		.transfer_in = 0,
+		.must_be_clock_source = 0,
+		.tag = 2,
+	},
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+	/* Once alsa gets supports for this kind of thing we can add it... */
+	{
+		/* digital compressed output */
+		.formats =  SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000,
+		.tag = 2,
+	},
+#endif
+	{}
+};
+
+static int onyx_usable(struct codec_info_item *cii,
+		       struct transfer_info *ti,
+		       struct transfer_info *out)
+{
+	u8 v;
+	struct onyx *onyx = cii->codec_data;
+	int spdif_enabled, analog_enabled;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+	analog_enabled =
+		(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
+		 != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
+	mutex_unlock(&onyx->mutex);
+
+	switch (ti->tag) {
+	case 0: return 1;
+	case 1:	return analog_enabled;
+	case 2: return spdif_enabled;
+	}
+	return 1;
+}
+
+static int onyx_prepare(struct codec_info_item *cii,
+			struct bus_info *bi,
+			struct snd_pcm_substream *substream)
+{
+	u8 v;
+	struct onyx *onyx = cii->codec_data;
+	int err = -EBUSY;
+
+	mutex_lock(&onyx->mutex);
+
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+	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,
+					ONYX_REG_DAC_CONTROL,
+					v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
+			goto out_unlock;
+		onyx->analog_locked = 1;
+		err = 0;
+		goto out_unlock;
+	}
+#endif
+	switch (substream->runtime->rate) {
+	case 32000:
+	case 44100:
+	case 48000:
+		/* these rates are ok for all outputs */
+		/* FIXME: program spdif channel control bits here so that
+		 *	  userspace doesn't have to if it only plays pcm! */
+		err = 0;
+		goto out_unlock;
+	default:
+		/* got some rate that the digital output can't do,
+		 * so disable and lock it */
+		onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
+		if (onyx_write_register(onyx,
+					ONYX_REG_DIG_INFO4,
+					v & ~ONYX_SPDIF_ENABLE))
+			goto out_unlock;
+		onyx->spdif_locked = 1;
+		err = 0;
+		goto out_unlock;
+	}
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+static int onyx_open(struct codec_info_item *cii,
+		     struct snd_pcm_substream *substream)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	onyx->open_count++;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_close(struct codec_info_item *cii,
+		      struct snd_pcm_substream *substream)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	onyx->open_count--;
+	if (!onyx->open_count)
+		onyx->spdif_locked = onyx->analog_locked = 0;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_switch_clock(struct codec_info_item *cii,
+			     enum clock_switch what)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	/* this *MUST* be more elaborate later... */
+	switch (what) {
+	case CLOCK_SWITCH_PREPARE_SLAVE:
+		onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
+		break;
+	case CLOCK_SWITCH_SLAVE:
+		onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
+		break;
+	default: /* silence warning */
+		break;
+	}
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+	struct onyx *onyx = cii->codec_data;
+	u8 v;
+	int err = -ENXIO;
+
+	mutex_lock(&onyx->mutex);
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+		goto out_unlock;
+	onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
+	/* Apple does a sleep here but the datasheet says to do it on resume */
+	err = 0;
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+static int onyx_resume(struct codec_info_item *cii)
+{
+	struct onyx *onyx = cii->codec_data;
+	u8 v;
+	int err = -ENXIO;
+
+	mutex_lock(&onyx->mutex);
+
+	/* reset codec */
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+
+	/* take codec out of suspend (if it still is after reset) */
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+		goto out_unlock;
+	onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
+	/* FIXME: should divide by sample rate, but 8k is the lowest we go */
+	msleep(2205000/8000);
+	/* reset all values */
+	onyx_register_init(onyx);
+	err = 0;
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+#endif /* CONFIG_PM */
+
+static struct codec_info onyx_codec_info = {
+	.transfers = onyx_transfers,
+	.sysclock_factor = 256,
+	.bus_factor = 64,
+	.owner = THIS_MODULE,
+	.usable = onyx_usable,
+	.prepare = onyx_prepare,
+	.open = onyx_open,
+	.close = onyx_close,
+	.switch_clock = onyx_switch_clock,
+#ifdef CONFIG_PM
+	.suspend = onyx_suspend,
+	.resume = onyx_resume,
+#endif
+};
+
+static int onyx_init_codec(struct aoa_codec *codec)
+{
+	struct onyx *onyx = codec_to_onyx(codec);
+	struct snd_kcontrol *ctl;
+	struct codec_info *ci = &onyx_codec_info;
+	u8 v;
+	int err;
+
+	if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
+		printk(KERN_ERR PFX "gpios not assigned!!\n");
+		return -EINVAL;
+	}
+
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+
+	if (onyx_register_init(onyx)) {
+		printk(KERN_ERR PFX "failed to initialise onyx registers\n");
+		return -ENODEV;
+	}
+
+	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) {
+		printk(KERN_ERR PFX "failed to create onyx snd device!\n");
+		return -ENODEV;
+	}
+
+	/* nothing connected? what a joke! */
+	if ((onyx->codec.connected & 0xF) == 0)
+		return -ENOTCONN;
+
+	/* if no inputs are present... */
+	if ((onyx->codec.connected & 0xC) == 0) {
+		if (!onyx->codec_info)
+			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+		if (!onyx->codec_info)
+			return -ENOMEM;
+		ci = onyx->codec_info;
+		*ci = onyx_codec_info;
+		ci->transfers++;
+	}
+
+	/* if no outputs are present... */
+	if ((onyx->codec.connected & 3) == 0) {
+		if (!onyx->codec_info)
+			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+		if (!onyx->codec_info)
+			return -ENOMEM;
+		ci = onyx->codec_info;
+		/* this is fine as there have to be inputs
+		 * if we end up in this part of the code */
+		*ci = onyx_codec_info;
+		ci->transfers[1].formats = 0;
+	}
+
+	if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
+						   aoa_get_card(),
+						   ci, onyx)) {
+		printk(KERN_ERR PFX "error creating onyx pcm\n");
+		return -ENODEV;
+	}
+#define ADDCTL(n)							\
+	do {								\
+		ctl = snd_ctl_new1(&n, onyx);				\
+		if (ctl) {						\
+			ctl->id.device =				\
+				onyx->codec.soundbus_dev->pcm->device;	\
+			err = aoa_snd_ctl_add(ctl);			\
+			if (err)					\
+				goto error;				\
+		}							\
+	} while (0)
+
+	if (onyx->codec.soundbus_dev->pcm) {
+		/* give the user appropriate controls
+		 * depending on what inputs are connected */
+		if ((onyx->codec.connected & 0xC) == 0xC)
+			ADDCTL(capture_source_control);
+		else if (onyx->codec.connected & 4)
+			onyx_set_capture_source(onyx, 0);
+		else
+			onyx_set_capture_source(onyx, 1);
+		if (onyx->codec.connected & 0xC)
+			ADDCTL(inputgain_control);
+
+		/* depending on what output is connected,
+		 * give the user appropriate controls */
+		if (onyx->codec.connected & 1) {
+			ADDCTL(volume_control);
+			ADDCTL(mute_control);
+			ADDCTL(ovr1_control);
+			ADDCTL(flt0_control);
+			ADDCTL(hpf_control);
+			ADDCTL(dm12_control);
+			/* spdif control defaults to off */
+		}
+		if (onyx->codec.connected & 2) {
+			ADDCTL(onyx_spdif_mask);
+			ADDCTL(onyx_spdif_ctrl);
+		}
+		if ((onyx->codec.connected & 3) == 3)
+			ADDCTL(spdif_control);
+		/* if only S/PDIF is connected, enable it unconditionally */
+		if ((onyx->codec.connected & 3) == 2) {
+			onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+			v |= ONYX_SPDIF_ENABLE;
+			onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+		}
+	}
+#undef ADDCTL
+	printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
+
+	return 0;
+ error:
+	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+	snd_device_free(aoa_get_card(), onyx);
+	return err;
+}
+
+static void onyx_exit_codec(struct aoa_codec *codec)
+{
+	struct onyx *onyx = codec_to_onyx(codec);
+
+	if (!onyx->codec.soundbus_dev) {
+		printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
+		return;
+	}
+	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+}
+
+static struct i2c_driver onyx_driver;
+
+static int onyx_create(struct i2c_adapter *adapter,
+		       struct device_node *node,
+		       int addr)
+{
+	struct onyx *onyx;
+	u8 dummy;
+
+	onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
+
+	if (!onyx)
+		return -ENOMEM;
+
+	mutex_init(&onyx->mutex);
+	onyx->i2c.driver = &onyx_driver;
+	onyx->i2c.adapter = adapter;
+	onyx->i2c.addr = addr & 0x7f;
+	strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE);
+
+	if (i2c_attach_client(&onyx->i2c)) {
+		printk(KERN_ERR PFX "failed to attach to i2c\n");
+		goto fail;
+	}
+
+	/* we try to read from register ONYX_REG_CONTROL
+	 * to check if the codec is present */
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
+		i2c_detach_client(&onyx->i2c);
+		printk(KERN_ERR PFX "failed to read control register\n");
+		goto fail;
+	}
+
+	strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
+	onyx->codec.owner = THIS_MODULE;
+	onyx->codec.init = onyx_init_codec;
+	onyx->codec.exit = onyx_exit_codec;
+	onyx->codec.node = of_node_get(node);
+
+	if (aoa_codec_register(&onyx->codec)) {
+		i2c_detach_client(&onyx->i2c);
+		goto fail;
+	}
+	printk(KERN_DEBUG PFX "created and attached onyx instance\n");
+	return 0;
+ fail:
+	kfree(onyx);
+	return -EINVAL;
+}
+
+static int onyx_i2c_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+		if (of_device_is_compatible(dev, "pcm3052")) {
+			const u32 *addr;
+			printk(KERN_DEBUG PFX "found pcm3052\n");
+			addr = of_get_property(dev, "reg", NULL);
+			if (!addr)
+				return -ENODEV;
+			return onyx_create(adapter, dev, (*addr)>>1);
+		}
+	}
+
+	/* if that didn't work, try desperate mode for older
+	 * machines that have stuff missing from the device tree */
+
+	if (!of_device_is_compatible(busnode, "k2-i2c"))
+		return -ENODEV;
+
+	printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
+	/* probe both possible addresses for the onyx chip */
+	if (onyx_create(adapter, NULL, 0x46) == 0)
+		return 0;
+	return onyx_create(adapter, NULL, 0x47);
+}
+
+static int onyx_i2c_detach(struct i2c_client *client)
+{
+	struct onyx *onyx = container_of(client, struct onyx, i2c);
+	int err;
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+	aoa_codec_unregister(&onyx->codec);
+	of_node_put(onyx->codec.node);
+	if (onyx->codec_info)
+		kfree(onyx->codec_info);
+	kfree(onyx);
+	return 0;
+}
+
+static struct i2c_driver onyx_driver = {
+	.driver = {
+		.name = "aoa_codec_onyx",
+		.owner = THIS_MODULE,
+	},
+	.attach_adapter = onyx_i2c_attach,
+	.detach_client = onyx_i2c_detach,
+};
+
+static int __init onyx_init(void)
+{
+	return i2c_add_driver(&onyx_driver);
+}
+
+static void __exit onyx_exit(void)
+{
+	i2c_del_driver(&onyx_driver);
+}
+
+module_init(onyx_init);
+module_exit(onyx_exit);
diff --git a/alsa/aoa/codecs/tas.c b/alsa/aoa/codecs/tas.c
new file mode 100644
index 0000000..36649ca
--- /dev/null
+++ b/alsa/aoa/codecs/tas.c
@@ -0,0 +1,6 @@
+#include "ppc-prom-hack.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+#include "tas_old_i2c.c"
+#else
+#include "../../alsa-kernel/aoa/codecs/tas.c"
+#endif
diff --git a/alsa/aoa/codecs/tas_old_i2c.c b/alsa/aoa/codecs/tas_old_i2c.c
new file mode 100644
index 0000000..f890bdf
--- /dev/null
+++ b/alsa/aoa/codecs/tas_old_i2c.c
@@ -0,0 +1,1012 @@
+/*
+ * Apple Onboard Audio driver for tas codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ * Open questions:
+ *  - How to distinguish between 3004 and versions?
+ *
+ * FIXMEs:
+ *  - This codec driver doesn't honour the 'connected'
+ *    property of the aoa_codec struct, hence if
+ *    it is used in machines where not everything is
+ *    connected it will display wrong mixer elements.
+ *  - Driver assumes that the microphone is always
+ *    monaureal and connected to the right channel of
+ *    the input. This should also be a codec-dependent
+ *    flag, maybe the codec should have 3 different
+ *    bits for the three different possibilities how
+ *    it can be hooked up...
+ *    But as long as I don't see any hardware hooked
+ *    up that way...
+ *  - As Apple notes in their code, the tas3004 seems
+ *    to delay the right channel by one sample. You can
+ *    see this when for example recording stereo in
+ *    audacity, or recording the tas output via cable
+ *    on another machine (use a sinus generator or so).
+ *    I tried programming the BiQuads but couldn't
+ *    make the delay work, maybe someone can read the
+ *    datasheet and fix it. The relevant Apple comment
+ *    is in AppleTAS3004Audio.cpp lines 1637 ff. Note
+ *    that their comment describing how they program
+ *    the filters sucks...
+ *
+ * Other things:
+ *  - this should actually register *two* aoa_codec
+ *    structs since it has two inputs. Then it must
+ *    use the prepare callback to forbid running the
+ *    secondary output on a different clock.
+ *    Also, whatever bus knows how to do this must
+ *    provide two soundbus_dev devices and the fabric
+ *    must be able to link them correctly.
+ *
+ *    I don't even know if Apple ever uses the second
+ *    port on the tas3004 though, I don't think their
+ *    i2s controllers can even do it. OTOH, they all
+ *    derive the clocks from common clocks, so it
+ *    might just be possible. The framework allows the
+ *    codec to refine the transfer_info items in the
+ *    usable callback, so we can simply remove the
+ *    rates the second instance is not using when it
+ *    actually is in use.
+ *    Maybe we'll need to make the sound busses have
+ *    a 'clock group id' value so the codec can
+ *    determine if the two outputs can be driven at
+ *    the same time. But that is likely overkill, up
+ *    to the fabric to not link them up incorrectly,
+ *    and up to the hardware designer to not wire
+ *    them up in some weird unusable way.
+ */
+#include <stddef.h>
+#include <linux/i2c.h>
+#include <asm/pmac_low_i2c.h>
+#include <asm/prom.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("tas codec driver for snd-aoa");
+
+#include "../../alsa-kernel/aoa/codecs/tas.h"
+#include "../../alsa-kernel/aoa/codecs/tas-gain-table.h"
+#include "../../alsa-kernel/aoa/codecs/tas-basstreble.h"
+#include "../../alsa-kernel/aoa/aoa.h"
+#include "../../alsa-kernel/aoa/soundbus/soundbus.h"
+
+#define PFX "snd-aoa-codec-tas: "
+
+
+struct tas {
+	struct aoa_codec	codec;
+	struct i2c_client	i2c;
+	u32			mute_l:1, mute_r:1 ,
+				controls_created:1 ,
+				drc_enabled:1,
+				hw_enabled:1;
+	u8			cached_volume_l, cached_volume_r;
+	u8			mixer_l[3], mixer_r[3];
+	u8			bass, treble;
+	u8			acr;
+	int			drc_range;
+	/* protects hardware access against concurrency from
+	 * userspace when hitting controls and during
+	 * codec init/suspend/resume */
+	struct mutex		mtx;
+};
+
+static int tas_reset_init(struct tas *tas);
+
+static struct tas *codec_to_tas(struct aoa_codec *codec)
+{
+	return container_of(codec, struct tas, codec);
+}
+
+static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
+{
+	if (len == 1)
+		return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
+	else
+		return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
+}
+
+static void tas3004_set_drc(struct tas *tas)
+{
+	unsigned char val[6];
+
+	if (tas->drc_enabled)
+		val[0] = 0x50; /* 3:1 above threshold */
+	else
+		val[0] = 0x51; /* disabled */
+	val[1] = 0x02; /* 1:1 below threshold */
+	if (tas->drc_range > 0xef)
+		val[2] = 0xef;
+	else if (tas->drc_range < 0)
+		val[2] = 0x00;
+	else
+		val[2] = tas->drc_range;
+	val[3] = 0xb0;
+	val[4] = 0x60;
+	val[5] = 0xa0;
+
+	tas_write_reg(tas, TAS_REG_DRC, 6, val);
+}
+
+static void tas_set_treble(struct tas *tas)
+{
+	u8 tmp;
+
+	tmp = tas3004_treble(tas->treble);
+	tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
+}
+
+static void tas_set_bass(struct tas *tas)
+{
+	u8 tmp;
+
+	tmp = tas3004_bass(tas->bass);
+	tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
+}
+
+static void tas_set_volume(struct tas *tas)
+{
+	u8 block[6];
+	int tmp;
+	u8 left, right;
+
+	left = tas->cached_volume_l;
+	right = tas->cached_volume_r;
+
+	if (left > 177) left = 177;
+	if (right > 177) right = 177;
+
+	if (tas->mute_l) left = 0;
+	if (tas->mute_r) right = 0;
+
+	/* analysing the volume and mixer tables shows
+	 * that they are similar enough when we shift
+	 * the mixer table down by 4 bits. The error
+	 * is miniscule, in just one item the error
+	 * is 1, at a value of 0x07f17b (mixer table
+	 * value is 0x07f17a) */
+	tmp = tas_gaintable[left];
+	block[0] = tmp>>20;
+	block[1] = tmp>>12;
+	block[2] = tmp>>4;
+	tmp = tas_gaintable[right];
+	block[3] = tmp>>20;
+	block[4] = tmp>>12;
+	block[5] = tmp>>4;
+	tas_write_reg(tas, TAS_REG_VOL, 6, block);
+}
+
+static void tas_set_mixer(struct tas *tas)
+{
+	u8 block[9];
+	int tmp, i;
+	u8 val;
+
+	for (i=0;i<3;i++) {
+		val = tas->mixer_l[i];
+		if (val > 177) val = 177;
+		tmp = tas_gaintable[val];
+		block[3*i+0] = tmp>>16;
+		block[3*i+1] = tmp>>8;
+		block[3*i+2] = tmp;
+	}
+	tas_write_reg(tas, TAS_REG_LMIX, 9, block);
+
+	for (i=0;i<3;i++) {
+		val = tas->mixer_r[i];
+		if (val > 177) val = 177;
+		tmp = tas_gaintable[val];
+		block[3*i+0] = tmp>>16;
+		block[3*i+1] = tmp>>8;
+		block[3*i+2] = tmp;
+	}
+	tas_write_reg(tas, TAS_REG_RMIX, 9, block);
+}
+
+/* alsa stuff */
+
+static int tas_dev_register(struct snd_device *dev)
+{
+	return 0;
+}
+
+static struct snd_device_ops ops = {
+	.dev_register = tas_dev_register,
+};
+
+static int tas_snd_vol_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 177;
+	return 0;
+}
+
+static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->cached_volume_l;
+	ucontrol->value.integer.value[1] = tas->cached_volume_r;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+	    ucontrol->value.integer.value[0] > 177)
+		return -EINVAL;
+	if (ucontrol->value.integer.value[1] < 0 ||
+	    ucontrol->value.integer.value[1] > 177)
+		return -EINVAL;
+
+	mutex_lock(&tas->mtx);
+	if (tas->cached_volume_l == ucontrol->value.integer.value[0]
+	 && tas->cached_volume_r == ucontrol->value.integer.value[1]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->cached_volume_l = ucontrol->value.integer.value[0];
+	tas->cached_volume_r = ucontrol->value.integer.value[1];
+	if (tas->hw_enabled)
+		tas_set_volume(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_vol_info,
+	.get = tas_snd_vol_get,
+	.put = tas_snd_vol_put,
+};
+
+#define tas_snd_mute_info	snd_ctl_boolean_stereo_info
+
+static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = !tas->mute_l;
+	ucontrol->value.integer.value[1] = !tas->mute_r;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	if (tas->mute_l == !ucontrol->value.integer.value[0]
+	 && tas->mute_r == !ucontrol->value.integer.value[1]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->mute_l = !ucontrol->value.integer.value[0];
+	tas->mute_r = !ucontrol->value.integer.value[1];
+	if (tas->hw_enabled)
+		tas_set_volume(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new mute_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Switch",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_mute_info,
+	.get = tas_snd_mute_get,
+	.put = tas_snd_mute_put,
+};
+
+static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 177;
+	return 0;
+}
+
+static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->mixer_l[idx];
+	ucontrol->value.integer.value[1] = tas->mixer_r[idx];
+	mutex_unlock(&tas->mtx);
+
+	return 0;
+}
+
+static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+
+	mutex_lock(&tas->mtx);
+	if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
+	 && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->mixer_l[idx] = ucontrol->value.integer.value[0];
+	tas->mixer_r[idx] = ucontrol->value.integer.value[1];
+
+	if (tas->hw_enabled)
+		tas_set_mixer(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+#define MIXER_CONTROL(n,descr,idx)			\
+static struct snd_kcontrol_new n##_control = {		\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
+	.name = descr " Playback Volume",		\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,	\
+	.info = tas_snd_mixer_info,			\
+	.get = tas_snd_mixer_get,			\
+	.put = tas_snd_mixer_put,			\
+	.private_value = idx,				\
+}
+
+MIXER_CONTROL(pcm1, "PCM", 0);
+MIXER_CONTROL(monitor, "Monitor", 2);
+
+static int tas_snd_drc_range_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 = TAS3004_DRC_MAX;
+	return 0;
+}
+
+static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->drc_range;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+	    ucontrol->value.integer.value[0] > TAS3004_DRC_MAX)
+		return -EINVAL;
+
+	mutex_lock(&tas->mtx);
+	if (tas->drc_range == ucontrol->value.integer.value[0]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->drc_range = ucontrol->value.integer.value[0];
+	if (tas->hw_enabled)
+		tas3004_set_drc(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new drc_range_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "DRC Range",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_drc_range_info,
+	.get = tas_snd_drc_range_get,
+	.put = tas_snd_drc_range_put,
+};
+
+#define tas_snd_drc_switch_info		snd_ctl_boolean_mono_info
+
+static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->drc_enabled;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	if (tas->drc_enabled == ucontrol->value.integer.value[0]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->drc_enabled = !!ucontrol->value.integer.value[0];
+	if (tas->hw_enabled)
+		tas3004_set_drc(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new drc_switch_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "DRC Range Switch",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_drc_switch_info,
+	.get = tas_snd_drc_switch_get,
+	.put = tas_snd_drc_switch_put,
+};
+
+static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Line-In", "Microphone" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int oldacr;
+
+	if (ucontrol->value.enumerated.item[0] > 1)
+		return -EINVAL;
+	mutex_lock(&tas->mtx);
+	oldacr = tas->acr;
+
+	/*
+	 * Despite what the data sheet says in one place, the
+	 * TAS_ACR_B_MONAUREAL bit forces mono output even when
+	 * input A (line in) is selected.
+	 */
+	tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL);
+	if (ucontrol->value.enumerated.item[0])
+		tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL |
+		      TAS_ACR_B_MON_SEL_RIGHT;
+	if (oldacr == tas->acr) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+	if (tas->hw_enabled)
+		tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* If we name this 'Input Source', it properly shows up in
+	 * alsamixer as a selection, * but it's shown under the
+	 * 'Playback' category.
+	 * If I name it 'Capture Source', it shows up in strange
+	 * ways (two bools of which one can be selected at a
+	 * time) but at least it's shown in the 'Capture'
+	 * category.
+	 * I was told that this was due to backward compatibility,
+	 * but I don't understand then why the mangling is *not*
+	 * done when I name it "Input Source".....
+	 */
+	.name = "Capture Source",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_capture_source_info,
+	.get = tas_snd_capture_source_get,
+	.put = tas_snd_capture_source_put,
+};
+
+static int tas_snd_treble_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 = TAS3004_TREBLE_MIN;
+	uinfo->value.integer.max = TAS3004_TREBLE_MAX;
+	return 0;
+}
+
+static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->treble;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN ||
+	    ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX)
+		return -EINVAL;
+	mutex_lock(&tas->mtx);
+	if (tas->treble == ucontrol->value.integer.value[0]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->treble = ucontrol->value.integer.value[0];
+	if (tas->hw_enabled)
+		tas_set_treble(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new treble_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Treble",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_treble_info,
+	.get = tas_snd_treble_get,
+	.put = tas_snd_treble_put,
+};
+
+static int tas_snd_bass_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 = TAS3004_BASS_MIN;
+	uinfo->value.integer.max = TAS3004_BASS_MAX;
+	return 0;
+}
+
+static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	mutex_lock(&tas->mtx);
+	ucontrol->value.integer.value[0] = tas->bass;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN ||
+	    ucontrol->value.integer.value[0] > TAS3004_BASS_MAX)
+		return -EINVAL;
+	mutex_lock(&tas->mtx);
+	if (tas->bass == ucontrol->value.integer.value[0]) {
+		mutex_unlock(&tas->mtx);
+		return 0;
+	}
+
+	tas->bass = ucontrol->value.integer.value[0];
+	if (tas->hw_enabled)
+		tas_set_bass(tas);
+	mutex_unlock(&tas->mtx);
+	return 1;
+}
+
+static struct snd_kcontrol_new bass_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Bass",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_bass_info,
+	.get = tas_snd_bass_get,
+	.put = tas_snd_bass_put,
+};
+
+static struct transfer_info tas_transfers[] = {
+	{
+		/* input */
+		.formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+		.transfer_in = 1,
+	},
+	{
+		/* output */
+		.formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+		.transfer_in = 0,
+	},
+	{}
+};
+
+static int tas_usable(struct codec_info_item *cii,
+		      struct transfer_info *ti,
+		      struct transfer_info *out)
+{
+	return 1;
+}
+
+static int tas_reset_init(struct tas *tas)
+{
+	u8 tmp;
+
+	tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
+	msleep(5);
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+	msleep(5);
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
+	msleep(20);
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+	msleep(10);
+	tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
+
+	tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
+	if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
+		goto outerr;
+
+	tas->acr |= TAS_ACR_ANALOG_PDOWN;
+	if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
+		goto outerr;
+
+	tmp = 0;
+	if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
+		goto outerr;
+
+	tas3004_set_drc(tas);
+
+	/* Set treble & bass to 0dB */
+	tas->treble = TAS3004_TREBLE_ZERO;
+	tas->bass = TAS3004_BASS_ZERO;
+	tas_set_treble(tas);
+	tas_set_bass(tas);
+
+	tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
+	if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
+		goto outerr;
+
+	return 0;
+ outerr:
+	return -ENODEV;
+}
+
+static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock)
+{
+	struct tas *tas = cii->codec_data;
+
+	switch(clock) {
+	case CLOCK_SWITCH_PREPARE_SLAVE:
+		/* Clocks are going away, mute mute mute */
+		tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
+		tas->hw_enabled = 0;
+		break;
+	case CLOCK_SWITCH_SLAVE:
+		/* Clocks are back, re-init the codec */
+		mutex_lock(&tas->mtx);
+		tas_reset_init(tas);
+		tas_set_volume(tas);
+		tas_set_mixer(tas);
+		tas->hw_enabled = 1;
+		tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
+		mutex_unlock(&tas->mtx);
+		break;
+	default:
+		/* doesn't happen as of now */
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/* we are controlled via i2c and assume that is always up
+ * If that wasn't the case, we'd have to suspend once
+ * our i2c device is suspended, and then take note of that! */
+static int tas_suspend(struct tas *tas)
+{
+	mutex_lock(&tas->mtx);
+	tas->hw_enabled = 0;
+	tas->acr |= TAS_ACR_ANALOG_PDOWN;
+	tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int tas_resume(struct tas *tas)
+{
+	/* reset codec */
+	mutex_lock(&tas->mtx);
+	tas_reset_init(tas);
+	tas_set_volume(tas);
+	tas_set_mixer(tas);
+	tas->hw_enabled = 1;
+	mutex_unlock(&tas->mtx);
+	return 0;
+}
+
+static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+	return tas_suspend(cii->codec_data);
+}
+
+static int _tas_resume(struct codec_info_item *cii)
+{
+	return tas_resume(cii->codec_data);
+}
+#else /* CONFIG_PM */
+#define _tas_suspend	NULL
+#define _tas_resume	NULL
+#endif /* CONFIG_PM */
+
+static struct codec_info tas_codec_info = {
+	.transfers = tas_transfers,
+	/* in theory, we can drive it at 512 too...
+	 * but so far the framework doesn't allow
+	 * for that and I don't see much point in it. */
+	.sysclock_factor = 256,
+	/* same here, could be 32 for just one 16 bit format */
+	.bus_factor = 64,
+	.owner = THIS_MODULE,
+	.usable = tas_usable,
+	.switch_clock = tas_switch_clock,
+	.suspend = _tas_suspend,
+	.resume = _tas_resume,
+};
+
+static int tas_init_codec(struct aoa_codec *codec)
+{
+	struct tas *tas = codec_to_tas(codec);
+	int err;
+
+	if (!tas->codec.gpio || !tas->codec.gpio->methods) {
+		printk(KERN_ERR PFX "gpios not assigned!!\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&tas->mtx);
+	if (tas_reset_init(tas)) {
+		printk(KERN_ERR PFX "tas failed to initialise\n");
+		mutex_unlock(&tas->mtx);
+		return -ENXIO;
+	}
+	tas->hw_enabled = 1;
+	mutex_unlock(&tas->mtx);
+
+	if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
+						   aoa_get_card(),
+						   &tas_codec_info, tas)) {
+		printk(KERN_ERR PFX "error attaching tas to soundbus\n");
+		return -ENODEV;
+	}
+
+	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) {
+		printk(KERN_ERR PFX "failed to create tas snd device!\n");
+		return -ENODEV;
+	}
+	err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas));
+	if (err)
+		goto error;
+
+	return 0;
+ error:
+	tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+	snd_device_free(aoa_get_card(), tas);
+	return err;
+}
+
+static void tas_exit_codec(struct aoa_codec *codec)
+{
+	struct tas *tas = codec_to_tas(codec);
+
+	if (!tas->codec.soundbus_dev)
+		return;
+	tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+}
+
+
+static struct i2c_driver tas_driver;
+
+static int tas_create(struct i2c_adapter *adapter,
+		       struct device_node *node,
+		       int addr)
+{
+	struct tas *tas;
+
+	tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
+
+	if (!tas)
+		return -ENOMEM;
+
+	mutex_init(&tas->mtx);
+	tas->i2c.driver = &tas_driver;
+	tas->i2c.adapter = adapter;
+	tas->i2c.addr = addr;
+	/* seems that half is a saner default */
+	tas->drc_range = TAS3004_DRC_MAX / 2;
+	strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE);
+
+	if (i2c_attach_client(&tas->i2c)) {
+		printk(KERN_ERR PFX "failed to attach to i2c\n");
+		goto fail;
+	}
+
+	strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
+	tas->codec.owner = THIS_MODULE;
+	tas->codec.init = tas_init_codec;
+	tas->codec.exit = tas_exit_codec;
+	tas->codec.node = of_node_get(node);
+
+	if (aoa_codec_register(&tas->codec)) {
+		goto detach;
+	}
+	printk(KERN_DEBUG
+	       "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
+	       addr, node->full_name);
+	return 0;
+ detach:
+	i2c_detach_client(&tas->i2c);
+ fail:
+	mutex_destroy(&tas->mtx);
+	kfree(tas);
+	return -EINVAL;
+}
+
+static int tas_i2c_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+		if (of_device_is_compatible(dev, "tas3004")) {
+			const u32 *addr;
+			printk(KERN_DEBUG PFX "found tas3004\n");
+			addr = of_get_property(dev, "reg", NULL);
+			if (!addr)
+				continue;
+			return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f);
+		}
+		/* older machines have no 'codec' node with a 'compatible'
+		 * property that says 'tas3004', they just have a 'deq'
+		 * node without any such property... */
+		if (strcmp(dev->name, "deq") == 0) {
+			const u32 *_addr;
+			u32 addr;
+			printk(KERN_DEBUG PFX "found 'deq' node\n");
+			_addr = of_get_property(dev, "i2c-address", NULL);
+			if (!_addr)
+				continue;
+			addr = ((*_addr) >> 1) & 0x7f;
+			/* now, if the address doesn't match any of the two
+			 * that a tas3004 can have, we cannot handle this.
+			 * I doubt it ever happens but hey. */
+			if (addr != 0x34 && addr != 0x35)
+				continue;
+			return tas_create(adapter, dev, addr);
+		}
+	}
+	return -ENODEV;
+}
+
+static int tas_i2c_detach(struct i2c_client *client)
+{
+	struct tas *tas = container_of(client, struct tas, i2c);
+	int err;
+	u8 tmp = TAS_ACR_ANALOG_PDOWN;
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+	aoa_codec_unregister(&tas->codec);
+	of_node_put(tas->codec.node);
+
+	/* power down codec chip */
+	tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
+
+	mutex_destroy(&tas->mtx);
+	kfree(tas);
+	return 0;
+}
+
+static struct i2c_driver tas_driver = {
+	.driver = {
+		.name = "aoa_codec_tas",
+		.owner = THIS_MODULE,
+	},
+	.attach_adapter = tas_i2c_attach,
+	.detach_client = tas_i2c_detach,
+};
+
+static int __init tas_init(void)
+{
+	return i2c_add_driver(&tas_driver);
+}
+
+static void __exit tas_exit(void)
+{
+	i2c_del_driver(&tas_driver);
+}
+
+module_init(tas_init);
+module_exit(tas_exit);
diff --git a/alsa/aoa/codecs/toonie.c b/alsa/aoa/codecs/toonie.c
new file mode 100644
index 0000000..2acb2e0
--- /dev/null
+++ b/alsa/aoa/codecs/toonie.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/aoa/codecs/toonie.c"
diff --git a/alsa/aoa/core/Makefile b/alsa/aoa/core/Makefile
new file mode 100644
index 0000000..7d5998f
--- /dev/null
+++ b/alsa/aoa/core/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/core/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/core/alsa.c b/alsa/aoa/core/alsa.c
new file mode 100644
index 0000000..fe98f04
--- /dev/null
+++ b/alsa/aoa/core/alsa.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/aoa/core/alsa.c"
diff --git a/alsa/aoa/core/core.c b/alsa/aoa/core/core.c
new file mode 100644
index 0000000..6fb491d
--- /dev/null
+++ b/alsa/aoa/core/core.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/aoa/core/core.c"
diff --git a/alsa/aoa/core/gpio-feature.c b/alsa/aoa/core/gpio-feature.c
new file mode 100644
index 0000000..893144e
--- /dev/null
+++ b/alsa/aoa/core/gpio-feature.c
@@ -0,0 +1,2 @@
+#include "ppc-prom-hack.h"
+#include "../../alsa-kernel/aoa/core/gpio-feature.c"
diff --git a/alsa/aoa/core/gpio-pmf.c b/alsa/aoa/core/gpio-pmf.c
new file mode 100644
index 0000000..72dc57c
--- /dev/null
+++ b/alsa/aoa/core/gpio-pmf.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/aoa/core/gpio-pmf.c"
diff --git a/alsa/aoa/fabrics/Makefile b/alsa/aoa/fabrics/Makefile
new file mode 100644
index 0000000..4c567e3
--- /dev/null
+++ b/alsa/aoa/fabrics/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/fabrics/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/fabrics/layout.c b/alsa/aoa/fabrics/layout.c
new file mode 100644
index 0000000..dd3aee6
--- /dev/null
+++ b/alsa/aoa/fabrics/layout.c
@@ -0,0 +1,2 @@
+#include "ppc-prom-hack.h"
+#include "../../alsa-kernel/aoa/fabrics/layout.c"
diff --git a/alsa/aoa/soundbus/Makefile b/alsa/aoa/soundbus/Makefile
new file mode 100644
index 0000000..e3289d5
--- /dev/null
+++ b/alsa/aoa/soundbus/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/soundbus/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/soundbus/core.c b/alsa/aoa/soundbus/core.c
new file mode 100644
index 0000000..b0a7b38
--- /dev/null
+++ b/alsa/aoa/soundbus/core.c
@@ -0,0 +1,2 @@
+#include "ppc-prom-hack.h"
+#include "../../alsa-kernel/aoa/soundbus/core.c"
diff --git a/alsa/aoa/soundbus/i2sbus/Makefile b/alsa/aoa/soundbus/i2sbus/Makefile
new file mode 100644
index 0000000..dc04f7e
--- /dev/null
+++ b/alsa/aoa/soundbus/i2sbus/Makefile
@@ -0,0 +1,10 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/aoa/soundbus/i2sbus/Makefile
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/aoa/soundbus/i2sbus/control.c b/alsa/aoa/soundbus/i2sbus/control.c
new file mode 100644
index 0000000..444408c
--- /dev/null
+++ b/alsa/aoa/soundbus/i2sbus/control.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../../alsa-kernel/aoa/soundbus/i2sbus/control.c"
diff --git a/alsa/aoa/soundbus/i2sbus/core.c b/alsa/aoa/soundbus/i2sbus/core.c
new file mode 100644
index 0000000..1d55474
--- /dev/null
+++ b/alsa/aoa/soundbus/i2sbus/core.c
@@ -0,0 +1,2 @@
+#include "ppc-prom-hack.h"
+#include "../../../alsa-kernel/aoa/soundbus/i2sbus/core.c"
diff --git a/alsa/aoa/soundbus/i2sbus/pcm.c b/alsa/aoa/soundbus/i2sbus/pcm.c
new file mode 100644
index 0000000..acf09de
--- /dev/null
+++ b/alsa/aoa/soundbus/i2sbus/pcm.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../../alsa-kernel/aoa/soundbus/i2sbus/pcm.c"
diff --git a/alsa/aoa/soundbus/sysfs.c b/alsa/aoa/soundbus/sysfs.c
new file mode 100644
index 0000000..abb7ea3
--- /dev/null
+++ b/alsa/aoa/soundbus/sysfs.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../../alsa-kernel/aoa/soundbus/sysfs.c"
diff --git a/alsa/arm/Kconfig b/alsa/arm/Kconfig
new file mode 100644
index 0000000..eee3171
--- /dev/null
+++ b/alsa/arm/Kconfig
@@ -0,0 +1,27 @@
+if SND_ARM
+
+config SND_SA11XX_UDA1341
+	tristate "SA11xx UDA1341TS driver (iPaq H3600)"
+	depends on ARCH_SA1100 && L3
+	select SND_PCM
+	help
+	  Say Y here if you have a Compaq iPaq H3x00 handheld computer
+	  and want to use its Philips UDA 1341 audio chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sa11xx-uda1341.
+
+config SND_S3C2410
+	tristate "S3C24XX Sound core"
+	depends on ARCH_S3C2410
+	select I2C_SENSOR
+	select SND_PCM
+	help
+	  Say Y here if you want to use the inbuilt audio controller
+	  on the S3C2410 or S3C2440
+
+config SND_PXA2xx_I2SOUND
+	tristate
+	select SND_PCM
+
+endif	# SND_ARM
diff --git a/alsa/arm/Makefile b/alsa/arm/Makefile
new file mode 100644
index 0000000..ce20860
--- /dev/null
+++ b/alsa/arm/Makefile
@@ -0,0 +1,18 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+include $(SND_TOPDIR)/alsa-kernel/arm/Makefile
+
+snd-sa11xx-uda1341-objs		:= sa11xx-uda1341.o
+snd-sa11x0-pcm-objs		:= sa11x0-pcm.o devdma.o
+snd-pxa2xx-i2sound-objs		:= pxa2xx-i2sound.o
+
+obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
+obj-$(CONFIG_SND_S3C2410)	+= s3c24xx-iis.o
+obj-$(CONFIG_SND_PXA2xx_I2SOUND)	+= snd-pxa2xx-i2sound.o
+
+include $(SND_TOPDIR)/Rules.make
diff --git a/alsa/arm/pxa2xx-ac97.c b/alsa/arm/pxa2xx-ac97.c
new file mode 100644
index 0000000..dc97eb2
--- /dev/null
+++ b/alsa/arm/pxa2xx-ac97.c
@@ -0,0 +1,2 @@
+#include "adriver.h"
+#include "../alsa-kernel/arm/pxa2xx-ac97.c"
diff --git a/alsa/arm/pxa2xx-i2sound.c b/alsa/arm/pxa2xx-i2sound.c
new file mode 100644
index 0000000..528bebb
--- /dev/null
+++ b/alsa/arm/pxa2xx-i2sound.c
@@ -0,0 +1,931 @@
+/*
+ * PXA2xx i2Sound: support for Intel PXA2xx I2S audio
+ *
+ * Copyright (c) 2004,2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * History:
+ *
+ * 2005-03	Initial release; Audio engine ((c) 2004) derived from pxa-uda1380.c
+ *		-- Giorgio Padrin
+ * 2005-06	Power management -- Giorgio Padrin
+ * 2005-10	Some finishing -- Giorgio Padrin
+ */
+
+#include "adriver.h"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/pm.h>